diff --git a/configure b/configure index 6edcd38e680..95c8ef64d87 100755 --- a/configure +++ b/configure @@ -1434,7 +1434,8 @@ while [ "$#" -gt 0 ]; do fi ;; feature-*) - FEATURE=`echo $VAR | sed 's,^[^-]*-\([^-]*\),\1,' | tr 'abcdefghijklmnopqrstuvwxyz-' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'` + FEATURE=`echo $VAR | sed 's,^[^-]*-\([^-]*\),\1,' | tr 'abcdefghijklmnopqrstuvwxyz-' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'` + if grep "^Feature: *${FEATURE} *\$" "$relpath"/src/corelib/global/qfeatures.txt >/dev/null 2>&1; then if [ "$VAL" = "no" ]; then QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_$FEATURE" elif [ "$VAL" = "yes" ] || [ "$VAL" = "unknown" ]; then @@ -1442,6 +1443,10 @@ while [ "$#" -gt 0 ]; do else UNKNOWN_OPT=yes fi + else + echo "ERROR: Unknown feature $FEATURE" + UNKNOWN_OPT=yes + fi ;; shared) if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then @@ -3183,6 +3188,7 @@ if [ "$XPLATFORM_IOS" = "yes" ]; then CFG_NOBUILD_PARTS="$CFG_NOBUILD_PARTS examples" CFG_SHARED="no" # iOS builds should be static to be able to submit to the App Store CFG_SKIP_MODULES="$CFG_SKIP_MODULES qtconnectivity qtdoc qtmacextras qtserialport qtwebkit qtwebkit-examples" + CFG_PRECOMPILE="no" # Precompiled headers not supported with multiple -arch arguments # If the user passes -sdk on the command line we build a SDK-specific Qt build. # Otherwise we build a joined simulator and device build, which is the default. diff --git a/dist/changes-5.4.0 b/dist/changes-5.4.0 index 927ca0f9f19..c3c7f532a3b 100644 --- a/dist/changes-5.4.0 +++ b/dist/changes-5.4.0 @@ -25,6 +25,10 @@ QtCore - Added QEnableSharedFromThis, a class that allows obtaining a QSharedPointer for an object already managed by a shared pointer. +QtGui +----- + + - QImageReader now automatically rotates JPEG images according to Exif orientation QtSql ----- @@ -43,3 +47,46 @@ OS X - OS X 10.10 is now supported. - QMacStyle has been updated with better OS 10.10 support. - The Qt binary packages are now configured with C++11 enabled. + +Windows +------- + + - [QTBUG-38259] Changed configure defaults so that Qt5Core does not + link against ICU libraries anymore. Pass '-icu' to enable it. + +**************************************************************************** +* Tools * +**************************************************************************** + +configure & build system +------------------------ + + - The -process/-fully-process/-dont-process configure options have been + removed due to being unnecessary and counterproductive. + - [QTBUG-36955] The -vcproj configure option was removed. Use "qmake -r -tp vc" + _after_ building Qt in case you want to use Visual Studio to work on Qt. + - [QTBUG-37961] Qt plugins contain version info again. + - [QTBUG-39216] Fixed more cases where the Qt build would pick up headers + from a pre-existing Qt installation. + - [QTBUG-41267] Fixed parallelized (jom) -debug-and-release builds. + +qmake +----- + + - [QTBUG-21910][Unix] Added 'make dist' target for SUBDIRS projects. + - [QTBUG-32895][iOS] Fixed structure of bundles. They can be signed now. + - [QTBUG-26782][VS] Fixed handling of TARGET_EXT. + - [QTBUG-30712][VS] Fixed handling of QMAKE_LIBFLAGS. + - [QTBUG-30373][VS] Using different RESOURCES in different build variants + no longer produces invalid vcxproj files. + - [QTBUG-37520][VS] Made it possible to suppress qmake warnings about + unknown compiler options. CONFIG+=suppress_vcproj_warnings. + - [QTBUG-37363][MSVC2012+] embed_manifest_exe is now properly supported. + - [QTBUG-41504][MSVC2012+] Building DLLs targeting Windows XP is now + supported. As a side effect, Windows CE makespecs must not add /ENTRY: to + QMAKE_LFLAGS_CONSOLE any more. The flag is hard-coded in console.prf now. + - [QTBUG-35318][Xcode] Fixed QMAKE_BUNDLE_DATA's path resolution. + - [QTBUG-39527] Fixed qtCompile() when used with jom -jN. + - QMAKE_EXTRA_COMPILERS' commands and depend_command are no longer mangled. + Use $$shell_path() and $$shell_quote() to prepare the commands correctly. + - Added link-time optimization support for Clang, GCC and ICC. CONFIG+=ltgc. diff --git a/doc/global/externalsites/qtcreator.qdoc b/doc/global/externalsites/qtcreator.qdoc index 46609de1606..a98fbd0a56c 100644 --- a/doc/global/externalsites/qtcreator.qdoc +++ b/doc/global/externalsites/qtcreator.qdoc @@ -483,3 +483,15 @@ \externalpage http://qt-project.org/doc/qtcreator/creator-developing-winrt.html \title Qt Creator: Connecting Windows Runtime Devices */ +/*! + \externalpage http://qt-project.org/doc/qtcreator/creator-clang-codemodel.html + \title Qt Creator: Parsing C++ Files +*/ +/*! + \externalpage http://qt-project.org/doc/qtcreator/creator-quick-ui-forms.html + \title Qt Creator: Qt Quick UI Forms +*/ +/*! + \externalpage http://qt-project.org/doc/qtcreator/creator-clang-static-analyzer.html + \title Qt Creator: Using Clang Static Analyzer +*/ diff --git a/doc/global/template/images/Qt-logo.png b/doc/global/template/images/Qt-logo.png index 64c1c4aaa34..01256ab08dc 100644 Binary files a/doc/global/template/images/Qt-logo.png and b/doc/global/template/images/Qt-logo.png differ diff --git a/doc/global/template/images/logo.png b/doc/global/template/images/logo.png index 1e7ed4cf213..698dde9215c 100644 Binary files a/doc/global/template/images/logo.png and b/doc/global/template/images/logo.png differ diff --git a/doc/global/template/images/sprites-combined.png b/doc/global/template/images/sprites-combined.png index 3a48b21f6b8..c4f01c4bb95 100644 Binary files a/doc/global/template/images/sprites-combined.png and b/doc/global/template/images/sprites-combined.png differ diff --git a/doc/global/template/style/offline.css b/doc/global/template/style/offline.css index 5adb699972b..16f26f43bb5 100644 --- a/doc/global/template/style/offline.css +++ b/doc/global/template/style/offline.css @@ -2,7 +2,6 @@ body { font: normal 400 14px/1.2 Arial; margin-top: 85px; font-family: Arial, Helvetica; - color: #313131; text-align: left; margin-left: 5px; margin-right: 5px; @@ -365,7 +364,9 @@ h3.fn, span.fn { margin: 0px; margin-top: 45px; } - +h3.fn code { + float: right; +} h3.fn:target { background-color: #F6F6D6; } @@ -711,8 +712,21 @@ Landing page float: left; } -.icons1of3 h2 { +.icons1of3 h2, .doc-column h2 { font-size: 15px; margin: 0px; padding: 0px; } + +div.multi-column { + position: relative; +} + +div.multi-column div { + display: -moz-inline-box; + display: inline-block; + vertical-align: top; + margin-top: 1em; + margin-right: 4em; + width: 24em; +} diff --git a/doc/src/images/analogclock-example.png b/doc/src/images/analogclock-example.png index ffd7baa7169..b195f8bf24b 100644 Binary files a/doc/src/images/analogclock-example.png and b/doc/src/images/analogclock-example.png differ diff --git a/doc/src/images/application.png b/doc/src/images/application.png index 2fb7f2f18e4..bff37369a48 100644 Binary files a/doc/src/images/application.png and b/doc/src/images/application.png differ diff --git a/doc/src/images/digitalclock-example.png b/doc/src/images/digitalclock-example.png index 473986608c4..917035a0f08 100644 Binary files a/doc/src/images/digitalclock-example.png and b/doc/src/images/digitalclock-example.png differ diff --git a/doc/src/images/scribble-example.png b/doc/src/images/scribble-example.png index a2cb1de3e84..54091baa6b7 100644 Binary files a/doc/src/images/scribble-example.png and b/doc/src/images/scribble-example.png differ diff --git a/examples/gui/doc/images/analogclock-window-example.png b/examples/gui/doc/images/analogclock-window-example.png index ffd7baa7169..f5e92e400ab 100644 Binary files a/examples/gui/doc/images/analogclock-window-example.png and b/examples/gui/doc/images/analogclock-window-example.png differ diff --git a/examples/network/bearermonitor/bearermonitor.cpp b/examples/network/bearermonitor/bearermonitor.cpp index 4590a91f4ff..2f5d6cda1cd 100644 --- a/examples/network/bearermonitor/bearermonitor.cpp +++ b/examples/network/bearermonitor/bearermonitor.cpp @@ -127,6 +127,9 @@ static void updateItem(QTreeWidgetItem *item, const QNetworkConfiguration &confi void BearerMonitor::configurationAdded(const QNetworkConfiguration &config, QTreeWidgetItem *parent) { + if (!config.isValid()) + return; + QTreeWidgetItem *item = new QTreeWidgetItem; updateItem(item, config); diff --git a/examples/network/securesocketclient/sslclient.cpp b/examples/network/securesocketclient/sslclient.cpp index 23ca7e41e78..0cec70c7428 100644 --- a/examples/network/securesocketclient/sslclient.cpp +++ b/examples/network/securesocketclient/sslclient.cpp @@ -181,7 +181,7 @@ void SslClient::sendData() form->sessionInput->clear(); } -void SslClient::socketError(QAbstractSocket::SocketError error) +void SslClient::socketError(QAbstractSocket::SocketError) { QMessageBox::critical(this, tr("Connection error"), socket->errorString()); } diff --git a/examples/network/securesocketclient/sslclient.ui b/examples/network/securesocketclient/sslclient.ui index 4b81fe46ebf..19bae83a09b 100644 --- a/examples/network/securesocketclient/sslclient.ui +++ b/examples/network/securesocketclient/sslclient.ui @@ -26,7 +26,7 @@ - imap.example.com + www.qt.io @@ -46,7 +46,7 @@ 65535 - 993 + 443 diff --git a/examples/opengl/legacy/framebufferobject2/cubelogo.png b/examples/opengl/legacy/framebufferobject2/cubelogo.png index 3ae0f9ba3f8..2ccbede7748 100644 Binary files a/examples/opengl/legacy/framebufferobject2/cubelogo.png and b/examples/opengl/legacy/framebufferobject2/cubelogo.png differ diff --git a/examples/opengl/legacy/pbuffers/cubelogo.png b/examples/opengl/legacy/pbuffers/cubelogo.png index 3ae0f9ba3f8..2ccbede7748 100644 Binary files a/examples/opengl/legacy/pbuffers/cubelogo.png and b/examples/opengl/legacy/pbuffers/cubelogo.png differ diff --git a/examples/sql/doc/images/drilldown-example.png b/examples/sql/doc/images/drilldown-example.png index fd315a437e0..fed51d36292 100644 Binary files a/examples/sql/doc/images/drilldown-example.png and b/examples/sql/doc/images/drilldown-example.png differ diff --git a/examples/sql/drilldown/images/qt-creator.png b/examples/sql/drilldown/images/qt-creator.png index fa0f6ed7cef..0602bdcad1d 100644 Binary files a/examples/sql/drilldown/images/qt-creator.png and b/examples/sql/drilldown/images/qt-creator.png differ diff --git a/examples/sql/drilldown/images/qt-logo.png b/examples/sql/drilldown/images/qt-logo.png index 53bc39c38c1..7603fa0c903 100644 Binary files a/examples/sql/drilldown/images/qt-logo.png and b/examples/sql/drilldown/images/qt-logo.png differ diff --git a/examples/sql/drilldown/images/qt-project.png b/examples/sql/drilldown/images/qt-project.png index c34d3f099dd..e066fbe3f98 100644 Binary files a/examples/sql/drilldown/images/qt-project.png and b/examples/sql/drilldown/images/qt-project.png differ diff --git a/examples/sql/drilldown/images/qt-quick.png b/examples/sql/drilldown/images/qt-quick.png index f66127e8e74..90d9fd075d8 100644 Binary files a/examples/sql/drilldown/images/qt-quick.png and b/examples/sql/drilldown/images/qt-quick.png differ diff --git a/examples/widgets/animation/animatedtiles/images/kinetic.png b/examples/widgets/animation/animatedtiles/images/kinetic.png index 55cfa5515f5..d5fc0af0f24 100644 Binary files a/examples/widgets/animation/animatedtiles/images/kinetic.png and b/examples/widgets/animation/animatedtiles/images/kinetic.png differ diff --git a/examples/widgets/animation/easing/images/qt-logo.png b/examples/widgets/animation/easing/images/qt-logo.png index 14ddf2a0289..6b72d5fb72c 100644 Binary files a/examples/widgets/animation/easing/images/qt-logo.png and b/examples/widgets/animation/easing/images/qt-logo.png differ diff --git a/examples/widgets/doc/images/dropsite-example.png b/examples/widgets/doc/images/dropsite-example.png index 2c42c7be69b..c555dd3609e 100644 Binary files a/examples/widgets/doc/images/dropsite-example.png and b/examples/widgets/doc/images/dropsite-example.png differ diff --git a/examples/widgets/doc/images/icons_qt_extended_16x16.png b/examples/widgets/doc/images/icons_qt_extended_16x16.png index 92743690e30..8bae9499e45 100644 Binary files a/examples/widgets/doc/images/icons_qt_extended_16x16.png and b/examples/widgets/doc/images/icons_qt_extended_16x16.png differ diff --git a/examples/widgets/doc/images/icons_qt_extended_17x17.png b/examples/widgets/doc/images/icons_qt_extended_17x17.png index e9bb24a282d..7ef4222f936 100644 Binary files a/examples/widgets/doc/images/icons_qt_extended_17x17.png and b/examples/widgets/doc/images/icons_qt_extended_17x17.png differ diff --git a/examples/widgets/doc/images/icons_qt_extended_32x32.png b/examples/widgets/doc/images/icons_qt_extended_32x32.png index cd3d0f32551..7b0c54bac3a 100644 Binary files a/examples/widgets/doc/images/icons_qt_extended_32x32.png and b/examples/widgets/doc/images/icons_qt_extended_32x32.png differ diff --git a/examples/widgets/doc/images/icons_qt_extended_33x33.png b/examples/widgets/doc/images/icons_qt_extended_33x33.png index a67565cc2bf..1a38f6e44b0 100644 Binary files a/examples/widgets/doc/images/icons_qt_extended_33x33.png and b/examples/widgets/doc/images/icons_qt_extended_33x33.png differ diff --git a/examples/widgets/doc/images/icons_qt_extended_48x48.png b/examples/widgets/doc/images/icons_qt_extended_48x48.png index 5aa2d73f71a..85dcb5f26c6 100644 Binary files a/examples/widgets/doc/images/icons_qt_extended_48x48.png and b/examples/widgets/doc/images/icons_qt_extended_48x48.png differ diff --git a/examples/widgets/doc/images/icons_qt_extended_64x64.png b/examples/widgets/doc/images/icons_qt_extended_64x64.png index 5aa2d73f71a..d0bfd97f10b 100644 Binary files a/examples/widgets/doc/images/icons_qt_extended_64x64.png and b/examples/widgets/doc/images/icons_qt_extended_64x64.png differ diff --git a/examples/widgets/doc/images/icons_qt_extended_8x8.png b/examples/widgets/doc/images/icons_qt_extended_8x8.png index 8de7fce038a..dcbb5811c6b 100644 Binary files a/examples/widgets/doc/images/icons_qt_extended_8x8.png and b/examples/widgets/doc/images/icons_qt_extended_8x8.png differ diff --git a/examples/widgets/doc/src/application.qdoc b/examples/widgets/doc/src/application.qdoc index 0d244bce002..e0379e9d753 100644 --- a/examples/widgets/doc/src/application.qdoc +++ b/examples/widgets/doc/src/application.qdoc @@ -75,12 +75,12 @@ \snippet mainwindows/application/mainwindow.cpp 0 - We start by including \c , a header file that contains the - definition of all classes in the Qt Core and Qt GUI + We start by including \c , a header file that contains the + definition of all classes in the Qt Core, Qt GUI and Qt Widgets modules. This saves us from the trouble of having to include every class individually. We also include \c mainwindow.h. - You might wonder why we don't include \c in \c + You might wonder why we don't include \c in \c mainwindow.h and be done with it. The reason is that including such a large header from another header file can rapidly degrade performances. Here, it wouldn't do any harm, but it's still diff --git a/examples/widgets/doc/src/dockwidgets.qdoc b/examples/widgets/doc/src/dockwidgets.qdoc index 2987ec1211b..a11524f4f43 100644 --- a/examples/widgets/doc/src/dockwidgets.qdoc +++ b/examples/widgets/doc/src/dockwidgets.qdoc @@ -55,8 +55,8 @@ \snippet mainwindows/dockwidgets/mainwindow.cpp 0 - We start by including \c , a header file that contains the - definition of all classes in the Qt Core and Qt GUI + We start by including \c , a header file that contains the + definition of all classes in the Qt Core, Qt GUI and Qt Widgets modules. This saves us from having to include every class individually and is especially convenient if we add new widgets. We also include \c mainwindow.h. diff --git a/examples/widgets/draganddrop/puzzle/example.jpg b/examples/widgets/draganddrop/puzzle/example.jpg index e09fb707570..023203c57aa 100644 Binary files a/examples/widgets/draganddrop/puzzle/example.jpg and b/examples/widgets/draganddrop/puzzle/example.jpg differ diff --git a/examples/widgets/graphicsview/boxes/qt-logo.jpg b/examples/widgets/graphicsview/boxes/qt-logo.jpg index 4014b4659c1..8d7fab052a0 100644 Binary files a/examples/widgets/graphicsview/boxes/qt-logo.jpg and b/examples/widgets/graphicsview/boxes/qt-logo.jpg differ diff --git a/examples/widgets/graphicsview/boxes/qt-logo.png b/examples/widgets/graphicsview/boxes/qt-logo.png index 7d3e97eb36e..0b0b15480cd 100644 Binary files a/examples/widgets/graphicsview/boxes/qt-logo.png and b/examples/widgets/graphicsview/boxes/qt-logo.png differ diff --git a/examples/widgets/itemviews/puzzle/example.jpg b/examples/widgets/itemviews/puzzle/example.jpg index e09fb707570..023203c57aa 100644 Binary files a/examples/widgets/itemviews/puzzle/example.jpg and b/examples/widgets/itemviews/puzzle/example.jpg differ diff --git a/examples/widgets/painting/basicdrawing/images/qt-logo.png b/examples/widgets/painting/basicdrawing/images/qt-logo.png index a8b452e07a5..abfc8caadbb 100644 Binary files a/examples/widgets/painting/basicdrawing/images/qt-logo.png and b/examples/widgets/painting/basicdrawing/images/qt-logo.png differ diff --git a/examples/widgets/widgets/icons/images/qt_extended_16x16.png b/examples/widgets/widgets/icons/images/qt_extended_16x16.png index 95d3bae8389..bee4e7d6cd2 100644 Binary files a/examples/widgets/widgets/icons/images/qt_extended_16x16.png and b/examples/widgets/widgets/icons/images/qt_extended_16x16.png differ diff --git a/examples/widgets/widgets/icons/images/qt_extended_32x32.png b/examples/widgets/widgets/icons/images/qt_extended_32x32.png index 7b7a790c122..6e7d000c047 100644 Binary files a/examples/widgets/widgets/icons/images/qt_extended_32x32.png and b/examples/widgets/widgets/icons/images/qt_extended_32x32.png differ diff --git a/examples/widgets/widgets/icons/images/qt_extended_48x48.png b/examples/widgets/widgets/icons/images/qt_extended_48x48.png index 8434dc26dbd..7a93d889001 100644 Binary files a/examples/widgets/widgets/icons/images/qt_extended_48x48.png and b/examples/widgets/widgets/icons/images/qt_extended_48x48.png differ diff --git a/examples/widgets/widgets/mousebuttons/buttontester.cpp b/examples/widgets/widgets/mousebuttons/buttontester.cpp index 41c6c95adf2..51287f541b3 100644 --- a/examples/widgets/widgets/mousebuttons/buttontester.cpp +++ b/examples/widgets/widgets/mousebuttons/buttontester.cpp @@ -41,6 +41,8 @@ #include "buttontester.h" +#include + void ButtonTester::mousePressEvent(QMouseEvent *e) { int j = ButtonTester::buttonByNumber (e->button()); diff --git a/examples/widgets/widgets/mousebuttons/buttontester.h b/examples/widgets/widgets/mousebuttons/buttontester.h index 9e7011ac9a3..41ae8d05829 100644 --- a/examples/widgets/widgets/mousebuttons/buttontester.h +++ b/examples/widgets/widgets/mousebuttons/buttontester.h @@ -41,10 +41,8 @@ #ifndef BUTTONTESTER_H #define BUTTONTESTER_H -#include #include #include -#include #include #include diff --git a/examples/widgets/widgets/mousebuttons/main.cpp b/examples/widgets/widgets/mousebuttons/main.cpp index 184547113e5..b5446df9e93 100644 --- a/examples/widgets/widgets/mousebuttons/main.cpp +++ b/examples/widgets/widgets/mousebuttons/main.cpp @@ -40,7 +40,10 @@ ****************************************************************************/ #include "buttontester.h" -#include + +#include +#include +#include int main(int argv, char **args) { diff --git a/mkspecs/common/clang.conf b/mkspecs/common/clang.conf index 6235296ef33..2c29bb88fb1 100644 --- a/mkspecs/common/clang.conf +++ b/mkspecs/common/clang.conf @@ -7,6 +7,9 @@ QMAKE_COMPILER = gcc clang llvm # clang pretends to be gcc QMAKE_CC = clang QMAKE_CXX = clang++ +QMAKE_LINK_C = $$QMAKE_CC +QMAKE_LINK_C_SHLIB = $$QMAKE_CC + QMAKE_LINK = $$QMAKE_CXX QMAKE_LINK_SHLIB = $$QMAKE_CXX diff --git a/mkspecs/common/qcc-base.conf b/mkspecs/common/qcc-base.conf index 122f940ec3e..f529d7fc7ba 100644 --- a/mkspecs/common/qcc-base.conf +++ b/mkspecs/common/qcc-base.conf @@ -11,11 +11,15 @@ QMAKE_COMPILER = rim_qcc gcc # qcc is mostly gcc in disguise +QMAKE_CFLAGS_OPTIMIZE = -O2 +QMAKE_CFLAGS_OPTIMIZE_FULL = -O3 + QMAKE_CFLAGS += -Wno-psabi QMAKE_CFLAGS_DEPS += -M QMAKE_CFLAGS_WARN_ON += -Wall -W QMAKE_CFLAGS_WARN_OFF += -w -QMAKE_CFLAGS_RELEASE += -O2 +QMAKE_CFLAGS_RELEASE += $$QMAKE_CFLAGS_OPTIMIZE +QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_OPTIMIZE -g QMAKE_CFLAGS_DEBUG += -g QMAKE_CFLAGS_SHLIB += -fPIC -shared QMAKE_CFLAGS_STATIC_LIB += -fPIC @@ -36,6 +40,7 @@ QMAKE_CXXFLAGS_DEPS += $$QMAKE_CFLAGS_DEPS QMAKE_CXXFLAGS_WARN_ON += $$QMAKE_CFLAGS_WARN_ON QMAKE_CXXFLAGS_WARN_OFF += $$QMAKE_CFLAGS_WARN_OFF QMAKE_CXXFLAGS_RELEASE += $$QMAKE_CFLAGS_RELEASE +QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO QMAKE_CXXFLAGS_DEBUG += $$QMAKE_CFLAGS_DEBUG QMAKE_CXXFLAGS_SHLIB += $$QMAKE_CFLAGS_SHLIB QMAKE_CXXFLAGS_STATIC_LIB += $$QMAKE_CFLAGS_STATIC_LIB 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 97d34074037..a6fc9697f41 100644 --- a/mkspecs/common/winrt_winphone/manifests/8.1/AppxManifest.xml.in +++ b/mkspecs/common/winrt_winphone/manifests/8.1/AppxManifest.xml.in @@ -34,7 +34,7 @@ - + $${WINRT_MANIFEST.rotation_preference} $${WINRT_MANIFEST.capabilities}$${WINRT_MANIFEST.dependencies} diff --git a/mkspecs/common/winrt_winphone/manifests/8.1_wp/AppxManifest.xml.in b/mkspecs/common/winrt_winphone/manifests/8.1_wp/AppxManifest.xml.in index cf18a4dc790..b75570ad4e3 100644 --- a/mkspecs/common/winrt_winphone/manifests/8.1_wp/AppxManifest.xml.in +++ b/mkspecs/common/winrt_winphone/manifests/8.1_wp/AppxManifest.xml.in @@ -37,7 +37,7 @@ - + $${WINRT_MANIFEST.rotation_preference} $${WINRT_MANIFEST.capabilities}$${WINRT_MANIFEST.dependencies} diff --git a/mkspecs/devices/linux-rasp-pi-g++/qmake.conf b/mkspecs/devices/linux-rasp-pi-g++/qmake.conf index 5f923ad5c67..6537d457ab9 100644 --- a/mkspecs/devices/linux-rasp-pi-g++/qmake.conf +++ b/mkspecs/devices/linux-rasp-pi-g++/qmake.conf @@ -4,8 +4,6 @@ include(../common/linux_device_pre.conf) -QT_QPA_DEFAULT_PLATFORM = wayland - QMAKE_LFLAGS += -Wl,-rpath-link,$$[QT_SYSROOT]/opt/vc/lib QMAKE_LIBDIR_OPENGL_ES2 = $$[QT_SYSROOT]/opt/vc/lib @@ -21,7 +19,6 @@ QMAKE_LIBS_EGL = -lEGL -lGLESv2 contains(DISTRO, squeeze) { #Debian Squeeze: Legacy everything QMAKE_LIBS_OPENGL_ES2 = -lGLESv2 -lEGL - QT_QPA_DEFAULT_PLATFORM = eglfs } else:contains(DISTRO, arch) { #On principle: no wizardry required } else { diff --git a/mkspecs/features/configure.prf b/mkspecs/features/configure.prf index 05e10c96411..6b37a044508 100644 --- a/mkspecs/features/configure.prf +++ b/mkspecs/features/configure.prf @@ -1,4 +1,7 @@ -equals(MAKEFILE_GENERATOR, UNIX) { +QMAKE_MAKE = $$(MAKE) +!isEmpty(QMAKE_MAKE) { + # We were called recursively. Use the right make, as MAKEFLAGS may be set as well. +} else:equals(MAKEFILE_GENERATOR, UNIX) { QMAKE_MAKE = make } else:equals(MAKEFILE_GENERATOR, MINGW) { !equals(QMAKE_HOST.os, Windows): \ diff --git a/mkspecs/features/mac/default_post.prf b/mkspecs/features/mac/default_post.prf index 530683552b4..246c9c60e69 100644 --- a/mkspecs/features/mac/default_post.prf +++ b/mkspecs/features/mac/default_post.prf @@ -35,6 +35,30 @@ qt:!isEmpty(QT_CONFIG) { QMAKE_LFLAGS += -stdlib=libstdc++ } } + # If Qt was built with shared libraries with rpath support and project does + # not specify own rpaths (including empty list) add one pointing to Qt + # libraries. This applies only to apps, since all loaded libraries inherit + # rpaths from current process executable. + else:!if(host_build:force_bootstrap):equals(TEMPLATE, app):!defined(QMAKE_RPATHDIR, var):contains(QT_CONFIG, rpath) { + # If app is outside of Qt SDK prefix use absolute path to Qt libraries, + # otherwise make it relative, so all SDK tools and examples work when + # relocated. + # Tests are an exception, since they are launched in their build not + # install location by CI, so we cannot use relative rpaths there. + if(!contains(target.path, "$$re_escape($$[QT_INSTALL_PREFIX])/.*")|\ + contains(target.path, "$$re_escape($$[QT_INSTALL_TESTS])/.*")) { + QMAKE_RPATHDIR = $$[QT_INSTALL_LIBS] + } else { + app_bundle { + ios: binpath = $$target.path/$${TARGET}.app + else: binpath = $$target.path/$${TARGET}.app/Contents/MacOS + } else { + binpath = $$target.path + } + QMAKE_RPATHDIR = @loader_path/$$relative_path($$[QT_INSTALL_LIBS], $$binpath) + unset(binpath) + } + } } macx-xcode:!isEmpty(QMAKE_XCODE_DEBUG_INFORMATION_FORMAT) { diff --git a/mkspecs/features/mac/sdk.prf b/mkspecs/features/mac/sdk.prf index 36bff004963..97be2115959 100644 --- a/mkspecs/features/mac/sdk.prf +++ b/mkspecs/features/mac/sdk.prf @@ -9,8 +9,12 @@ isEmpty(QMAKE_MAC_SDK.$${QMAKE_MAC_SDK}.path) { QMAKE_MAC_SDK_PATH = $$system("/usr/bin/xcodebuild -sdk $$QMAKE_MAC_SDK -version Path 2>/dev/null") isEmpty(QMAKE_MAC_SDK_PATH): error("Could not resolve SDK path for \'$$QMAKE_MAC_SDK\'") cache(QMAKE_MAC_SDK.$${QMAKE_MAC_SDK}.path, set stash, QMAKE_MAC_SDK_PATH) + QMAKE_MAC_SDK_VERSION = $$system("/usr/bin/xcodebuild -sdk $$QMAKE_MAC_SDK -version SDKVersion 2>/dev/null") + isEmpty(QMAKE_MAC_SDK_VERSION): error("Could not resolve SDK version for \'$$QMAKE_MAC_SDK\'") + cache(QMAKE_MAC_SDK.$${QMAKE_MAC_SDK}.version, set stash, QMAKE_MAC_SDK_VERSION) } else { QMAKE_MAC_SDK_PATH = $$eval(QMAKE_MAC_SDK.$${QMAKE_MAC_SDK}.path) + QMAKE_MAC_SDK_VERSION = $$eval(QMAKE_MAC_SDK.$${QMAKE_MAC_SDK}.version) } !equals(MAKEFILE_GENERATOR, XCODE) { diff --git a/mkspecs/features/qt_common.prf b/mkspecs/features/qt_common.prf index ebc5f00b8f9..af9d6cae67f 100644 --- a/mkspecs/features/qt_common.prf +++ b/mkspecs/features/qt_common.prf @@ -44,20 +44,20 @@ warnings_are_errors:warning_clean { # This setting is compiler-dependent anyway because it depends on the version of the # compiler. clang { - # Apple clang 4.0-4.2,5.0 + # Apple clang 4.0-4.2,5.0-5.1 # Regular clang 3.3 & 3.4 apple_ver = $${QT_APPLE_CLANG_MAJOR_VERSION}.$${QT_APPLE_CLANG_MINOR_VERSION} reg_ver = $${QT_CLANG_MAJOR_VERSION}.$${QT_CLANG_MINOR_VERSION} - contains(apple_ver, "4\\.[012]|5\\.0")|contains(reg_ver, "3\\.[34]") { + contains(apple_ver, "4\\.[012]|5\\.[01]")|contains(reg_ver, "3\\.[34]") { QMAKE_CXXFLAGS_WARN_ON += -Werror -Wno-error=\\$${LITERAL_HASH}warnings -Wno-error=deprecated-declarations $$WERROR # glibc's bswap_XX macros use the "register" keyword linux:equals(reg_ver, "3.4"): QMAKE_CXXFLAGS_WARN_ON += -Wno-error=deprecated-register } } else:intel_icc:linux { - # Intel CC 13.0 - 14.0, on Linux only + # Intel CC 13.0 - 15.0, on Linux only ver = $${QT_ICC_MAJOR_VERSION}.$${QT_ICC_MINOR_VERSION} - linux:contains(ver, "(13\\.|14\\.0)") { + linux:contains(ver, "(1[34]\\.|15\\.0)") { # 177: function "entity" was declared but never referenced # (too aggressive; ICC reports even for functions created due to template instantiation) # 1224: #warning directive @@ -67,9 +67,9 @@ warnings_are_errors:warning_clean { QMAKE_CXXFLAGS_WARN_ON += -Werror -ww177,1224,1478,1881 $$WERROR } } else:gcc:!clang:!intel_icc { - # GCC 4.6-4.8 + # GCC 4.6-4.9 ver = $${QT_GCC_MAJOR_VERSION}.$${QT_GCC_MINOR_VERSION} - contains(ver, "4\\.[678]") { + contains(ver, "4\\.[6789]") { QMAKE_CXXFLAGS_WARN_ON += -Werror -Wno-error=cpp -Wno-error=deprecated-declarations $$WERROR # GCC prints this bogus warning, after it has inlined a lot of code diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf index 8599a47ecd3..d213f9e2603 100644 --- a/mkspecs/features/qt_module.prf +++ b/mkspecs/features/qt_module.prf @@ -94,6 +94,8 @@ else: \ # OS X and iOS frameworks mac:CONFIG(shared, static|shared):contains(QT_CONFIG, qt_framework) { + # Set the CFBundleIdentifier prefix for Qt frameworks + QMAKE_TARGET_BUNDLE_PREFIX = org.qt-project #QMAKE_FRAMEWORK_VERSION = 4.0 CONFIG += lib_bundle sliced_bundle qt_framework CONFIG -= qt_install_headers #no need to install these as well diff --git a/mkspecs/features/qt_module_headers.prf b/mkspecs/features/qt_module_headers.prf index baeb22d9b46..5015d58861c 100644 --- a/mkspecs/features/qt_module_headers.prf +++ b/mkspecs/features/qt_module_headers.prf @@ -58,7 +58,9 @@ MODULE_MASTER_DEPS_HEADER = $$MODULE_BASE_OUTDIR/include/$$MODULE_INCNAME/$${MOD MODULE_MASTER_DEPS_HEADER_CONT = $$autogen_warning MODULE_MASTER_DEPS_HEADER_CONT += "$${LITERAL_HASH}ifdef __cplusplus /* create empty PCH in C mode */" for(dep, MODULE_DEPENDS) { - depname = $$eval(QT.$${dep}.name) + depname = $$eval(QT.$${dep}.master_header) + isEmpty(depname): \ + depname = $$eval(QT.$${dep}.name) MODULE_MASTER_DEPS_HEADER_CONT += "$${LITERAL_HASH}include <$$depname/$$depname>" } MODULE_MASTER_DEPS_HEADER_CONT += "$${LITERAL_HASH}endif" diff --git a/mkspecs/features/qt_module_pris.prf b/mkspecs/features/qt_module_pris.prf index 3d438e52f48..9a876caf5ed 100644 --- a/mkspecs/features/qt_module_pris.prf +++ b/mkspecs/features/qt_module_pris.prf @@ -74,6 +74,10 @@ MODULE_FWD_PRI = $$mod_work_pfx/qt_lib_$${MODULE_ID}.pri module_plugtypes = "QT.$${MODULE_ID}.plugin_types = $$replace(MODULE_PLUGIN_TYPES, /.*$, )" else: \ module_plugtypes = + !isEmpty(MODULE_MASTER_HEADER): \ + module_master = "QT.$${MODULE_ID}.master_header = $$MODULE_MASTER_HEADER" + else: \ + module_master = !no_module_headers:!minimal_syncqt { MODULE_INCLUDES = \$\$QT_MODULE_INCLUDE_BASE \$\$QT_MODULE_INCLUDE_BASE/$$MODULE_INCNAME MODULE_PRIVATE_INCLUDES = \$\$QT_MODULE_INCLUDE_BASE/$$MODULE_INCNAME/$$VERSION \ @@ -97,6 +101,7 @@ MODULE_FWD_PRI = $$mod_work_pfx/qt_lib_$${MODULE_ID}.pri "QT.$${MODULE_ID}.name = $$TARGET" \ "QT.$${MODULE_ID}.libs = $$module_libs" \ $$module_rpath \ + $$module_master \ "QT.$${MODULE_ID}.includes = $$MODULE_INCLUDES" !host_build: MODULE_PRI_CONT += \ "QT.$${MODULE_ID}.bins = \$\$QT_MODULE_BIN_BASE" \ diff --git a/mkspecs/features/resources.prf b/mkspecs/features/resources.prf index 27db7d7d7a8..8564731a222 100644 --- a/mkspecs/features/resources.prf +++ b/mkspecs/features/resources.prf @@ -11,7 +11,7 @@ rcc.name = RCC ${QMAKE_FILE_IN} rcc.depend_command = $$QMAKE_RCC_DEP -list $$QMAKE_RESOURCE_FLAGS ${QMAKE_FILE_IN} rcc.CONFIG += add_inputs_as_makefile_deps -resources_small|ltcg|macx-xcode|contains(TEMPLATE, "vc.*") { +!resources_big|ltcg|macx-xcode|contains(TEMPLATE, "vc.*") { rcc.output = $$RCC_DIR/$${first(QMAKE_MOD_RCC)}_${QMAKE_FILE_BASE}$${first(QMAKE_EXT_CPP)} rcc.commands = $$QMAKE_RCC $$QMAKE_RESOURCE_FLAGS ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} diff --git a/mkspecs/features/winrt/package_manifest.prf b/mkspecs/features/winrt/package_manifest.prf index b4242bfdaa5..2ccb5db9633 100644 --- a/mkspecs/features/winrt/package_manifest.prf +++ b/mkspecs/features/winrt/package_manifest.prf @@ -24,6 +24,7 @@ # WINRT_MANIFEST.logo_medium: Medium logo image file. Default provided by the mkspec. # WINRT_MANIFEST.logo_large: Large logo image file. Default provided by the mkspec. # WINRT_MANIFEST.splash_screen: Splash screen image file. Default provided by the mkspec. +# WINRT_MANIFEST.rotation_preference: Orientation specification. Default is empty. (portrait, landscape, landscapeFlipped) # WINRT_MANIFEST.iconic_tile_icon: Image file for the "iconic" tile template icon. Default provided by the mkspec. # WINRT_MANIFEST.iconic_tile_small: Image file for the small "iconic" tile template logo. Default provided by the mkspec. # WINRT_MANIFEST.default_language: Specifies the default language of the application @@ -87,6 +88,20 @@ isEmpty(WINRT_MANIFEST.foreground): WINRT_MANIFEST.foreground = light isEmpty(WINRT_MANIFEST.default_language): WINRT_MANIFEST.default_language = en + INDENT = "$$escape_expand(\\r\\n) " + + VS_XML_NAMESPACE = "m2" + winphone: VS_XML_NAMESPACE = "m3" + WINRT_MANIFEST.rotation_preference = $$unique(WINRT_MANIFEST.rotation_preference) + !isEmpty(WINRT_MANIFEST.rotation_preference) { + MANIFEST_ROTATION += "<$${VS_XML_NAMESPACE}:InitialRotationPreference>" + for(ROTATION, WINRT_MANIFEST.rotation_preference): \ + MANIFEST_ROTATION += " <$${VS_XML_NAMESPACE}:Rotation Preference=\"$$ROTATION\" />" + MANIFEST_ROTATION += "" + + WINRT_MANIFEST.rotation_preference = $$join(MANIFEST_ROTATION, $$INDENT, $$INDENT) + } + INDENT = "$$escape_expand(\\r\\n) " # Capabilities are given as a string list and may change with the configuration (network, sensors, etc.) diff --git a/mkspecs/macx-clang-32/Info.plist.lib b/mkspecs/macx-clang-32/Info.plist.lib index 2a44d1721ec..7cbdb9af129 100644 --- a/mkspecs/macx-clang-32/Info.plist.lib +++ b/mkspecs/macx-clang-32/Info.plist.lib @@ -14,6 +14,8 @@ @TYPEINFO@ CFBundleExecutable @LIBRARY@ + CFBundleIdentifier + @BUNDLEIDENTIFIER@ NOTE Please, do NOT change this file -- It was generated by Qt/QMake. diff --git a/mkspecs/macx-clang/Info.plist.lib b/mkspecs/macx-clang/Info.plist.lib index 2a44d1721ec..7cbdb9af129 100644 --- a/mkspecs/macx-clang/Info.plist.lib +++ b/mkspecs/macx-clang/Info.plist.lib @@ -14,6 +14,8 @@ @TYPEINFO@ CFBundleExecutable @LIBRARY@ + CFBundleIdentifier + @BUNDLEIDENTIFIER@ NOTE Please, do NOT change this file -- It was generated by Qt/QMake. diff --git a/mkspecs/macx-g++-32/Info.plist.lib b/mkspecs/macx-g++-32/Info.plist.lib index 2a44d1721ec..7cbdb9af129 100644 --- a/mkspecs/macx-g++-32/Info.plist.lib +++ b/mkspecs/macx-g++-32/Info.plist.lib @@ -14,6 +14,8 @@ @TYPEINFO@ CFBundleExecutable @LIBRARY@ + CFBundleIdentifier + @BUNDLEIDENTIFIER@ NOTE Please, do NOT change this file -- It was generated by Qt/QMake. diff --git a/mkspecs/macx-g++/Info.plist.lib b/mkspecs/macx-g++/Info.plist.lib index 2a44d1721ec..7cbdb9af129 100644 --- a/mkspecs/macx-g++/Info.plist.lib +++ b/mkspecs/macx-g++/Info.plist.lib @@ -14,6 +14,8 @@ @TYPEINFO@ CFBundleExecutable @LIBRARY@ + CFBundleIdentifier + @BUNDLEIDENTIFIER@ NOTE Please, do NOT change this file -- It was generated by Qt/QMake. diff --git a/mkspecs/macx-g++40/Info.plist.lib b/mkspecs/macx-g++40/Info.plist.lib index 2a44d1721ec..7cbdb9af129 100644 --- a/mkspecs/macx-g++40/Info.plist.lib +++ b/mkspecs/macx-g++40/Info.plist.lib @@ -14,6 +14,8 @@ @TYPEINFO@ CFBundleExecutable @LIBRARY@ + CFBundleIdentifier + @BUNDLEIDENTIFIER@ NOTE Please, do NOT change this file -- It was generated by Qt/QMake. diff --git a/mkspecs/macx-g++42/Info.plist.lib b/mkspecs/macx-g++42/Info.plist.lib index 2a44d1721ec..7cbdb9af129 100644 --- a/mkspecs/macx-g++42/Info.plist.lib +++ b/mkspecs/macx-g++42/Info.plist.lib @@ -14,6 +14,8 @@ @TYPEINFO@ CFBundleExecutable @LIBRARY@ + CFBundleIdentifier + @BUNDLEIDENTIFIER@ NOTE Please, do NOT change this file -- It was generated by Qt/QMake. diff --git a/mkspecs/macx-icc/Info.plist.lib b/mkspecs/macx-icc/Info.plist.lib index 2a44d1721ec..7cbdb9af129 100644 --- a/mkspecs/macx-icc/Info.plist.lib +++ b/mkspecs/macx-icc/Info.plist.lib @@ -14,6 +14,8 @@ @TYPEINFO@ CFBundleExecutable @LIBRARY@ + CFBundleIdentifier + @BUNDLEIDENTIFIER@ NOTE Please, do NOT change this file -- It was generated by Qt/QMake. diff --git a/mkspecs/macx-icc/qmake.conf b/mkspecs/macx-icc/qmake.conf index a1783c97ad3..5e45e67d0ca 100644 --- a/mkspecs/macx-icc/qmake.conf +++ b/mkspecs/macx-icc/qmake.conf @@ -52,8 +52,7 @@ QMAKE_CXXFLAGS_SHLIB = $$QMAKE_CFLAGS_SHLIB QMAKE_CXXFLAGS_STATIC_LIB = $$QMAKE_CFLAGS_STATIC_LIB QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD -# Disabled, due to invalid C++11 code on Apple headers -#QMAKE_CXXFLAGS_CXX11 = -std=c++11 +QMAKE_CXXFLAGS_CXX11 = -std=c++11 QMAKE_CXXFLAGS_SPLIT_SECTIONS = $$QMAKE_CFLAGS_SPLIT_SECTIONS QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG @@ -85,7 +84,7 @@ QMAKE_CXXFLAGS_PRECOMPILE = -c -pch-create ${QMAKE_PCH_OUTPUT} -include ${QMAKE_ QMAKE_CFLAGS_HIDESYMS += -fvisibility=hidden QMAKE_CXXFLAGS_HIDESYMS += $$QMAKE_CFLAGS_HIDESYMS -fvisibility-inlines-hidden -QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7 +QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.9 include(../common/macx.conf) diff --git a/mkspecs/macx-ios-clang/Info.plist.app b/mkspecs/macx-ios-clang/Info.plist.app index 2987804e334..623ed496c5f 100755 --- a/mkspecs/macx-ios-clang/Info.plist.app +++ b/mkspecs/macx-ios-clang/Info.plist.app @@ -24,6 +24,8 @@ 1.0 LSRequiresIPhoneOS + UILaunchStoryboardName + LaunchScreen UISupportedInterfaceOrientations UIInterfaceOrientationPortrait diff --git a/mkspecs/macx-ios-clang/LaunchScreen.xib b/mkspecs/macx-ios-clang/LaunchScreen.xib new file mode 100644 index 00000000000..d28c06b375c --- /dev/null +++ b/mkspecs/macx-ios-clang/LaunchScreen.xib @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mkspecs/macx-ios-clang/features/default_post.prf b/mkspecs/macx-ios-clang/features/default_post.prf index 79024c588c7..643a17e23e4 100644 --- a/mkspecs/macx-ios-clang/features/default_post.prf +++ b/mkspecs/macx-ios-clang/features/default_post.prf @@ -184,6 +184,14 @@ macx-xcode { QMAKE_SUBSTITUTES += copy_image launch_images.files = $$copy_image.output QMAKE_BUNDLE_DATA += launch_images + + # Set up default LaunchScreen to support iPhone6/6+ + launch_screen = LaunchScreen.xib + copy_launch_screen.input = $$QMAKESPEC/$$launch_screen + copy_launch_screen.output = $$OUT_PWD/$${TARGET}.xcodeproj/$$launch_screen + QMAKE_SUBSTITUTES += copy_launch_screen + launch_screens.files = $$copy_launch_screen.output + QMAKE_BUNDLE_DATA += launch_screens } macx-xcode { @@ -193,22 +201,32 @@ macx-xcode { arch_iphonesimulator.value = $$QMAKE_IOS_SIMULATOR_ARCHS QMAKE_MAC_XCODE_SETTINGS += arch_iphoneos arch_iphonesimulator - unset(QMAKE_XCODE_ARCHS) -} else { -# Be more specific about which architecture we're targeting - equals(QT_ARCH, arm): \ - actual_archs = $$QMAKE_IOS_DEVICE_ARCHS - else: \ - actual_archs = $$QMAKE_IOS_SIMULATOR_ARCHS + QMAKE_XCODE_ARCHS = $$QMAKE_IOS_DEVICE_ARCHS $$QMAKE_IOS_SIMULATOR_ARCHS - for(arch, actual_archs): \ - arch_flags += -arch $$arch + only_active_arch.name = ONLY_ACTIVE_ARCH + only_active_arch.value = YES + only_active_arch.build = debug + QMAKE_MAC_XCODE_SETTINGS += only_active_arch +} else { + # Be more specific about which architecture we're targeting + contains(QT_ARCH, arm.*): \ + VALID_ARCHS = $$QMAKE_IOS_DEVICE_ARCHS + else: \ + VALID_ARCHS = $$QMAKE_IOS_SIMULATOR_ARCHS + + single_arch: VALID_ARCHS = $$first(VALID_ARCHS) + + ACTIVE_ARCHS = $(filter $(EXPORT_VALID_ARCHS), $(ARCHS)) + ARCH_ARGS = $(foreach arch, $(if $(EXPORT_ACTIVE_ARCHS), $(EXPORT_ACTIVE_ARCHS), $(EXPORT_VALID_ARCHS)), -arch $(arch)) + + QMAKE_EXTRA_VARIABLES += VALID_ARCHS ACTIVE_ARCHS ARCH_ARGS + + arch_flags = $(EXPORT_ARCH_ARGS) QMAKE_CFLAGS += $$arch_flags QMAKE_CXXFLAGS += $$arch_flags QMAKE_OBJECTIVE_CFLAGS += $$arch_flags QMAKE_LFLAGS += $$arch_flags } -unset(actual_archs) load(default_post) diff --git a/mkspecs/macx-ios-clang/features/qt.prf b/mkspecs/macx-ios-clang/features/qt.prf index a5b00377eed..7ca3198dbef 100644 --- a/mkspecs/macx-ios-clang/features/qt.prf +++ b/mkspecs/macx-ios-clang/features/qt.prf @@ -32,17 +32,19 @@ equals(TEMPLATE, app):contains(QT, gui(-private)?) { # called 'qt_main' now. macx-xcode { - objects_dir = "${OBJECT_FILE_DIR}-${CURRENT_VARIANT}/${CURRENT_ARCH}" + objects_dir = "${OBJECT_FILE_DIR}-${CURRENT_VARIANT}" + archs = "${ARCHS}" } else { objects_dir = $$OBJECTS_DIR isEmpty(objects_dir): \ objects_dir = . + archs = "$$QMAKE_IOS_DEVICE_ARCHS $$QMAKE_IOS_SIMULATOR_ARCHS" } !isEmpty(QMAKE_PRE_LINK): \ QMAKE_PRE_LINK += ";" - QMAKE_PRE_LINK += $$QMAKESPEC/rename_main.sh $${objects_dir} + QMAKE_PRE_LINK += $$QMAKESPEC/rename_main.sh $${objects_dir} \"$${archs}\" } } diff --git a/mkspecs/macx-ios-clang/features/qt_config.prf b/mkspecs/macx-ios-clang/features/qt_config.prf index d9a13f65eb5..d1a1a369337 100644 --- a/mkspecs/macx-ios-clang/features/qt_config.prf +++ b/mkspecs/macx-ios-clang/features/qt_config.prf @@ -9,4 +9,8 @@ isEmpty(QT_ARCH) { QT_ARCH = arm else: \ # Simulator QT_ARCH = i386 + + # Prevent the arch/config tests from building as multi-arch binaries, + # as we only want the lowest common denominator features. + CONFIG += single_arch } diff --git a/mkspecs/macx-ios-clang/features/sdk.prf b/mkspecs/macx-ios-clang/features/sdk.prf new file mode 100644 index 00000000000..607a71bb262 --- /dev/null +++ b/mkspecs/macx-ios-clang/features/sdk.prf @@ -0,0 +1,4 @@ +load(sdk) + +lessThan(QMAKE_MAC_SDK_VERSION, "8.0"): \ + error("Current $$QMAKE_MAC_SDK SDK version ($$QMAKE_MAC_SDK_VERSION) is too old. Please upgrade Xcode.") diff --git a/mkspecs/macx-ios-clang/qmake.conf b/mkspecs/macx-ios-clang/qmake.conf index 7b2e7a17e7e..0c083edf801 100644 --- a/mkspecs/macx-ios-clang/qmake.conf +++ b/mkspecs/macx-ios-clang/qmake.conf @@ -15,8 +15,8 @@ DEFINES += DARWIN_NO_CARBON QT_NO_PRINTER QT_NO_PRINTDIALOG # Universal target (iPhone and iPad) QMAKE_IOS_TARGETED_DEVICE_FAMILY = 1,2 -QMAKE_IOS_DEVICE_ARCHS = armv7 -QMAKE_IOS_SIMULATOR_ARCHS = i386 +QMAKE_IOS_DEVICE_ARCHS = armv7 arm64 +QMAKE_IOS_SIMULATOR_ARCHS = i386 x86_64 include(../common/ios.conf) include(../common/gcc-base-mac.conf) diff --git a/mkspecs/macx-ios-clang/rename_main.sh b/mkspecs/macx-ios-clang/rename_main.sh index b1321e855ee..040140b7eeb 100755 --- a/mkspecs/macx-ios-clang/rename_main.sh +++ b/mkspecs/macx-ios-clang/rename_main.sh @@ -41,10 +41,14 @@ ## ############################################################################# -if [ $# -eq 0 ]; then - echo "usage: $0 " +if [ $# -ne 2 ]; then + echo "$0: wrong number of arguments for internal tool used by iOS mkspec" else - for f in $(find $1 -name '*.o'); do + arch_paths="" + for a in $2; do + arch_paths="$arch_paths $1/$a" + done + for f in $(find $arch_paths -name '*.o'); do # Skip object files without the _main symbol nm $f 2>/dev/null | grep -q 'T _main$' || continue diff --git a/mkspecs/macx-llvm/Info.plist.lib b/mkspecs/macx-llvm/Info.plist.lib index 2a44d1721ec..7cbdb9af129 100644 --- a/mkspecs/macx-llvm/Info.plist.lib +++ b/mkspecs/macx-llvm/Info.plist.lib @@ -14,6 +14,8 @@ @TYPEINFO@ CFBundleExecutable @LIBRARY@ + CFBundleIdentifier + @BUNDLEIDENTIFIER@ NOTE Please, do NOT change this file -- It was generated by Qt/QMake. diff --git a/mkspecs/unsupported/freebsd-clang/qmake.conf b/mkspecs/unsupported/freebsd-clang/qmake.conf index ad4fa3487ed..2cfd763688e 100644 --- a/mkspecs/unsupported/freebsd-clang/qmake.conf +++ b/mkspecs/unsupported/freebsd-clang/qmake.conf @@ -13,6 +13,7 @@ QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD QMAKE_INCDIR = /usr/local/include QMAKE_LIBDIR = /usr/local/lib +QMAKE_LFLAGS_NOUNDEF = -Wl,--no-undefined QMAKE_LFLAGS_THREAD = -pthread QMAKE_LIBS = @@ -28,6 +29,5 @@ QMAKE_RANLIB = include(../../common/unix.conf) include(../../common/gcc-base-unix.conf) -include(../../common/g++-unix.conf) include(../../common/clang.conf) load(qt_config) diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index 36596213918..0ff42500de2 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -1029,6 +1029,21 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) if (!project->isEmpty("QMAKE_PRE_LINK")) { QString phase_key = keyFor("QMAKE_PBX_PRELINK_BUILDPHASE"); project->values("QMAKE_PBX_BUILDPHASES").append(phase_key); + + ProStringList inputPaths; + ProStringList outputPaths; + const ProStringList &archs = project->values("QMAKE_XCODE_ARCHS"); + if (!archs.isEmpty()) { + for (int i = 0; i < archs.size(); ++i) { + const ProString &arch = archs.at(i); + inputPaths << "$(OBJECT_FILE_DIR_$(CURRENT_VARIANT))/" + arch + "/"; + outputPaths << "$(LINK_FILE_LIST_$(CURRENT_VARIANT)_" + arch + ")"; + } + } else { + inputPaths << "$(OBJECT_FILE_DIR_$(CURRENT_VARIANT))/$(CURRENT_ARCH)/"; + outputPaths << "$(LINK_FILE_LIST_$(CURRENT_VARIANT)_$(CURRENT_ARCH))"; + } + t << "\t\t" << phase_key << " = {\n" << "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";\n" << "\t\t\t" << writeSettings("files", ProStringList(), SettingsAsList, 4) << ";\n" @@ -1036,8 +1051,8 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) // resolved dependenices, so we have to ensure that this phase is run after the // compilation phase, and before the link phase. Making the phase depend on the // object file directory, and "write" to the list of files to link achieves that. - << "\t\t\t" << writeSettings("inputPaths", ProStringList("$(OBJECT_FILE_DIR_$(CURRENT_VARIANT))/$(CURRENT_ARCH)/"), SettingsAsList, 4) << ";\n" - << "\t\t\t" << writeSettings("outputPaths", ProStringList("$(LINK_FILE_LIST_$(CURRENT_VARIANT)_$(CURRENT_ARCH))"), SettingsAsList, 4) << ";\n" + << "\t\t\t" << writeSettings("inputPaths", inputPaths, SettingsAsList, 4) << ";\n" + << "\t\t\t" << writeSettings("outputPaths", outputPaths, SettingsAsList, 4) << ";\n" << "\t\t\t" << writeSettings("isa", "PBXShellScriptBuildPhase", SettingsNoQuote) << ";\n" << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";\n" << "\t\t\t" << writeSettings("name", "Qt Prelink") << ";\n" @@ -1107,9 +1122,12 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) << "\t\t\t" << writeSettings("shellScript", fixForOutput("cp -r $BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME " + escapeFilePath(destDir))) << ";\n" << "\t\t};\n"; } + bool copyBundleResources = project->isActiveConfig("app_bundle") && project->first("TEMPLATE") == "app"; + ProStringList bundle_resources_files; // Copy Bundle Data if (!project->isEmpty("QMAKE_BUNDLE_DATA")) { ProStringList bundle_file_refs; + bool ios = project->isActiveConfig("ios"); //all bundle data const ProStringList &bundle_data = project->values("QMAKE_BUNDLE_DATA"); @@ -1137,21 +1155,27 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) << "\t\t};\n"; } - QString phase_key = keyFor("QMAKE_PBX_BUNDLE_COPY." + bundle_data[i]); - if (!project->isEmpty(ProKey(bundle_data[i] + ".version"))) { - //### - } + if (copyBundleResources && ((ios && path.isEmpty()) + || (!ios && path == QLatin1String("Contents/Resources")))) { + foreach (const ProString &s, bundle_files) + bundle_resources_files << s; + } else { + QString phase_key = keyFor("QMAKE_PBX_BUNDLE_COPY." + bundle_data[i]); + if (!project->isEmpty(ProKey(bundle_data[i] + ".version"))) { + //### + } - project->values("QMAKE_PBX_BUILDPHASES").append(phase_key); - t << "\t\t" << phase_key << " = {\n" - << "\t\t\t" << writeSettings("name", "Copy '" + bundle_data[i] + "' Files to Bundle") << ";\n" - << "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";\n" - << "\t\t\t" << writeSettings("dstPath", escapeFilePath(path)) << ";\n" - << "\t\t\t" << writeSettings("dstSubfolderSpec", "1", SettingsNoQuote) << ";\n" - << "\t\t\t" << writeSettings("files", bundle_files, SettingsAsList, 4) << ";\n" - << "\t\t\t" << writeSettings("isa", "PBXCopyFilesBuildPhase", SettingsNoQuote) << ";\n" - << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";\n" - << "\t\t};\n"; + project->values("QMAKE_PBX_BUILDPHASES").append(phase_key); + t << "\t\t" << phase_key << " = {\n" + << "\t\t\t" << writeSettings("name", "Copy '" + bundle_data[i] + "' Files to Bundle") << ";\n" + << "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";\n" + << "\t\t\t" << writeSettings("dstPath", escapeFilePath(path)) << ";\n" + << "\t\t\t" << writeSettings("dstSubfolderSpec", "1", SettingsNoQuote) << ";\n" + << "\t\t\t" << writeSettings("isa", "PBXCopyFilesBuildPhase", SettingsNoQuote) << ";\n" + << "\t\t\t" << writeSettings("files", bundle_files, SettingsAsList, 4) << ";\n" + << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";\n" + << "\t\t};\n"; + } } QString bundle_data_key = keyFor("QMAKE_PBX_BUNDLE_DATA"); @@ -1166,8 +1190,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) // Copy bundle resources. Optimizes resources, and puts them into the Resources // subdirectory on OSX, but doesn't support paths. - if (project->isActiveConfig("app_bundle") && project->first("TEMPLATE") == "app") { - ProStringList bundle_resources_files; + if (copyBundleResources) { if (!project->isEmpty("ICON")) { ProString icon = project->first("ICON"); if (icon.length() >= 2 && (icon.at(0) == '"' || icon.at(0) == '\'') && icon.endsWith(icon.at(0))) diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index d9b0e10057f..8270f02febc 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -814,22 +814,26 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) } commonSedArgs << "-e \"s,@TYPEINFO@,"<< (project->isEmpty("QMAKE_PKGINFO_TYPEINFO") ? QString::fromLatin1("????") : project->first("QMAKE_PKGINFO_TYPEINFO").left(4)) << ",g\" "; + + QString bundlePrefix = project->first("QMAKE_TARGET_BUNDLE_PREFIX").toQString(); + if (bundlePrefix.isEmpty()) + bundlePrefix = "com.yourcompany"; + if (bundlePrefix.endsWith(".")) + bundlePrefix.chop(1); + QString bundleIdentifier = bundlePrefix + "." + var("QMAKE_BUNDLE"); + if (bundleIdentifier.endsWith(".app")) + bundleIdentifier.chop(4); + if (bundleIdentifier.endsWith(".framework")) + bundleIdentifier.chop(10); + commonSedArgs << "-e \"s,@BUNDLEIDENTIFIER@," << bundleIdentifier << ",g\" "; + if (isApp) { QString icon = fileFixify(var("ICON")); - QString bundlePrefix = project->first("QMAKE_TARGET_BUNDLE_PREFIX").toQString(); - if (bundlePrefix.isEmpty()) - bundlePrefix = "com.yourcompany"; - if (bundlePrefix.endsWith(".")) - bundlePrefix.chop(1); - QString bundleIdentifier = bundlePrefix + "." + var("QMAKE_BUNDLE"); - if (bundleIdentifier.endsWith(".app")) - bundleIdentifier.chop(4); t << "@$(DEL_FILE) " << info_plist_out << "\n\t" << "@sed "; foreach (const ProString &arg, commonSedArgs) t << arg; t << "-e \"s,@ICON@," << icon.section(Option::dir_sep, -1) << ",g\" " - << "-e \"s,@BUNDLEIDENTIFIER@," << bundleIdentifier << ",g\" " << "-e \"s,@EXECUTABLE@," << var("QMAKE_ORIG_TARGET") << ",g\" " << "-e \"s,@TYPEINFO@,"<< (project->isEmpty("QMAKE_PKGINFO_TYPEINFO") ? QString::fromLatin1("????") : project->first("QMAKE_PKGINFO_TYPEINFO").left(4)) << ",g\" " diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp index f2d55d481d3..4ddb76032e1 100644 --- a/qmake/generators/win32/msbuild_objectmodel.cpp +++ b/qmake/generators/win32/msbuild_objectmodel.cpp @@ -46,6 +46,7 @@ QT_BEGIN_NAMESPACE const char _CLCompile[] = "ClCompile"; const char _ItemGroup[] = "ItemGroup"; const char _Link[] = "Link"; +const char _Lib[] = "Lib"; const char _ManifestTool[] = "ManifestTool"; const char _Midl[] = "Midl"; const char _ResourceCompile[] = "ResourceCompile"; @@ -757,8 +758,11 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProject &tool) // ClCompile write(xml, config.compiler); - // Link - write(xml, config.linker); + // Librarian / Linker + if (config.ConfigurationType == typeStaticLibrary) + write(xml, config.librarian); + else + write(xml, config.linker); // Midl write(xml, config.idl); @@ -1686,7 +1690,7 @@ void VCXProjectWriter::write(XmlOutput &xml, const VCCustomBuildTool &tool) void VCXProjectWriter::write(XmlOutput &xml, const VCLibrarianTool &tool) { xml - << tag(_Link) + << tag(_Lib) << attrTagX(_AdditionalDependencies, tool.AdditionalDependencies, ";") << attrTagX(_AdditionalLibraryDirectories, tool.AdditionalLibraryDirectories, ";") << attrTagX(_AdditionalOptions, tool.AdditionalOptions, " ") @@ -1706,7 +1710,7 @@ void VCXProjectWriter::write(XmlOutput &xml, const VCLibrarianTool &tool) //unused << attrTagS(_TargetMachine, tool.TargetMachine) //unused << attrTagT(_TreatLibWarningAsErrors, tool.TreatLibWarningAsErrors) //unused << attrTagT(_Verbose, tool.Verbose) - << closetag(_Link); + << closetag(_Lib); } void VCXProjectWriter::write(XmlOutput &xml, const VCResourceCompilerTool &tool) @@ -1911,10 +1915,10 @@ bool VCXProjectWriter::outputFileConfig(OutputFilterData *d, XmlOutput &xml, Xml } // Actual XML output ---------------------------------- - if (hasCustomBuildStep || filter.useCompilerTool + if (hasCustomBuildStep || filter.useCustomBuildTool || filter.useCompilerTool || !d->inBuild || filter.Name.startsWith("Deployment Files")) { - if (hasCustomBuildStep) + if (hasCustomBuildStep || filter.useCustomBuildTool) { if (!fileAdded) { fileAdded = true; diff --git a/qmake/library/proitems.cpp b/qmake/library/proitems.cpp index e4dc840b223..97cc590d849 100644 --- a/qmake/library/proitems.cpp +++ b/qmake/library/proitems.cpp @@ -416,8 +416,8 @@ QStringList ProStringList::toQStringList() const { QStringList ret; ret.reserve(size()); - foreach (const ProString &str, *this) - ret << str.toQString(); + for (int i = 0; i < size(); i++) // foreach causes MSVC2010 ICE + ret << at(i).toQString(); return ret; } diff --git a/qtbase.pro b/qtbase.pro index d6861cf09fb..6d0de44f6d4 100644 --- a/qtbase.pro +++ b/qtbase.pro @@ -140,7 +140,7 @@ for (ft, features) { "$${LITERAL_HASH} define QT_NO_$$ft" \ "$${LITERAL_HASH}endif" FEATURES_PRI += \ - "contains(QT_DISABLED_FEATURES, "^($$lower($$join($$list($$replace(features.$${ft}.depends, _, -)), "|")))$"): \\" \ + "contains(QT_DISABLED_FEATURES, "$$lower($$join($$list($$replace(features.$${ft}.depends, _, -)), "|"))"): \\" \ " QT_DISABLED_FEATURES += $$lower($$replace(ft, _, -))" } } @@ -168,7 +168,8 @@ for (def, QT_NO_DEFINES) { } no_features = $$unique(no_features) -# Can't simply add these to QT_CONFIG, as e.g., contains(QT_CONFIG, accessibility) matches no-accessibililty. +# Don't simply add these to QT_CONFIG, as then one might expect them to be there without load(qfeatures). +# And we don't want to do that automatically, as the dynamic dependency resolution is somewhat expensive. FEATURES_PRI = \ "$${LITERAL_HASH} Features disabled by configure:" \ "QT_DISABLED_FEATURES =$$lower($$join($$list($$replace(no_features, _, -)), " ", " "))" \ diff --git a/src/3rdparty/angle/AUTHORS b/src/3rdparty/angle/AUTHORS index b79bb5d1614..be114bcf68b 100644 --- a/src/3rdparty/angle/AUTHORS +++ b/src/3rdparty/angle/AUTHORS @@ -21,10 +21,12 @@ Mozilla Corporation Turbulenz Klarälvdalens Datakonsult AB Microsoft Open Technologies, Inc. +NVIDIA Corporation Jacek Caban Mark Callow Ginn Chen +Tibor den Ouden James Hauxwell Sam Hocevar Pierre Leveille diff --git a/src/3rdparty/angle/CONTRIBUTORS b/src/3rdparty/angle/CONTRIBUTORS index 0cae10a0f6e..94d009f2b3e 100644 --- a/src/3rdparty/angle/CONTRIBUTORS +++ b/src/3rdparty/angle/CONTRIBUTORS @@ -78,7 +78,12 @@ Turbulenz Ulrik Persson (ddefrostt) Mark Banner (standard8mbp) David Kilzer +Jacek Caban +Tibor den Ouden Microsoft Open Technologies, Inc. Cooper Partin Austin Kinross + +NVIDIA Corporation + Olli Etuaho diff --git a/src/3rdparty/angle/include/EGL/egl.h b/src/3rdparty/angle/include/EGL/egl.h index ab2f0cdfbea..12590a0e203 100644 --- a/src/3rdparty/angle/include/EGL/egl.h +++ b/src/3rdparty/angle/include/EGL/egl.h @@ -238,7 +238,7 @@ EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void); #ifndef EGL_VERSION_1_5 #define EGL_VERSION_1_5 1 typedef void *EGLSync; -typedef khronos_intptr_t EGLAttrib; +typedef intptr_t EGLAttrib; typedef khronos_utime_nanoseconds_t EGLTime; #define EGL_CONTEXT_MAJOR_VERSION 0x3098 #define EGL_CONTEXT_MINOR_VERSION 0x30FB diff --git a/src/3rdparty/angle/include/EGL/eglext.h b/src/3rdparty/angle/include/EGL/eglext.h index 989359b0268..0cc5eec2930 100644 --- a/src/3rdparty/angle/include/EGL/eglext.h +++ b/src/3rdparty/angle/include/EGL/eglext.h @@ -59,7 +59,7 @@ extern "C" { #ifndef EGL_KHR_cl_event2 #define EGL_KHR_cl_event2 1 typedef void *EGLSyncKHR; -typedef khronos_intptr_t EGLAttribKHR; +typedef intptr_t EGLAttribKHR; typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNC64KHRPROC) (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list); #ifdef EGL_EGLEXT_PROTOTYPES EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list); @@ -442,20 +442,22 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu #define EGL_ANGLE_platform_angle 1 #define EGL_PLATFORM_ANGLE_ANGLE 0x3201 #define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202 -#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3203 +#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3203 +#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3204 +#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3205 #endif /* EGL_ANGLE_platform_angle */ #ifndef EGL_ANGLE_platform_angle_d3d #define EGL_ANGLE_platform_angle_d3d 1 -#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3204 -#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3205 -#define EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE 0x3206 +#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3206 +#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3207 +#define EGL_PLATFORM_ANGLE_USE_WARP_ANGLE 0x3208 #endif /* EGL_ANGLE_platform_angle_d3d */ #ifndef EGL_ANGLE_platform_angle_opengl #define EGL_ANGLE_platform_angle_opengl 1 -#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x3207 -#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x3208 +#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x3209 +#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320A #endif /* EGL_ANGLE_platform_angle_opengl */ #ifndef EGL_ARM_pixmap_multisample_discard diff --git a/src/3rdparty/angle/include/EGL/eglplatform.h b/src/3rdparty/angle/include/EGL/eglplatform.h index ea9f5778ee3..2eb3674a0ba 100644 --- a/src/3rdparty/angle/include/EGL/eglplatform.h +++ b/src/3rdparty/angle/include/EGL/eglplatform.h @@ -67,23 +67,22 @@ * implementations. */ -#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) /* Windows Runtime */ - -struct IUnknown; - -typedef IUnknown *EGLNativeDisplayType; -typedef void *EGLNativePixmapType; -typedef IUnknown *EGLNativeWindowType; - -#elif defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */ +#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN 1 #endif #include -typedef HDC EGLNativeDisplayType; typedef HBITMAP EGLNativePixmapType; + +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) /* Windows Store */ +#include +typedef IInspectable* EGLNativeDisplayType; +typedef IInspectable* EGLNativeWindowType; +#else +typedef HDC EGLNativeDisplayType; typedef HWND EGLNativeWindowType; +#endif #elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */ diff --git a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h index b7989f5f7ed..647fed6a026 100644 --- a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h +++ b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h @@ -27,6 +27,10 @@ #include "KHR/khrplatform.h" +#include +#include +#include + // // This is the platform independent interface between an OGL driver // and the shading language compiler. @@ -42,18 +46,17 @@ typedef unsigned int GLenum; // Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h #include "ShaderVars.h" -#ifdef __cplusplus -extern "C" { -#endif - // Version number for shader translation API. // It is incremented every time the API changes. -#define ANGLE_SH_VERSION 130 +#define ANGLE_SH_VERSION 132 typedef enum { SH_GLES2_SPEC = 0x8B40, SH_WEBGL_SPEC = 0x8B41, + SH_GLES3_SPEC = 0x8B86, + SH_WEBGL2_SPEC = 0x8B87, + // The CSS Shaders spec is a subset of the WebGL spec. // // In both CSS vertex and fragment shaders, ANGLE: @@ -85,31 +88,6 @@ typedef enum { SH_HLSL11_OUTPUT = 0x8B48 } ShShaderOutput; -typedef enum { - SH_PRECISION_HIGHP = 0x5001, - SH_PRECISION_MEDIUMP = 0x5002, - SH_PRECISION_LOWP = 0x5003, - SH_PRECISION_UNDEFINED = 0 -} ShPrecisionType; - -typedef enum { - SH_INFO_LOG_LENGTH = 0x8B84, - SH_OBJECT_CODE_LENGTH = 0x8B88, // GL_SHADER_SOURCE_LENGTH - SH_ACTIVE_UNIFORMS = 0x8B86, - SH_ACTIVE_UNIFORM_MAX_LENGTH = 0x8B87, - SH_ACTIVE_ATTRIBUTES = 0x8B89, - SH_ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A, - SH_VARYINGS = 0x8BBB, - SH_VARYING_MAX_LENGTH = 0x8BBC, - SH_MAPPED_NAME_MAX_LENGTH = 0x6000, - SH_NAME_MAX_LENGTH = 0x6001, - SH_HASHED_NAME_MAX_LENGTH = 0x6002, - SH_HASHED_NAMES_COUNT = 0x6003, - SH_SHADER_VERSION = 0x6004, - SH_RESOURCES_STRING_LENGTH = 0x6005, - SH_OUTPUT_TYPE = 0x6006 -} ShShaderInfo; - // Compile options. typedef enum { SH_VALIDATE = 0, @@ -208,14 +186,14 @@ typedef enum { // // Driver must call this first, once, before doing any other // compiler operations. -// If the function succeeds, the return value is nonzero, else zero. +// If the function succeeds, the return value is true, else false. // -COMPILER_EXPORT int ShInitialize(); +COMPILER_EXPORT bool ShInitialize(); // // Driver should call this at shutdown. -// If the function succeeds, the return value is nonzero, else zero. +// If the function succeeds, the return value is true, else false. // -COMPILER_EXPORT int ShFinalize(); +COMPILER_EXPORT bool ShFinalize(); // The 64 bits hash function. The first parameter is the input string; the // second parameter is the string length. @@ -246,6 +224,12 @@ typedef struct int EXT_frag_depth; int EXT_shader_texture_lod; + // Set to 1 to enable replacing GL_EXT_draw_buffers #extension directives + // with GL_NV_draw_buffers in ESSL output. This flag can be used to emulate + // EXT_draw_buffers by using it in combination with GLES3.0 glDrawBuffers + // function. This applies to Tegra K1 devices. + int NV_draw_buffers; + // Set to 1 if highp precision is supported in the fragment language. // Default is 0. int FragmentPrecisionHigh; @@ -274,8 +258,10 @@ typedef struct // // Initialize built-in resources with minimum expected values. +// Parameters: +// resources: The object to initialize. Will be comparable with memcmp. // -COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources* resources); +COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources *resources); // // ShHandle held by but opaque to the driver. It is allocated, @@ -284,18 +270,15 @@ COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources* resources); // // If handle creation fails, 0 will be returned. // -typedef void* ShHandle; +typedef void *ShHandle; // -// Returns the a concatenated list of the items in ShBuiltInResources as a string. +// Returns the a concatenated list of the items in ShBuiltInResources as a +// null-terminated string. // This function must be updated whenever ShBuiltInResources is changed. // Parameters: // handle: Specifies the handle of the compiler to be used. -// outStringLen: Specifies the size of the buffer, in number of characters. The size -// of the buffer required to store the resources string can be obtained -// by calling ShGetInfo with SH_RESOURCES_STRING_LENGTH. -// outStr: Returns a null-terminated string representing all the built-in resources. -COMPILER_EXPORT void ShGetBuiltInResourcesString(const ShHandle handle, size_t outStringLen, char *outStr); +COMPILER_EXPORT const std::string &ShGetBuiltInResourcesString(const ShHandle handle); // // Driver calls these to create and destroy compiler objects. @@ -313,12 +296,12 @@ COMPILER_EXPORT ShHandle ShConstructCompiler( sh::GLenum type, ShShaderSpec spec, ShShaderOutput output, - const ShBuiltInResources* resources); + const ShBuiltInResources *resources); COMPILER_EXPORT void ShDestruct(ShHandle handle); // // Compiles the given shader source. -// If the function succeeds, the return value is nonzero, else zero. +// If the function succeeds, the return value is true, else false. // Parameters: // handle: Specifies the handle of compiler to be used. // shaderStrings: Specifies an array of pointers to null-terminated strings @@ -340,123 +323,36 @@ COMPILER_EXPORT void ShDestruct(ShHandle handle); // SH_VARIABLES: Extracts attributes, uniforms, and varyings. // Can be queried by calling ShGetVariableInfo(). // -COMPILER_EXPORT int ShCompile( +COMPILER_EXPORT bool ShCompile( const ShHandle handle, - const char* const shaderStrings[], + const char * const shaderStrings[], size_t numStrings, - int compileOptions - ); + int compileOptions); -// Returns a parameter from a compiled shader. +// Return the version of the shader language. +COMPILER_EXPORT int ShGetShaderVersion(const ShHandle handle); + +// Return the currently set language output type. +COMPILER_EXPORT ShShaderOutput ShGetShaderOutputType( + const ShHandle handle); + +// Returns null-terminated information log for a compiled shader. // Parameters: // handle: Specifies the compiler -// pname: Specifies the parameter to query. -// The following parameters are defined: -// SH_INFO_LOG_LENGTH: the number of characters in the information log -// including the null termination character. -// SH_OBJECT_CODE_LENGTH: the number of characters in the object code -// including the null termination character. -// SH_ACTIVE_ATTRIBUTES: the number of active attribute variables. -// SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: the length of the longest active attribute -// variable name including the null -// termination character. -// SH_ACTIVE_UNIFORMS: the number of active uniform variables. -// SH_ACTIVE_UNIFORM_MAX_LENGTH: the length of the longest active uniform -// variable name including the null -// termination character. -// SH_VARYINGS: the number of varying variables. -// SH_VARYING_MAX_LENGTH: the length of the longest varying variable name -// including the null termination character. -// SH_MAPPED_NAME_MAX_LENGTH: the length of the mapped variable name including -// the null termination character. -// SH_NAME_MAX_LENGTH: the max length of a user-defined name including the -// null termination character. -// SH_HASHED_NAME_MAX_LENGTH: the max length of a hashed name including the -// null termination character. -// SH_HASHED_NAMES_COUNT: the number of hashed names from the latest compile. -// SH_SHADER_VERSION: the version of the shader language -// SH_OUTPUT_TYPE: the currently set language output type -// -// params: Requested parameter -COMPILER_EXPORT void ShGetInfo(const ShHandle handle, - ShShaderInfo pname, - size_t* params); - -// Returns nul-terminated information log for a compiled shader. -// Parameters: -// handle: Specifies the compiler -// infoLog: Specifies an array of characters that is used to return -// the information log. It is assumed that infoLog has enough memory -// to accomodate the information log. The size of the buffer required -// to store the returned information log can be obtained by calling -// ShGetInfo with SH_INFO_LOG_LENGTH. -COMPILER_EXPORT void ShGetInfoLog(const ShHandle handle, char* infoLog); +COMPILER_EXPORT const std::string &ShGetInfoLog(const ShHandle handle); // Returns null-terminated object code for a compiled shader. // Parameters: // handle: Specifies the compiler -// infoLog: Specifies an array of characters that is used to return -// the object code. It is assumed that infoLog has enough memory to -// accomodate the object code. The size of the buffer required to -// store the returned object code can be obtained by calling -// ShGetInfo with SH_OBJECT_CODE_LENGTH. -COMPILER_EXPORT void ShGetObjectCode(const ShHandle handle, char* objCode); +COMPILER_EXPORT const std::string &ShGetObjectCode(const ShHandle handle); -// Returns information about a shader variable. +// Returns a (original_name, hash) map containing all the user defined +// names in the shader, including variable names, function names, struct +// names, and struct field names. // Parameters: // handle: Specifies the compiler -// variableType: Specifies the variable type; options include -// SH_ACTIVE_ATTRIBUTES, SH_ACTIVE_UNIFORMS, SH_VARYINGS. -// index: Specifies the index of the variable to be queried. -// length: Returns the number of characters actually written in the string -// indicated by name (excluding the null terminator) if a value other -// than NULL is passed. -// size: Returns the size of the variable. -// type: Returns the data type of the variable. -// precision: Returns the precision of the variable. -// staticUse: Returns 1 if the variable is accessed in a statement after -// pre-processing, whether or not run-time flow of control will -// cause that statement to be executed. -// Returns 0 otherwise. -// name: Returns a null terminated string containing the name of the -// variable. It is assumed that name has enough memory to accormodate -// the variable name. The size of the buffer required to store the -// variable name can be obtained by calling ShGetInfo with -// SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_ACTIVE_UNIFORM_MAX_LENGTH, -// SH_VARYING_MAX_LENGTH. -// mappedName: Returns a null terminated string containing the mapped name of -// the variable, It is assumed that mappedName has enough memory -// (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care about the -// mapped name. If the name is not mapped, then name and mappedName -// are the same. -COMPILER_EXPORT void ShGetVariableInfo(const ShHandle handle, - ShShaderInfo variableType, - int index, - size_t* length, - int* size, - sh::GLenum* type, - ShPrecisionType* precision, - int* staticUse, - char* name, - char* mappedName); - -// Returns information about a name hashing entry from the latest compile. -// Parameters: -// handle: Specifies the compiler -// index: Specifies the index of the name hashing entry to be queried. -// name: Returns a null terminated string containing the user defined name. -// It is assumed that name has enough memory to accomodate the name. -// The size of the buffer required to store the user defined name can -// be obtained by calling ShGetInfo with SH_NAME_MAX_LENGTH. -// hashedName: Returns a null terminated string containing the hashed name of -// the uniform variable, It is assumed that hashedName has enough -// memory to accomodate the name. The size of the buffer required -// to store the name can be obtained by calling ShGetInfo with -// SH_HASHED_NAME_MAX_LENGTH. -COMPILER_EXPORT void ShGetNameHashingEntry(const ShHandle handle, - int index, - char* name, - char* hashedName); +COMPILER_EXPORT const std::map *ShGetNameHashingMap( + const ShHandle handle); // Shader variable inspection. // Returns a pointer to a list of variables of the designated type. @@ -476,17 +372,17 @@ typedef struct int size; } ShVariableInfo; -// Returns 1 if the passed in variables pack in maxVectors following +// Returns true if the passed in variables pack in maxVectors following // the packing rules from the GLSL 1.017 spec, Appendix A, section 7. -// Returns 0 otherwise. Also look at the SH_ENFORCE_PACKING_RESTRICTIONS +// Returns false otherwise. Also look at the SH_ENFORCE_PACKING_RESTRICTIONS // flag above. // Parameters: // maxVectors: the available rows of registers. // varInfoArray: an array of variable info (types and sizes). // varInfoArraySize: the size of the variable array. -COMPILER_EXPORT int ShCheckVariablesWithinPackingLimits( +COMPILER_EXPORT bool ShCheckVariablesWithinPackingLimits( int maxVectors, - ShVariableInfo* varInfoArray, + ShVariableInfo *varInfoArray, size_t varInfoArraySize); // Gives the compiler-assigned register for an interface block. @@ -497,7 +393,7 @@ COMPILER_EXPORT int ShCheckVariablesWithinPackingLimits( // interfaceBlockName: Specifies the interface block // indexOut: output variable that stores the assigned register COMPILER_EXPORT bool ShGetInterfaceBlockRegister(const ShHandle handle, - const char *interfaceBlockName, + const std::string &interfaceBlockName, unsigned int *indexOut); // Gives the compiler-assigned register for uniforms in the default @@ -509,11 +405,7 @@ COMPILER_EXPORT bool ShGetInterfaceBlockRegister(const ShHandle handle, // interfaceBlockName: Specifies the uniform // indexOut: output variable that stores the assigned register COMPILER_EXPORT bool ShGetUniformRegister(const ShHandle handle, - const char *uniformName, + const std::string &uniformName, unsigned int *indexOut); -#ifdef __cplusplus -} -#endif - #endif // _COMPILER_INTERFACE_INCLUDED_ diff --git a/src/3rdparty/angle/include/GLSLANG/ShaderVars.h b/src/3rdparty/angle/include/GLSLANG/ShaderVars.h index 9c38647dda6..da21c3e76e8 100644 --- a/src/3rdparty/angle/include/GLSLANG/ShaderVars.h +++ b/src/3rdparty/angle/include/GLSLANG/ShaderVars.h @@ -52,6 +52,21 @@ struct COMPILER_EXPORT ShaderVariable unsigned int elementCount() const { return std::max(1u, arraySize); } bool isStruct() const { return !fields.empty(); } + // All of the shader's variables are described using nested data + // structures. This is needed in order to disambiguate similar looking + // types, such as two structs containing the same fields, but in + // different orders. "findInfoByMappedName" provides an easy query for + // users to dive into the data structure and fetch the unique variable + // instance corresponding to a dereferencing chain of the top-level + // variable. + // Given a mapped name like 'a[0].b.c[0]', return the ShaderVariable + // that defines 'c' in |leafVar|, and the original name 'A[0].B.C[0]' + // in |originalName|, based on the assumption that |this| defines 'a'. + // If no match is found, return false. + bool findInfoByMappedName(const std::string &mappedFullName, + const ShaderVariable **leafVar, + std::string* originalFullName) const; + GLenum type; GLenum precision; std::string name; @@ -60,6 +75,16 @@ struct COMPILER_EXPORT ShaderVariable bool staticUse; std::vector fields; std::string structName; + + protected: + bool isSameVariableAtLinkTime(const ShaderVariable &other, + bool matchPrecision) const; + + bool operator==(const ShaderVariable &other) const; + bool operator!=(const ShaderVariable &other) const + { + return !operator==(other); + } }; struct COMPILER_EXPORT Uniform : public ShaderVariable @@ -68,6 +93,16 @@ struct COMPILER_EXPORT Uniform : public ShaderVariable ~Uniform(); Uniform(const Uniform &other); Uniform &operator=(const Uniform &other); + bool operator==(const Uniform &other) const; + bool operator!=(const Uniform &other) const + { + return !operator==(other); + } + + // Decide whether two uniforms are the same at shader link time, + // assuming one from vertex shader and the other from fragment shader. + // See GLSL ES Spec 3.00.3, sec 4.3.5. + bool isSameUniformAtLinkTime(const Uniform &other) const; }; struct COMPILER_EXPORT Attribute : public ShaderVariable @@ -76,6 +111,11 @@ struct COMPILER_EXPORT Attribute : public ShaderVariable ~Attribute(); Attribute(const Attribute &other); Attribute &operator=(const Attribute &other); + bool operator==(const Attribute &other) const; + bool operator!=(const Attribute &other) const + { + return !operator==(other); + } int location; }; @@ -86,6 +126,18 @@ struct COMPILER_EXPORT InterfaceBlockField : public ShaderVariable ~InterfaceBlockField(); InterfaceBlockField(const InterfaceBlockField &other); InterfaceBlockField &operator=(const InterfaceBlockField &other); + bool operator==(const InterfaceBlockField &other) const; + bool operator!=(const InterfaceBlockField &other) const + { + return !operator==(other); + } + + // Decide whether two InterfaceBlock fields are the same at shader + // link time, assuming one from vertex shader and the other from + // fragment shader. + // See GLSL ES Spec 3.00.3, sec 4.3.7. + bool isSameInterfaceBlockFieldAtLinkTime( + const InterfaceBlockField &other) const; bool isRowMajorLayout; }; @@ -94,8 +146,18 @@ struct COMPILER_EXPORT Varying : public ShaderVariable { Varying(); ~Varying(); - Varying(const Varying &other); + Varying(const Varying &otherg); Varying &operator=(const Varying &other); + bool operator==(const Varying &other) const; + bool operator!=(const Varying &other) const + { + return !operator==(other); + } + + // Decide whether two varyings are the same at shader link time, + // assuming one from vertex shader and the other from fragment shader. + // See GLSL ES Spec 3.00.3, sec 4.3.9. + bool isSameVaryingAtLinkTime(const Varying &other) const; InterpolationType interpolation; bool isInvariant; diff --git a/src/3rdparty/angle/include/angle_windowsstore.h b/src/3rdparty/angle/include/angle_windowsstore.h new file mode 100644 index 00000000000..53ec93e037d --- /dev/null +++ b/src/3rdparty/angle/include/angle_windowsstore.h @@ -0,0 +1,37 @@ +// +// 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. +// +// angle_windowsstore.h: + +#ifndef ANGLE_WINDOWSSTORE_H_ +#define ANGLE_WINDOWSSTORE_H_ + +// The following properties can be set on the CoreApplication to support additional +// ANGLE configuration options. +// +// The Visual Studio sample templates provided with this version of ANGLE have examples +// of how to set these property values. + +// +// Property: EGLNativeWindowTypeProperty +// Type: IInspectable +// Description: Set this property to specify the window type to use for creating a surface. +// If this property is missing, surface creation will fail. +// +const wchar_t EGLNativeWindowTypeProperty[] = L"EGLNativeWindowTypeProperty"; + +// +// Property: EGLRenderSurfaceSizeProperty +// Type: Size +// Description: Set this property to specify a preferred size in pixels of the render surface. +// The render surface size width and height must be greater than 0. +// If this property is set, then the render surface size is fixed. +// If this property is missing, a default behavior will be provided. +// The default behavior uses the window size if a CoreWindow is specified or +// the size of the SwapChainPanel control if one is specified. +// +const wchar_t EGLRenderSurfaceSizeProperty[] = L"EGLRenderSurfaceSizeProperty"; + +#endif // ANGLE_WINDOWSSTORE_H_ diff --git a/src/3rdparty/angle/src/commit.h b/src/3rdparty/angle/src/commit.h index a2e761b131a..08fc893c251 100644 --- a/src/3rdparty/angle/src/commit.h +++ b/src/3rdparty/angle/src/commit.h @@ -7,6 +7,6 @@ // This is a default commit hash header, when git is not available. // -#define ANGLE_COMMIT_HASH "abce76206141" +#define ANGLE_COMMIT_HASH "30d6c255d238" #define ANGLE_COMMIT_HASH_SIZE 12 -#define ANGLE_COMMIT_DATE "2014-09-23 19:37:05 +0000" +#define ANGLE_COMMIT_DATE "2014-11-13 17:37:03 +0000" diff --git a/src/3rdparty/angle/src/common/NativeWindow.h b/src/3rdparty/angle/src/common/NativeWindow.h new file mode 100644 index 00000000000..c4a0e42bcc5 --- /dev/null +++ b/src/3rdparty/angle/src/common/NativeWindow.h @@ -0,0 +1,82 @@ +// +// 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. +// + +// NativeWindow.h: Defines NativeWindow, a class for managing and +// performing operations on an EGLNativeWindowType. +// It is used for HWND (Desktop Windows) and IInspectable objects +//(Windows Store Applications). + +#ifndef COMMON_NATIVEWINDOW_H_ +#define COMMON_NATIVEWINDOW_H_ + +#include +#include "common/debug.h" +#include "common/platform.h" + +// DXGISwapChain and DXGIFactory are typedef'd to specific required +// types. The HWND NativeWindow implementation requires IDXGISwapChain +// and IDXGIFactory and the Windows Store NativeWindow +// implementation requires IDXGISwapChain1 and IDXGIFactory2. +#if defined(ANGLE_ENABLE_WINDOWS_STORE) +typedef IDXGISwapChain1 DXGISwapChain; +typedef IDXGIFactory2 DXGIFactory; + +#include +#include +#include +#include + +namespace rx +{ +class InspectableNativeWindow; +} + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; + +#else +typedef IDXGISwapChain DXGISwapChain; +typedef IDXGIFactory DXGIFactory; +#endif + +namespace rx +{ + +class NativeWindow +{ +public: + explicit NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display); + + bool initialize(); + bool getClientRect(LPRECT rect); + bool isIconic(); + +# if defined(ANGLE_ENABLE_D3D11) + typedef ID3D11Device Device; +#else + typedef IDirect3DDevice9 Device; +#endif + HRESULT createSwapChain(Device* device, DXGIFactory* factory, + DXGI_FORMAT format, UINT width, UINT height, + DXGISwapChain** swapChain); + + inline EGLNativeWindowType getNativeWindow() const { return mWindow; } + inline EGLNativeDisplayType getNativeDisplay() const { return mDisplay; } + + private: + EGLNativeWindowType mWindow; + EGLNativeDisplayType mDisplay; + +#if defined(ANGLE_ENABLE_WINDOWS_STORE) + std::shared_ptr mImpl; +#endif + +}; + +bool IsValidEGLNativeWindowType(EGLNativeWindowType window); +} + +#endif // COMMON_NATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/common/angleutils.cpp b/src/3rdparty/angle/src/common/angleutils.cpp index 2673abf30ac..c1367c460a3 100644 --- a/src/3rdparty/angle/src/common/angleutils.cpp +++ b/src/3rdparty/angle/src/common/angleutils.cpp @@ -5,26 +5,33 @@ // #include "common/angleutils.h" - +#include "debug.h" +#include #include +size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector& outBuffer) +{ + // Attempt to just print to the current buffer + int len = vsnprintf(&(outBuffer.front()), outBuffer.size(), fmt, vararg); + if (len < 0 || static_cast(len) >= outBuffer.size()) + { + // Buffer was not large enough, calculate the required size and resize the buffer + len = vsnprintf(NULL, 0, fmt, vararg); + outBuffer.resize(len + 1); + + // Print again + len = vsnprintf(&(outBuffer.front()), outBuffer.size(), fmt, vararg); + } + ASSERT(len >= 0); + return static_cast(len); +} + std::string FormatString(const char *fmt, va_list vararg) { static std::vector buffer(512); - // Attempt to just print to the current buffer - int len = vsnprintf(&buffer[0], buffer.size(), fmt, vararg); - if (len < 0 || static_cast(len) >= buffer.size()) - { - // Buffer was not large enough, calculate the required size and resize the buffer - len = vsnprintf(NULL, 0, fmt, vararg); - buffer.resize(len + 1); - - // Print again - vsnprintf(&buffer[0], buffer.size(), fmt, vararg); - } - - return std::string(buffer.data(), len); + size_t len = FormatStringIntoVector(fmt, vararg, buffer); + return std::string(&buffer[0], len); } std::string FormatString(const char *fmt, ...) diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h index ddbbd5f5010..b343ece5bc5 100644 --- a/src/3rdparty/angle/src/common/angleutils.h +++ b/src/3rdparty/angle/src/common/angleutils.h @@ -17,6 +17,7 @@ #include #include #include +#include // A macro to disallow the copy constructor and operator= functions // This must be used in the private: declarations for a class @@ -95,6 +96,13 @@ inline void StructZero(T *obj) memset(obj, 0, sizeof(T)); } +template +inline bool IsMaskFlagSet(T mask, T flag) +{ + // Handles multibit flags as well + return (mask & flag) == flag; +} + inline const char* MakeStaticString(const std::string &str) { static std::set strings; @@ -132,9 +140,12 @@ inline std::string Str(int i) return strstr.str(); } +size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector& buffer); + std::string FormatString(const char *fmt, va_list vararg); std::string FormatString(const char *fmt, ...); +// snprintf is not defined with MSVC prior to to msvc14 #if defined(_MSC_VER) && _MSC_VER < 1900 #define snprintf _snprintf #endif diff --git a/src/3rdparty/angle/src/common/debug.cpp b/src/3rdparty/angle/src/common/debug.cpp index dcad3275640..5f55ff1e394 100644 --- a/src/3rdparty/angle/src/common/debug.cpp +++ b/src/3rdparty/angle/src/common/debug.cpp @@ -17,41 +17,211 @@ 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_ENABLE_DEBUG_ANNOTATIONS) +// Wraps the D3D9/D3D11 debug annotation functions. +class DebugAnnotationWrapper { -#if defined(ANGLE_ENABLE_PERF) || defined(ANGLE_ENABLE_TRACE) - std::string formattedMessage = FormatString(format, vararg); + public: + DebugAnnotationWrapper() { }; + virtual ~DebugAnnotationWrapper() { }; + virtual void beginEvent(const std::wstring &eventName) = 0; + virtual void endEvent() = 0; + virtual void setMarker(const std::wstring &markerName) = 0; + virtual bool getStatus() = 0; +}; + +#if defined(ANGLE_ENABLE_D3D9) +class D3D9DebugAnnotationWrapper : public DebugAnnotationWrapper +{ + public: + void beginEvent(const std::wstring &eventName) + { + D3DPERF_BeginEvent(0, eventName.c_str()); + } + + void endEvent() + { + D3DPERF_EndEvent(); + } + + void setMarker(const std::wstring &markerName) + { + D3DPERF_SetMarker(0, markerName.c_str()); + } + + bool getStatus() + { + return !!D3DPERF_GetStatus(); + } +}; +#endif // ANGLE_ENABLE_D3D9 + +#if defined(ANGLE_ENABLE_D3D11) +class D3D11DebugAnnotationWrapper : public DebugAnnotationWrapper +{ + public: + + D3D11DebugAnnotationWrapper() + : mInitialized(false), + mD3d11Module(NULL), + mUserDefinedAnnotation(NULL) + { + // D3D11 devices can't be created during DllMain. + // We defer device creation until the object is actually used. + } + + ~D3D11DebugAnnotationWrapper() + { + if (mInitialized) + { + SafeRelease(mUserDefinedAnnotation); + FreeLibrary(mD3d11Module); + } + } + + virtual void beginEvent(const std::wstring &eventName) + { + initializeDevice(); + + mUserDefinedAnnotation->BeginEvent(eventName.c_str()); + } + + virtual void endEvent() + { + initializeDevice(); + + mUserDefinedAnnotation->EndEvent(); + } + + virtual void setMarker(const std::wstring &markerName) + { + initializeDevice(); + + mUserDefinedAnnotation->SetMarker(markerName.c_str()); + } + + virtual bool getStatus() + { + // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in Visual Studio 2013. + +#if defined(_DEBUG) && defined(ANGLE_ENABLE_WINDOWS_STORE) + // In the Windows Store, we can use IDXGraphicsAnalysis. The call to GetDebugInterface1 only succeeds if the app is under capture. + // This should only be called in DEBUG mode. + // If an app links against DXGIGetDebugInterface1 in release mode then it will fail Windows Store ingestion checks. + IDXGraphicsAnalysis* graphicsAnalysis; + DXGIGetDebugInterface1(0, IID_PPV_ARGS(&graphicsAnalysis)); + bool underCapture = (graphicsAnalysis != NULL); + SafeRelease(graphicsAnalysis); + return underCapture; #endif -#if defined(ANGLE_ENABLE_PERF) + // Otherwise, we have to return true here. + return true; + } + + protected: + + void initializeDevice() + { + if (!mInitialized) + { +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); + ASSERT(mD3d11Module); + + PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); + ASSERT(D3D11CreateDevice != NULL); +#endif // !ANGLE_ENABLE_WINDOWS_STORE + + ID3D11Device* device = NULL; + ID3D11DeviceContext* context = NULL; + + HRESULT hr = E_FAIL; + + // Create a D3D_DRIVER_TYPE_NULL device, which is much cheaper than other types of device. + hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &device, NULL, &context); + ASSERT(SUCCEEDED(hr)); + + hr = context->QueryInterface(__uuidof(mUserDefinedAnnotation), reinterpret_cast(&mUserDefinedAnnotation)); + ASSERT(SUCCEEDED(hr) && mUserDefinedAnnotation != NULL); + + SafeRelease(device); + SafeRelease(context); + + mInitialized = true; + } + } + + bool mInitialized; + HMODULE mD3d11Module; + ID3DUserDefinedAnnotation* mUserDefinedAnnotation; +}; +#endif // ANGLE_ENABLE_D3D11 + +static DebugAnnotationWrapper* g_DebugAnnotationWrapper = NULL; + +void InitializeDebugAnnotations() +{ +#if defined(ANGLE_ENABLE_D3D9) + g_DebugAnnotationWrapper = new D3D9DebugAnnotationWrapper(); +#elif defined(ANGLE_ENABLE_D3D11) + // If the project uses D3D9 then we can use the D3D9 debug annotations, even with the D3D11 renderer. + // However, if D3D9 is unavailable (e.g. in Windows Store), then we use D3D11 debug annotations. + // The D3D11 debug annotations are methods on ID3DUserDefinedAnnotation, which is implemented by the DeviceContext. + // This doesn't have to be the same DeviceContext that the renderer uses, though. + g_DebugAnnotationWrapper = new D3D11DebugAnnotationWrapper(); +#endif +} + +void UninitializeDebugAnnotations() +{ + if (g_DebugAnnotationWrapper != NULL) + { + SafeDelete(g_DebugAnnotationWrapper); + } +} + +#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS + +enum DebugTraceOutputType +{ + DebugTraceOutputTypeNone, + DebugTraceOutputTypeSetMarker, + DebugTraceOutputTypeBeginEvent +}; + +static void output(bool traceInDebugOnly, DebugTraceOutputType outputType, const char *format, va_list vararg) +{ +#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) + static std::vector buffer(512); + if (perfActive()) { - // The perf function only accepts wide strings, widen the ascii message - static std::wstring wideMessage; - if (wideMessage.capacity() < formattedMessage.length()) + size_t len = FormatStringIntoVector(format, vararg, buffer); + std::wstring formattedWideMessage(buffer.begin(), buffer.begin() + len); + + switch (outputType) { - wideMessage.reserve(formattedMessage.size()); + case DebugTraceOutputTypeNone: + break; + case DebugTraceOutputTypeBeginEvent: + g_DebugAnnotationWrapper->beginEvent(formattedWideMessage); + break; + case DebugTraceOutputTypeSetMarker: + g_DebugAnnotationWrapper->setMarker(formattedWideMessage); + break; } - - wideMessage.assign(formattedMessage.begin(), formattedMessage.end()); - - perfFunc(0, wideMessage.c_str()); } -#endif // ANGLE_ENABLE_PERF +#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS -#if defined(ANGLE_ENABLE_TRACE) +#if defined(ANGLE_ENABLE_DEBUG_TRACE) #if defined(NDEBUG) - if (traceFileDebugOnly) + if (traceInDebugOnly) { return; } #endif // NDEBUG + std::string formattedMessage = FormatString(format, vararg); static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app); if (file) @@ -60,25 +230,29 @@ static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const c file.flush(); } -#endif // ANGLE_ENABLE_TRACE +#if defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER) + OutputDebugStringA(formattedMessage.c_str()); +#endif // ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER + +#endif // ANGLE_ENABLE_DEBUG_TRACE } -void trace(bool traceFileDebugOnly, const char *format, ...) +void trace(bool traceInDebugOnly, const char *format, ...) { va_list vararg; va_start(vararg, format); -#if defined(ANGLE_ENABLE_PERF) - output(traceFileDebugOnly, D3DPERF_SetMarker, format, vararg); +#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) + output(traceInDebugOnly, DebugTraceOutputTypeSetMarker, format, vararg); #else - output(traceFileDebugOnly, NULL, format, vararg); + output(traceInDebugOnly, DebugTraceOutputTypeNone, format, vararg); #endif va_end(vararg); } bool perfActive() { -#if defined(ANGLE_ENABLE_PERF) - static bool active = D3DPERF_GetStatus() != 0; +#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) + static bool active = g_DebugAnnotationWrapper->getStatus(); return active; #else return false; @@ -87,26 +261,28 @@ bool perfActive() ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...) { -#if defined(ANGLE_ENABLE_PERF) -#if !defined(ANGLE_ENABLE_TRACE) +#if !defined(ANGLE_ENABLE_DEBUG_TRACE) if (!perfActive()) { return; } -#endif // !ANGLE_ENABLE_TRACE +#endif // !ANGLE_ENABLE_DEBUG_TRACE va_list vararg; va_start(vararg, format); - output(true, reinterpret_cast(D3DPERF_BeginEvent), format, vararg); +#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) + output(true, DebugTraceOutputTypeBeginEvent, format, vararg); +#else + output(true, DebugTraceOutputTypeNone, format, vararg); +#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS va_end(vararg); -#endif // ANGLE_ENABLE_PERF } ScopedPerfEventHelper::~ScopedPerfEventHelper() { -#if defined(ANGLE_ENABLE_PERF) +#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) if (perfActive()) { - D3DPERF_EndEvent(); + g_DebugAnnotationWrapper->endEvent(); } #endif } diff --git a/src/3rdparty/angle/src/common/debug.h b/src/3rdparty/angle/src/common/debug.h index bf2bca8f242..c177f513142 100644 --- a/src/3rdparty/angle/src/common/debug.h +++ b/src/3rdparty/angle/src/common/debug.h @@ -20,8 +20,8 @@ namespace gl { - // Outputs text to the debugging log - void trace(bool traceFileDebugOnly, const char *format, ...); + // Outputs text to the debugging log, or the debugging window + void trace(bool traceInDebugOnly, const char *format, ...); // Returns whether D3DPERF is active. bool perfActive(); @@ -36,31 +36,34 @@ namespace gl private: DISALLOW_COPY_AND_ASSIGN(ScopedPerfEventHelper); }; + + void InitializeDebugAnnotations(); + void UninitializeDebugAnnotations(); } // A macro to output a trace of a function call and its arguments to the debugging log -#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF) +#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) #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_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF) +#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) #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_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF) +#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) #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_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF) +#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) #if defined(_MSC_VER) #define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__("%s" message "\n", __FUNCTION__, __VA_ARGS__); #else @@ -83,7 +86,7 @@ namespace gl #define UNUSED_ASSERTION_VARIABLE(variable) ((void)variable) #endif -#ifndef ANGLE_ENABLE_TRACE +#ifndef ANGLE_ENABLE_DEBUG_TRACE #define UNUSED_TRACE_VARIABLE(variable) ((void)variable) #else #define UNUSED_TRACE_VARIABLE(variable) @@ -128,7 +131,7 @@ namespace gl #endif // A macro functioning as a compile-time assert to validate constant conditions -#if defined(_MSC_VER) && _MSC_VER >= 1600 +#if (defined(_MSC_VER) && _MSC_VER >= 1600) || (defined(__GNUC__) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3)) #define META_ASSERT_MSG(condition, msg) static_assert(condition, msg) #else #define META_ASSERT_CONCAT(a, b) a ## b diff --git a/src/3rdparty/angle/src/common/features.h b/src/3rdparty/angle/src/common/features.h new file mode 100644 index 00000000000..b49a0ee8526 --- /dev/null +++ b/src/3rdparty/angle/src/common/features.h @@ -0,0 +1,35 @@ +// +// 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. +// + +#define ANGLE_DISABLED 0 +#define ANGLE_ENABLED 1 + +// Feature defaults + +// Direct3D9EX +// The "Debug This Pixel..." feature in PIX often fails when using the +// D3D9Ex interfaces. In order to get debug pixel to work on a Vista/Win 7 +// machine, define "ANGLE_D3D9EX=0" in your project file. +#if !defined(ANGLE_D3D9EX) +#define ANGLE_D3D9EX ANGLE_ENABLED +#endif + +// Vsync +// ENABLED allows Vsync to be configured at runtime +// DISABLED disallows Vsync +#if !defined(ANGLE_VSYNC) +#define ANGLE_VSYNC ANGLE_ENABLED +#endif + +// Program binary loading +#if !defined(ANGLE_PROGRAM_BINARY_LOAD) +#define ANGLE_PROGRAM_BINARY_LOAD ANGLE_ENABLED +#endif + +// Shader debug info +#if !defined(ANGLE_SHADER_DEBUG_INFO) +#define ANGLE_SHADER_DEBUG_INFO ANGLE_DISABLED +#endif diff --git a/src/3rdparty/angle/src/common/mathutil.h b/src/3rdparty/angle/src/common/mathutil.h index 52f2bc1c0e8..a1717892fd6 100644 --- a/src/3rdparty/angle/src/common/mathutil.h +++ b/src/3rdparty/angle/src/common/mathutil.h @@ -109,7 +109,7 @@ inline unsigned int unorm(float x) inline bool supportsSSE2() { -#ifdef ANGLE_PLATFORM_WINDOWS +#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM) static bool checked = false; static bool supports = false; @@ -118,7 +118,6 @@ inline bool supportsSSE2() return supports; } -#if defined(_M_IX86) || defined(_M_AMD64) // ARM doesn't provide __cpuid() int info[4]; __cpuid(info, 0); @@ -128,7 +127,6 @@ inline bool supportsSSE2() supports = (info[3] >> 26) & 1; } -#endif checked = true; diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h index b53394f3371..5bf97f91844 100644 --- a/src/3rdparty/angle/src/common/platform.h +++ b/src/3rdparty/angle/src/common/platform.h @@ -11,9 +11,6 @@ #if defined(_WIN32) || defined(_WIN64) # define ANGLE_PLATFORM_WINDOWS 1 -# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) -# define ANGLE_PLATFORM_WINRT 1 -# endif #elif defined(__APPLE__) # define ANGLE_PLATFORM_APPLE 1 # define ANGLE_PLATFORM_POSIX 1 @@ -37,6 +34,9 @@ #endif #ifdef ANGLE_PLATFORM_WINDOWS +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) +# define ANGLE_ENABLE_WINDOWS_STORE 1 +# endif # ifndef STRICT # define STRICT 1 # endif @@ -50,8 +50,9 @@ # include # include -# if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_PERF) +# if defined(ANGLE_ENABLE_D3D9) # include +# include # if !defined(COMPILER_IMPLEMENTATION) # include # endif @@ -62,13 +63,26 @@ # include # include # include -# if _MSC_VER >= 1700 +# if defined(_MSC_VER) && (_MSC_VER >= 1700) +# include # include # endif # if !defined(COMPILER_IMPLEMENTATION) # include # endif -# if defined(__MINGW32__) +# endif + +# if defined(ANGLE_ENABLE_WINDOWS_STORE) +# include +# if defined(_DEBUG) +# if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) +# include +# endif +# include +# endif +# endif + +# if defined(__MINGW32__) // Missing defines on MinGW typedef enum D3D11_MAP_FLAG { D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000L @@ -78,8 +92,68 @@ typedef struct D3D11_QUERY_DATA_SO_STATISTICS UINT64 NumPrimitivesWritten; UINT64 PrimitivesStorageNeeded; } D3D11_QUERY_DATA_SO_STATISTICS; -# endif -# endif +typedef HRESULT (WINAPI *PFN_D3D11_CREATE_DEVICE)( + IDXGIAdapter *, D3D_DRIVER_TYPE, HMODULE, UINT, CONST D3D_FEATURE_LEVEL *, + UINT FeatureLevels, UINT, ID3D11Device **, D3D_FEATURE_LEVEL *, ID3D11DeviceContext **); +#define D3D11_MESSAGE_CATEGORY UINT +#define D3D11_MESSAGE_SEVERITY UINT +#define D3D11_MESSAGE_ID UINT +struct D3D11_MESSAGE; +typedef struct D3D11_INFO_QUEUE_FILTER_DESC +{ + UINT NumCategories; + D3D11_MESSAGE_CATEGORY *pCategoryList; + UINT NumSeverities; + D3D11_MESSAGE_SEVERITY *pSeverityList; + UINT NumIDs; + D3D11_MESSAGE_ID *pIDList; +} D3D11_INFO_QUEUE_FILTER_DESC; +typedef struct D3D11_INFO_QUEUE_FILTER +{ + D3D11_INFO_QUEUE_FILTER_DESC AllowList; + D3D11_INFO_QUEUE_FILTER_DESC DenyList; +} D3D11_INFO_QUEUE_FILTER; +static const IID IID_ID3D11InfoQueue = { 0x6543dbb6, 0x1b48, 0x42f5, 0xab, 0x82, 0xe9, 0x7e, 0xc7, 0x43, 0x26, 0xf6 }; +MIDL_INTERFACE("6543dbb6-1b48-42f5-ab82-e97ec74326f6") ID3D11InfoQueue : public IUnknown +{ +public: + virtual HRESULT __stdcall SetMessageCountLimit(UINT64) = 0; + virtual void __stdcall ClearStoredMessages() = 0; + virtual HRESULT __stdcall GetMessage(UINT64, D3D11_MESSAGE *, SIZE_T *) = 0; + virtual UINT64 __stdcall GetNumMessagesAllowedByStorageFilter() = 0; + virtual UINT64 __stdcall GetNumMessagesDeniedByStorageFilter() = 0; + virtual UINT64 __stdcall GetNumStoredMessages() = 0; + virtual UINT64 __stdcall GetNumStoredMessagesAllowedByRetrievalFilter() = 0; + virtual UINT64 __stdcall GetNumMessagesDiscardedByMessageCountLimit() = 0; + virtual UINT64 __stdcall GetMessageCountLimit() = 0; + virtual HRESULT __stdcall AddStorageFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0; + virtual HRESULT __stdcall GetStorageFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0; + virtual void __stdcall ClearStorageFilter() = 0; + virtual HRESULT __stdcall PushEmptyStorageFilter() = 0; + virtual HRESULT __stdcall PushCopyOfStorageFilter() = 0; + virtual HRESULT __stdcall PushStorageFilter(D3D11_INFO_QUEUE_FILTER *) = 0; + virtual void __stdcall PopStorageFilter() = 0; + virtual UINT __stdcall GetStorageFilterStackSize() = 0; + virtual HRESULT __stdcall AddRetrievalFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0; + virtual HRESULT __stdcall GetRetrievalFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0; + virtual void __stdcall ClearRetrievalFilter() = 0; + virtual HRESULT __stdcall PushEmptyRetrievalFilter() = 0; + virtual HRESULT __stdcall PushCopyOfRetrievalFilter() = 0; + virtual HRESULT __stdcall PushRetrievalFilter(D3D11_INFO_QUEUE_FILTER *) = 0; + virtual void __stdcall PopRetrievalFilter() = 0; + virtual UINT __stdcall GetRetrievalFilterStackSize() = 0; + virtual HRESULT __stdcall AddMessage(D3D11_MESSAGE_CATEGORY, D3D11_MESSAGE_SEVERITY, D3D11_MESSAGE_ID, LPCSTR) = 0; + virtual HRESULT __stdcall AddApplicationMessage(D3D11_MESSAGE_SEVERITY, LPCSTR) = 0; + virtual HRESULT __stdcall SetBreakOnCategory(D3D11_MESSAGE_CATEGORY, BOOL) = 0; + virtual HRESULT __stdcall SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY, BOOL) = 0; + virtual HRESULT __stdcall SetBreakOnID(D3D11_MESSAGE_ID, BOOL) = 0; + virtual BOOL __stdcall GetBreakOnCategory(D3D11_MESSAGE_CATEGORY) = 0; + virtual BOOL __stdcall GetBreakOnSeverity(D3D11_MESSAGE_SEVERITY) = 0; + virtual BOOL __stdcall GetBreakOnID(D3D11_MESSAGE_ID) = 0; + virtual void __stdcall SetMuteDebugOutput(BOOL) = 0; + virtual BOOL __stdcall GetMuteDebugOutput() = 0; +}; +#endif // __MINGW32__ # undef near # undef far diff --git a/src/3rdparty/angle/src/common/tls.cpp b/src/3rdparty/angle/src/common/tls.cpp index c46fab5303e..cb1b32d3258 100644 --- a/src/3rdparty/angle/src/common/tls.cpp +++ b/src/3rdparty/angle/src/common/tls.cpp @@ -10,29 +10,50 @@ #include -#if defined(ANGLE_PLATFORM_WINRT) +#ifdef ANGLE_ENABLE_WINDOWS_STORE #include -std::vector *tls = nullptr; -std::vector *freeIndices = nullptr; +#include +#include +#include + +#include +#include +#include + +using namespace std; +using namespace Windows::Foundation; +using namespace ABI::Windows::System::Threading; + +// Thread local storage for Windows Store support +typedef vector ThreadLocalData; + +static __declspec(thread) ThreadLocalData* currentThreadData = nullptr; +static set allThreadData; +static DWORD nextTlsIndex = 0; +static vector freeTlsIndices; + #endif TLSIndex CreateTLSIndex() { TLSIndex index; -#if defined(ANGLE_PLATFORM_WINRT) - if (!tls) - tls = new std::vector; - if (freeIndices && !freeIndices->empty()) { - index = freeIndices->back(); - freeIndices->pop_back(); - return index; - } else { - tls->push_back(nullptr); - return tls->size() - 1; +#ifdef ANGLE_PLATFORM_WINDOWS +#ifdef ANGLE_ENABLE_WINDOWS_STORE + if (!freeTlsIndices.empty()) + { + DWORD result = freeTlsIndices.back(); + freeTlsIndices.pop_back(); + index = result; } -#elif defined(ANGLE_PLATFORM_WINDOWS) + else + { + index = nextTlsIndex++; + } +#else index = TlsAlloc(); +#endif + #elif defined(ANGLE_PLATFORM_POSIX) // Create global pool key if ((pthread_key_create(&index, NULL)) != 0) @@ -53,13 +74,23 @@ bool DestroyTLSIndex(TLSIndex index) return false; } -#if defined(ANGLE_PLATFORM_WINRT) - if (!freeIndices) - freeIndices = new std::vector; - freeIndices->push_back(index); +#ifdef ANGLE_PLATFORM_WINDOWS +#ifdef ANGLE_ENABLE_WINDOWS_STORE + assert(index < nextTlsIndex); + assert(find(freeTlsIndices.begin(), freeTlsIndices.end(), index) == freeTlsIndices.end()); + + freeTlsIndices.push_back(index); + for (auto threadData : allThreadData) + { + if (threadData->size() > index) + { + threadData->at(index) = nullptr; + } + } return true; -#elif ANGLE_PLATFORM_WINDOWS +#else return (TlsFree(index) == TRUE); +#endif #elif defined(ANGLE_PLATFORM_POSIX) return (pthread_key_delete(index) == 0); #endif @@ -73,11 +104,25 @@ bool SetTLSValue(TLSIndex index, void *value) return false; } -#if defined(ANGLE_PLATFORM_WINRT) - tls->at(index) = value; +#ifdef ANGLE_PLATFORM_WINDOWS +#ifdef ANGLE_ENABLE_WINDOWS_STORE + ThreadLocalData* threadData = currentThreadData; + if (!threadData) + { + threadData = new ThreadLocalData(index + 1, nullptr); + allThreadData.insert(threadData); + currentThreadData = threadData; + } + else if (threadData->size() <= index) + { + threadData->resize(index + 1, nullptr); + } + + threadData->at(index) = value; return true; -#elif defined(ANGLE_PLATFORM_WINDOWS) +#else return (TlsSetValue(index, value) == TRUE); +#endif #elif defined(ANGLE_PLATFORM_POSIX) return (pthread_setspecific(index, value) == 0); #endif @@ -85,18 +130,26 @@ bool SetTLSValue(TLSIndex index, void *value) void *GetTLSValue(TLSIndex index) { -#if !defined(ANGLE_PLATFORM_WINRT) // Valid on WinRT, as Alloc handles the index creation assert(index != TLS_INVALID_INDEX && "GetTLSValue(): Invalid TLS Index"); -#endif if (index == TLS_INVALID_INDEX) { return NULL; } -#if defined(ANGLE_PLATFORM_WINRT) - return tls->at(index); -#elif defined(ANGLE_PLATFORM_WINDOWS) +#ifdef ANGLE_PLATFORM_WINDOWS +#ifdef ANGLE_ENABLE_WINDOWS_STORE + ThreadLocalData* threadData = currentThreadData; + if (threadData && threadData->size() > index) + { + return threadData->at(index); + } + else + { + return nullptr; + } +#else return TlsGetValue(index); +#endif #elif defined(ANGLE_PLATFORM_POSIX) return pthread_getspecific(index); #endif diff --git a/src/3rdparty/angle/src/common/tls.h b/src/3rdparty/angle/src/common/tls.h index c40ae1a0614..8a06e92d1ad 100644 --- a/src/3rdparty/angle/src/common/tls.h +++ b/src/3rdparty/angle/src/common/tls.h @@ -11,11 +11,15 @@ #include "common/platform.h" -#if defined(ANGLE_PLATFORM_WINRT) - typedef size_t TLSIndex; -# define TLS_OUT_OF_INDEXES (static_cast(-1)) -# define TLS_INVALID_INDEX TLS_OUT_OF_INDEXES -#elif defined(ANGLE_PLATFORM_WINDOWS) +#ifdef ANGLE_PLATFORM_WINDOWS + +// TLS does not exist for Windows Store and needs to be emulated +# ifdef ANGLE_ENABLE_WINDOWS_STORE +# define TLS_OUT_OF_INDEXES -1 +# ifndef CREATE_SUSPENDED +# define CREATE_SUSPENDED 0x00000004 +# endif +# endif typedef DWORD TLSIndex; # define TLS_INVALID_INDEX (TLS_OUT_OF_INDEXES) #elif defined(ANGLE_PLATFORM_POSIX) @@ -28,6 +32,9 @@ # error Unsupported platform. #endif +// TODO(kbr): for POSIX platforms this will have to be changed to take +// in a destructor function pointer, to allow the thread-local storage +// to be properly deallocated upon thread exit. TLSIndex CreateTLSIndex(); bool DestroyTLSIndex(TLSIndex index); diff --git a/src/3rdparty/angle/src/common/utilities.cpp b/src/3rdparty/angle/src/common/utilities.cpp index 4b8e325d22c..9d797a6612f 100644 --- a/src/3rdparty/angle/src/common/utilities.cpp +++ b/src/3rdparty/angle/src/common/utilities.cpp @@ -9,17 +9,16 @@ #include "common/utilities.h" #include "common/mathutil.h" #include "common/platform.h" -#if defined(ANGLE_PLATFORM_WINRT) -# include -# include -# include -# include - using namespace Microsoft::WRL; - using namespace ABI::Windows::Storage; -#endif #include +#if defined(ANGLE_ENABLE_WINDOWS_STORE) +# include +# include +# include +# include +#endif + namespace gl { @@ -447,50 +446,10 @@ int VariableSortOrder(GLenum type) } +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) std::string getTempPath() { -#if defined(ANGLE_PLATFORM_WINRT) - static std::string path; - - while (path.empty()) - { - ComPtr factory; - Wrappers::HStringReference classId(RuntimeClass_Windows_Storage_ApplicationData); - HRESULT result = RoGetActivationFactory(classId.Get(), IID_PPV_ARGS(&factory)); - if (FAILED(result)) - break; - - ComPtr applicationData; - result = factory->get_Current(&applicationData); - if (FAILED(result)) - break; - - ComPtr storageFolder; - result = applicationData->get_LocalFolder(&storageFolder); - if (FAILED(result)) - break; - - ComPtr localFolder; - result = storageFolder.As(&localFolder); - if (FAILED(result)) - break; - - HSTRING localFolderPath; - result = localFolder->get_Path(&localFolderPath); - if (FAILED(result)) - break; - - std::wstring_convert< std::codecvt_utf8 > converter; - path = converter.to_bytes(WindowsGetStringRawBuffer(localFolderPath, NULL)); - if (path.empty()) - { - UNREACHABLE(); - break; - } - } - - return path; -#elif defined(ANGLE_PLATFORM_WINDOWS) +#ifdef ANGLE_PLATFORM_WINDOWS char path[MAX_PATH]; DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path); if (pathLen == 0) @@ -525,3 +484,33 @@ void writeFile(const char* path, const void* content, size_t size) fwrite(content, sizeof(char), size, file); fclose(file); } +#endif // !ANGLE_ENABLE_WINDOWS_STORE + +#if defined(ANGLE_ENABLE_WINDOWS_STORE) + +void Sleep(unsigned long dwMilliseconds) +{ + static HANDLE singletonEvent = nullptr; + HANDLE sleepEvent = singletonEvent; + if (!sleepEvent) + { + sleepEvent = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); + + if (!sleepEvent) + return; + + HANDLE previousEvent = InterlockedCompareExchangePointerRelease(&singletonEvent, sleepEvent, nullptr); + + if (previousEvent) + { + // Back out if multiple threads try to demand create at the same time. + CloseHandle(sleepEvent); + sleepEvent = previousEvent; + } + } + + // Emulate sleep by waiting with timeout on an event that is never signalled. + WaitForSingleObjectEx(sleepEvent, dwMilliseconds, false); +} + +#endif // ANGLE_ENABLE_WINDOWS_STORE diff --git a/src/3rdparty/angle/src/common/utilities.h b/src/3rdparty/angle/src/common/utilities.h index a823184ecdb..2cf6bed176c 100644 --- a/src/3rdparty/angle/src/common/utilities.h +++ b/src/3rdparty/angle/src/common/utilities.h @@ -46,7 +46,13 @@ template outT uiround(GLfloat value) { return static_cast( } +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) std::string getTempPath(); void writeFile(const char* path, const void* data, size_t size); +#endif + +#if defined(ANGLE_ENABLE_WINDOWS_STORE) +void Sleep(_In_ unsigned long dwMilliseconds); +#endif #endif // LIBGLESV2_UTILITIES_H diff --git a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp new file mode 100644 index 00000000000..46082a2e280 --- /dev/null +++ b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp @@ -0,0 +1,66 @@ +// +// 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. +// + +// NativeWindow.cpp: Handler for managing HWND native window types. + +#include "common/NativeWindow.h" +#include "common/debug.h" + +namespace rx +{ +bool IsValidEGLNativeWindowType(EGLNativeWindowType window) +{ + return (IsWindow(window) == TRUE); +} + +NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display) : mWindow(window), mDisplay(display) +{ +} + +bool NativeWindow::initialize() +{ + return true; +} + +bool NativeWindow::getClientRect(LPRECT rect) +{ + return GetClientRect(mWindow, rect) == TRUE; +} + +bool NativeWindow::isIconic() +{ + return IsIconic(mWindow) == TRUE; +} + +HRESULT NativeWindow::createSwapChain(NativeWindow::Device* device, DXGIFactory* factory, + DXGI_FORMAT format, unsigned int width, unsigned int height, + DXGISwapChain** swapChain) +{ + if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) + { + return E_INVALIDARG; + } + + DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 }; + swapChainDesc.BufferCount = 1; + swapChainDesc.BufferDesc.Format = format; + swapChainDesc.BufferDesc.Width = width; + swapChainDesc.BufferDesc.Height = height; + 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; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.Flags = 0; + swapChainDesc.OutputWindow = mWindow; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Windowed = TRUE; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + + return factory->CreateSwapChain(device, &swapChainDesc, swapChain); +} +} diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp new file mode 100644 index 00000000000..9b65c156258 --- /dev/null +++ b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp @@ -0,0 +1,200 @@ +// +// 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. +// + +// CoreWindowNativeWindow.cpp: NativeWindow for managing ICoreWindow native window types. + +#include +#include "common/winrt/CoreWindowNativeWindow.h" +using namespace ABI::Windows::Foundation::Collections; + +namespace rx +{ + +typedef ITypedEventHandler SizeChangedHandler; + +CoreWindowNativeWindow::~CoreWindowNativeWindow() +{ + unregisterForSizeChangeEvents(); +} + +bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) +{ + ComPtr props = propertySet; + ComPtr win = window; + ComPtr displayInformation = display; + SIZE swapChainSize = {}; + bool swapChainSizeSpecified = false; + HRESULT result = S_OK; + + // IPropertySet is an optional parameter and can be null. + // If one is specified, cache as an IMap and read the properties + // used for initial host initialization. + if (propertySet) + { + result = props.As(&mPropertyMap); + if (SUCCEEDED(result)) + { + // The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet + // was prevalidated to contain the EGLNativeWindowType before being passed to + // this host. + result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &swapChainSizeSpecified); + } + } + + if (SUCCEEDED(result)) + { + result = win.As(&mCoreWindow); + } + + if (SUCCEEDED(result)) + { + result = displayInformation.As(&mDisplayInformation); + } + + if (SUCCEEDED(result)) + { +#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP + ComPtr displayInformation2; + result = mDisplayInformation.As(&displayInformation2); + ASSERT(SUCCEEDED(result)); + + result = displayInformation2->get_RawPixelsPerViewPixel(&mScaleFactor); + ASSERT(SUCCEEDED(result)); +#else + ABI::Windows::Graphics::Display::ResolutionScale resolutionScale; + result = mDisplayInformation->get_ResolutionScale(&resolutionScale); + ASSERT(SUCCEEDED(result)); + + mScaleFactor = DOUBLE(resolutionScale) / 100.0; +#endif + } + + if (SUCCEEDED(result)) + { + // If a swapchain size is specfied, then the automatic resize + // behaviors implemented by the host should be disabled. The swapchain + // will be still be scaled when being rendered to fit the bounds + // of the host. + // Scaling of the swapchain output occurs automatically because if + // the scaling mode setting DXGI_SCALING_STRETCH on the swapchain. + if (swapChainSizeSpecified) + { + mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy }; + mSupportsSwapChainResize = false; + } + else + { + ABI::Windows::Foundation::Rect rect; + HRESULT result = mCoreWindow->get_Bounds(&rect); + if (SUCCEEDED(result)) + { + LONG width = std::floor(rect.Width * mScaleFactor + 0.5); + LONG height = std::floor(rect.Height * mScaleFactor + 0.5); + mClientRect = { 0, 0, width, height }; + } + } + } + + if (SUCCEEDED(result)) + { + mNewClientRect = mClientRect; + mClientRectChanged = false; + return registerForSizeChangeEvents(); + } + + return false; +} + +bool CoreWindowNativeWindow::registerForSizeChangeEvents() +{ + HRESULT result = mCoreWindow->add_SizeChanged(Callback(this, &CoreWindowNativeWindow::onSizeChanged).Get(), + &mSizeChangedEventToken); + + if (SUCCEEDED(result)) + { + return true; + } + + return false; +} + +void CoreWindowNativeWindow::unregisterForSizeChangeEvents() +{ + if (mCoreWindow) + { + (void)mCoreWindow->remove_SizeChanged(mSizeChangedEventToken); + } + mSizeChangedEventToken.value = 0; +} + +HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) +{ + if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) + { + return E_INVALIDARG; + } + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 }; + swapChainDesc.Width = width; + swapChainDesc.Height = height; + swapChainDesc.Format = format; + swapChainDesc.Stereo = FALSE; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.BufferCount = 2; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + + *swapChain = nullptr; + + ComPtr newSwapChain; + HRESULT result = factory->CreateSwapChainForCoreWindow(device, mCoreWindow.Get(), &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf()); + if (SUCCEEDED(result)) + { + +#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) // This block is disabled for Qt applications, as the resize events are expected + // Test if swapchain supports resize. On Windows Phone devices, this will return DXGI_ERROR_UNSUPPORTED. On + // other devices DXGI_ERROR_INVALID_CALL should be returned because the combination of flags passed + // (DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) are invalid flag combinations. + if (newSwapChain->ResizeBuffers(swapChainDesc.BufferCount, swapChainDesc.Width, swapChainDesc.Height, swapChainDesc.Format, DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) == DXGI_ERROR_UNSUPPORTED) + { + mSupportsSwapChainResize = false; + } +#endif // (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + + result = newSwapChain.CopyTo(swapChain); + } + + if (SUCCEEDED(result)) + { + // If automatic swapchain resize behaviors have been disabled, then + // unregister for the resize change events. + if (mSupportsSwapChainResize == false) + { + unregisterForSizeChangeEvents(); + } + } + + return result; +} + +// Basically, this shouldn't be used on Phone +HRESULT CoreWindowNativeWindow::onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *e) +{ + ABI::Windows::Foundation::Size size; + if (SUCCEEDED(e->get_Size(&size))) + { + SIZE windowSizeInPixels = { + std::floor(size.Width * mScaleFactor + 0.5), + std::floor(size.Height * mScaleFactor + 0.5) + }; + setNewClientSize(windowSizeInPixels); + } + + return S_OK; +} +} diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h new file mode 100644 index 00000000000..1c5512417d7 --- /dev/null +++ b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.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. +// + +// CoreWindowNativeWindow.h: NativeWindow for managing ICoreWindow native window types. + +#ifndef COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_ +#define COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_ + +#include "common/winrt/InspectableNativeWindow.h" +#include +#include + +namespace rx +{ + +class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this +{ + public: + ~CoreWindowNativeWindow(); + + bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet); + bool registerForSizeChangeEvents(); + void unregisterForSizeChangeEvents(); + HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain); + + private: + HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *); + + ComPtr mCoreWindow; + ComPtr mDisplayInformation; + ComPtr> mPropertyMap; +}; + +} + +#endif // COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp new file mode 100644 index 00000000000..0589f6dce5e --- /dev/null +++ b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp @@ -0,0 +1,274 @@ +// +// 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. +// + +// InspectableNativeWindow.cpp: NativeWindow base class for managing IInspectable native window types. + +#include "common/winrt/CoreWindowNativeWindow.h" +#include "common/winrt/SwapChainPanelNativeWindow.h" + +namespace rx +{ +NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display) + : mWindow(window), mDisplay(display) +{ +} + +bool NativeWindow::initialize() +{ + // If the native window type is a IPropertySet, extract the + // EGLNativeWindowType (IInspectable) and initialize the + // proper host with this IPropertySet. + ComPtr propertySet; + ComPtr eglNativeWindow; + if (IsEGLConfiguredPropertySet(mWindow, &propertySet, &eglNativeWindow)) + { + // A property set was found and the EGLNativeWindowType was + // retrieved. The mWindow member of the host to must be updated + // to use the EGLNativeWindowType specified in the property set. + // mWindow is treated as a raw pointer not an AddRef'd interface, so + // the old mWindow does not need a Release() before this assignment. + mWindow = eglNativeWindow.Get(); + } + + ComPtr coreWindow; + ComPtr swapChainPanel; + if (IsCoreWindow(mWindow, &coreWindow)) + { + mImpl = std::make_shared(); + if (mImpl) + { + return mImpl->initialize(mWindow, mDisplay, propertySet.Get()); + } + } + else if (IsSwapChainPanel(mWindow, &swapChainPanel)) + { + mImpl = std::make_shared(); + if (mImpl) + { + return mImpl->initialize(mWindow, mDisplay, propertySet.Get()); + } + } + else + { + ERR("Invalid IInspectable EGLNativeWindowType detected. Valid IInspectables include ICoreWindow, ISwapChainPanel and IPropertySet"); + } + + return false; +} + +bool NativeWindow::getClientRect(RECT *rect) +{ + if (mImpl) + { + return mImpl->getClientRect(rect); + } + + return false; +} + +bool NativeWindow::isIconic() +{ + return false; +} + +HRESULT NativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) +{ + if (mImpl) + { + return mImpl->createSwapChain(device, factory, format, width, height, swapChain); + } + + return E_UNEXPECTED; +} + +bool IsCoreWindow(EGLNativeWindowType window, ComPtr *coreWindow) +{ + if (!window) + { + return false; + } + + ComPtr win = window; + ComPtr coreWin; + if (SUCCEEDED(win.As(&coreWin))) + { + if (coreWindow != nullptr) + { + *coreWindow = coreWin.Detach(); + } + return true; + } + + return false; +} + +bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr *swapChainPanel) +{ + if (!window) + { + return false; + } + + ComPtr win = window; + ComPtr panel; + if (SUCCEEDED(win.As(&panel))) + { + if (swapChainPanel != nullptr) + { + *swapChainPanel = panel.Detach(); + } + return true; + } + + return false; +} + +bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet, IInspectable **eglNativeWindow) +{ + if (!window) + { + return false; + } + + ComPtr props = window; + ComPtr propSet; + ComPtr nativeWindow; + ComPtr> propMap; + boolean hasEglNativeWindowPropertyKey = false; + + HRESULT result = props.As(&propSet); + if (SUCCEEDED(result)) + { + result = propSet.As(&propMap); + } + + // Look for the presence of the EGLNativeWindowType in the property set + if (SUCCEEDED(result)) + { + result = propMap->HasKey(HStringReference(EGLNativeWindowTypeProperty).Get(), &hasEglNativeWindowPropertyKey); + } + + // If the IPropertySet does not contain the required EglNativeWindowType key, the property set is + // considered invalid. + if (SUCCEEDED(result) && !hasEglNativeWindowPropertyKey) + { + ERR("Could not find EGLNativeWindowTypeProperty in IPropertySet. Valid EGLNativeWindowTypeProperty values include ICoreWindow"); + return false; + } + + // The EglNativeWindowType property exists, so retreive the IInspectable that represents the EGLNativeWindowType + if (SUCCEEDED(result) && hasEglNativeWindowPropertyKey) + { + result = propMap->Lookup(HStringReference(EGLNativeWindowTypeProperty).Get(), &nativeWindow); + } + + if (SUCCEEDED(result)) + { + if (propertySet != nullptr) + { + result = propSet.CopyTo(propertySet); + } + } + + if (SUCCEEDED(result)) + { + if (eglNativeWindow != nullptr) + { + result = nativeWindow.CopyTo(eglNativeWindow); + } + } + + if (SUCCEEDED(result)) + { + return true; + } + + return false; +} + +// A Valid EGLNativeWindowType IInspectable can only be: +// +// ICoreWindow +// IPropertySet +// +// Anything else will be rejected as an invalid IInspectable. +bool IsValidEGLNativeWindowType(EGLNativeWindowType window) +{ + return IsCoreWindow(window) || IsSwapChainPanel(window) || IsEGLConfiguredPropertySet(window); +} + +// Attempts to read an optional SIZE property value that is assumed to be in the form of +// an ABI::Windows::Foundation::Size. This function validates the Size value before returning +// it to the caller. +// +// Possible return values are: +// S_OK, valueExists == true - optional SIZE value was successfully retrieved and validated +// S_OK, valueExists == false - optional SIZE value was not found +// E_INVALIDARG, valueExists = false - optional SIZE value was malformed in the property set. +// * Incorrect property type ( must be PropertyType_Size) +// * Invalid property value (width/height must be > 0) +// Additional errors may be returned from IMap or IPropertyValue +// +HRESULT GetOptionalSizePropertyValue(const ComPtr>& propertyMap, const wchar_t *propertyName, SIZE *value, bool *valueExists) +{ + if (!propertyMap || !propertyName || !value || !valueExists) + { + return false; + } + + // Assume that the value does not exist + *valueExists = false; + *value = { 0, 0 }; + + ComPtr propertyValue; + ABI::Windows::Foundation::PropertyType propertyType = ABI::Windows::Foundation::PropertyType::PropertyType_Empty; + Size sizeValue = { 0, 0 }; + boolean hasKey = false; + + HRESULT result = propertyMap->HasKey(HStringReference(propertyName).Get(), &hasKey); + if (SUCCEEDED(result) && !hasKey) + { + // Value does not exist, so return S_OK and set the exists parameter to false to indicate + // that a the optional property does not exist. + *valueExists = false; + return S_OK; + } + + if (SUCCEEDED(result)) + { + result = propertyMap->Lookup(HStringReference(propertyName).Get(), &propertyValue); + } + + if (SUCCEEDED(result)) + { + result = propertyValue->get_Type(&propertyType); + } + + // Check if the expected Size property is of PropertyType_Size type. + if (SUCCEEDED(result) && propertyType == ABI::Windows::Foundation::PropertyType::PropertyType_Size) + { + if (SUCCEEDED(propertyValue->GetSize(&sizeValue)) && (sizeValue.Width > 0 && sizeValue.Height > 0)) + { + // A valid property value exists + *value = { static_cast(sizeValue.Width), static_cast(sizeValue.Height) }; + *valueExists = true; + result = S_OK; + } + else + { + // An invalid Size property was detected. Width/Height values must > 0 + result = E_INVALIDARG; + } + } + else + { + // An invalid property type was detected. Size property must be of PropertyType_Size + result = E_INVALIDARG; + } + + return result; +} +} diff --git a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h new file mode 100644 index 00000000000..402941a7882 --- /dev/null +++ b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h @@ -0,0 +1,91 @@ +// +// 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. +// + +// InspectableNativeWindow.h: Host specific implementation interface for +// managing IInspectable native window types. + +#ifndef COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_ +#define COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_ + +#include "common/platform.h" +#include "common/NativeWindow.h" +#include "angle_windowsstore.h" + +#include +#include + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; + +namespace rx +{ +class InspectableNativeWindow +{ + public: + InspectableNativeWindow() : + mSupportsSwapChainResize(true), + mRequiresSwapChainScaling(false), + mClientRectChanged(false), + mClientRect({0,0,0,0}), + mNewClientRect({0,0,0,0}), + mScaleFactor(1.0) + { + mSizeChangedEventToken.value = 0; + } + virtual ~InspectableNativeWindow(){} + + virtual bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) = 0; + virtual HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) = 0; + virtual bool registerForSizeChangeEvents() = 0; + virtual void unregisterForSizeChangeEvents() = 0; + virtual HRESULT scaleSwapChain(const SIZE& newSize) { return S_OK; } + + bool getClientRect(RECT *rect) + { + if (mClientRectChanged && mSupportsSwapChainResize) + { + mClientRect = mNewClientRect; + mClientRectChanged = false; + } + + *rect = mClientRect; + + return true; + } + + void setNewClientSize(const SIZE &newSize) + { + if (mSupportsSwapChainResize && !mRequiresSwapChainScaling) + { + mNewClientRect = { 0, 0, newSize.cx, newSize.cy }; + mClientRectChanged = true; + } + + if (mRequiresSwapChainScaling) + { + scaleSwapChain(newSize); + } + } + +protected: + bool mSupportsSwapChainResize; + bool mRequiresSwapChainScaling; + RECT mClientRect; + RECT mNewClientRect; + bool mClientRectChanged; + DOUBLE mScaleFactor; + + EventRegistrationToken mSizeChangedEventToken; +}; + +bool IsCoreWindow(EGLNativeWindowType window, ComPtr *coreWindow = nullptr); +bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr *swapChainPanel = nullptr); +bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet = nullptr, IInspectable **inspectable = nullptr); +HRESULT GetOptionalSizePropertyValue(const ComPtr>& propertyMap, const wchar_t *propertyName, SIZE *value, bool *valueExists); +} +#endif // COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp new file mode 100644 index 00000000000..268dfbd8f08 --- /dev/null +++ b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp @@ -0,0 +1,226 @@ +// +// 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. +// + +// SwapChainPanelNativeWindow.cpp: NativeWindow for managing ISwapChainPanel native window types. + +#include "common/winrt/SwapChainPanelNativeWindow.h" +#include +#include +using namespace ABI::Windows::Foundation::Collections; + +namespace rx +{ +SwapChainPanelNativeWindow::~SwapChainPanelNativeWindow() +{ + unregisterForSizeChangeEvents(); +} + +bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) +{ + ComPtr props = propertySet; + ComPtr win = window; + SIZE swapChainSize = {}; + bool swapChainSizeSpecified = false; + HRESULT result = S_OK; + + // IPropertySet is an optional parameter and can be null. + // If one is specified, cache as an IMap and read the properties + // used for initial host initialization. + if (propertySet) + { + result = props.As(&mPropertyMap); + if (SUCCEEDED(result)) + { + // The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet + // was prevalidated to contain the EGLNativeWindowType before being passed to + // this host. + result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &swapChainSizeSpecified); + } + } + + if (SUCCEEDED(result)) + { + result = win.As(&mSwapChainPanel); + } + + if (SUCCEEDED(result)) + { + // If a swapchain size is specfied, then the automatic resize + // behaviors implemented by the host should be disabled. The swapchain + // will be still be scaled when being rendered to fit the bounds + // of the host. + // Scaling of the swapchain output needs to be handled by the + // host for swapchain panels even though the scaling mode setting + // DXGI_SCALING_STRETCH is configured on the swapchain. + if (swapChainSizeSpecified) + { + mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy }; + + // Enable host swapchain scaling + mRequiresSwapChainScaling = true; + } + else + { + result = GetSwapChainPanelSize(mSwapChainPanel, &mClientRect); + } + } + + if (SUCCEEDED(result)) + { + mNewClientRect = mClientRect; + mClientRectChanged = false; + return registerForSizeChangeEvents(); + } + + return false; +} + +bool SwapChainPanelNativeWindow::registerForSizeChangeEvents() +{ + ComPtr sizeChangedHandler; + ComPtr frameworkElement; + HRESULT result = Microsoft::WRL::MakeAndInitialize(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this()); + + if (SUCCEEDED(result)) + { + result = mSwapChainPanel.As(&frameworkElement); + } + + if (SUCCEEDED(result)) + { + result = frameworkElement->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken); + } + + if (SUCCEEDED(result)) + { + return true; + } + + return false; +} + +void SwapChainPanelNativeWindow::unregisterForSizeChangeEvents() +{ + ComPtr frameworkElement; + if (SUCCEEDED(mSwapChainPanel.As(&frameworkElement))) + { + (void)frameworkElement->remove_SizeChanged(mSizeChangedEventToken); + } + + mSizeChangedEventToken.value = 0; +} + +HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) +{ + if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) + { + return E_INVALIDARG; + } + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 }; + swapChainDesc.Width = width; + swapChainDesc.Height = height; + swapChainDesc.Format = format; + swapChainDesc.Stereo = FALSE; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.BufferCount = 2; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + + *swapChain = nullptr; + + ComPtr newSwapChain; + ComPtr swapChainPanelNative; + RECT currentPanelSize = {}; + + HRESULT result = factory->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf()); + + if (SUCCEEDED(result)) + { + result = mSwapChainPanel.As(&swapChainPanelNative); + } + + if (SUCCEEDED(result)) + { + result = swapChainPanelNative->SetSwapChain(newSwapChain.Get()); + } + + if (SUCCEEDED(result)) + { + // The swapchain panel host requires an instance of the swapchain set on the SwapChainPanel + // to perform the runtime-scale behavior. This swapchain is cached here because there are + // no methods for retreiving the currently configured on from ISwapChainPanelNative. + mSwapChain = newSwapChain; + result = newSwapChain.CopyTo(swapChain); + } + + // If the host is responsible for scaling the output of the swapchain, then + // scale it now before returning an instance to the caller. This is done by + // first reading the current size of the swapchain panel, then scaling + if (SUCCEEDED(result) && mRequiresSwapChainScaling) + { + result = GetSwapChainPanelSize(mSwapChainPanel, ¤tPanelSize); + } + + // Scale the swapchain to fit inside the contents of the panel. + if (SUCCEEDED(result) && mRequiresSwapChainScaling) + { + SIZE currentSize = { currentPanelSize.right, currentPanelSize.bottom }; + result = scaleSwapChain(currentSize); + } + + if (SUCCEEDED(result)) + { + // If automatic swapchain resize behaviors have been disabled, then + // unregister for the resize change events. + if (mSupportsSwapChainResize == false) + { + unregisterForSizeChangeEvents(); + } + } + + return result; +} + +HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const SIZE &newSize) +{ + ABI::Windows::Foundation::Size renderScale = { (float)newSize.cx/(float)mClientRect.right, (float)newSize.cy/(float)mClientRect.bottom }; + // Setup a scale matrix for the swap chain + DXGI_MATRIX_3X2_F scaleMatrix = {}; + scaleMatrix._11 = renderScale.Width; + scaleMatrix._22 = renderScale.Height; + + ComPtr swapChain2; + HRESULT result = mSwapChain.As(&swapChain2); + if (SUCCEEDED(result)) + { + result = swapChain2->SetMatrixTransform(&scaleMatrix); + } + + return result; +} + +HRESULT GetSwapChainPanelSize(const ComPtr &swapChainPanel, RECT *windowSize) +{ + ComPtr uiElement; + ABI::Windows::Foundation::Size renderSize = { 0, 0 }; + HRESULT result = swapChainPanel.As(&uiElement); + if (SUCCEEDED(result)) + { + result = uiElement->get_RenderSize(&renderSize); + } + + if (SUCCEEDED(result)) + { + *windowSize = { 0, 0, lround(renderSize.Width), lround(renderSize.Height) }; + } + + return result; +} +} diff --git a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h new file mode 100644 index 00000000000..5bbf274e647 --- /dev/null +++ b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h @@ -0,0 +1,79 @@ +// +// 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. +// + +// SwapChainPanelNativeWindow.h: NativeWindow for managing ISwapChainPanel native window types. + +#ifndef COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ +#define COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ + +#include "common/winrt/InspectableNativeWindow.h" + +namespace rx +{ +class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this +{ + public: + ~SwapChainPanelNativeWindow(); + + bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet); + bool registerForSizeChangeEvents(); + void unregisterForSizeChangeEvents(); + HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain); + HRESULT scaleSwapChain(const SIZE &newSize); + + private: + ComPtr mSwapChainPanel; + ComPtr> mPropertyMap; + ComPtr mSwapChain; +}; + +[uuid(8ACBD974-8187-4508-AD80-AEC77F93CF36)] +class SwapChainPanelSizeChangedHandler : + public Microsoft::WRL::RuntimeClass, ABI::Windows::UI::Xaml::ISizeChangedEventHandler> +{ + public: + SwapChainPanelSizeChangedHandler() { } + HRESULT RuntimeClassInitialize(std::shared_ptr host) + { + if (!host) + { + return E_INVALIDARG; + } + + mHost = host; + return S_OK; + } + + // ISizeChangedEventHandler + IFACEMETHOD(Invoke)(IInspectable *sender, ABI::Windows::UI::Xaml::ISizeChangedEventArgs *sizeChangedEventArgs) + { + std::shared_ptr host = mHost.lock(); + if (host) + { + // The size of the ISwapChainPanel control is returned in DIPs. + // We are keeping these in dips because the swapchain created for composition + // also uses dip units. This keeps dimensions, viewports, etc in the same unit. + // XAML Clients of the ISwapChainPanel are required to use dips to define their + // layout sizes as well. + ABI::Windows::Foundation::Size newSize; + HRESULT result = sizeChangedEventArgs->get_NewSize(&newSize); + if (SUCCEEDED(result)) + { + SIZE windowSize = { lround(newSize.Width), lround(newSize.Height) }; + host->setNewClientSize(windowSize); + } + } + + return S_OK; + } + + private: + std::weak_ptr mHost; +}; + +HRESULT GetSwapChainPanelSize(const ComPtr &swapChainPanel, RECT *windowSize); +} +#endif // COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h index 040b25c6a24..eec0d5e5f05 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h @@ -29,7 +29,8 @@ class DirectiveHandler // Handle pragma of form: #pragma name[(value)] virtual void handlePragma(const SourceLocation &loc, const std::string &name, - const std::string &value) = 0; + const std::string &value, + bool stdgl) = 0; virtual void handleExtension(const SourceLocation &loc, const std::string &name, diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp index 6434d5cb5c8..7803ee845ab 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp +++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp @@ -38,19 +38,19 @@ enum DirectiveType DirectiveType getDirective(const pp::Token *token) { - static const std::string kDirectiveDefine("define"); - static const std::string kDirectiveUndef("undef"); - static const std::string kDirectiveIf("if"); - static const std::string kDirectiveIfdef("ifdef"); - static const std::string kDirectiveIfndef("ifndef"); - static const std::string kDirectiveElse("else"); - static const std::string kDirectiveElif("elif"); - static const std::string kDirectiveEndif("endif"); - static const std::string kDirectiveError("error"); - static const std::string kDirectivePragma("pragma"); - static const std::string kDirectiveExtension("extension"); - static const std::string kDirectiveVersion("version"); - static const std::string kDirectiveLine("line"); + const char kDirectiveDefine[] = "define"; + const char kDirectiveUndef[] = "undef"; + const char kDirectiveIf[] = "if"; + const char kDirectiveIfdef[] = "ifdef"; + const char kDirectiveIfndef[] = "ifndef"; + const char kDirectiveElse[] = "else"; + const char kDirectiveElif[] = "elif"; + const char kDirectiveEndif[] = "endif"; + const char kDirectiveError[] = "error"; + const char kDirectivePragma[] = "pragma"; + const char kDirectiveExtension[] = "extension"; + const char kDirectiveVersion[] = "version"; + const char kDirectiveLine[] = "line"; if (token->type != pp::Token::IDENTIFIER) return DIRECTIVE_NONE; @@ -155,7 +155,7 @@ class DefinedParser : public Lexer protected: virtual void lex(Token *token) { - static const std::string kDefined("defined"); + const char kDefined[] = "defined"; mLexer->lex(token); if (token->type != Token::IDENTIFIER) @@ -592,6 +592,11 @@ void DirectiveParser::parsePragma(Token *token) int state = PRAGMA_NAME; mTokenizer->lex(token); + bool stdgl = token->text == "STDGL"; + if (stdgl) + { + mTokenizer->lex(token); + } while ((token->type != '\n') && (token->type != Token::LAST)) { switch(state++) @@ -627,7 +632,7 @@ void DirectiveParser::parsePragma(Token *token) } else if (state > PRAGMA_NAME) // Do not notify for empty pragma. { - mDirectiveHandler->handlePragma(token->location, name, value); + mDirectiveHandler->handlePragma(token->location, name, value, stdgl); } } diff --git a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp index d7e0c834657..69e2f390693 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp +++ b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp @@ -194,8 +194,8 @@ bool MacroExpander::expandMacro(const Macro ¯o, if (macro.predefined) { - static const std::string kLine = "__LINE__"; - static const std::string kFile = "__FILE__"; + const char kLine[] = "__LINE__"; + const char kFile[] = "__FILE__"; assert(replacements->size() == 1); Token& repl = replacements->front(); diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp index 368cd2ae4ad..5c62a64d10b 100644 --- a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp @@ -29,24 +29,27 @@ bool IsWebGLBasedSpec(ShShaderSpec spec) { - return spec == SH_WEBGL_SPEC || spec == SH_CSS_SHADERS_SPEC; + return (spec == SH_WEBGL_SPEC || + spec == SH_CSS_SHADERS_SPEC || + spec == SH_WEBGL2_SPEC); } size_t GetGlobalMaxTokenSize(ShShaderSpec spec) { // WebGL defines a max token legnth of 256, while ES2 leaves max token // size undefined. ES3 defines a max size of 1024 characters. - if (IsWebGLBasedSpec(spec)) + switch (spec) { + case SH_WEBGL_SPEC: + case SH_CSS_SHADERS_SPEC: return 256; - } - else - { + default: return 1024; } } namespace { + class TScopedPoolAllocator { public: @@ -82,6 +85,24 @@ class TScopedSymbolTableLevel private: TSymbolTable* mTable; }; + +int MapSpecToShaderVersion(ShShaderSpec spec) +{ + switch (spec) + { + case SH_GLES2_SPEC: + case SH_WEBGL_SPEC: + case SH_CSS_SHADERS_SPEC: + return 100; + case SH_GLES3_SPEC: + case SH_WEBGL2_SPEC: + return 300; + default: + UNREACHABLE(); + return 0; + } +} + } // namespace TShHandleBase::TShHandleBase() @@ -178,9 +199,21 @@ bool TCompiler::compile(const char* const shaderStrings[], (parseContext.treeRoot != NULL); shaderVersion = parseContext.getShaderVersion(); + if (success && MapSpecToShaderVersion(shaderSpec) < shaderVersion) + { + infoSink.info.prefix(EPrefixError); + infoSink.info << "unsupported shader version"; + success = false; + } if (success) { + mPragma = parseContext.pragma(); + if (mPragma.stdgl.invariantAll) + { + symbolTable.setGlobalInvariant(); + } + TIntermNode* root = parseContext.treeRoot; success = intermediate.postProcess(root); @@ -360,7 +393,8 @@ void TCompiler::setResourceString() << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset - << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset; + << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset + << ":NV_draw_buffers:" << compileResources.NV_draw_buffers; builtInResourcesString = strstream.str(); } @@ -377,7 +411,6 @@ void TCompiler::clearResults() uniforms.clear(); expandedUniforms.clear(); varyings.clear(); - expandedVaryings.clear(); interfaceBlocks.clear(); builtInFunctionEmulator.Cleanup(); @@ -507,13 +540,12 @@ void TCompiler::collectVariables(TIntermNode* root) &uniforms, &varyings, &interfaceBlocks, - hashFunction); + hashFunction, + symbolTable); root->traverse(&collect); - // For backwards compatiblity with ShGetVariableInfo, expand struct - // uniforms and varyings into separate variables for each field. - sh::ExpandVariables(uniforms, &expandedUniforms); - sh::ExpandVariables(varyings, &expandedVaryings); + // This is for enforcePackingRestriction(). + sh::ExpandUniforms(uniforms, &expandedUniforms); } bool TCompiler::enforcePackingRestrictions() @@ -581,3 +613,10 @@ const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const { return builtInFunctionEmulator; } + +void TCompiler::writePragma() +{ + TInfoSinkBase &sink = infoSink.obj; + if (mPragma.stdgl.invariantAll) + sink << "#pragma STDGL invariant(all)\n"; +} diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.h b/src/3rdparty/angle/src/compiler/translator/Compiler.h index ca0c157884f..b6c9d13ed06 100644 --- a/src/3rdparty/angle/src/compiler/translator/Compiler.h +++ b/src/3rdparty/angle/src/compiler/translator/Compiler.h @@ -18,6 +18,7 @@ #include "compiler/translator/ExtensionBehavior.h" #include "compiler/translator/HashNames.h" #include "compiler/translator/InfoSink.h" +#include "compiler/translator/Pragma.h" #include "compiler/translator/SymbolTable.h" #include "compiler/translator/VariableInfo.h" #include "third_party/compiler/ArrayBoundsClamper.h" @@ -71,9 +72,7 @@ class TCompiler : public TShHandleBase const std::vector &getAttributes() const { return attributes; } const std::vector &getOutputVariables() const { return outputVariables; } const std::vector &getUniforms() const { return uniforms; } - const std::vector &getExpandedUniforms() const { return expandedUniforms; } const std::vector &getVaryings() const { return varyings; } - const std::vector &getExpandedVaryings() const { return expandedVaryings; } const std::vector &getInterfaceBlocks() const { return interfaceBlocks; } ShHashFunction64 getHashFunction() const { return hashFunction; } @@ -81,7 +80,7 @@ class TCompiler : public TShHandleBase TSymbolTable& getSymbolTable() { return symbolTable; } ShShaderSpec getShaderSpec() const { return shaderSpec; } ShShaderOutput getOutputType() const { return outputType; } - std::string getBuiltInResourcesString() const { return builtInResourcesString; } + const std::string &getBuiltInResourcesString() const { return builtInResourcesString; } // Get the resources set by InitBuiltInSymbolTable const ShBuiltInResources& getResources() const; @@ -131,6 +130,8 @@ class TCompiler : public TShHandleBase bool limitExpressionComplexity(TIntermNode* root); // Get built-in extensions with default behavior. const TExtensionBehavior& getExtensionBehavior() const; + const TPragma& getPragma() const { return mPragma; } + void writePragma(); const ArrayBoundsClamper& getArrayBoundsClamper() const; ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const; @@ -141,7 +142,6 @@ class TCompiler : public TShHandleBase std::vector uniforms; std::vector expandedUniforms; std::vector varyings; - std::vector expandedVaryings; std::vector interfaceBlocks; private: @@ -174,6 +174,8 @@ class TCompiler : public TShHandleBase // name hashing. ShHashFunction64 hashFunction; NameMap nameMap; + + TPragma mPragma; }; // diff --git a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp index 334eb0bfa8b..f98d32b2b7b 100644 --- a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp +++ b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp @@ -14,6 +14,9 @@ namespace sh { + +// Detect Loop Discontinuity + bool DetectLoopDiscontinuity::traverse(TIntermNode *node) { mLoopDepth = 0; @@ -74,6 +77,55 @@ bool containsLoopDiscontinuity(TIntermNode *node) return detectLoopDiscontinuity.traverse(node); } +// Detect Any Loop + +bool DetectAnyLoop::traverse(TIntermNode *node) +{ + mHasLoop = false; + node->traverse(this); + return mHasLoop; +} + +bool DetectAnyLoop::visitLoop(Visit visit, TIntermLoop *loop) +{ + mHasLoop = true; + return false; +} + +// The following definitions stop all traversal when we have found a loop +bool DetectAnyLoop::visitBinary(Visit, TIntermBinary *) +{ + return !mHasLoop; +} + +bool DetectAnyLoop::visitUnary(Visit, TIntermUnary *) +{ + return !mHasLoop; +} + +bool DetectAnyLoop::visitSelection(Visit, TIntermSelection *) +{ + return !mHasLoop; +} + +bool DetectAnyLoop::visitAggregate(Visit, TIntermAggregate *) +{ + return !mHasLoop; +} + +bool DetectAnyLoop::visitBranch(Visit, TIntermBranch *) +{ + return !mHasLoop; +} + +bool containsAnyLoop(TIntermNode *node) +{ + DetectAnyLoop detectAnyLoop; + return detectAnyLoop.traverse(node); +} + +// Detect Gradient Operation + bool DetectGradientOperation::traverse(TIntermNode *node) { mGradientOperation = false; diff --git a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h index 35d66cbc2e5..67e37be3981 100644 --- a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h +++ b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h @@ -32,6 +32,25 @@ class DetectLoopDiscontinuity : public TIntermTraverser bool containsLoopDiscontinuity(TIntermNode *node); +// Checks for the existence of any loop +class DetectAnyLoop : public TIntermTraverser +{ +public: + bool traverse(TIntermNode *node); + +protected: + bool visitBinary(Visit, TIntermBinary *); + bool visitUnary(Visit, TIntermUnary *); + bool visitSelection(Visit, TIntermSelection *); + bool visitAggregate(Visit, TIntermAggregate *); + bool visitLoop(Visit, TIntermLoop *); + bool visitBranch(Visit, TIntermBranch *); + + bool mHasLoop; +}; + +bool containsAnyLoop(TIntermNode *node); + // Checks for intrinsic functions which compute gradients class DetectGradientOperation : public TIntermTraverser { diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp index 59d2835f7b7..f67a03aa932 100644 --- a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp +++ b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp @@ -13,10 +13,10 @@ static TBehavior getBehavior(const std::string& str) { - static const std::string kRequire("require"); - static const std::string kEnable("enable"); - static const std::string kDisable("disable"); - static const std::string kWarn("warn"); + const char kRequire[] = "require"; + const char kEnable[] = "enable"; + const char kDisable[] = "disable"; + const char kWarn[] = "warn"; if (str == kRequire) return EBhRequire; else if (str == kEnable) return EBhEnable; @@ -46,50 +46,61 @@ void TDirectiveHandler::handleError(const pp::SourceLocation& loc, void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc, const std::string& name, - const std::string& value) + const std::string& value, + bool stdgl) { - static const std::string kSTDGL("STDGL"); - static const std::string kOptimize("optimize"); - static const std::string kDebug("debug"); - static const std::string kOn("on"); - static const std::string kOff("off"); + if (stdgl) + { + const char kInvariant[] = "invariant"; + const char kAll[] = "all"; - bool invalidValue = false; - if (name == kSTDGL) - { + if (name == kInvariant && value == kAll) + mPragma.stdgl.invariantAll = true; // The STDGL pragma is used to reserve pragmas for use by future - // revisions of GLSL. Ignore it. + // revisions of GLSL. Do not generate an error on unexpected + // name and value. return; } - else if (name == kOptimize) - { - if (value == kOn) mPragma.optimize = true; - else if (value == kOff) mPragma.optimize = false; - else invalidValue = true; - } - else if (name == kDebug) - { - if (value == kOn) mPragma.debug = true; - else if (value == kOff) mPragma.debug = false; - else invalidValue = true; - } else { - mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name); - return; - } + const char kOptimize[] = "optimize"; + const char kDebug[] = "debug"; + const char kOn[] = "on"; + const char kOff[] = "off"; - if (invalidValue) - mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, - "invalid pragma value", value, - "'on' or 'off' expected"); + bool invalidValue = false; + if (name == kOptimize) + { + if (value == kOn) mPragma.optimize = true; + else if (value == kOff) mPragma.optimize = false; + else invalidValue = true; + } + else if (name == kDebug) + { + if (value == kOn) mPragma.debug = true; + else if (value == kOff) mPragma.debug = false; + else invalidValue = true; + } + else + { + mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name); + return; + } + + if (invalidValue) + { + mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, + "invalid pragma value", value, + "'on' or 'off' expected"); + } + } } void TDirectiveHandler::handleExtension(const pp::SourceLocation& loc, const std::string& name, const std::string& behavior) { - static const std::string kExtAll("all"); + const char kExtAll[] = "all"; TBehavior behaviorVal = getBehavior(behavior); if (behaviorVal == EBhUndefined) diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h index 69418c277af..0433c3bf898 100644 --- a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h +++ b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h @@ -29,7 +29,8 @@ class TDirectiveHandler : public pp::DirectiveHandler virtual void handlePragma(const pp::SourceLocation& loc, const std::string& name, - const std::string& value); + const std::string& value, + bool stdgl); virtual void handleExtension(const pp::SourceLocation& loc, const std::string& name, diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp index b155545ad2b..aa0f31d1708 100644 --- a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp +++ b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp @@ -133,6 +133,14 @@ bool CompareStructure(const TType &leftNodeType, // //////////////////////////////////////////////////////////////// +void TIntermTyped::setTypePreservePrecision(const TType &t) +{ + TPrecision precision = getPrecision(); + mType = t; + ASSERT(mType.getBasicType() != EbtBool || precision == EbpUndefined); + mType.setPrecision(precision); +} + #define REPLACE_IF_IS(node, type, original, replacement) \ if (node == original) { \ node = static_cast(replacement); \ @@ -237,6 +245,52 @@ void TIntermAggregate::enqueueChildren(std::queue *nodeQueue) con } } +void TIntermAggregate::setPrecisionFromChildren() +{ + if (getBasicType() == EbtBool) + { + mType.setPrecision(EbpUndefined); + return; + } + + TPrecision precision = EbpUndefined; + TIntermSequence::iterator childIter = mSequence.begin(); + while (childIter != mSequence.end()) + { + TIntermTyped *typed = (*childIter)->getAsTyped(); + if (typed) + precision = GetHigherPrecision(typed->getPrecision(), precision); + ++childIter; + } + mType.setPrecision(precision); +} + +void TIntermAggregate::setBuiltInFunctionPrecision() +{ + // All built-ins returning bool should be handled as ops, not functions. + ASSERT(getBasicType() != EbtBool); + + TPrecision precision = EbpUndefined; + TIntermSequence::iterator childIter = mSequence.begin(); + while (childIter != mSequence.end()) + { + TIntermTyped *typed = (*childIter)->getAsTyped(); + // ESSL spec section 8: texture functions get their precision from the sampler. + if (typed && IsSampler(typed->getBasicType())) + { + precision = typed->getPrecision(); + break; + } + ++childIter; + } + // ESSL 3.0 spec section 8: textureSize always gets highp precision. + // All other functions that take a sampler are assumed to be texture functions. + if (mName.find("textureSize") == 0) + mType.setPrecision(EbpHigh); + else + mType.setPrecision(precision); +} + bool TIntermSelection::replaceChildNode( TIntermNode *original, TIntermNode *replacement) { @@ -336,6 +390,7 @@ bool TIntermUnary::promote(TInfoSink &) return false; break; case EOpNegative: + case EOpPositive: case EOpPostIncrement: case EOpPostDecrement: case EOpPreIncrement: @@ -1068,6 +1123,27 @@ TIntermTyped *TIntermConstantUnion::fold( } break; + case EOpPositive: + switch (getType().getBasicType()) + { + case EbtFloat: + tempConstArray[i].setFConst(unionArray[i].getFConst()); + break; + case EbtInt: + tempConstArray[i].setIConst(unionArray[i].getIConst()); + break; + case EbtUInt: + tempConstArray[i].setUConst(static_cast( + static_cast(unionArray[i].getUConst()))); + break; + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return NULL; + } + break; + case EOpLogicalNot: // this code is written for possible future use, // will not get executed currently diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.h b/src/3rdparty/angle/src/compiler/translator/IntermNode.h index ec440da0109..32c70f4671b 100644 --- a/src/3rdparty/angle/src/compiler/translator/IntermNode.h +++ b/src/3rdparty/angle/src/compiler/translator/IntermNode.h @@ -45,6 +45,7 @@ enum TOperator // EOpNegative, + EOpPositive, EOpLogicalNot, EOpVectorLogicalNot, @@ -265,6 +266,7 @@ class TIntermTyped : public TIntermNode virtual bool hasSideEffects() const = 0; void setType(const TType &t) { mType = t; } + void setTypePreservePrecision(const TType &t); const TType &getType() const { return mType; } TType *getTypePointer() { return &mType; } @@ -613,6 +615,9 @@ class TIntermAggregate : public TIntermOperator virtual void enqueueChildren(std::queue *nodeQueue) const; + void setPrecisionFromChildren(); + void setBuiltInFunctionPrecision(); + protected: TIntermAggregate(const TIntermAggregate &); // disallow copy constructor TIntermAggregate &operator=(const TIntermAggregate &); // disallow assignment operator diff --git a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp index ef4f83307cd..e558683c559 100644 --- a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp @@ -198,6 +198,7 @@ TIntermTyped *TIntermediate::addUnaryMath( case EOpPostDecrement: case EOpPreDecrement: case EOpNegative: + case EOpPositive: if (child->getType().getBasicType() == EbtStruct || child->getType().isArray()) { diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp index 6d07cccc04f..ed590967b12 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp @@ -395,6 +395,7 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node) switch (node->getOp()) { case EOpNegative: preString = "(-"; break; + case EOpPositive: preString = "(+"; break; case EOpVectorLogicalNot: preString = "not("; break; case EOpLogicalNot: preString = "(!"; break; @@ -574,7 +575,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) // Function declaration. ASSERT(visit == PreVisit); writeVariableType(node->getType()); - out << " " << hashName(node->getName()); + out << " " << hashFunctionName(node->getName()); out << "("; writeFunctionParameters(*(node->getSequence())); @@ -649,17 +650,18 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) mDeclaringVariables = false; } break; - case EOpInvariantDeclaration: { - // Invariant declaration. - ASSERT(visit == PreVisit); + case EOpInvariantDeclaration: + // Invariant declaration. + ASSERT(visit == PreVisit); + { const TIntermSequence *sequence = node->getSequence(); ASSERT(sequence && sequence->size() == 1); const TIntermSymbol *symbol = sequence->front()->getAsSymbolNode(); ASSERT(symbol); - out << "invariant " << symbol->getSymbol() << ";"; - visitChildren = false; - break; + out << "invariant " << hashVariableName(symbol->getSymbol()); } + visitChildren = false; + break; case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break; @@ -741,7 +743,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) writeBuiltInFunctionTriplet(visit, "notEqual(", useEmulatedFunction); break; case EOpComma: - writeTriplet(visit, NULL, ", ", NULL); + writeTriplet(visit, "(", ", ", ")"); break; case EOpMod: diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp index a5ea71599d2..30bbbff0f5f 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp @@ -135,6 +135,7 @@ OutputHLSL::OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator) mUniqueIndex = 0; mContainsLoopDiscontinuity = false; + mContainsAnyLoop = false; mOutputLod0Function = false; mInsideDiscontinuousLoop = false; mNestedLoopDepth = 0; @@ -172,6 +173,7 @@ OutputHLSL::~OutputHLSL() void OutputHLSL::output() { mContainsLoopDiscontinuity = mContext.shaderType == GL_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot); + mContainsAnyLoop = containsAnyLoop(mContext.treeRoot); const std::vector &flaggedStructs = FlagStd140ValueStructs(mContext.treeRoot); makeFlaggedStructMaps(flaggedStructs); @@ -320,14 +322,22 @@ void OutputHLSL::header() if (mUsesDiscardRewriting) { - out << "#define ANGLE_USES_DISCARD_REWRITING" << "\n"; + out << "#define ANGLE_USES_DISCARD_REWRITING\n"; } if (mUsesNestedBreak) { - out << "#define ANGLE_USES_NESTED_BREAK" << "\n"; + out << "#define ANGLE_USES_NESTED_BREAK\n"; } + out << "#ifdef ANGLE_ENABLE_LOOP_FLATTEN\n" + "#define LOOP [loop]\n" + "#define FLATTEN [flatten]\n" + "#else\n" + "#define LOOP\n" + "#define FLATTEN\n" + "#endif\n"; + if (mContext.shaderType == GL_FRAGMENT_SHADER) { TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers"); @@ -1747,6 +1757,7 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) switch (node->getOp()) { case EOpNegative: outputTriplet(visit, "(-", "", ")"); break; + case EOpPositive: outputTriplet(visit, "(+", "", ")"); break; case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")"); break; case EOpLogicalNot: outputTriplet(visit, "(!", "", ")"); break; case EOpPostIncrement: outputTriplet(visit, "(", "", "++)"); break; @@ -1860,15 +1871,20 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration { - if (!mInsideFunction) - { - out << "static "; - } - - out << TypeString(variable->getType()) + " "; - for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++) { + if (isSingleStatement(*sit)) + { + mUnfoldShortCircuit->traverse(*sit); + } + + if (!mInsideFunction) + { + out << "static "; + } + + out << TypeString(variable->getType()) + " "; + TIntermSymbol *symbol = (*sit)->getAsSymbolNode(); if (symbol) @@ -1884,7 +1900,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) if (*sit != sequence->back()) { - out << ", "; + out << ";\n"; } } } @@ -1925,7 +1941,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) case EOpPrototype: if (visit == PreVisit) { - out << TypeString(node->getType()) << " " << Decorate(node->getName()) << (mOutputLod0Function ? "Lod0(" : "("); + out << TypeString(node->getType()) << " " << Decorate(TFunction::unmangleName(node->getName())) << (mOutputLod0Function ? "Lod0(" : "("); TIntermSequence *arguments = node->getSequence(); @@ -2287,6 +2303,15 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) { mUnfoldShortCircuit->traverse(node->getCondition()); + // D3D errors when there is a gradient operation in a loop in an unflattened if + // however flattening all the ifs in branch heavy shaders made D3D error too. + // As a temporary workaround we flatten the ifs only if there is at least a loop + // present somewhere in the shader. + if (mContext.shaderType == GL_FRAGMENT_SHADER && mContainsAnyLoop) + { + out << "FLATTEN "; + } + out << "if ("; node->getCondition()->traverse(this); @@ -2367,14 +2392,14 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) if (node->getType() == ELoopDoWhile) { - out << "{do\n"; + out << "{LOOP do\n"; outputLineDirective(node->getLine().first_line); out << "{\n"; } else { - out << "{for("; + out << "{LOOP for("; if (node->getInit()) { @@ -2503,6 +2528,12 @@ bool OutputHLSL::isSingleStatement(TIntermNode *node) { return false; } + else if (aggregate->getOp() == EOpDeclaration) + { + // Declaring multiple comma-separated variables must be considered multiple statements + // because each individual declaration has side effects which are visible in the next. + return false; + } else { for (TIntermSequence::iterator sit = aggregate->getSequence()->begin(); sit != aggregate->getSequence()->end(); sit++) @@ -2675,7 +2706,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) // for(int index = initial; index < clampedLimit; index += increment) - out << "for("; + out << "LOOP for("; index->traverse(this); out << " = "; out << initial; diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h index bec02479bbc..5525e6eaa62 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h @@ -144,6 +144,7 @@ class OutputHLSL : public TIntermTraverser int mUniqueIndex; // For creating unique names bool mContainsLoopDiscontinuity; + bool mContainsAnyLoop; bool mOutputLod0Function; bool mInsideDiscontinuousLoop; int mNestedLoopDepth; diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp index ff0a49667c8..37969b54684 100644 --- a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp @@ -1004,12 +1004,12 @@ void TParseContext::handleExtensionDirective(const TSourceLoc& loc, const char* directiveHandler.handleExtension(srcLoc, extName, behavior); } -void TParseContext::handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value) +void TParseContext::handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value, bool stdgl) { pp::SourceLocation srcLoc; srcLoc.file = loc.first_file; srcLoc.line = loc.first_line; - directiveHandler.handlePragma(srcLoc, name, value); + directiveHandler.handlePragma(srcLoc, name, value, stdgl); } ///////////////////////////////////////////////////////////////////////////////// @@ -1364,11 +1364,18 @@ TIntermAggregate* TParseContext::parseInvariantDeclaration(const TSourceLoc &inv { error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str()); recover(); - return NULL; } else { + const TString kGlFrontFacing("gl_FrontFacing"); + if (*identifier == kGlFrontFacing) + { + error(identifierLoc, "identifier should not be declared as invariant", identifier->c_str()); + recover(); + return NULL; + } + symbolTable.addInvariantVarying(*identifier); const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol); ASSERT(variable); const TType &type = variable->getType(); diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.h b/src/3rdparty/angle/src/compiler/translator/ParseContext.h index 1f4cbdeba95..414c475cbbd 100644 --- a/src/3rdparty/angle/src/compiler/translator/ParseContext.h +++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.h @@ -116,7 +116,7 @@ struct TParseContext { bool supportsExtension(const char* extension); bool isExtensionEnabled(const char* extension) const; void handleExtensionDirective(const TSourceLoc& loc, const char* extName, const char* behavior); - void handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value); + void handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value, bool stdgl); bool containsSampler(TType& type); bool areAllChildConst(TIntermAggregate* aggrNode); diff --git a/src/3rdparty/angle/src/compiler/translator/Pragma.h b/src/3rdparty/angle/src/compiler/translator/Pragma.h index 2f744123b82..4a930a29628 100644 --- a/src/3rdparty/angle/src/compiler/translator/Pragma.h +++ b/src/3rdparty/angle/src/compiler/translator/Pragma.h @@ -7,13 +7,23 @@ #ifndef COMPILER_PRAGMA_H_ #define COMPILER_PRAGMA_H_ -struct TPragma { +struct TPragma +{ + struct STDGL + { + STDGL() : invariantAll(false) { } + + bool invariantAll; + }; + + // By default optimization is turned on and debug is turned off. TPragma() : optimize(true), debug(false) { } TPragma(bool o, bool d) : optimize(o), debug(d) { } bool optimize; bool debug; + STDGL stdgl; }; #endif // COMPILER_PRAGMA_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp index 20ce71605ce..0d6a1d64cfc 100644 --- a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp @@ -37,72 +37,6 @@ bool isInitialized = false; // and the shading language compiler. // -static bool CheckVariableMaxLengths(const ShHandle handle, - size_t expectedValue) -{ - size_t activeUniformLimit = 0; - ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit); - size_t activeAttribLimit = 0; - ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit); - size_t varyingLimit = 0; - ShGetInfo(handle, SH_VARYING_MAX_LENGTH, &varyingLimit); - return (expectedValue == activeUniformLimit && - expectedValue == activeAttribLimit && - expectedValue == varyingLimit); -} - -bool CheckMappedNameMaxLength(const ShHandle handle, size_t expectedValue) -{ - size_t mappedNameMaxLength = 0; - ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength); - return (expectedValue == mappedNameMaxLength); -} - -template -const sh::ShaderVariable *ReturnVariable(const std::vector &infoList, int index) -{ - if (index < 0 || static_cast(index) >= infoList.size()) - { - return NULL; - } - - return &infoList[index]; -} - -const sh::ShaderVariable *GetVariable(const TCompiler *compiler, ShShaderInfo varType, int index) -{ - switch (varType) - { - case SH_ACTIVE_ATTRIBUTES: - return ReturnVariable(compiler->getAttributes(), index); - case SH_ACTIVE_UNIFORMS: - return ReturnVariable(compiler->getExpandedUniforms(), index); - case SH_VARYINGS: - return ReturnVariable(compiler->getExpandedVaryings(), index); - default: - UNREACHABLE(); - return NULL; - } -} - -ShPrecisionType ConvertPrecision(sh::GLenum precision) -{ - switch (precision) - { - case GL_HIGH_FLOAT: - case GL_HIGH_INT: - return SH_PRECISION_HIGHP; - case GL_MEDIUM_FLOAT: - case GL_MEDIUM_INT: - return SH_PRECISION_MEDIUMP; - case GL_LOW_FLOAT: - case GL_LOW_INT: - return SH_PRECISION_LOWP; - default: - return SH_PRECISION_UNDEFINED; - } -} - template const std::vector *GetVariableList(const TCompiler *compiler, ShaderVariableType variableType); @@ -150,32 +84,48 @@ const std::vector *GetShaderVariables(const ShHandle handle, ShaderVariabl return GetVariableList(compiler, variableType); } +TCompiler *GetCompilerFromHandle(ShHandle handle) +{ + if (!handle) + return NULL; + TShHandleBase *base = static_cast(handle); + return base->getAsCompiler(); } +TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle) +{ + if (!handle) + return NULL; + TShHandleBase *base = static_cast(handle); + return base->getAsTranslatorHLSL(); +} + +} // namespace anonymous + // // Driver must call this first, once, before doing any other compiler operations. // Subsequent calls to this function are no-op. // -int ShInitialize() +bool ShInitialize() { if (!isInitialized) { isInitialized = InitProcess(); } - return isInitialized ? 1 : 0; + return isInitialized; } // // Cleanup symbol tables // -int ShFinalize() +bool ShFinalize() { if (isInitialized) { DetachProcess(); isInitialized = false; } - return 1; + return true; } // @@ -183,6 +133,9 @@ int ShFinalize() // void ShInitBuiltInResources(ShBuiltInResources* resources) { + // Make comparable. + memset(resources, 0, sizeof(*resources)); + // Constants. resources->MaxVertexAttribs = 8; resources->MaxVertexUniformVectors = 128; @@ -201,6 +154,8 @@ void ShInitBuiltInResources(ShBuiltInResources* resources) resources->EXT_frag_depth = 0; resources->EXT_shader_texture_lod = 0; + resources->NV_draw_buffers = 0; + // Disable highp precision in fragment shader by default. resources->FragmentPrecisionHigh = 0; @@ -251,23 +206,13 @@ void ShDestruct(ShHandle handle) DeleteCompiler(base->getAsCompiler()); } -void ShGetBuiltInResourcesString(const ShHandle handle, size_t outStringLen, char *outString) +const std::string &ShGetBuiltInResourcesString(const ShHandle handle) { - if (!handle || !outString) - { - return; - } - - TShHandleBase *base = static_cast(handle); - TCompiler *compiler = base->getAsCompiler(); - if (!compiler) - { - return; - } - - strncpy(outString, compiler->getBuiltInResourcesString().c_str(), outStringLen); - outString[outStringLen - 1] = '\0'; + TCompiler *compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); + return compiler->getBuiltInResourcesString(); } + // // Do an actual compile on the given strings. The result is left // in the given compile object. @@ -275,219 +220,62 @@ void ShGetBuiltInResourcesString(const ShHandle handle, size_t outStringLen, cha // Return: The return value of ShCompile is really boolean, indicating // success or failure. // -int ShCompile( +bool ShCompile( const ShHandle handle, - const char* const shaderStrings[], + const char *const shaderStrings[], size_t numStrings, int compileOptions) { - if (handle == 0) - return 0; + TCompiler *compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); - TShHandleBase* base = reinterpret_cast(handle); - TCompiler* compiler = base->getAsCompiler(); - if (compiler == 0) - return 0; - - bool success = compiler->compile(shaderStrings, numStrings, compileOptions); - return success ? 1 : 0; + return compiler->compile(shaderStrings, numStrings, compileOptions); } -void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params) +int ShGetShaderVersion(const ShHandle handle) { - if (!handle || !params) - return; + TCompiler* compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); + return compiler->getShaderVersion(); +} - TShHandleBase* base = static_cast(handle); - TCompiler* compiler = base->getAsCompiler(); - if (!compiler) return; - - switch(pname) - { - case SH_INFO_LOG_LENGTH: - *params = compiler->getInfoSink().info.size() + 1; - break; - case SH_OBJECT_CODE_LENGTH: - *params = compiler->getInfoSink().obj.size() + 1; - break; - case SH_ACTIVE_UNIFORMS: - *params = compiler->getExpandedUniforms().size(); - break; - case SH_ACTIVE_UNIFORM_MAX_LENGTH: - *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); - break; - case SH_ACTIVE_ATTRIBUTES: - *params = compiler->getAttributes().size(); - break; - case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: - *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); - break; - case SH_VARYINGS: - *params = compiler->getExpandedVaryings().size(); - break; - case SH_VARYING_MAX_LENGTH: - *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); - break; - case SH_MAPPED_NAME_MAX_LENGTH: - // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to - // handle array and struct dereferences. - *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); - break; - case SH_NAME_MAX_LENGTH: - *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); - break; - case SH_HASHED_NAME_MAX_LENGTH: - if (compiler->getHashFunction() == NULL) { - *params = 0; - } else { - // 64 bits hashing output requires 16 bytes for hex - // representation. - const char HashedNamePrefix[] = HASHED_NAME_PREFIX; - (void)HashedNamePrefix; - *params = 16 + sizeof(HashedNamePrefix); - } - break; - case SH_HASHED_NAMES_COUNT: - *params = compiler->getNameMap().size(); - break; - case SH_SHADER_VERSION: - *params = compiler->getShaderVersion(); - break; - case SH_RESOURCES_STRING_LENGTH: - *params = compiler->getBuiltInResourcesString().length() + 1; - break; - case SH_OUTPUT_TYPE: - *params = compiler->getOutputType(); - break; - default: UNREACHABLE(); - } +ShShaderOutput ShGetShaderOutputType(const ShHandle handle) +{ + TCompiler* compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); + return compiler->getOutputType(); } // // Return any compiler log of messages for the application. // -void ShGetInfoLog(const ShHandle handle, char* infoLog) +const std::string &ShGetInfoLog(const ShHandle handle) { - if (!handle || !infoLog) - return; + TCompiler *compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); - TShHandleBase* base = static_cast(handle); - TCompiler* compiler = base->getAsCompiler(); - if (!compiler) return; - - TInfoSink& infoSink = compiler->getInfoSink(); - strcpy(infoLog, infoSink.info.c_str()); + TInfoSink &infoSink = compiler->getInfoSink(); + return infoSink.info.str(); } // // Return any object code. // -void ShGetObjectCode(const ShHandle handle, char* objCode) +const std::string &ShGetObjectCode(const ShHandle handle) { - if (!handle || !objCode) - return; + TCompiler *compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); - TShHandleBase* base = static_cast(handle); - TCompiler* compiler = base->getAsCompiler(); - if (!compiler) return; - - TInfoSink& infoSink = compiler->getInfoSink(); - strcpy(objCode, infoSink.obj.c_str()); + TInfoSink &infoSink = compiler->getInfoSink(); + return infoSink.obj.str(); } -void ShGetVariableInfo(const ShHandle handle, - ShShaderInfo varType, - int index, - size_t* length, - int* size, - sh::GLenum* type, - ShPrecisionType* precision, - int* staticUse, - char* name, - char* mappedName) +const std::map *ShGetNameHashingMap( + const ShHandle handle) { - if (!handle || !size || !type || !precision || !staticUse || !name) - return; - ASSERT((varType == SH_ACTIVE_ATTRIBUTES) || - (varType == SH_ACTIVE_UNIFORMS) || - (varType == SH_VARYINGS)); - - TShHandleBase* base = reinterpret_cast(handle); - TCompiler* compiler = base->getAsCompiler(); - if (compiler == 0) - return; - - const sh::ShaderVariable *varInfo = GetVariable(compiler, varType, index); - if (!varInfo) - { - return; - } - - if (length) *length = varInfo->name.size(); - *size = varInfo->elementCount(); - *type = varInfo->type; - *precision = ConvertPrecision(varInfo->precision); - *staticUse = varInfo->staticUse ? 1 : 0; - - // This size must match that queried by - // SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH - // in ShGetInfo, below. - size_t variableLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); - ASSERT(CheckVariableMaxLengths(handle, variableLength)); - strncpy(name, varInfo->name.c_str(), variableLength); - name[variableLength - 1] = 0; - if (mappedName) - { - // This size must match that queried by - // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below. - size_t maxMappedNameLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); - ASSERT(CheckMappedNameMaxLength(handle, maxMappedNameLength)); - strncpy(mappedName, varInfo->mappedName.c_str(), maxMappedNameLength); - mappedName[maxMappedNameLength - 1] = 0; - } -} - -void ShGetNameHashingEntry(const ShHandle handle, - int index, - char* name, - char* hashedName) -{ - if (!handle || !name || !hashedName || index < 0) - return; - - TShHandleBase* base = static_cast(handle); - TCompiler* compiler = base->getAsCompiler(); - if (!compiler) return; - - const NameMap& nameMap = compiler->getNameMap(); - if (index >= static_cast(nameMap.size())) - return; - - NameMap::const_iterator it = nameMap.begin(); - for (int i = 0; i < index; ++i) - ++it; - - size_t len = it->first.length() + 1; - size_t max_len = 0; - ShGetInfo(handle, SH_NAME_MAX_LENGTH, &max_len); - if (len > max_len) { - ASSERT(false); - len = max_len; - } - strncpy(name, it->first.c_str(), len); - // To be on the safe side in case the source is longer than expected. - name[len - 1] = '\0'; - - len = it->second.length() + 1; - max_len = 0; - ShGetInfo(handle, SH_HASHED_NAME_MAX_LENGTH, &max_len); - if (len > max_len) { - ASSERT(false); - len = max_len; - } - strncpy(hashedName, it->second.c_str(), len); - // To be on the safe side in case the source is longer than expected. - hashedName[len - 1] = '\0'; + TCompiler *compiler = GetCompilerFromHandle(handle); + ASSERT(compiler); + return &(compiler->getNameMap()); } const std::vector *ShGetUniforms(const ShHandle handle) @@ -515,11 +303,11 @@ const std::vector *ShGetInterfaceBlocks(const ShHandle handl return GetShaderVariables(handle, SHADERVAR_INTERFACEBLOCK); } -int ShCheckVariablesWithinPackingLimits( - int maxVectors, ShVariableInfo* varInfoArray, size_t varInfoArraySize) +bool ShCheckVariablesWithinPackingLimits( + int maxVectors, ShVariableInfo *varInfoArray, size_t varInfoArraySize) { if (varInfoArraySize == 0) - return 1; + return true; ASSERT(varInfoArray); std::vector variables; for (size_t ii = 0; ii < varInfoArraySize; ++ii) @@ -528,24 +316,17 @@ int ShCheckVariablesWithinPackingLimits( variables.push_back(var); } VariablePacker packer; - return packer.CheckVariablesWithinPackingLimits(maxVectors, variables) ? 1 : 0; + return packer.CheckVariablesWithinPackingLimits(maxVectors, variables); } bool ShGetInterfaceBlockRegister(const ShHandle handle, - const char *interfaceBlockName, + const std::string &interfaceBlockName, unsigned int *indexOut) { - if (!handle || !interfaceBlockName || !indexOut) - { - return false; - } + ASSERT(indexOut); - TShHandleBase* base = static_cast(handle); - TranslatorHLSL* translator = base->getAsTranslatorHLSL(); - if (!translator) - { - return false; - } + TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); + ASSERT(translator); if (!translator->hasInterfaceBlock(interfaceBlockName)) { @@ -557,20 +338,12 @@ bool ShGetInterfaceBlockRegister(const ShHandle handle, } bool ShGetUniformRegister(const ShHandle handle, - const char *uniformName, + const std::string &uniformName, unsigned int *indexOut) { - if (!handle || !uniformName || !indexOut) - { - return false; - } - - TShHandleBase* base = static_cast(handle); - TranslatorHLSL* translator = base->getAsTranslatorHLSL(); - if (!translator) - { - return false; - } + ASSERT(indexOut); + TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); + ASSERT(translator); if (!translator->hasUniform(uniformName)) { diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp index 822c558c9bd..3098a7f0c95 100644 --- a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp @@ -9,6 +9,8 @@ #include +#include "compiler/translator/compilerdebug.h" + namespace sh { @@ -53,6 +55,126 @@ ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other) return *this; } +bool ShaderVariable::operator==(const ShaderVariable &other) const +{ + if (type != other.type || + precision != other.precision || + name != other.name || + mappedName != other.mappedName || + arraySize != other.arraySize || + staticUse != other.staticUse || + fields.size() != other.fields.size() || + structName != other.structName) + { + return false; + } + for (size_t ii = 0; ii < fields.size(); ++ii) + { + if (fields[ii] != other.fields[ii]) + return false; + } + return true; +} + +bool ShaderVariable::findInfoByMappedName( + const std::string &mappedFullName, + const ShaderVariable **leafVar, std::string *originalFullName) const +{ + ASSERT(leafVar && originalFullName); + // There are three cases: + // 1) the top variable is of struct type; + // 2) the top variable is an array; + // 3) otherwise. + size_t pos = mappedFullName.find_first_of(".["); + std::string topName; + + if (pos == std::string::npos) + { + // Case 3. + if (mappedFullName != this->mappedName) + return false; + *originalFullName = this->name; + *leafVar = this; + return true; + } + else + { + std::string topName = mappedFullName.substr(0, pos); + if (topName != this->mappedName) + return false; + std::string originalName = this->name; + std::string remaining; + if (mappedFullName[pos] == '[') + { + // Case 2. + size_t closePos = mappedFullName.find_first_of(']'); + if (closePos < pos || closePos == std::string::npos) + return false; + // Append '[index]'. + originalName += mappedFullName.substr(pos, closePos - pos + 1); + if (closePos + 1 == mappedFullName.size()) + { + *originalFullName = originalName; + *leafVar = this; + return true; + } + else + { + // In the form of 'a[0].b', so after ']', '.' is expected. + if (mappedFullName[closePos + 1] != '.') + return false; + remaining = mappedFullName.substr(closePos + 2); // Skip "]." + } + } + else + { + // Case 1. + remaining = mappedFullName.substr(pos + 1); // Skip "." + } + for (size_t ii = 0; ii < this->fields.size(); ++ii) + { + const ShaderVariable *fieldVar = NULL; + std::string originalFieldName; + bool found = fields[ii].findInfoByMappedName( + remaining, &fieldVar, &originalFieldName); + if (found) + { + *originalFullName = originalName + "." + originalFieldName; + *leafVar = fieldVar; + return true; + } + } + return false; + } +} + +bool ShaderVariable::isSameVariableAtLinkTime( + const ShaderVariable &other, bool matchPrecision) const +{ + if (type != other.type) + return false; + if (matchPrecision && precision != other.precision) + return false; + if (name != other.name) + return false; + ASSERT(mappedName == other.mappedName); + if (arraySize != other.arraySize) + return false; + if (fields.size() != other.fields.size()) + return false; + for (size_t ii = 0; ii < fields.size(); ++ii) + { + if (!fields[ii].isSameVariableAtLinkTime(other.fields[ii], + matchPrecision)) + { + return false; + } + } + if (structName != other.structName) + return false; + return true; +} + Uniform::Uniform() {} @@ -69,6 +191,16 @@ Uniform &Uniform::operator=(const Uniform &other) return *this; } +bool Uniform::operator==(const Uniform &other) const +{ + return ShaderVariable::operator==(other); +} + +bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const +{ + return ShaderVariable::isSameVariableAtLinkTime(other, true); +} + Attribute::Attribute() : location(-1) {} @@ -88,6 +220,12 @@ Attribute &Attribute::operator=(const Attribute &other) return *this; } +bool Attribute::operator==(const Attribute &other) const +{ + return (ShaderVariable::operator==(other) && + location == other.location); +} + InterfaceBlockField::InterfaceBlockField() : isRowMajorLayout(false) {} @@ -107,6 +245,19 @@ InterfaceBlockField &InterfaceBlockField::operator=(const InterfaceBlockField &o return *this; } +bool InterfaceBlockField::operator==(const InterfaceBlockField &other) const +{ + return (ShaderVariable::operator==(other) && + isRowMajorLayout == other.isRowMajorLayout); +} + +bool InterfaceBlockField::isSameInterfaceBlockFieldAtLinkTime( + const InterfaceBlockField &other) const +{ + return (ShaderVariable::isSameVariableAtLinkTime(other, true) && + isRowMajorLayout == other.isRowMajorLayout); +} + Varying::Varying() : interpolation(INTERPOLATION_SMOOTH), isInvariant(false) @@ -129,6 +280,20 @@ Varying &Varying::operator=(const Varying &other) return *this; } +bool Varying::operator==(const Varying &other) const +{ + return (ShaderVariable::operator==(other) && + interpolation == other.interpolation && + isInvariant == other.isInvariant); +} + +bool Varying::isSameVaryingAtLinkTime(const Varying &other) const +{ + return (ShaderVariable::isSameVariableAtLinkTime(other, false) && + interpolation == other.interpolation && + isInvariant == other.isInvariant); +} + InterfaceBlock::InterfaceBlock() : arraySize(0), layout(BLOCKLAYOUT_PACKED), diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h index 6b0e0c0a033..9cd74218dc5 100644 --- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h +++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h @@ -31,6 +31,7 @@ // #include +#include #include "common/angleutils.h" #include "compiler/translator/InfoSink.h" @@ -299,19 +300,21 @@ class TSymbolTableLevel tLevel level; }; -enum ESymbolLevel -{ - COMMON_BUILTINS = 0, - ESSL1_BUILTINS = 1, - ESSL3_BUILTINS = 2, - LAST_BUILTIN_LEVEL = ESSL3_BUILTINS, - GLOBAL_LEVEL = 3 -}; +// Define ESymbolLevel as int rather than an enum since level can go +// above GLOBAL_LEVEL and cause atBuiltInLevel() to fail if the +// compiler optimizes the >= of the last element to ==. +typedef int ESymbolLevel; +const int COMMON_BUILTINS = 0; +const int ESSL1_BUILTINS = 1; +const int ESSL3_BUILTINS = 2; +const int LAST_BUILTIN_LEVEL = ESSL3_BUILTINS; +const int GLOBAL_LEVEL = 3; class TSymbolTable { public: TSymbolTable() + : mGlobalInvariant(false) { // The symbol table cannot be used until push() is called, but // the lack of an initial call to push() can be used to detect @@ -408,6 +411,25 @@ class TSymbolTable // for the specified TBasicType TPrecision getDefaultPrecision(TBasicType type) const; + // This records invariant varyings declared through + // "invariant varying_name;". + void addInvariantVarying(const TString &originalName) + { + mInvariantVaryings.insert(originalName); + } + // If this returns false, the varying could still be invariant + // if it is set as invariant during the varying variable + // declaration - this piece of information is stored in the + // variable's type, not here. + bool isVaryingInvariant(const TString &originalName) const + { + return (mGlobalInvariant || + mInvariantVaryings.count(originalName) > 0); + } + + void setGlobalInvariant() { mGlobalInvariant = true; } + bool getGlobalInvariant() const { return mGlobalInvariant; } + static int nextUniqueId() { return ++uniqueIdCounter; @@ -423,6 +445,9 @@ class TSymbolTable typedef TMap PrecisionStackLevel; std::vector< PrecisionStackLevel *> precisionStack; + std::set mInvariantVaryings; + bool mGlobalInvariant; + static int uniqueIdCounter; }; diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp index 5b99fea9489..dcbf3cea1d4 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp @@ -16,6 +16,8 @@ TranslatorESSL::TranslatorESSL(sh::GLenum type, ShShaderSpec spec) void TranslatorESSL::translate(TIntermNode* root) { TInfoSinkBase& sink = getInfoSink().obj; + writePragma(); + // Write built-in extension behaviors. writeExtensionBehavior(); @@ -37,8 +39,13 @@ void TranslatorESSL::writeExtensionBehavior() { for (TExtensionBehavior::const_iterator iter = extensionBehavior.begin(); iter != extensionBehavior.end(); ++iter) { if (iter->second != EBhUndefined) { - sink << "#extension " << iter->first << " : " - << getBehaviorString(iter->second) << "\n"; + if (getResources().NV_draw_buffers && iter->first == "GL_EXT_draw_buffers") { + sink << "#extension GL_NV_draw_buffers : " + << getBehaviorString(iter->second) << "\n"; + } else { + sink << "#extension " << iter->first << " : " + << getBehaviorString(iter->second) << "\n"; + } } } } diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp index 4b2aecab33a..6acbf7c5a84 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp @@ -9,18 +9,6 @@ #include "compiler/translator/OutputGLSL.h" #include "compiler/translator/VersionGLSL.h" -static void writeVersion(sh::GLenum type, TIntermNode* root, - TInfoSinkBase& sink) { - TVersionGLSL versionGLSL(type); - root->traverse(&versionGLSL); - int version = versionGLSL.getVersion(); - // We need to write version directive only if it is greater than 110. - // If there is no version directive in the shader, 110 is implied. - if (version > 110) { - sink << "#version " << version << "\n"; - } -} - TranslatorGLSL::TranslatorGLSL(sh::GLenum type, ShShaderSpec spec) : TCompiler(type, spec, SH_GLSL_OUTPUT) { } @@ -29,7 +17,9 @@ void TranslatorGLSL::translate(TIntermNode* root) { TInfoSinkBase& sink = getInfoSink().obj; // Write GLSL version. - writeVersion(getShaderType(), root, sink); + writeVersion(root); + + writePragma(); // Write extension behaviour as needed writeExtensionBehavior(); @@ -46,6 +36,20 @@ void TranslatorGLSL::translate(TIntermNode* root) { root->traverse(&outputGLSL); } +void TranslatorGLSL::writeVersion(TIntermNode *root) +{ + TVersionGLSL versionGLSL(getShaderType(), getPragma()); + root->traverse(&versionGLSL); + int version = versionGLSL.getVersion(); + // We need to write version directive only if it is greater than 110. + // If there is no version directive in the shader, 110 is implied. + if (version > 110) + { + TInfoSinkBase& sink = getInfoSink().obj; + sink << "#version " << version << "\n"; + } +} + void TranslatorGLSL::writeExtensionBehavior() { TInfoSinkBase& sink = getInfoSink().obj; const TExtensionBehavior& extensionBehavior = getExtensionBehavior(); diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h index 3c6c2e426af..766d8d910e4 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h @@ -9,14 +9,16 @@ #include "compiler/translator/Compiler.h" -class TranslatorGLSL : public TCompiler { -public: +class TranslatorGLSL : public TCompiler +{ + public: TranslatorGLSL(sh::GLenum type, ShShaderSpec spec); -protected: - virtual void translate(TIntermNode* root); + protected: + virtual void translate(TIntermNode *root); -private: + private: + void writeVersion(TIntermNode *root); void writeExtensionBehavior(); }; diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp index c1a7b7524f1..896e1cd7a01 100644 --- a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp @@ -94,6 +94,7 @@ const char *GetOperatorString(TOperator op) case EOpLogicalXor: return "^^"; case EOpLogicalAnd: return "&&"; case EOpNegative: return "-"; + case EOpPositive: return "+"; case EOpVectorLogicalNot: return "not"; case EOpLogicalNot: return "!"; case EOpPostIncrement: return "++"; diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp index f26c1566ac8..d8e13788b79 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp @@ -5,6 +5,7 @@ // #include "angle_gl.h" +#include "compiler/translator/SymbolTable.h" #include "compiler/translator/VariableInfo.h" #include "compiler/translator/util.h" #include "common/utilities.h" @@ -131,7 +132,8 @@ CollectVariables::CollectVariables(std::vector *attribs, std::vector *uniforms, std::vector *varyings, std::vector *interfaceBlocks, - ShHashFunction64 hashFunction) + ShHashFunction64 hashFunction, + const TSymbolTable &symbolTable) : mAttribs(attribs), mOutputVariables(outputVariables), mUniforms(uniforms), @@ -140,7 +142,10 @@ CollectVariables::CollectVariables(std::vector *attribs, mPointCoordAdded(false), mFrontFacingAdded(false), mFragCoordAdded(false), - mHashFunction(hashFunction) + mPositionAdded(false), + mPointSizeAdded(false), + mHashFunction(hashFunction), + mSymbolTable(symbolTable) { } @@ -200,12 +205,14 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) if (!mFragCoordAdded) { Varying info; - info.name = "gl_FragCoord"; - info.mappedName = "gl_FragCoord"; + const char kName[] = "gl_FragCoord"; + info.name = kName; + info.mappedName = kName; info.type = GL_FLOAT_VEC4; info.arraySize = 0; - info.precision = GL_MEDIUM_FLOAT; // Use mediump as it doesn't really matter. + info.precision = GL_MEDIUM_FLOAT; // Defined by spec. info.staticUse = true; + info.isInvariant = mSymbolTable.isVaryingInvariant(kName); mVaryings->push_back(info); mFragCoordAdded = true; } @@ -214,12 +221,14 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) if (!mFrontFacingAdded) { Varying info; - info.name = "gl_FrontFacing"; - info.mappedName = "gl_FrontFacing"; + const char kName[] = "gl_FrontFacing"; + info.name = kName; + info.mappedName = kName; info.type = GL_BOOL; info.arraySize = 0; info.precision = GL_NONE; info.staticUse = true; + info.isInvariant = mSymbolTable.isVaryingInvariant(kName); mVaryings->push_back(info); mFrontFacingAdded = true; } @@ -228,16 +237,50 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) if (!mPointCoordAdded) { Varying info; - info.name = "gl_PointCoord"; - info.mappedName = "gl_PointCoord"; + const char kName[] = "gl_PointCoord"; + info.name = kName; + info.mappedName = kName; info.type = GL_FLOAT_VEC2; info.arraySize = 0; - info.precision = GL_MEDIUM_FLOAT; // Use mediump as it doesn't really matter. + info.precision = GL_MEDIUM_FLOAT; // Defined by spec. info.staticUse = true; + info.isInvariant = mSymbolTable.isVaryingInvariant(kName); mVaryings->push_back(info); mPointCoordAdded = true; } return; + case EvqPosition: + if (!mPositionAdded) + { + Varying info; + const char kName[] = "gl_Position"; + info.name = kName; + info.mappedName = kName; + info.type = GL_FLOAT_VEC4; + info.arraySize = 0; + info.precision = GL_HIGH_FLOAT; // Defined by spec. + info.staticUse = true; + info.isInvariant = mSymbolTable.isVaryingInvariant(kName); + mVaryings->push_back(info); + mPositionAdded = true; + } + return; + case EvqPointSize: + if (!mPointSizeAdded) + { + Varying info; + const char kName[] = "gl_PointSize"; + info.name = kName; + info.mappedName = kName; + info.type = GL_FLOAT; + info.arraySize = 0; + info.precision = GL_MEDIUM_FLOAT; // Defined by spec. + info.staticUse = true; + info.isInvariant = mSymbolTable.isVaryingInvariant(kName); + mVaryings->push_back(info); + mPointSizeAdded = true; + } + return; default: break; } @@ -251,8 +294,10 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) class NameHashingTraverser : public GetVariableTraverser { public: - NameHashingTraverser(ShHashFunction64 hashFunction) - : mHashFunction(hashFunction) + NameHashingTraverser(ShHashFunction64 hashFunction, + const TSymbolTable &symbolTable) + : GetVariableTraverser(symbolTable), + mHashFunction(hashFunction) {} private: @@ -312,7 +357,7 @@ void CollectVariables::visitVariable(const TIntermSymbol *variable, const TString &fullFieldName = InterfaceBlockFieldName(*blockType, field); const TType &fieldType = *field.type(); - GetVariableTraverser traverser; + GetVariableTraverser traverser(mSymbolTable); traverser.traverse(fieldType, fullFieldName, &interfaceBlock.fields); interfaceBlock.fields.back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor); @@ -325,7 +370,7 @@ template void CollectVariables::visitVariable(const TIntermSymbol *variable, std::vector *infoList) const { - NameHashingTraverser traverser(mHashFunction); + NameHashingTraverser traverser(mHashFunction, mSymbolTable); traverser.traverse(variable->getType(), variable->getSymbol(), infoList); } @@ -421,9 +466,8 @@ bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode) return true; } -template -void ExpandVariables(const std::vector &compact, - std::vector *expanded) +void ExpandUniforms(const std::vector &compact, + std::vector *expanded) { for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++) { @@ -432,7 +476,4 @@ void ExpandVariables(const std::vector &compact, } } -template void ExpandVariables(const std::vector &, std::vector *); -template void ExpandVariables(const std::vector &, std::vector *); - } diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h index 5ac4c46baa5..92d376d8795 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h +++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h @@ -11,6 +11,8 @@ #include "compiler/translator/IntermNode.h" +class TSymbolTable; + namespace sh { @@ -23,7 +25,8 @@ class CollectVariables : public TIntermTraverser std::vector *uniforms, std::vector *varyings, std::vector *interfaceBlocks, - ShHashFunction64 hashFunction); + ShHashFunction64 hashFunction, + const TSymbolTable &symbolTable); virtual void visitSymbol(TIntermSymbol *symbol); virtual bool visitAggregate(Visit, TIntermAggregate *node); @@ -48,13 +51,17 @@ class CollectVariables : public TIntermTraverser bool mFrontFacingAdded; bool mFragCoordAdded; + bool mPositionAdded; + bool mPointSizeAdded; + ShHashFunction64 mHashFunction; + + const TSymbolTable &mSymbolTable; }; -// Expand struct variables to flattened lists of split variables -template -void ExpandVariables(const std::vector &compact, - std::vector *expanded); +// Expand struct uniforms to flattened lists of split variables +void ExpandUniforms(const std::vector &compact, + std::vector *expanded); } diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp index 8edbd009b06..05b111a7a74 100644 --- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp @@ -26,18 +26,12 @@ static const int GLSL_VERSION_120 = 120; // GLSL 1.2 relaxed the restriction on arrays, section 5.8: "Variables that // are built-in types, entire structures or arrays... are all l-values." // -// TODO(alokp): The following two cases of invariant decalaration get lost -// during parsing - they do not get carried over to the intermediate tree. -// Handle these cases: -// 1. When a pragma is used to force all output variables to be invariant: -// - #pragma STDGL invariant(all) -// 2. When a previously decalared or built-in variable is marked invariant: -// - invariant gl_Position; -// - varying vec3 color; invariant color; -// -TVersionGLSL::TVersionGLSL(sh::GLenum type) - : mVersion(GLSL_VERSION_110) +TVersionGLSL::TVersionGLSL(sh::GLenum type, const TPragma &pragma) { + if (pragma.stdgl.invariantAll) + mVersion = GLSL_VERSION_120; + else + mVersion = GLSL_VERSION_110; } void TVersionGLSL::visitSymbol(TIntermSymbol *node) diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h index 30f5a138a0f..72368e39d66 100644 --- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h @@ -9,6 +9,8 @@ #include "compiler/translator/IntermNode.h" +#include "compiler/translator/Pragma.h" + // Traverses the intermediate tree to return the minimum GLSL version // required to legally access all built-in features used in the shader. // GLSL 1.1 which is mandated by OpenGL 2.0 provides: @@ -27,7 +29,7 @@ class TVersionGLSL : public TIntermTraverser { public: - TVersionGLSL(sh::GLenum type); + TVersionGLSL(sh::GLenum type, const TPragma &pragma); // Returns 120 if the following is used the shader: // - "invariant", diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.y b/src/3rdparty/angle/src/compiler/translator/glslang.y index 5c945ad5adc..e271de978c0 100644 --- a/src/3rdparty/angle/src/compiler/translator/glslang.y +++ b/src/3rdparty/angle/src/compiler/translator/glslang.y @@ -354,6 +354,15 @@ function_call // Treat it like a built-in unary operator. // $$ = context->intermediate.addUnaryMath(op, $1.intermNode, @1); + const TType& returnType = fnCandidate->getReturnType(); + if (returnType.getBasicType() == EbtBool) { + // Bool types should not have precision, so we'll override any precision + // that might have been set by addUnaryMath. + $$->setType(returnType); + } else { + // addUnaryMath has set the precision of the node based on the operand. + $$->setTypePreservePrecision(returnType); + } if ($$ == 0) { std::stringstream extraInfoStream; extraInfoStream << "built in unary operator function. Type: " << static_cast($1.intermNode)->getCompleteString(); @@ -362,20 +371,29 @@ function_call YYERROR; } } else { - $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1); + TIntermAggregate *aggregate = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1); + aggregate->setType(fnCandidate->getReturnType()); + aggregate->setPrecisionFromChildren(); + $$ = aggregate; } } else { // This is a real function call - $$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1); - $$->setType(fnCandidate->getReturnType()); + TIntermAggregate *aggregate = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1); + aggregate->setType(fnCandidate->getReturnType()); // this is how we know whether the given function is a builtIn function or a user defined function // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also // if builtIn == true, it's definitely a builtIn function with EOpNull if (!builtIn) - $$->getAsAggregate()->setUserDefined(); - $$->getAsAggregate()->setName(fnCandidate->getMangledName()); + aggregate->setUserDefined(); + aggregate->setName(fnCandidate->getMangledName()); + + // This needs to happen after the name is set + if (builtIn) + aggregate->setBuiltInFunctionPrecision(); + + $$ = aggregate; TQualifier qual; for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) { @@ -388,7 +406,6 @@ function_call } } } - $$->setType(fnCandidate->getReturnType()); } else { // error message was put out by PaFindFunction() // Put on a dummy node for error recovery @@ -500,6 +517,7 @@ unary_expression const char* errorOp = ""; switch($1.op) { case EOpNegative: errorOp = "-"; break; + case EOpPositive: errorOp = "+"; break; case EOpLogicalNot: errorOp = "!"; break; default: break; } @@ -514,7 +532,7 @@ unary_expression // Grammar Note: No traditional style type casts. unary_operator - : PLUS { $$.op = EOpNull; } + : PLUS { $$.op = EOpPositive; } | DASH { $$.op = EOpNegative; } | BANG { $$.op = EOpLogicalNot; } ; @@ -762,7 +780,7 @@ declaration TIntermAggregate *prototype = new TIntermAggregate; prototype->setType(function.getReturnType()); - prototype->setName(function.getName()); + prototype->setName(function.getMangledName()); for (size_t i = 0; i < function.getParamCount(); i++) { diff --git a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp index 56340c6f9e7..00780f04543 100644 --- a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp +++ b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp @@ -62,7 +62,9 @@ TString TType::getCompleteString() const TStringStream stream; if (qualifier != EvqTemporary && qualifier != EvqGlobal) - stream << getQualifierString() << " " << getPrecisionString() << " "; + stream << getQualifierString() << " "; + if (precision != EbpUndefined) + stream << getPrecisionString() << " "; if (array) stream << "array[" << getArraySize() << "] of "; if (isMatrix()) @@ -221,6 +223,7 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node) switch (node->getOp()) { case EOpNegative: out << "Negate value"; break; + case EOpPositive: out << "Positive sign"; break; case EOpVectorLogicalNot: case EOpLogicalNot: out << "Negate conditional"; break; @@ -292,6 +295,7 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) case EOpFunction: out << "Function Definition: " << node->getName(); break; case EOpFunctionCall: out << "Function Call: " << node->getName(); break; case EOpParameters: out << "Function Parameters: "; break; + case EOpPrototype: out << "Function Prototype: " << node->getName(); break; case EOpConstructFloat: out << "Construct float"; break; case EOpConstructVec2: out << "Construct vec2"; break; diff --git a/src/3rdparty/angle/src/compiler/translator/util.cpp b/src/3rdparty/angle/src/compiler/translator/util.cpp index f74c7d11731..8cc06a658a5 100644 --- a/src/3rdparty/angle/src/compiler/translator/util.cpp +++ b/src/3rdparty/angle/src/compiler/translator/util.cpp @@ -9,6 +9,7 @@ #include #include "compiler/preprocessor/numeric_lex.h" +#include "compiler/translator/SymbolTable.h" #include "common/utilities.h" bool atof_clamp(const char *str, float *value) @@ -281,8 +282,47 @@ InterpolationType GetInterpolationType(TQualifier qualifier) } } +GetVariableTraverser::GetVariableTraverser(const TSymbolTable &symbolTable) + : mSymbolTable(symbolTable) +{ +} + +template void GetVariableTraverser::setTypeSpecificInfo( + const TType &type, const TString& name, InterfaceBlockField *variable); +template void GetVariableTraverser::setTypeSpecificInfo( + const TType &type, const TString& name, ShaderVariable *variable); +template void GetVariableTraverser::setTypeSpecificInfo( + const TType &type, const TString& name, Uniform *variable); + +template<> +void GetVariableTraverser::setTypeSpecificInfo( + const TType &type, const TString& name, Varying *variable) +{ + ASSERT(variable); + switch (type.getQualifier()) + { + case EvqInvariantVaryingIn: + case EvqInvariantVaryingOut: + variable->isInvariant = true; + break; + case EvqVaryingIn: + case EvqVaryingOut: + if (mSymbolTable.isVaryingInvariant(name)) + { + variable->isInvariant = true; + } + break; + default: + break; + } + + variable->interpolation = GetInterpolationType(type.getQualifier()); +} + template -void GetVariableTraverser::traverse(const TType &type, const TString &name, std::vector *output) +void GetVariableTraverser::traverse(const TType &type, + const TString &name, + std::vector *output) { const TStructure *structure = type.getStruct(); @@ -309,15 +349,16 @@ void GetVariableTraverser::traverse(const TType &type, const TString &name, std: traverse(*field->type(), field->name(), &variable.fields); } } - + setTypeSpecificInfo(type, name, &variable); visitVariable(&variable); ASSERT(output); output->push_back(variable); } +template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector *); +template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector *); template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector *); template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector *); -template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector *); } diff --git a/src/3rdparty/angle/src/compiler/translator/util.h b/src/3rdparty/angle/src/compiler/translator/util.h index 241e2cc1c20..fb5308759e3 100644 --- a/src/3rdparty/angle/src/compiler/translator/util.h +++ b/src/3rdparty/angle/src/compiler/translator/util.h @@ -24,6 +24,8 @@ extern bool atof_clamp(const char *str, float *value); // Return false if overflow happens. extern bool atoi_clamp(const char *str, int *value); +class TSymbolTable; + namespace sh { @@ -38,7 +40,7 @@ TString ArrayString(const TType &type); class GetVariableTraverser { public: - GetVariableTraverser() {} + GetVariableTraverser(const TSymbolTable &symbolTable); template void traverse(const TType &type, const TString &name, std::vector *output); @@ -48,6 +50,14 @@ class GetVariableTraverser virtual void visitVariable(ShaderVariable *newVar) {} private: + // Helper function called by traverse() to fill specific fields + // for attributes/varyings/uniforms. + template + void setTypeSpecificInfo( + const TType &type, const TString &name, VarT *variable) {} + + const TSymbolTable &mSymbolTable; + DISALLOW_COPY_AND_ASSIGN(GetVariableTraverser); }; diff --git a/src/3rdparty/angle/src/libEGL/AttributeMap.cpp b/src/3rdparty/angle/src/libEGL/AttributeMap.cpp new file mode 100644 index 00000000000..28dd3d842ec --- /dev/null +++ b/src/3rdparty/angle/src/libEGL/AttributeMap.cpp @@ -0,0 +1,40 @@ +// +// 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. +// + +#include "libEGL/AttributeMap.h" + +namespace egl +{ + +AttributeMap::AttributeMap() +{ +} + +AttributeMap::AttributeMap(const EGLint *attributes) +{ + for (const EGLint *curAttrib = attributes; curAttrib[0] != EGL_NONE; curAttrib += 2) + { + insert(curAttrib[0], curAttrib[1]); + } +} + +void AttributeMap::insert(EGLint key, EGLint value) +{ + mAttributes[key] = value; +} + +bool AttributeMap::contains(EGLint key) const +{ + return (mAttributes.find(key) != mAttributes.end()); +} + +EGLint AttributeMap::get(EGLint key, EGLint defaultValue) const +{ + std::map::const_iterator iter = mAttributes.find(key); + return (mAttributes.find(key) != mAttributes.end()) ? iter->second : defaultValue; +} + +} diff --git a/src/3rdparty/angle/src/libEGL/AttributeMap.h b/src/3rdparty/angle/src/libEGL/AttributeMap.h new file mode 100644 index 00000000000..f2f082fe219 --- /dev/null +++ b/src/3rdparty/angle/src/libEGL/AttributeMap.h @@ -0,0 +1,33 @@ +// +// 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. +// + +#ifndef LIBEGL_ATTRIBUTEMAP_H_ +#define LIBEGL_ATTRIBUTEMAP_H_ + +#include + +#include + +namespace egl +{ + +class AttributeMap +{ + public: + AttributeMap(); + explicit AttributeMap(const EGLint *attributes); + + virtual void insert(EGLint key, EGLint value); + virtual bool contains(EGLint key) const; + virtual EGLint get(EGLint key, EGLint defaultValue) const; + + private: + std::map mAttributes; +}; + +} + +#endif // LIBEGL_ATTRIBUTEMAP_H_ diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp index 5a50e4baf54..eea93b1d872 100644 --- a/src/3rdparty/angle/src/libEGL/Display.cpp +++ b/src/3rdparty/angle/src/libEGL/Display.cpp @@ -35,32 +35,36 @@ static DisplayMap *GetDisplayMap() return &displays; } -egl::Display *Display::getDisplay(EGLNativeDisplayType displayId, EGLint displayType) +egl::Display *Display::getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap) { + Display *display = NULL; + DisplayMap *displays = GetDisplayMap(); DisplayMap::const_iterator iter = displays->find(displayId); if (iter != displays->end()) { - return iter->second; + display = iter->second; + } + else + { + display = new egl::Display(displayId); + displays->insert(std::make_pair(displayId, display)); } - - // FIXME: Check if displayId is a valid display device context - egl::Display *display = new egl::Display(displayId, displayType); - displays->insert(std::make_pair(displayId, display)); + // Apply new attributes if the display is not initialized yet. + if (!display->isInitialized()) + { + display->setAttributes(attribMap); + } return display; } -Display::Display(EGLNativeDisplayType displayId, EGLint displayType) +Display::Display(EGLNativeDisplayType displayId) : mDisplayId(displayId), - mRequestedDisplayType(displayType), + mAttributeMap(), mRenderer(NULL) { -#if defined(ANGLE_PLATFORM_WINRT) - if (mDisplayId) - mDisplayId->AddRef(); -#endif } Display::~Display() @@ -73,28 +77,29 @@ Display::~Display() { displays->erase(iter); } - -#if defined(ANGLE_PLATFORM_WINRT) - if (mDisplayId) - mDisplayId->Release(); -#endif } -bool Display::initialize() +void Display::setAttributes(const AttributeMap &attribMap) +{ + mAttributeMap = attribMap; +} + +Error Display::initialize() { if (isInitialized()) { - return true; + return Error(EGL_SUCCESS); } - mRenderer = glCreateRenderer(this, mDisplayId, mRequestedDisplayType); + mRenderer = glCreateRenderer(this, mDisplayId, mAttributeMap); if (!mRenderer) { terminate(); - return error(EGL_NOT_INITIALIZED, false); + return Error(EGL_NOT_INITIALIZED); } + //TODO(jmadill): should be part of caps? EGLint minSwapInterval = mRenderer->getMinSwapInterval(); EGLint maxSwapInterval = mRenderer->getMaxSwapInterval(); EGLint maxTextureSize = mRenderer->getRendererCaps().max2DTextureSize; @@ -125,13 +130,13 @@ bool Display::initialize() if (!isInitialized()) { terminate(); - return false; + return Error(EGL_NOT_INITIALIZED); } initDisplayExtensionString(); initVendorString(); - return true; + return Error(EGL_SUCCESS); } void Display::terminate() @@ -148,6 +153,8 @@ void Display::terminate() glDestroyRenderer(mRenderer); mRenderer = NULL; + + mConfigSet.mSet.clear(); } bool Display::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig) @@ -202,7 +209,7 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) -EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList) +Error Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList, EGLSurface *outSurface) { const Config *configuration = mConfigSet.get(config); EGLint postSubBufferSupported = EGL_FALSE; @@ -223,9 +230,9 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co case EGL_BACK_BUFFER: break; case EGL_SINGLE_BUFFER: - return error(EGL_BAD_MATCH, EGL_NO_SURFACE); // Rendering directly to front buffer not supported + return Error(EGL_BAD_MATCH); // Rendering directly to front buffer not supported default: - return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + return Error(EGL_BAD_ATTRIBUTE); } break; case EGL_POST_SUB_BUFFER_SUPPORTED_NV: @@ -241,11 +248,11 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co fixedSize = attribList[1]; break; case EGL_VG_COLORSPACE: - return error(EGL_BAD_MATCH, EGL_NO_SURFACE); + return Error(EGL_BAD_MATCH); case EGL_VG_ALPHA_FORMAT: - return error(EGL_BAD_MATCH, EGL_NO_SURFACE); + return Error(EGL_BAD_MATCH); default: - return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + return Error(EGL_BAD_ATTRIBUTE); } attribList += 2; @@ -254,7 +261,7 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co if (width < 0 || height < 0) { - return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); + return Error(EGL_BAD_PARAMETER); } if (!fixedSize) @@ -265,29 +272,33 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co if (hasExistingWindowSurface(window)) { - return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return Error(EGL_BAD_ALLOC); } if (mRenderer->testDeviceLost(false)) { - if (!restoreLostDevice()) - return EGL_NO_SURFACE; + Error error = restoreLostDevice(); + if (error.isError()) + { + return error; + } } Surface *surface = new Surface(this, configuration, window, fixedSize, width, height, postSubBufferSupported); - - if (!surface->initialize()) + Error error = surface->initialize(); + if (error.isError()) { - delete surface; - return EGL_NO_SURFACE; + SafeDelete(surface); + return error; } mSurfaceSet.insert(surface); - return success(surface); + *outSurface = surface; + return Error(EGL_SUCCESS); } -EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList) +Error Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList, EGLSurface *outSurface) { EGLint width = 0, height = 0; EGLenum textureFormat = EGL_NO_TEXTURE; @@ -319,7 +330,7 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, textureFormat = attribList[1]; break; default: - return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + return Error(EGL_BAD_ATTRIBUTE); } break; case EGL_TEXTURE_TARGET: @@ -330,19 +341,19 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, textureTarget = attribList[1]; break; default: - return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + return Error(EGL_BAD_ATTRIBUTE); } break; case EGL_MIPMAP_TEXTURE: if (attribList[1] != EGL_FALSE) - return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + return Error(EGL_BAD_ATTRIBUTE); break; case EGL_VG_COLORSPACE: - return error(EGL_BAD_MATCH, EGL_NO_SURFACE); + return Error(EGL_BAD_MATCH); case EGL_VG_ALPHA_FORMAT: - return error(EGL_BAD_MATCH, EGL_NO_SURFACE); + return Error(EGL_BAD_MATCH); default: - return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + return Error(EGL_BAD_ATTRIBUTE); } attribList += 2; @@ -351,88 +362,100 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, if (width < 0 || height < 0) { - return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); + return Error(EGL_BAD_PARAMETER); } if (width == 0 || height == 0) { - return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + return Error(EGL_BAD_ATTRIBUTE); } if (textureFormat != EGL_NO_TEXTURE && !mRenderer->getRendererExtensions().textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height))) { - return error(EGL_BAD_MATCH, EGL_NO_SURFACE); + return Error(EGL_BAD_MATCH); } if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) || (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE)) { - return error(EGL_BAD_MATCH, EGL_NO_SURFACE); + return Error(EGL_BAD_MATCH); } if (!(configuration->mSurfaceType & EGL_PBUFFER_BIT)) { - return error(EGL_BAD_MATCH, EGL_NO_SURFACE); + return Error(EGL_BAD_MATCH); } if ((textureFormat == EGL_TEXTURE_RGB && configuration->mBindToTextureRGB != EGL_TRUE) || (textureFormat == EGL_TEXTURE_RGBA && configuration->mBindToTextureRGBA != EGL_TRUE)) { - return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + return Error(EGL_BAD_ATTRIBUTE); } if (mRenderer->testDeviceLost(false)) { - if (!restoreLostDevice()) - return EGL_NO_SURFACE; + Error error = restoreLostDevice(); + if (error.isError()) + { + return error; + } } Surface *surface = new Surface(this, configuration, shareHandle, width, height, textureFormat, textureTarget); - - if (!surface->initialize()) + Error error = surface->initialize(); + if (error.isError()) { - delete surface; - return EGL_NO_SURFACE; + SafeDelete(surface); + return error; } mSurfaceSet.insert(surface); - return success(surface); + *outSurface = surface; + return Error(EGL_SUCCESS); } -EGLContext Display::createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets, bool robustAccess) +Error Display::createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets, + bool robustAccess, EGLContext *outContext) { if (!mRenderer) { - return EGL_NO_CONTEXT; + *outContext = EGL_NO_CONTEXT; + return Error(EGL_SUCCESS); } else if (mRenderer->testDeviceLost(false)) // Lost device { - if (!restoreLostDevice()) + Error error = restoreLostDevice(); + if (error.isError()) { - return error(EGL_CONTEXT_LOST, EGL_NO_CONTEXT); + return error; } } + //TODO(jmadill): shader model is not cross-platform if (clientVersion > 2 && mRenderer->getMajorShaderModel() < 4) { - return error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); + return Error(EGL_BAD_CONFIG); } gl::Context *context = glCreateContext(clientVersion, shareContext, mRenderer, notifyResets, robustAccess); mContextSet.insert(context); - return success(context); + *outContext = context; + return Error(EGL_SUCCESS); } -bool Display::restoreLostDevice() +Error Display::restoreLostDevice() { for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++) { if ((*ctx)->isResetNotificationEnabled()) - return false; // If reset notifications have been requested, application must delete all contexts first + { + // If reset notifications have been requested, application must delete all contexts first + return Error(EGL_CONTEXT_LOST); + } } - + // Release surface resources to make the Reset() succeed for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) { @@ -441,16 +464,20 @@ bool Display::restoreLostDevice() if (!mRenderer->resetDevice()) { - return error(EGL_BAD_ALLOC, false); + return Error(EGL_BAD_ALLOC); } // Restore any surfaces that may have been lost for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) { - (*surface)->resetSwapChain(); + Error error = (*surface)->resetSwapChain(); + if (error.isError()) + { + return error; + } } - return true; + return Error(EGL_SUCCESS); } @@ -472,7 +499,6 @@ void Display::notifyDeviceLost() { (*context)->markContextLost(); } - egl::error(EGL_CONTEXT_LOST); } void Display::recreateSwapChains() @@ -604,10 +630,11 @@ void Display::initVendorString() LUID adapterLuid = {0}; + //TODO(jmadill): LUID is not cross-platform if (mRenderer && mRenderer->getLUID(&adapterLuid)) { char adapterLuidString[64]; - snprintf(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart); + sprintf_s(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 73ba7673ffb..b3ffcc84c5c 100644 --- a/src/3rdparty/angle/src/libEGL/Display.h +++ b/src/3rdparty/angle/src/libEGL/Display.h @@ -14,7 +14,9 @@ #include #include +#include "libEGL/Error.h" #include "libEGL/Config.h" +#include "libEGL/AttributeMap.h" namespace gl { @@ -30,10 +32,10 @@ class Display public: ~Display(); - bool initialize(); + Error initialize(); void terminate(); - static egl::Display *getDisplay(EGLNativeDisplayType displayId, EGLint displayType); + static egl::Display *getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap); static const char *getExtensionString(egl::Display *display); @@ -43,9 +45,10 @@ class Display bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig); bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value); - EGLSurface createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList); - EGLSurface createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList); - EGLContext createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets, bool robustAccess); + Error createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList, EGLSurface *outSurface); + Error createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList, EGLSurface *outSurface); + Error createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets, + bool robustAccess, EGLContext *outContext); void destroySurface(egl::Surface *surface); void destroyContext(gl::Context *context); @@ -64,18 +67,19 @@ class Display const char *getExtensionString() const; const char *getVendorString() const; - EGLNativeDisplayType getDisplayId() const { return mDisplayId; } private: DISALLOW_COPY_AND_ASSIGN(Display); - Display(EGLNativeDisplayType displayId, EGLint displayType); + Display(EGLNativeDisplayType displayId); - bool restoreLostDevice(); + void setAttributes(const AttributeMap &attribMap); + + Error restoreLostDevice(); EGLNativeDisplayType mDisplayId; - EGLint mRequestedDisplayType; + AttributeMap mAttributeMap; typedef std::set SurfaceSet; SurfaceSet mSurfaceSet; diff --git a/src/3rdparty/angle/src/libEGL/Error.cpp b/src/3rdparty/angle/src/libEGL/Error.cpp new file mode 100644 index 00000000000..df5f163d328 --- /dev/null +++ b/src/3rdparty/angle/src/libEGL/Error.cpp @@ -0,0 +1,48 @@ +// +// 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. +// + +// Error.cpp: Implements the egl::Error class which encapsulates an EGL error +// and optional error message. + +#include "libEGL/Error.h" + +#include "common/angleutils.h" + +#include + +namespace egl +{ + +Error::Error(EGLint errorCode) + : mCode(errorCode), + mMessage() +{ +} + +Error::Error(EGLint errorCode, const char *msg, ...) + : mCode(errorCode), + mMessage() +{ + va_list vararg; + va_start(vararg, msg); + mMessage = FormatString(msg, vararg); + va_end(vararg); +} + +Error::Error(const Error &other) + : mCode(other.mCode), + mMessage(other.mMessage) +{ +} + +Error &Error::operator=(const Error &other) +{ + mCode = other.mCode; + mMessage = other.mMessage; + return *this; +} + +} diff --git a/src/3rdparty/angle/src/libEGL/Error.h b/src/3rdparty/angle/src/libEGL/Error.h new file mode 100644 index 00000000000..71805d2fb76 --- /dev/null +++ b/src/3rdparty/angle/src/libEGL/Error.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. + +// Error.h: Defines the egl::Error class which encapsulates an EGL error +// and optional error message. + +#ifndef LIBEGL_ERROR_H_ +#define LIBEGL_ERROR_H_ + +#include + +#include + +namespace egl +{ + +class Error +{ + public: + explicit Error(EGLint errorCode); + Error(EGLint errorCode, const char *msg, ...); + Error(const Error &other); + Error &operator=(const Error &other); + + EGLint getCode() const { return mCode; } + bool isError() const { return (mCode != EGL_SUCCESS); } + + const std::string &getMessage() const { return mMessage; } + + private: + EGLint mCode; + std::string mMessage; +}; + +} + +#endif // LIBEGL_ERROR_H_ diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp index fa7996152ad..b664a8530e2 100644 --- a/src/3rdparty/angle/src/libEGL/Surface.cpp +++ b/src/3rdparty/angle/src/libEGL/Surface.cpp @@ -22,23 +22,19 @@ #include "libEGL/main.h" #include "libEGL/Display.h" -#if defined(ANGLE_PLATFORM_WINRT) -# include "wrl.h" -# include "windows.graphics.display.h" -# include "windows.ui.core.h" -using namespace ABI::Windows::Graphics::Display; -using namespace ABI::Windows::Foundation; -using namespace ABI::Windows::UI::Core; -using namespace Microsoft::WRL; -#endif +#include "common/NativeWindow.h" + +//TODO(jmadill): phase this out +#include "libGLESv2/renderer/d3d/RendererD3D.h" namespace egl { -Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported) - : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported) +Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported) + : mDisplay(display), mConfig(config), mNativeWindow(window, display->getDisplayId()), mPostSubBufferSupported(postSubBufferSupported) { - mRenderer = mDisplay->getRenderer(); + //TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues) + mRenderer = static_cast(mDisplay->getRenderer()); mSwapChain = NULL; mShareHandle = NULL; mTexture = NULL; @@ -51,27 +47,19 @@ Surface::Surface(Display *display, const Config *config, EGLNativeWindowType win mSwapInterval = -1; mWidth = width; mHeight = height; + mFixedWidth = mWidth; + mFixedHeight = mHeight; setSwapInterval(1); mFixedSize = fixedSize; - mSwapFlags = rx::SWAP_NORMAL; -#if defined(ANGLE_PLATFORM_WINRT) - if (mWindow) - mWindow->AddRef(); - mScaleFactor = 1.0; - mSizeToken.value = 0; - mDpiToken.value = 0; -# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP - mOrientationToken.value = 0; -# endif -#endif subclassWindow(); } Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType) - : mDisplay(display), mWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE) + : mDisplay(display), mNativeWindow(NULL, NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE) { - mRenderer = mDisplay->getRenderer(); + //TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues) + mRenderer = static_cast(mDisplay->getRenderer()); mSwapChain = NULL; mWindowSubclassed = false; mTexture = NULL; @@ -85,90 +73,33 @@ Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGL setSwapInterval(1); // This constructor is for offscreen surfaces, which are always fixed-size. mFixedSize = EGL_TRUE; - mSwapFlags = rx::SWAP_NORMAL; -#if defined(ANGLE_PLATFORM_WINRT) - mScaleFactor = 1.0; - mSizeToken.value = 0; - mDpiToken.value = 0; -# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP - mOrientationToken.value = 0; -# endif -#endif + mFixedWidth = mWidth; + mFixedHeight = mHeight; } Surface::~Surface() { -#if defined(ANGLE_PLATFORM_WINRT) - if (mSizeToken.value) { - ComPtr coreWindow; - HRESULT hr = mWindow->QueryInterface(coreWindow.GetAddressOf()); - ASSERT(SUCCEEDED(hr)); - - hr = coreWindow->remove_SizeChanged(mSizeToken); - ASSERT(SUCCEEDED(hr)); - } - if (mDpiToken.value) { - ComPtr displayInformation; - HRESULT hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf()); - ASSERT(SUCCEEDED(hr)); - - hr = displayInformation->remove_DpiChanged(mDpiToken); - ASSERT(SUCCEEDED(hr)); - } -# if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP - if (mOrientationToken.value) { - ComPtr displayInformation; - HRESULT hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf()); - ASSERT(SUCCEEDED(hr)); - - hr = displayInformation->remove_OrientationChanged(mOrientationToken); - ASSERT(SUCCEEDED(hr)); - } -# endif -#endif unsubclassWindow(); release(); } -bool Surface::initialize() +Error Surface::initialize() { -#if defined(ANGLE_PLATFORM_WINRT) - if (!mFixedSize) { - HRESULT hr; - ComPtr displayInformation; - hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf()); - ASSERT(SUCCEEDED(hr)); - onDpiChanged(displayInformation.Get(), 0); - hr = displayInformation->add_DpiChanged(Callback>(this, &Surface::onDpiChanged).Get(), - &mDpiToken); - ASSERT(SUCCEEDED(hr)); - -# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP - onOrientationChanged(displayInformation.Get(), 0); - hr = displayInformation->add_OrientationChanged(Callback>(this, &Surface::onOrientationChanged).Get(), - &mOrientationToken); - ASSERT(SUCCEEDED(hr)); -# endif - - ComPtr coreWindow; - hr = mWindow->QueryInterface(coreWindow.GetAddressOf()); - ASSERT(SUCCEEDED(hr)); - - Rect rect; - hr = coreWindow->get_Bounds(&rect); - ASSERT(SUCCEEDED(hr)); - mWidth = rect.Width * mScaleFactor; - mHeight = rect.Height * mScaleFactor; - hr = coreWindow->add_SizeChanged(Callback>(this, &Surface::onSizeChanged).Get(), - &mSizeToken); - ASSERT(SUCCEEDED(hr)); + if (mNativeWindow.getNativeWindow()) + { + if (!mNativeWindow.initialize()) + { + return Error(EGL_BAD_SURFACE); + } } -#endif - if (!resetSwapChain()) - return false; + Error error = resetSwapChain(); + if (error.isError()) + { + return error; + } - return true; + return Error(EGL_SUCCESS); } void Surface::release() @@ -181,85 +112,80 @@ void Surface::release() mTexture->releaseTexImage(); mTexture = NULL; } - -#if defined(ANGLE_PLATFORM_WINRT) - if (mWindow) - mWindow->Release(); -#endif } -bool Surface::resetSwapChain() +Error Surface::resetSwapChain() { ASSERT(!mSwapChain); int width; int height; -#if !defined(ANGLE_PLATFORM_WINRT) if (!mFixedSize) { RECT windowRect; - if (!GetClientRect(getWindowHandle(), &windowRect)) + if (!mNativeWindow.getClientRect(&windowRect)) { ASSERT(false); - ERR("Could not retrieve the window dimensions"); - return error(EGL_BAD_SURFACE, false); + return Error(EGL_BAD_SURFACE, "Could not retrieve the window dimensions"); } width = windowRect.right - windowRect.left; height = windowRect.bottom - windowRect.top; } else -#endif { // non-window surface - size is determined at creation width = mWidth; height = mHeight; } - mSwapChain = mRenderer->createSwapChain(mWindow, mShareHandle, + mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, mConfig->mRenderTargetFormat, mConfig->mDepthStencilFormat); if (!mSwapChain) { - return error(EGL_BAD_ALLOC, false); + return Error(EGL_BAD_ALLOC); } - if (!resetSwapChain(width, height)) + Error error = resetSwapChain(width, height); + if (error.isError()) { - delete mSwapChain; - mSwapChain = NULL; - return false; + SafeDelete(mSwapChain); + return error; } - return true; + return Error(EGL_SUCCESS); } -bool Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight) +Error Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight) { - ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); ASSERT(mSwapChain); - EGLint status = mSwapChain->resize(std::max(1, backbufferWidth), std::max(1, backbufferHeight)); +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + backbufferWidth = std::max(1, backbufferWidth); + backbufferHeight = std::max(1, backbufferHeight); +#endif + EGLint status = mSwapChain->resize(backbufferWidth, backbufferHeight); if (status == EGL_CONTEXT_LOST) { mDisplay->notifyDeviceLost(); - return false; + return Error(status); } else if (status != EGL_SUCCESS) { - return error(status, false); + return Error(status); } mWidth = backbufferWidth; mHeight = backbufferHeight; - return true; + return Error(EGL_SUCCESS); } -bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) +Error Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) { ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); ASSERT(mSwapChain); @@ -269,69 +195,71 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) if (status == EGL_CONTEXT_LOST) { mRenderer->notifyDeviceLost(); - return false; + return Error(status); } else if (status != EGL_SUCCESS) { - return error(status, false); + return Error(status); } mWidth = backbufferWidth; mHeight = backbufferHeight; mSwapIntervalDirty = false; - return true; + return Error(EGL_SUCCESS); } -bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) +Error Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) { if (!mSwapChain) { - return true; + return Error(EGL_SUCCESS); } - if (x + width > mWidth) + if (x + width > abs(mWidth)) { - width = mWidth - x; + width = abs(mWidth) - x; } - if (y + height > mHeight) + if (y + height > abs(mHeight)) { - height = mHeight - y; + height = abs(mHeight) - y; } if (width == 0 || height == 0) { - return true; + return Error(EGL_SUCCESS); } - EGLint status = mSwapChain->swapRect(x, y, width, height, mSwapFlags); + ASSERT(width > 0); + ASSERT(height > 0); + + EGLint status = mSwapChain->swapRect(x, y, width, height); if (status == EGL_CONTEXT_LOST) { mRenderer->notifyDeviceLost(); - return false; + return Error(status); } else if (status != EGL_SUCCESS) { - return error(status, false); + return Error(status); } checkForOutOfDateSwapChain(); - return true; + return Error(EGL_SUCCESS); } EGLNativeWindowType Surface::getWindowHandle() { - return mWindow; + return mNativeWindow.getNativeWindow(); } - +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) #define kSurfaceProperty _TEXT("Egl::SurfaceOwner") #define kParentWndProc _TEXT("Egl::SurfaceParentWndProc") -#if !defined(ANGLE_PLATFORM_WINRT) static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { if (message == WM_SIZE) @@ -349,45 +277,50 @@ static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam void Surface::subclassWindow() { -#if !defined(ANGLE_PLATFORM_WINRT) - if (!mWindow) +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + HWND window = mNativeWindow.getNativeWindow(); + if (!window) { return; } DWORD processId; - DWORD threadId = GetWindowThreadProcessId(mWindow, &processId); + DWORD threadId = GetWindowThreadProcessId(window, &processId); if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId()) { return; } SetLastError(0); - LONG_PTR oldWndProc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, reinterpret_cast(SurfaceWindowProc)); + LONG_PTR oldWndProc = SetWindowLongPtr(window, GWLP_WNDPROC, reinterpret_cast(SurfaceWindowProc)); if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS) { mWindowSubclassed = false; return; } - SetProp(mWindow, kSurfaceProperty, reinterpret_cast(this)); - SetProp(mWindow, kParentWndProc, reinterpret_cast(oldWndProc)); + SetProp(window, kSurfaceProperty, reinterpret_cast(this)); + SetProp(window, kParentWndProc, reinterpret_cast(oldWndProc)); mWindowSubclassed = true; -#else - mWindowSubclassed = false; #endif } void Surface::unsubclassWindow() { -#if !defined(ANGLE_PLATFORM_WINRT) if(!mWindowSubclassed) { return; } +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + HWND window = mNativeWindow.getNativeWindow(); + if (!window) + { + return; + } + // un-subclass - LONG_PTR parentWndFunc = reinterpret_cast(GetProp(mWindow, kParentWndProc)); + LONG_PTR parentWndFunc = reinterpret_cast(GetProp(window, kParentWndProc)); // Check the windowproc is still SurfaceWindowProc. // If this assert fails, then it is likely the application has subclassed the @@ -396,29 +329,28 @@ void Surface::unsubclassWindow() // EGL context, or to unsubclass before destroying the EGL context. if(parentWndFunc) { - LONG_PTR prevWndFunc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, parentWndFunc); + LONG_PTR prevWndFunc = SetWindowLongPtr(window, GWLP_WNDPROC, parentWndFunc); UNUSED_ASSERTION_VARIABLE(prevWndFunc); ASSERT(prevWndFunc == reinterpret_cast(SurfaceWindowProc)); } - RemoveProp(mWindow, kSurfaceProperty); - RemoveProp(mWindow, kParentWndProc); - mWindowSubclassed = false; + RemoveProp(window, kSurfaceProperty); + RemoveProp(window, kParentWndProc); #endif + mWindowSubclassed = false; } bool Surface::checkForOutOfDateSwapChain() { + RECT client; int clientWidth = getWidth(); int clientHeight = getHeight(); bool sizeDirty = false; -#if !defined(ANGLE_PLATFORM_WINRT) - if (!mFixedSize && !IsIconic(getWindowHandle())) + if (!mFixedSize && !mNativeWindow.isIconic()) { - RECT client; // 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. - if (!GetClientRect(getWindowHandle(), &client)) + if (!mNativeWindow.getClientRect(&client)) { ASSERT(false); return false; @@ -429,7 +361,13 @@ bool Surface::checkForOutOfDateSwapChain() clientHeight = client.bottom - client.top; sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); } -#endif + + if (mFixedSize && (mWidth != mFixedWidth || mHeight != mFixedHeight)) + { + clientWidth = mFixedWidth; + clientHeight = mFixedHeight; + sizeDirty = true; + } bool wasDirty = (mSwapIntervalDirty || sizeDirty); @@ -455,17 +393,17 @@ bool Surface::checkForOutOfDateSwapChain() return false; } -bool Surface::swap() +Error Surface::swap() { - return swapRect(0, 0, mWidth, mHeight); + return swapRect(0, 0, abs(mWidth), abs(mHeight)); } -bool Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) +Error Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) { if (!mPostSubBufferSupported) { // Spec is not clear about how this should be handled. - return true; + return Error(EGL_SUCCESS); } return swapRect(x, y, width, height); @@ -550,77 +488,18 @@ EGLint Surface::isFixedSize() const return mFixedSize; } +void Surface::setFixedWidth(EGLint width) +{ + mFixedWidth = width; +} + +void Surface::setFixedHeight(EGLint height) +{ + mFixedHeight = height; +} + EGLenum Surface::getFormat() const { return mConfig->mRenderTargetFormat; } - -#if defined(ANGLE_PLATFORM_WINRT) - -HRESULT Surface::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *args) -{ - HRESULT hr; - Size size; - hr = args->get_Size(&size); - ASSERT(SUCCEEDED(hr)); - - resizeSwapChain(std::floor(size.Width * mScaleFactor + 0.5), - std::floor(size.Height * mScaleFactor + 0.5)); - - if (static_cast(getCurrentDrawSurface()) == this) - { - glMakeCurrent(glGetCurrentContext(), static_cast(getCurrentDisplay()), this); - } - - return S_OK; -} - -HRESULT Surface::onDpiChanged(IDisplayInformation *displayInformation, IInspectable *) -{ - HRESULT hr; -# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP - ComPtr displayInformation2; - hr = displayInformation->QueryInterface(displayInformation2.GetAddressOf()); - ASSERT(SUCCEEDED(hr)); - - hr = displayInformation2->get_RawPixelsPerViewPixel(&mScaleFactor); - ASSERT(SUCCEEDED(hr)); -# else - ResolutionScale resolutionScale; - hr = displayInformation->get_ResolutionScale(&resolutionScale); - ASSERT(SUCCEEDED(hr)); - - mScaleFactor = double(resolutionScale) / 100.0; -# endif - return S_OK; -} - -# if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP -HRESULT Surface::onOrientationChanged(IDisplayInformation *displayInformation, IInspectable *) -{ - HRESULT hr; - DisplayOrientations orientation; - hr = displayInformation->get_CurrentOrientation(&orientation); - ASSERT(SUCCEEDED(hr)); - switch (orientation) { - default: - case DisplayOrientations_Portrait: - mSwapFlags = rx::SWAP_NORMAL; - break; - case DisplayOrientations_Landscape: - mSwapFlags = rx::SWAP_ROTATE_90; - break; - case DisplayOrientations_LandscapeFlipped: - mSwapFlags = rx::SWAP_ROTATE_270; - break; - case DisplayOrientations_PortraitFlipped: - mSwapFlags = rx::SWAP_ROTATE_180; - break; - } - return S_OK; -} -# endif - -#endif - } diff --git a/src/3rdparty/angle/src/libEGL/Surface.h b/src/3rdparty/angle/src/libEGL/Surface.h index ebffce8fed6..46382d06e1f 100644 --- a/src/3rdparty/angle/src/libEGL/Surface.h +++ b/src/3rdparty/angle/src/libEGL/Surface.h @@ -11,23 +11,12 @@ #ifndef LIBEGL_SURFACE_H_ #define LIBEGL_SURFACE_H_ +#include "libEGL/Error.h" + #include #include "common/angleutils.h" - -#if defined(ANGLE_PLATFORM_WINRT) -#include -namespace ABI { namespace Windows { - namespace UI { namespace Core { - struct ICoreWindow; - struct IWindowSizeChangedEventArgs; - } } - namespace Graphics { namespace Display { - struct IDisplayInformation; - } } -} } -struct IInspectable; -#endif +#include "common/NativeWindow.h" namespace gl { @@ -35,8 +24,8 @@ class Texture2D; } namespace rx { -class Renderer; class SwapChain; +class RendererD3D; //TODO(jmadill): remove this } namespace egl @@ -52,13 +41,13 @@ class Surface virtual ~Surface(); - bool initialize(); + Error initialize(); void release(); - bool resetSwapChain(); + Error resetSwapChain(); EGLNativeWindowType getWindowHandle(); - bool swap(); - bool postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height); + Error swap(); + Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height); virtual EGLint isPostSubBufferSupported() const; @@ -81,35 +70,31 @@ class Surface virtual gl::Texture2D *getBoundTexture() const; EGLint isFixedSize() const; + void setFixedWidth(EGLint width); + void setFixedHeight(EGLint height); -private: + private: DISALLOW_COPY_AND_ASSIGN(Surface); -#if defined(ANGLE_PLATFORM_WINRT) - HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *); - HRESULT onDpiChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *); -# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP - HRESULT onOrientationChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *); -# endif -#endif - Display *const mDisplay; - rx::Renderer *mRenderer; + rx::RendererD3D *mRenderer; HANDLE mShareHandle; rx::SwapChain *mSwapChain; void subclassWindow(); void unsubclassWindow(); - bool resizeSwapChain(int backbufferWidth, int backbufferHeight); - bool resetSwapChain(int backbufferWidth, int backbufferHeight); - bool swapRect(EGLint x, EGLint y, EGLint width, EGLint height); + Error resizeSwapChain(int backbufferWidth, int backbufferHeight); + Error resetSwapChain(int backbufferWidth, int backbufferHeight); + Error swapRect(EGLint x, EGLint y, EGLint width, EGLint height); - const EGLNativeWindowType mWindow; // Window that the surface is created for. + rx::NativeWindow mNativeWindow; // Handler for the 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 EGLint mWidth; // Width of surface + EGLint mFixedHeight; // Pending height of the surface + EGLint mFixedWidth; // Pending width of the surface // EGLint horizontalResolution; // Horizontal dot pitch // EGLint verticalResolution; // Vertical dot pitch // EGLBoolean largestPBuffer; // If true, create largest pbuffer possible @@ -126,18 +111,9 @@ private: EGLint mSwapInterval; EGLint mPostSubBufferSupported; EGLint mFixedSize; - EGLint mSwapFlags; bool mSwapIntervalDirty; gl::Texture2D *mTexture; -#if defined(ANGLE_PLATFORM_WINRT) - double mScaleFactor; - EventRegistrationToken mSizeToken; - EventRegistrationToken mDpiToken; -# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP - EventRegistrationToken mOrientationToken; -# endif -#endif }; } diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp index c2e0fd6d3d8..68399d63a4b 100644 --- a/src/3rdparty/angle/src/libEGL/libEGL.cpp +++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp @@ -13,7 +13,6 @@ #include "common/debug.h" #include "common/version.h" -#include "common/platform.h" #include "libGLESv2/Context.h" #include "libGLESv2/Texture.h" #include "libGLESv2/main.h" @@ -26,16 +25,20 @@ #include "libEGL/Display.h" #include "libEGL/Surface.h" +#include "common/NativeWindow.h" + bool validateDisplay(egl::Display *display) { if (display == EGL_NO_DISPLAY) { - return egl::error(EGL_BAD_DISPLAY, false); + recordError(egl::Error(EGL_BAD_DISPLAY)); + return false; } if (!display->isInitialized()) { - return egl::error(EGL_NOT_INITIALIZED, false); + recordError(egl::Error(EGL_NOT_INITIALIZED)); + return false; } return true; @@ -50,7 +53,8 @@ bool validateConfig(egl::Display *display, EGLConfig config) if (!display->isValidConfig(config)) { - return egl::error(EGL_BAD_CONFIG, false); + recordError(egl::Error(EGL_BAD_CONFIG)); + return false; } return true; @@ -65,7 +69,8 @@ bool validateContext(egl::Display *display, gl::Context *context) if (!display->isValidContext(context)) { - return egl::error(EGL_BAD_CONTEXT, false); + recordError(egl::Error(EGL_BAD_CONTEXT)); + return false; } return true; @@ -80,7 +85,8 @@ bool validateSurface(egl::Display *display, egl::Surface *surface) if (!display->isValidSurface(surface)) { - return egl::error(EGL_BAD_SURFACE, false); + recordError(egl::Error(EGL_BAD_SURFACE)); + return false; } return true; @@ -93,12 +99,7 @@ EGLint __stdcall eglGetError(void) EVENT("()"); EGLint error = egl::getCurrentError(); - - if (error != EGL_SUCCESS) - { - egl::setCurrentError(EGL_SUCCESS); - } - + recordError(egl::Error(EGL_SUCCESS)); return error; } @@ -106,7 +107,7 @@ EGLDisplay __stdcall eglGetDisplay(EGLNativeDisplayType display_id) { EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id); - return egl::Display::getDisplay(display_id, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE); + return egl::Display::getDisplay(display_id, egl::AttributeMap()); } EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list) @@ -120,19 +121,26 @@ EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_dis break; default: - return egl::error(EGL_BAD_CONFIG, EGL_NO_DISPLAY); + recordError(egl::Error(EGL_BAD_CONFIG)); + return EGL_NO_DISPLAY; } EGLNativeDisplayType displayId = static_cast(native_display); -#if !defined(ANGLE_PLATFORM_WINRT) + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) // Validate the display device context if (WindowFromDC(displayId) == NULL) { - return egl::success(EGL_NO_DISPLAY); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_NO_DISPLAY; } #endif - EGLint requestedDisplayType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE; + EGLint platformType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE; + bool majorVersionSpecified = false; + bool minorVersionSpecified = false; + bool requestedWARP = false; + if (attrib_list) { for (const EGLint *curAttrib = attrib_list; curAttrib[0] != EGL_NONE; curAttrib += 2) @@ -140,7 +148,69 @@ EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_dis switch (curAttrib[0]) { case EGL_PLATFORM_ANGLE_TYPE_ANGLE: - requestedDisplayType = curAttrib[1]; + switch (curAttrib[1]) + { + case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE: + break; + + case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE: + case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE: + if (!egl::Display::supportsPlatformD3D()) + { + recordError(egl::Error(EGL_SUCCESS)); + return EGL_NO_DISPLAY; + } + break; + + case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE: + case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE: + if (!egl::Display::supportsPlatformOpenGL()) + { + recordError(egl::Error(EGL_SUCCESS)); + return EGL_NO_DISPLAY; + } + break; + + default: + recordError(egl::Error(EGL_SUCCESS)); + return EGL_NO_DISPLAY; + } + platformType = curAttrib[1]; + break; + + case EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE: + if (curAttrib[1] != EGL_DONT_CARE) + { + majorVersionSpecified = true; + } + break; + + case EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE: + if (curAttrib[1] != EGL_DONT_CARE) + { + minorVersionSpecified = true; + } + break; + + case EGL_PLATFORM_ANGLE_USE_WARP_ANGLE: + if (!egl::Display::supportsPlatformD3D()) + { + recordError(egl::Error(EGL_SUCCESS)); + return EGL_NO_DISPLAY; + } + + switch (curAttrib[1]) + { + case EGL_FALSE: + case EGL_TRUE: + break; + + default: + recordError(egl::Error(EGL_SUCCESS)); + return EGL_NO_DISPLAY; + } + + requestedWARP = (curAttrib[1] == EGL_TRUE); break; default: @@ -149,33 +219,20 @@ EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_dis } } - switch (requestedDisplayType) + if (!majorVersionSpecified && minorVersionSpecified) { - case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE: - break; - - case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE: - case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE: - case EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE: - if (!egl::Display::supportsPlatformD3D()) - { - return egl::success(EGL_NO_DISPLAY); - } - break; - - case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE: - case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE: - if (!egl::Display::supportsPlatformOpenGL()) - { - return egl::success(EGL_NO_DISPLAY); - } - break; - - default: - return egl::success(EGL_NO_DISPLAY); + recordError(egl::Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_DISPLAY; } - return egl::Display::getDisplay(displayId, requestedDisplayType); + if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE && requestedWARP) + { + recordError(egl::Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_DISPLAY; + } + + recordError(egl::Error(EGL_SUCCESS)); + return egl::Display::getDisplay(displayId, egl::AttributeMap(attrib_list)); } EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) @@ -185,20 +242,24 @@ EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) if (dpy == EGL_NO_DISPLAY) { - return egl::error(EGL_BAD_DISPLAY, EGL_FALSE); + recordError(egl::Error(EGL_BAD_DISPLAY)); + return EGL_FALSE; } egl::Display *display = static_cast(dpy); - if (!display->initialize()) + egl::Error error = display->initialize(); + if (error.isError()) { - return egl::error(EGL_NOT_INITIALIZED, EGL_FALSE); + recordError(error); + return EGL_FALSE; } if (major) *major = 1; if (minor) *minor = 4; - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLBoolean __stdcall eglTerminate(EGLDisplay dpy) @@ -207,14 +268,16 @@ EGLBoolean __stdcall eglTerminate(EGLDisplay dpy) if (dpy == EGL_NO_DISPLAY) { - return egl::error(EGL_BAD_DISPLAY, EGL_FALSE); + recordError(egl::Error(EGL_BAD_DISPLAY)); + return EGL_FALSE; } egl::Display *display = static_cast(dpy); display->terminate(); - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name) @@ -227,19 +290,28 @@ const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name) return NULL; } + const char *result; switch (name) { case EGL_CLIENT_APIS: - return egl::success("OpenGL_ES"); + result = "OpenGL_ES"; + break; case EGL_EXTENSIONS: - return egl::success(egl::Display::getExtensionString(display)); + result = egl::Display::getExtensionString(display); + break; case EGL_VENDOR: - return egl::success(display->getVendorString()); + result = display->getVendorString(); + break; case EGL_VERSION: - return egl::success("1.4 (ANGLE " ANGLE_VERSION_STRING ")"); + result = "1.4 (ANGLE " ANGLE_VERSION_STRING ")"; + break; default: - return egl::error(EGL_BAD_PARAMETER, (const char*)NULL); + recordError(egl::Error(EGL_BAD_PARAMETER)); + return NULL; } + + recordError(egl::Error(EGL_SUCCESS)); + return result; } EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) @@ -257,17 +329,20 @@ EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint co if (!num_config) { - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); + recordError(egl::Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; } const EGLint attribList[] = {EGL_NONE}; if (!display->getConfigs(configs, attribList, config_size, num_config)) { - return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; } - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) @@ -285,7 +360,8 @@ EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, if (!num_config) { - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); + recordError(egl::Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; } const EGLint attribList[] = {EGL_NONE}; @@ -297,7 +373,8 @@ EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, display->getConfigs(configs, attrib_list, config_size, num_config); - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) @@ -314,10 +391,12 @@ EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint if (!display->getConfigAttrib(config, attribute, value)) { - return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; } - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list) @@ -332,16 +411,21 @@ EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EG return EGL_NO_SURFACE; } -#if !defined(ANGLE_PLATFORM_WINRT) - HWND window = (HWND)win; - - if (!IsWindow(window)) + if (!rx::IsValidEGLNativeWindowType(win)) { - return egl::error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); + recordError(egl::Error(EGL_BAD_NATIVE_WINDOW)); + return EGL_NO_SURFACE; } -#endif - return display->createWindowSurface(win, config, attrib_list); + EGLSurface surface = EGL_NO_SURFACE; + egl::Error error = display->createWindowSurface(win, config, attrib_list, &surface); + if (error.isError()) + { + recordError(error); + return EGL_NO_SURFACE; + } + + return surface; } EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) @@ -356,7 +440,15 @@ EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, c return EGL_NO_SURFACE; } - return display->createOffscreenSurface(config, NULL, attrib_list); + EGLSurface surface = EGL_NO_SURFACE; + egl::Error error = display->createOffscreenSurface(config, NULL, attrib_list, &surface); + if (error.isError()) + { + recordError(error); + return EGL_NO_SURFACE; + } + + return surface; } EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) @@ -373,7 +465,8 @@ EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EG UNIMPLEMENTED(); // FIXME - return egl::success(EGL_NO_SURFACE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_NO_SURFACE; } EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface) @@ -390,12 +483,14 @@ EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface) if (surface == EGL_NO_SURFACE) { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_SURFACE)); + return EGL_FALSE; } display->destroySurface((egl::Surface*)surface); - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) @@ -413,7 +508,8 @@ EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint if (surface == EGL_NO_SURFACE) { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_SURFACE)); + return EGL_FALSE; } switch (attribute) @@ -473,10 +569,12 @@ EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint *value = eglSurface->isFixedSize(); break; default: - return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; } - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value) @@ -498,7 +596,8 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf if (surface == EGL_NO_SURFACE) { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_SURFACE)); + return EGL_FALSE; } rx::SwapChain *swapchain = eglSurface->getSwapChain(); @@ -522,7 +621,8 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf if (renderer->getMajorShaderModel() < 4) { - return egl::error(EGL_BAD_CONTEXT, EGL_FALSE); + recordError(egl::Error(EGL_BAD_CONTEXT)); + return EGL_FALSE; } *value = static_cast(renderer)->getDevice(); @@ -530,10 +630,12 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf break; #endif default: - return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; } - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLBoolean __stdcall eglBindAPI(EGLenum api) @@ -544,16 +646,19 @@ EGLBoolean __stdcall eglBindAPI(EGLenum api) { case EGL_OPENGL_API: case EGL_OPENVG_API: - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); // Not supported by this implementation + recordError(egl::Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; // Not supported by this implementation case EGL_OPENGL_ES_API: break; default: - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); + recordError(egl::Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; } egl::setCurrentAPI(api); - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLenum __stdcall eglQueryAPI(void) @@ -562,7 +667,8 @@ EGLenum __stdcall eglQueryAPI(void) EGLenum API = egl::getCurrentAPI(); - return egl::success(API); + recordError(egl::Error(EGL_SUCCESS)); + return API; } EGLBoolean __stdcall eglWaitClient(void) @@ -571,7 +677,8 @@ EGLBoolean __stdcall eglWaitClient(void) UNIMPLEMENTED(); // FIXME - return egl::success(0); + recordError(egl::Error(EGL_SUCCESS)); + return 0; } EGLBoolean __stdcall eglReleaseThread(void) @@ -580,7 +687,8 @@ EGLBoolean __stdcall eglReleaseThread(void) eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE); - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) @@ -598,10 +706,19 @@ EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum bu if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer) { - return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); + recordError(egl::Error(EGL_BAD_PARAMETER)); + return EGL_NO_SURFACE; } - return display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list); + EGLSurface surface = EGL_NO_SURFACE; + egl::Error error = display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list, &surface); + if (error.isError()) + { + recordError(error); + return EGL_NO_SURFACE; + } + + return surface; } EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) @@ -617,9 +734,30 @@ EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint return EGL_FALSE; } + switch (attribute) + { + case EGL_WIDTH: + if (!eglSurface->isFixedSize() || !value) { + recordError(egl::Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; + } + eglSurface->setFixedWidth(value); + return EGL_TRUE; + case EGL_HEIGHT: + if (!eglSurface->isFixedSize() || !value) { + recordError(egl::Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; + } + eglSurface->setFixedHeight(value); + return EGL_TRUE; + default: + break; + } + UNIMPLEMENTED(); // FIXME - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) @@ -636,30 +774,36 @@ EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint if (buffer != EGL_BACK_BUFFER) { - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); + recordError(egl::Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; } if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_SURFACE)); + return EGL_FALSE; } if (eglSurface->getBoundTexture()) { - return egl::error(EGL_BAD_ACCESS, EGL_FALSE); + recordError(egl::Error(EGL_BAD_ACCESS)); + return EGL_FALSE; } if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) { - return egl::error(EGL_BAD_MATCH, EGL_FALSE); + recordError(egl::Error(EGL_BAD_MATCH)); + return EGL_FALSE; } if (!glBindTexImage(eglSurface)) { - return egl::error(EGL_BAD_MATCH, EGL_FALSE); + recordError(egl::Error(EGL_BAD_MATCH)); + return EGL_FALSE; } - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) @@ -676,17 +820,20 @@ EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLi if (buffer != EGL_BACK_BUFFER) { - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); + recordError(egl::Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; } if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_SURFACE)); + return EGL_FALSE; } if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) { - return egl::error(EGL_BAD_MATCH, EGL_FALSE); + recordError(egl::Error(EGL_BAD_MATCH)); + return EGL_FALSE; } gl::Texture2D *texture = eglSurface->getBoundTexture(); @@ -696,7 +843,8 @@ EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLi texture->releaseTexImage(); } - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval) @@ -714,12 +862,14 @@ EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval) if (draw_surface == NULL) { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_SURFACE)); + return EGL_FALSE; } draw_surface->setSwapInterval(interval); - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) @@ -744,27 +894,38 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT: if (attribute[1] == EGL_TRUE) { - return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); // Unimplemented + recordError(egl::Error(EGL_BAD_CONFIG)); // Unimplemented + return EGL_NO_CONTEXT; // robust_access = true; } else if (attribute[1] != EGL_FALSE) - return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); + { + recordError(egl::Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_CONTEXT; + } break; case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT: if (attribute[1] == EGL_LOSE_CONTEXT_ON_RESET_EXT) + { reset_notification = true; + } else if (attribute[1] != EGL_NO_RESET_NOTIFICATION_EXT) - return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); + { + recordError(egl::Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_CONTEXT; + } break; default: - return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); + recordError(egl::Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_CONTEXT; } } } if (client_version != 2 && client_version != 3) { - return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); + recordError(egl::Error(EGL_BAD_CONFIG)); + return EGL_NO_CONTEXT; } egl::Display *display = static_cast(dpy); @@ -775,18 +936,21 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte if (sharedGLContext->isResetNotificationEnabled() != reset_notification) { - return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT); + recordError(egl::Error(EGL_BAD_MATCH)); + return EGL_NO_CONTEXT; } if (sharedGLContext->getClientVersion() != client_version) { - return egl::error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT); + recordError(egl::Error(EGL_BAD_CONTEXT)); + return EGL_NO_CONTEXT; } // Can not share contexts between displays if (sharedGLContext->getRenderer() != display->getRenderer()) { - return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT); + recordError(egl::Error(EGL_BAD_MATCH)); + return EGL_NO_CONTEXT; } } @@ -795,7 +959,16 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte return EGL_NO_CONTEXT; } - return display->createContext(config, client_version, static_cast(share_context), reset_notification, robust_access); + EGLContext context = EGL_NO_CONTEXT; + egl::Error error = display->createContext(config, client_version, static_cast(share_context), + reset_notification, robust_access, &context); + if (error.isError()) + { + recordError(error); + return EGL_NO_CONTEXT; + } + + return context; } EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx) @@ -812,12 +985,14 @@ EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx) if (ctx == EGL_NO_CONTEXT) { - return egl::error(EGL_BAD_CONTEXT, EGL_FALSE); + recordError(egl::Error(EGL_BAD_CONTEXT)); + return EGL_FALSE; } display->destroyContext(context); - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) @@ -832,7 +1007,8 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface bool noSurface = (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE); if (noContext != noSurface) { - return egl::error(EGL_BAD_MATCH, EGL_FALSE); + recordError(egl::Error(EGL_BAD_MATCH)); + return EGL_FALSE; } if (ctx != EGL_NO_CONTEXT && !validateContext(display, context)) @@ -850,7 +1026,8 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface if (renderer->isDeviceLost()) { - return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); + recordError(egl::Error(EGL_CONTEXT_LOST)); + return EGL_FALSE; } } @@ -871,7 +1048,8 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface glMakeCurrent(context, display, static_cast(draw)); - return egl::success(EGL_TRUE); + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLContext __stdcall eglGetCurrentContext(void) @@ -880,7 +1058,8 @@ EGLContext __stdcall eglGetCurrentContext(void) EGLContext context = glGetCurrentContext(); - return egl::success(context); + recordError(egl::Error(EGL_SUCCESS)); + return context; } EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw) @@ -889,17 +1068,18 @@ EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw) if (readdraw == EGL_READ) { - EGLSurface read = egl::getCurrentReadSurface(); - return egl::success(read); + recordError(egl::Error(EGL_SUCCESS)); + return egl::getCurrentReadSurface(); } else if (readdraw == EGL_DRAW) { - EGLSurface draw = egl::getCurrentDrawSurface(); - return egl::success(draw); + recordError(egl::Error(EGL_SUCCESS)); + return egl::getCurrentDrawSurface(); } else { - return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); + recordError(egl::Error(EGL_BAD_PARAMETER)); + return EGL_NO_SURFACE; } } @@ -909,7 +1089,8 @@ EGLDisplay __stdcall eglGetCurrentDisplay(void) EGLDisplay dpy = egl::getCurrentDisplay(); - return egl::success(dpy); + recordError(egl::Error(EGL_SUCCESS)); + return dpy; } EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) @@ -927,7 +1108,8 @@ EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attr UNIMPLEMENTED(); // FIXME - return egl::success(0); + recordError(egl::Error(EGL_SUCCESS)); + return 0; } EGLBoolean __stdcall eglWaitGL(void) @@ -936,7 +1118,8 @@ EGLBoolean __stdcall eglWaitGL(void) UNIMPLEMENTED(); // FIXME - return egl::success(0); + recordError(egl::Error(EGL_SUCCESS)); + return 0; } EGLBoolean __stdcall eglWaitNative(EGLint engine) @@ -945,7 +1128,8 @@ EGLBoolean __stdcall eglWaitNative(EGLint engine) UNIMPLEMENTED(); // FIXME - return egl::success(0); + recordError(egl::Error(EGL_SUCCESS)); + return 0; } EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) @@ -962,20 +1146,25 @@ EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) if (display->getRenderer()->isDeviceLost()) { - return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); + recordError(egl::Error(EGL_CONTEXT_LOST)); + return EGL_FALSE; } if (surface == EGL_NO_SURFACE) { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_SURFACE)); + return EGL_FALSE; } - if (eglSurface->swap()) + egl::Error error = eglSurface->swap(); + if (error.isError()) { - return egl::success(EGL_TRUE); + recordError(error); + return EGL_FALSE; } - return EGL_FALSE; + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) @@ -992,12 +1181,14 @@ EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativ if (display->getRenderer()->isDeviceLost()) { - return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); + recordError(egl::Error(EGL_CONTEXT_LOST)); + return EGL_FALSE; } UNIMPLEMENTED(); // FIXME - return egl::success(0); + recordError(egl::Error(EGL_SUCCESS)); + return 0; } EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height) @@ -1006,7 +1197,8 @@ EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLi if (x < 0 || y < 0 || width < 0 || height < 0) { - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); + recordError(egl::Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; } egl::Display *display = static_cast(dpy); @@ -1019,20 +1211,25 @@ EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLi if (display->getRenderer()->isDeviceLost()) { - return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); + recordError(egl::Error(EGL_CONTEXT_LOST)); + return EGL_FALSE; } if (surface == EGL_NO_SURFACE) { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + recordError(egl::Error(EGL_BAD_SURFACE)); + return EGL_FALSE; } - if (eglSurface->postSubBuffer(x, y, width, height)) + egl::Error error = eglSurface->postSubBuffer(x, y, width, height); + if (error.isError()) { - return egl::success(EGL_TRUE); + recordError(error); + return EGL_FALSE; } - return EGL_FALSE; + recordError(egl::Error(EGL_SUCCESS)); + return EGL_TRUE; } __eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char *procname) diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp index e74737eabaa..e88cad775f9 100644 --- a/src/3rdparty/angle/src/libEGL/main.cpp +++ b/src/3rdparty/angle/src/libEGL/main.cpp @@ -11,9 +11,6 @@ #include "common/debug.h" #include "common/tls.h" -#if defined(ANGLE_PLATFORM_WINRT) -__declspec(thread) -#endif static TLSIndex currentTLS = TLS_OUT_OF_INDEXES; namespace egl @@ -21,12 +18,6 @@ namespace egl Current *AllocateCurrent() { -#if defined(ANGLE_PLATFORM_WINRT) - if (currentTLS == TLS_OUT_OF_INDEXES) - { - currentTLS = CreateTLSIndex(); - } -#endif ASSERT(currentTLS != TLS_OUT_OF_INDEXES); if (currentTLS == TLS_OUT_OF_INDEXES) { @@ -51,12 +42,6 @@ Current *AllocateCurrent() void DeallocateCurrent() { -#if defined(ANGLE_PLATFORM_WINRT) - if (currentTLS == TLS_OUT_OF_INDEXES) - { - return; - } -#endif Current *current = reinterpret_cast(GetTLSValue(currentTLS)); SafeDelete(current); SetTLSValue(currentTLS, NULL); @@ -72,7 +57,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved { case DLL_PROCESS_ATTACH: { -#if defined(ANGLE_ENABLE_TRACE) +#if defined(ANGLE_ENABLE_DEBUG_TRACE) FILE *debug = fopen(TRACE_OUTPUT_FILE, "rt"); if (debug) @@ -87,15 +72,15 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved } #endif -#if defined(ANGLE_PLATFORM_WINRT) // On WinRT, don't handle TLS from DllMain - return DisableThreadLibraryCalls(instance); -#endif - currentTLS = CreateTLSIndex(); if (currentTLS == TLS_OUT_OF_INDEXES) { return FALSE; } + +#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS + gl::InitializeDebugAnnotations(); +#endif } // Fall through to initialize index case DLL_THREAD_ATTACH: @@ -105,15 +90,17 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved break; case DLL_THREAD_DETACH: { -#if !defined(ANGLE_PLATFORM_WINRT) egl::DeallocateCurrent(); -#endif } break; case DLL_PROCESS_DETACH: { egl::DeallocateCurrent(); DestroyTLSIndex(currentTLS); + +#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS + gl::UninitializeDebugAnnotations(); +#endif } break; default: @@ -143,11 +130,11 @@ Current *GetCurrentData() #endif } -void setCurrentError(EGLint error) +void recordError(const Error &error) { Current *current = GetCurrentData(); - current->error = error; + current->error = error.getCode(); } EGLint getCurrentError() @@ -213,9 +200,4 @@ EGLSurface getCurrentReadSurface() return current->readSurface; } -void error(EGLint errorCode) -{ - egl::setCurrentError(errorCode); -} - } diff --git a/src/3rdparty/angle/src/libEGL/main.h b/src/3rdparty/angle/src/libEGL/main.h index 07f5b9e6754..e5361a4a5ef 100644 --- a/src/3rdparty/angle/src/libEGL/main.h +++ b/src/3rdparty/angle/src/libEGL/main.h @@ -9,6 +9,8 @@ #ifndef LIBEGL_MAIN_H_ #define LIBEGL_MAIN_H_ +#include "libEGL/Error.h" + #include #include @@ -23,7 +25,7 @@ struct Current EGLSurface readSurface; }; -void setCurrentError(EGLint error); +void recordError(const Error &error); EGLint getCurrentError(); void setCurrentAPI(EGLenum API); @@ -38,24 +40,6 @@ EGLSurface getCurrentDrawSurface(); void setCurrentReadSurface(EGLSurface surface); EGLSurface getCurrentReadSurface(); -void error(EGLint errorCode); - -template -const T &error(EGLint errorCode, const T &returnValue) -{ - error(errorCode); - - return returnValue; -} - -template -const T &success(const T &returnValue) -{ - egl::setCurrentError(EGL_SUCCESS); - - return returnValue; -} - } #endif // LIBEGL_MAIN_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/BinaryStream.h b/src/3rdparty/angle/src/libGLESv2/BinaryStream.h index 4d7dde04e1e..4f7f5f2c85f 100644 --- a/src/3rdparty/angle/src/libGLESv2/BinaryStream.h +++ b/src/3rdparty/angle/src/libGLESv2/BinaryStream.h @@ -15,6 +15,7 @@ #include #include #include +#include namespace gl { @@ -26,7 +27,7 @@ class BinaryInputStream { mError = false; mOffset = 0; - mData = static_cast(data); + mData = static_cast(data); mLength = length; } @@ -85,7 +86,7 @@ class BinaryInputStream return; } - v->assign(mData + mOffset, length); + v->assign(reinterpret_cast(mData) + mOffset, length); mOffset += length; } @@ -115,11 +116,16 @@ class BinaryInputStream return mOffset == mLength; } + const uint8_t *data() + { + return mData; + } + private: DISALLOW_COPY_AND_ASSIGN(BinaryInputStream); bool mError; size_t mOffset; - const char *mData; + const uint8_t *mData; size_t mLength; template diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.h b/src/3rdparty/angle/src/libGLESv2/Buffer.h index 35a6767502c..daa862ca0d5 100644 --- a/src/3rdparty/angle/src/libGLESv2/Buffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Buffer.h @@ -19,7 +19,6 @@ namespace rx { -class Renderer; class BufferImpl; }; diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp index 5342de1331b..b87689cd3f5 100644 --- a/src/3rdparty/angle/src/libGLESv2/Context.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp @@ -9,10 +9,8 @@ #include "libGLESv2/Context.h" -#include "libGLESv2/main.h" #include "common/utilities.h" #include "common/platform.h" -#include "libGLESv2/formatutils.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/Fence.h" #include "libGLESv2/Framebuffer.h" @@ -21,14 +19,15 @@ #include "libGLESv2/Program.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/Query.h" -#include "libGLESv2/Texture.h" #include "libGLESv2/ResourceManager.h" -#include "libGLESv2/renderer/d3d/IndexDataManager.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/VertexArray.h" #include "libGLESv2/Sampler.h" -#include "libGLESv2/validationES.h" +#include "libGLESv2/Texture.h" #include "libGLESv2/TransformFeedback.h" +#include "libGLESv2/VertexArray.h" +#include "libGLESv2/formatutils.h" +#include "libGLESv2/main.h" +#include "libGLESv2/validationES.h" +#include "libGLESv2/renderer/Renderer.h" #include "libEGL/Surface.h" @@ -38,7 +37,7 @@ namespace gl { -Context::Context(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) +Context::Context(int clientVersion, const Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) : mRenderer(renderer) { ASSERT(robustAccess == false); // Unimplemented @@ -66,22 +65,24 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere // In order that access to these initial textures not be lost, they are treated as texture // objects all of whose names are 0. - mZeroTextures[GL_TEXTURE_2D].set(new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), 0)); - bindTexture(GL_TEXTURE_2D, 0); + Texture2D *zeroTexture2D = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), 0); + mZeroTextures[GL_TEXTURE_2D].set(zeroTexture2D); - mZeroTextures[GL_TEXTURE_CUBE_MAP].set(new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), 0)); - bindTexture(GL_TEXTURE_CUBE_MAP, 0); + TextureCubeMap *zeroTextureCube = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), 0); + mZeroTextures[GL_TEXTURE_CUBE_MAP].set(zeroTextureCube); if (mClientVersion >= 3) { // TODO: These could also be enabled via extension - mZeroTextures[GL_TEXTURE_3D].set(new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), 0)); - bindTexture(GL_TEXTURE_3D, 0); + Texture3D *zeroTexture3D = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), 0); + mZeroTextures[GL_TEXTURE_3D].set(zeroTexture3D); - mZeroTextures[GL_TEXTURE_2D_ARRAY].set(new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), 0)); - bindTexture(GL_TEXTURE_2D_ARRAY, 0); + Texture2DArray *zeroTexture2DArray = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), 0); + mZeroTextures[GL_TEXTURE_2D_ARRAY].set(zeroTexture2DArray); } + mState.initializeZeroTextures(mZeroTextures); + bindVertexArray(0); bindArrayBuffer(0); bindElementArrayBuffer(0); @@ -91,13 +92,13 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere bindRenderbuffer(0); bindGenericUniformBuffer(0); - for (int i = 0; i < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; i++) + for (unsigned int i = 0; i < mCaps.maxCombinedUniformBlocks; i++) { bindIndexedUniformBuffer(0, i, 0, -1); } bindGenericTransformFeedbackBuffer(0); - for (int i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) + for (unsigned int i = 0; i < mCaps.maxTransformFeedbackSeparateAttributes; i++) { bindIndexedTransformFeedbackBuffer(0, i, 0, -1); } @@ -119,8 +120,6 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere mResetStatus = GL_NO_ERROR; mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT); mRobustAccess = robustAccess; - - mState.setContext(this); } Context::~Context() @@ -175,7 +174,10 @@ Context::~Context() } mZeroTextures.clear(); - mResourceManager->release(); + if (mResourceManager) + { + mResourceManager->release(); + } } void Context::makeCurrent(egl::Surface *surface) @@ -194,14 +196,11 @@ void Context::makeCurrent(egl::Surface *surface) // Wrap the existing swapchain resources into GL objects and assign them to the '0' names rx::SwapChain *swapchain = surface->getSwapChain(); - Colorbuffer *colorbufferZero = new Colorbuffer(mRenderer, swapchain); - DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(mRenderer, swapchain); - Framebuffer *framebufferZero = new DefaultFramebuffer(mRenderer, colorbufferZero, depthStencilbufferZero); + rx::RenderbufferImpl *colorbufferZero = mRenderer->createRenderbuffer(swapchain, false); + rx::RenderbufferImpl *depthStencilbufferZero = mRenderer->createRenderbuffer(swapchain, true); + Framebuffer *framebufferZero = new DefaultFramebuffer(colorbufferZero, depthStencilbufferZero); setFramebufferZero(framebufferZero); - - // Store the current client version in the renderer - mRenderer->setCurrentClientVersion(mClientVersion); } // NOTE: this function should not assume that this context is current! @@ -229,7 +228,7 @@ GLuint Context::createProgram() GLuint Context::createShader(GLenum type) { - return mResourceManager->createShader(type); + return mResourceManager->createShader(getData(), type); } GLuint Context::createTexture() @@ -242,15 +241,10 @@ GLuint Context::createRenderbuffer() return mResourceManager->createRenderbuffer(); } -GLsync Context::createFenceSync(GLenum condition) +GLsync Context::createFenceSync() { GLuint handle = mResourceManager->createFenceSync(); - gl::FenceSync *fenceSync = mResourceManager->getFenceSync(handle); - ASSERT(fenceSync); - - fenceSync->set(condition); - return reinterpret_cast(handle); } @@ -294,7 +288,7 @@ GLuint Context::createFenceNV() { GLuint handle = mFenceNVHandleAllocator.allocate(); - mFenceNVMap[handle] = new FenceNV(mRenderer); + mFenceNVMap[handle] = new FenceNV(mRenderer->createFenceNV()); return handle; } @@ -355,12 +349,12 @@ void Context::deleteFenceSync(GLsync fenceSync) // wait commands finish. However, since the name becomes invalid, we cannot query the fence, // and since our API is currently designed for being called from a single thread, we can delete // the fence immediately. - mResourceManager->deleteFenceSync(uintptr_t(fenceSync)); + mResourceManager->deleteFenceSync(reinterpret_cast(fenceSync)); } void Context::deleteVertexArray(GLuint vertexArray) { - auto vertexArrayObject = mVertexArrayMap.find(vertexArray); + VertexArrayMap::iterator vertexArrayObject = mVertexArrayMap.find(vertexArray); if (vertexArrayObject != mVertexArrayMap.end()) { @@ -461,12 +455,12 @@ Renderbuffer *Context::getRenderbuffer(GLuint handle) FenceSync *Context::getFenceSync(GLsync handle) const { - return mResourceManager->getFenceSync(uintptr_t(handle)); + return mResourceManager->getFenceSync(reinterpret_cast(handle)); } VertexArray *Context::getVertexArray(GLuint handle) const { - auto vertexArray = mVertexArrayMap.find(handle); + VertexArrayMap::const_iterator vertexArray = mVertexArrayMap.find(handle); if (vertexArray == mVertexArrayMap.end()) { @@ -515,18 +509,30 @@ void Context::bindElementArrayBuffer(unsigned int buffer) mState.getVertexArray()->setElementArrayBuffer(getBuffer(buffer)); } -void Context::bindTexture(GLenum target, GLuint texture) +void Context::bindTexture(GLenum target, GLuint handle) { - mResourceManager->checkTextureAllocation(texture, target); + Texture *texture = NULL; - mState.setSamplerTexture(target, getTexture(texture)); + if (handle == 0) + { + texture = mZeroTextures[target].get(); + } + else + { + mResourceManager->checkTextureAllocation(handle, target); + texture = getTexture(handle); + } + + ASSERT(texture); + + mState.setSamplerTexture(target, texture); } void Context::bindReadFramebuffer(GLuint framebuffer) { if (!getFramebuffer(framebuffer)) { - mFramebufferMap[framebuffer] = new Framebuffer(mRenderer, framebuffer); + mFramebufferMap[framebuffer] = new Framebuffer(framebuffer); } mState.setReadFramebufferBinding(getFramebuffer(framebuffer)); @@ -536,7 +542,7 @@ void Context::bindDrawFramebuffer(GLuint framebuffer) { if (!getFramebuffer(framebuffer)) { - mFramebufferMap[framebuffer] = new Framebuffer(mRenderer, framebuffer); + mFramebufferMap[framebuffer] = new Framebuffer(framebuffer); } mState.setDrawFramebufferBinding(getFramebuffer(framebuffer)); @@ -640,33 +646,44 @@ void Context::useProgram(GLuint program) } } -void Context::linkProgram(GLuint program) +Error Context::linkProgram(GLuint program) { Program *programObject = mResourceManager->getProgram(program); - bool linked = programObject->link(getCaps()); + Error error = programObject->link(getData()); + if (error.isError()) + { + return error; + } // if the current program was relinked successfully we // need to install the new executables - if (linked && program == mState.getCurrentProgramId()) + if (programObject->isLinked() && program == mState.getCurrentProgramId()) { mState.setCurrentProgramBinary(programObject->getProgramBinary()); } + + return Error(GL_NO_ERROR); } -void Context::setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length) +Error Context::setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length) { Program *programObject = mResourceManager->getProgram(program); - bool loaded = programObject->setProgramBinary(binaryFormat, binary, length); + Error error = programObject->setProgramBinary(binaryFormat, binary, length); + if (error.isError()) + { + return error; + } // if the current program was reloaded successfully we // need to install the new executables - if (loaded && program == mState.getCurrentProgramId()) + if (programObject->isLinked() && program == mState.getCurrentProgramId()) { mState.setCurrentProgramBinary(programObject->getProgramBinary()); } + return Error(GL_NO_ERROR); } void Context::bindTransformFeedback(GLuint transformFeedback) @@ -724,33 +741,6 @@ void Context::setFramebufferZero(Framebuffer *buffer) mFramebufferMap[0] = buffer; } -void Context::setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) -{ - ASSERT(getTextureCaps().get(internalformat).renderable); - - RenderbufferStorage *renderbuffer = NULL; - - const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); - if (formatInfo.depthBits > 0 && formatInfo.stencilBits > 0) - { - renderbuffer = new gl::DepthStencilbuffer(mRenderer, width, height, samples); - } - else if (formatInfo.depthBits > 0) - { - renderbuffer = new gl::Depthbuffer(mRenderer, width, height, samples); - } - else if (formatInfo.stencilBits > 0) - { - renderbuffer = new gl::Stencilbuffer(mRenderer, width, height, samples); - } - else - { - renderbuffer = new gl::Colorbuffer(mRenderer, width, height, internalformat, samples); - } - - mState.getCurrentRenderbuffer()->setStorage(renderbuffer); -} - Framebuffer *Context::getFramebuffer(unsigned int handle) const { FramebufferMap::const_iterator framebuffer = mFramebufferMap.find(handle); @@ -837,14 +827,7 @@ Texture2DArray *Context::getTexture2DArray() const Texture *Context::getSamplerTexture(unsigned int sampler, GLenum type) const { - if (mState.getSamplerTextureId(sampler, type) == 0) - { - return mZeroTextures.at(type).get(); - } - else - { - return mState.getSamplerTexture(sampler, type); - } + return mState.getSamplerTexture(sampler, type); } void Context::getBooleanv(GLenum pname, GLboolean *params) @@ -962,7 +945,7 @@ void Context::getIntegerv(GLenum pname, GLint *params) *params = static_cast(mExtensionStrings.size()); break; default: - mState.getIntegerv(pname, params); + mState.getIntegerv(getData(), pname, params); break; } } @@ -1309,309 +1292,6 @@ bool Context::getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned return false; } -// Applies the render target surface, depth stencil surface, viewport rectangle and -// scissor rectangle to the renderer -Error Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport) -{ - Framebuffer *framebufferObject = mState.getDrawFramebuffer(); - ASSERT(framebufferObject && framebufferObject->completeness() == GL_FRAMEBUFFER_COMPLETE); - - gl::Error error = mRenderer->applyRenderTarget(framebufferObject); - if (error.isError()) - { - return error; - } - - float nearZ, farZ; - mState.getDepthRange(&nearZ, &farZ); - mRenderer->setViewport(mState.getViewport(), nearZ, farZ, drawMode, mState.getRasterizerState().frontFace, - ignoreViewport); - - mRenderer->setScissorRectangle(mState.getScissor(), mState.isScissorTestEnabled()); - - return gl::Error(GL_NO_ERROR); -} - -// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device -Error Context::applyState(GLenum drawMode) -{ - Framebuffer *framebufferObject = mState.getDrawFramebuffer(); - int samples = framebufferObject->getSamples(); - - RasterizerState rasterizer = mState.getRasterizerState(); - rasterizer.pointDrawMode = (drawMode == GL_POINTS); - rasterizer.multiSample = (samples != 0); - - Error error = mRenderer->setRasterizerState(rasterizer); - if (error.isError()) - { - return error; - } - - unsigned int mask = 0; - if (mState.isSampleCoverageEnabled()) - { - GLclampf coverageValue; - bool coverageInvert = false; - mState.getSampleCoverageParams(&coverageValue, &coverageInvert); - if (coverageValue != 0) - { - float threshold = 0.5f; - - for (int i = 0; i < samples; ++i) - { - mask <<= 1; - - if ((i + 1) * coverageValue >= threshold) - { - threshold += 1.0f; - mask |= 1; - } - } - } - - if (coverageInvert) - { - mask = ~mask; - } - } - else - { - mask = 0xFFFFFFFF; - } - error = mRenderer->setBlendState(framebufferObject, mState.getBlendState(), mState.getBlendColor(), mask); - if (error.isError()) - { - return error; - } - - error = mRenderer->setDepthStencilState(mState.getDepthStencilState(), mState.getStencilRef(), mState.getStencilBackRef(), - rasterizer.frontFace == GL_CCW); - if (error.isError()) - { - return error; - } - - return Error(GL_NO_ERROR); -} - -// Applies the shaders and shader constants to the Direct3D 9 device -Error Context::applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive) -{ - const VertexAttribute *vertexAttributes = mState.getVertexArray()->getVertexAttributes(); - - VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]; - VertexFormat::GetInputLayout(inputLayout, programBinary, vertexAttributes, mState.getVertexAttribCurrentValues()); - - const Framebuffer *fbo = mState.getDrawFramebuffer(); - - Error error = mRenderer->applyShaders(programBinary, inputLayout, fbo, mState.getRasterizerState().rasterizerDiscard, transformFeedbackActive); - if (error.isError()) - { - return error; - } - - return programBinary->applyUniforms(); -} - -Error Context::generateSwizzles(ProgramBinary *programBinary, SamplerType type) -{ - size_t samplerRange = programBinary->getUsedSamplerRange(type); - - for (size_t i = 0; i < samplerRange; i++) - { - GLenum textureType = programBinary->getSamplerTextureType(type, i); - GLint textureUnit = programBinary->getSamplerMapping(type, i, getCaps()); - if (textureUnit != -1) - { - Texture* texture = getSamplerTexture(textureUnit, textureType); - if (texture->getSamplerState().swizzleRequired()) - { - Error error = mRenderer->generateSwizzle(texture); - if (error.isError()) - { - return error; - } - } - } - } - - return Error(GL_NO_ERROR); -} - -Error Context::generateSwizzles(ProgramBinary *programBinary) -{ - Error error = generateSwizzles(programBinary, SAMPLER_VERTEX); - if (error.isError()) - { - return error; - } - - error = generateSwizzles(programBinary, SAMPLER_PIXEL); - if (error.isError()) - { - return error; - } - - return Error(GL_NO_ERROR); -} - -// For each Direct3D sampler of either the pixel or vertex stage, -// looks up the corresponding OpenGL texture image unit and texture type, -// and sets the texture and its addressing/filtering state (or NULL when inactive). -Error Context::applyTextures(ProgramBinary *programBinary, SamplerType shaderType, - const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount) -{ - size_t samplerRange = programBinary->getUsedSamplerRange(shaderType); - for (size_t samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++) - { - GLenum textureType = programBinary->getSamplerTextureType(shaderType, samplerIndex); - GLint textureUnit = programBinary->getSamplerMapping(shaderType, samplerIndex, getCaps()); - if (textureUnit != -1) - { - SamplerState sampler; - Texture* texture = getSamplerTexture(textureUnit, textureType); - texture->getSamplerStateWithNativeOffset(&sampler); - - Sampler *samplerObject = mState.getSampler(textureUnit); - if (samplerObject) - { - samplerObject->getState(&sampler); - } - - // TODO: std::binary_search may become unavailable using older versions of GCC - if (texture->isSamplerComplete(sampler, mTextureCaps, mExtensions, mClientVersion) && - !std::binary_search(framebufferSerials.begin(), framebufferSerials.begin() + framebufferSerialCount, texture->getTextureSerial())) - { - Error error = mRenderer->setSamplerState(shaderType, samplerIndex, sampler); - if (error.isError()) - { - return error; - } - - error = mRenderer->setTexture(shaderType, samplerIndex, texture); - if (error.isError()) - { - return error; - } - } - else - { - // Texture is not sampler complete or it is in use by the framebuffer. Bind the incomplete texture. - Texture *incompleteTexture = getIncompleteTexture(textureType); - gl::Error error = mRenderer->setTexture(shaderType, samplerIndex, incompleteTexture); - if (error.isError()) - { - return error; - } - } - } - else - { - // No texture bound to this slot even though it is used by the shader, bind a NULL texture - Error error = mRenderer->setTexture(shaderType, samplerIndex, NULL); - if (error.isError()) - { - return error; - } - } - } - - // Set all the remaining textures to NULL - size_t samplerCount = (shaderType == SAMPLER_PIXEL) ? mCaps.maxTextureImageUnits - : mCaps.maxVertexTextureImageUnits; - for (size_t samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++) - { - Error error = mRenderer->setTexture(shaderType, samplerIndex, NULL); - if (error.isError()) - { - return error; - } - } - - return Error(GL_NO_ERROR); -} - -Error Context::applyTextures(ProgramBinary *programBinary) -{ - FramebufferTextureSerialArray framebufferSerials; - size_t framebufferSerialCount = getBoundFramebufferTextureSerials(&framebufferSerials); - - Error error = applyTextures(programBinary, SAMPLER_VERTEX, framebufferSerials, framebufferSerialCount); - if (error.isError()) - { - return error; - } - - error = applyTextures(programBinary, SAMPLER_PIXEL, framebufferSerials, framebufferSerialCount); - if (error.isError()) - { - return error; - } - - return Error(GL_NO_ERROR); -} - -Error Context::applyUniformBuffers() -{ - Program *programObject = getProgram(mState.getCurrentProgramId()); - ProgramBinary *programBinary = programObject->getProgramBinary(); - - std::vector boundBuffers; - - for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < programBinary->getActiveUniformBlockCount(); uniformBlockIndex++) - { - GLuint blockBinding = programObject->getUniformBlockBinding(uniformBlockIndex); - - if (mState.getIndexedUniformBuffer(blockBinding)->id() == 0) - { - // undefined behaviour - return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to have a used but unbound uniform buffer."); - } - else - { - Buffer *uniformBuffer = mState.getIndexedUniformBuffer(blockBinding); - ASSERT(uniformBuffer); - boundBuffers.push_back(uniformBuffer); - } - } - - return programBinary->applyUniformBuffers(boundBuffers, getCaps()); -} - -bool Context::applyTransformFeedbackBuffers() -{ - TransformFeedback *curTransformFeedback = mState.getCurrentTransformFeedback(); - if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) - { - Buffer *transformFeedbackBuffers[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; - GLintptr transformFeedbackOffsets[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; - for (size_t i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) - { - transformFeedbackBuffers[i] = mState.getIndexedTransformFeedbackBuffer(i); - transformFeedbackOffsets[i] = mState.getIndexedTransformFeedbackBufferOffset(i); - } - mRenderer->applyTransformFeedbackBuffers(transformFeedbackBuffers, transformFeedbackOffsets); - return true; - } - else - { - return false; - } -} - -void Context::markTransformFeedbackUsage() -{ - for (size_t i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) - { - Buffer *buffer = mState.getIndexedTransformFeedbackBuffer(i); - if (buffer) - { - buffer->markTransformFeedbackUsage(); - } - } -} - Error Context::clear(GLbitfield mask) { if (mState.isRasterizerDiscardEnabled()) @@ -1619,290 +1299,71 @@ Error Context::clear(GLbitfield mask) return Error(GL_NO_ERROR); } - ClearParameters clearParams = mState.getClearParameters(mask); - - applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport - - return mRenderer->clear(clearParams, mState.getDrawFramebuffer()); + return mRenderer->clear(getData(), mask); } -Error Context::clearBufferfv(GLenum buffer, int drawbuffer, const float *values) +Error Context::clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values) { if (mState.isRasterizerDiscardEnabled()) { return Error(GL_NO_ERROR); } - // glClearBufferfv can be called to clear the color buffer or depth buffer - ClearParameters clearParams = mState.getClearParameters(0); - - if (buffer == GL_COLOR) - { - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = (drawbuffer == static_cast(i)); - } - clearParams.colorFClearValue = ColorF(values[0], values[1], values[2], values[3]); - clearParams.colorClearType = GL_FLOAT; - } - - if (buffer == GL_DEPTH) - { - clearParams.clearDepth = true; - clearParams.depthClearValue = values[0]; - } - - applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport - - return mRenderer->clear(clearParams, mState.getDrawFramebuffer()); + return mRenderer->clearBufferfv(getData(), buffer, drawbuffer, values); } -Error Context::clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values) +Error Context::clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values) { if (mState.isRasterizerDiscardEnabled()) { return Error(GL_NO_ERROR); } - // glClearBufferuv can only be called to clear a color buffer - ClearParameters clearParams = mState.getClearParameters(0); - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = (drawbuffer == static_cast(i)); - } - clearParams.colorUIClearValue = ColorUI(values[0], values[1], values[2], values[3]); - clearParams.colorClearType = GL_UNSIGNED_INT; - - applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport - - return mRenderer->clear(clearParams, mState.getDrawFramebuffer()); + return mRenderer->clearBufferuiv(getData(), buffer, drawbuffer, values); } -Error Context::clearBufferiv(GLenum buffer, int drawbuffer, const int *values) +Error Context::clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values) { if (mState.isRasterizerDiscardEnabled()) { return Error(GL_NO_ERROR); } - // glClearBufferfv can be called to clear the color buffer or stencil buffer - ClearParameters clearParams = mState.getClearParameters(0); - - if (buffer == GL_COLOR) - { - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = (drawbuffer == static_cast(i)); - } - clearParams.colorIClearValue = ColorI(values[0], values[1], values[2], values[3]); - clearParams.colorClearType = GL_INT; - } - - if (buffer == GL_STENCIL) - { - clearParams.clearStencil = true; - clearParams.stencilClearValue = values[1]; - } - - applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport - - return mRenderer->clear(clearParams, mState.getDrawFramebuffer()); + return mRenderer->clearBufferiv(getData(), buffer, drawbuffer, values); } -Error Context::clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil) +Error Context::clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) { if (mState.isRasterizerDiscardEnabled()) { return Error(GL_NO_ERROR); } - // glClearBufferfi can only be called to clear a depth stencil buffer - ClearParameters clearParams = mState.getClearParameters(0); - clearParams.clearDepth = true; - clearParams.depthClearValue = depth; - clearParams.clearStencil = true; - clearParams.stencilClearValue = stencil; - - applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport - - return mRenderer->clear(clearParams, mState.getDrawFramebuffer()); + return mRenderer->clearBufferfi(getData(), buffer, drawbuffer, depth, stencil); } Error Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels) { - Framebuffer *framebuffer = mState.getReadFramebuffer(); - - GLenum sizedInternalFormat = GetSizedInternalFormat(format, type); - const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat); - GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, width, mState.getPackAlignment()); - - return mRenderer->readPixels(framebuffer, x, y, width, height, format, type, outputPitch, mState.getPackState(), - reinterpret_cast(pixels)); + return mRenderer->readPixels(getData(), x, y, width, height, format, type, bufSize, pixels); } Error Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances) { - ASSERT(mState.getCurrentProgramId() != 0); - - ProgramBinary *programBinary = mState.getCurrentProgramBinary(); - programBinary->updateSamplerMapping(); - - Error error = generateSwizzles(programBinary); - if (error.isError()) - { - return error; - } - - if (!mRenderer->applyPrimitiveType(mode, count)) - { - return Error(GL_NO_ERROR); - } - - error = applyRenderTarget(mode, false); - if (error.isError()) - { - return error; - } - - error = applyState(mode); - if (error.isError()) - { - return error; - } - - error = mRenderer->applyVertexBuffer(programBinary, mState.getVertexArray()->getVertexAttributes(), mState.getVertexAttribCurrentValues(), first, count, instances); - if (error.isError()) - { - return error; - } - - bool transformFeedbackActive = applyTransformFeedbackBuffers(); - - error = applyShaders(programBinary, transformFeedbackActive); - if (error.isError()) - { - return error; - } - - error = applyTextures(programBinary); - if (error.isError()) - { - return error; - } - - error = applyUniformBuffers(); - if (error.isError()) - { - return error; - } - - if (!skipDraw(mode)) - { - error = mRenderer->drawArrays(mode, count, instances, transformFeedbackActive); - if (error.isError()) - { - return error; - } - - if (transformFeedbackActive) - { - markTransformFeedbackUsage(); - } - } - - return gl::Error(GL_NO_ERROR); + return mRenderer->drawArrays(getData(), mode, first, count, instances); } Error Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances, const rx::RangeUI &indexRange) { - ASSERT(mState.getCurrentProgramId() != 0); - - ProgramBinary *programBinary = mState.getCurrentProgramBinary(); - programBinary->updateSamplerMapping(); - - Error error = generateSwizzles(programBinary); - if (error.isError()) - { - return error; - } - - if (!mRenderer->applyPrimitiveType(mode, count)) - { - return Error(GL_NO_ERROR); - } - - error = applyRenderTarget(mode, false); - if (error.isError()) - { - return error; - } - - error = applyState(mode); - if (error.isError()) - { - return error; - } - - VertexArray *vao = mState.getVertexArray(); - rx::TranslatedIndexData indexInfo; - indexInfo.indexRange = indexRange; - error = mRenderer->applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo); - if (error.isError()) - { - return error; - } - - GLsizei vertexCount = indexInfo.indexRange.length() + 1; - error = mRenderer->applyVertexBuffer(programBinary, vao->getVertexAttributes(), - mState.getVertexAttribCurrentValues(), - indexInfo.indexRange.start, vertexCount, instances); - if (error.isError()) - { - return error; - } - - bool transformFeedbackActive = applyTransformFeedbackBuffers(); - // Transform feedback is not allowed for DrawElements, this error should have been caught at the API validation - // layer. - ASSERT(!transformFeedbackActive); - - error = applyShaders(programBinary, transformFeedbackActive); - if (error.isError()) - { - return error; - } - - error = applyTextures(programBinary); - if (error.isError()) - { - return error; - } - - error = applyUniformBuffers(); - if (error.isError()) - { - return error; - } - - if (!skipDraw(mode)) - { - error = mRenderer->drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances); - if (error.isError()) - { - return error; - } - } - - return Error(GL_NO_ERROR); + return mRenderer->drawElements(getData(), mode, count, type, indices, instances, indexRange); } // Implements glFlush when block is false, glFinish when block is true -void Context::sync(bool block) +Error Context::sync(bool block) { - mRenderer->sync(block); + return mRenderer->sync(block); } void Context::recordError(const Error &error) @@ -1931,6 +1392,7 @@ GLenum Context::getError() GLenum Context::getResetStatus() { + //TODO(jmadill): needs MANGLE reworking if (mResetStatus == GL_NO_ERROR && !mContextLost) { // mResetStatus will be set by the markContextLost callback @@ -1981,7 +1443,7 @@ const Extensions &Context::getExtensions() const void Context::getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type) { Framebuffer *framebuffer = mState.getReadFramebuffer(); - ASSERT(framebuffer && framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE); + ASSERT(framebuffer && framebuffer->completeness(getData()) == GL_FRAMEBUFFER_COMPLETE); FramebufferAttachment *attachment = framebuffer->getReadColorbuffer(); ASSERT(attachment); @@ -2000,7 +1462,7 @@ void Context::detachTexture(GLuint texture) // allocation map management either here or in the resource manager at detach time. // Zero textures are held by the Context, and we don't attempt to request them from // the State. - mState.detachTexture(texture); + mState.detachTexture(mZeroTextures, texture); } void Context::detachBuffer(GLuint buffer) @@ -2072,95 +1534,6 @@ void Context::detachSampler(GLuint sampler) mState.detachSampler(sampler); } -Texture *Context::getIncompleteTexture(GLenum type) -{ - if (mIncompleteTextures.find(type) == mIncompleteTextures.end()) - { - const GLubyte color[] = { 0, 0, 0, 255 }; - const PixelUnpackState incompleteUnpackState(1); - - Texture* t = NULL; - switch (type) - { - default: - UNREACHABLE(); - // default falls through to TEXTURE_2D - - case GL_TEXTURE_2D: - { - Texture2D *incomplete2d = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), Texture::INCOMPLETE_TEXTURE_ID); - incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - t = incomplete2d; - } - break; - - case GL_TEXTURE_CUBE_MAP: - { - TextureCubeMap *incompleteCube = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), Texture::INCOMPLETE_TEXTURE_ID); - - incompleteCube->setImagePosX(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - incompleteCube->setImageNegX(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - incompleteCube->setImagePosY(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - incompleteCube->setImageNegY(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - incompleteCube->setImagePosZ(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - incompleteCube->setImageNegZ(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - - t = incompleteCube; - } - break; - - case GL_TEXTURE_3D: - { - Texture3D *incomplete3d = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), Texture::INCOMPLETE_TEXTURE_ID); - incomplete3d->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - - t = incomplete3d; - } - break; - - case GL_TEXTURE_2D_ARRAY: - { - Texture2DArray *incomplete2darray = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), Texture::INCOMPLETE_TEXTURE_ID); - incomplete2darray->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - - t = incomplete2darray; - } - break; - } - - mIncompleteTextures[type].set(t); - } - - return mIncompleteTextures[type].get(); -} - -bool Context::skipDraw(GLenum drawMode) -{ - if (drawMode == GL_POINTS) - { - // ProgramBinary assumes non-point rendering if gl_PointSize isn't written, - // which affects varying interpolation. Since the value of gl_PointSize is - // undefined when not written, just skip drawing to avoid unexpected results. - if (!mState.getCurrentProgramBinary()->usesPointSize()) - { - // This is stictly speaking not an error, but developers should be - // notified of risking undefined behavior. - ERR("Point rendering without writing to gl_PointSize."); - - return true; - } - } - else if (IsTriangleMode(drawMode)) - { - if (mState.getRasterizerState().cullFace && mState.getRasterizerState().cullMode == GL_FRONT_AND_BACK) - { - return true; - } - } - - return false; -} - void Context::setVertexAttribDivisor(GLuint index, GLuint divisor) { mState.getVertexArray()->setVertexAttribDivisor(index, divisor); @@ -2293,63 +1666,12 @@ size_t Context::getExtensionStringCount() const return mExtensionStrings.size(); } -size_t Context::getBoundFramebufferTextureSerials(FramebufferTextureSerialArray *outSerialArray) +Error Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) { - size_t serialCount = 0; - - Framebuffer *drawFramebuffer = mState.getDrawFramebuffer(); - for (unsigned int i = 0; i < IMPLEMENTATION_MAX_DRAW_BUFFERS; i++) - { - FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i); - if (attachment && attachment->isTexture()) - { - Texture *texture = attachment->getTexture(); - (*outSerialArray)[serialCount++] = texture->getTextureSerial(); - } - } - - FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer(); - if (depthStencilAttachment && depthStencilAttachment->isTexture()) - { - Texture *depthStencilTexture = depthStencilAttachment->getTexture(); - (*outSerialArray)[serialCount++] = depthStencilTexture->getTextureSerial(); - } - - std::sort(outSerialArray->begin(), outSerialArray->begin() + serialCount); - - return serialCount; -} - -void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter) -{ - Framebuffer *readFramebuffer = mState.getReadFramebuffer(); - Framebuffer *drawFramebuffer = mState.getDrawFramebuffer(); - - bool blitRenderTarget = false; - bool blitDepth = false; - bool blitStencil = false; - if ((mask & GL_COLOR_BUFFER_BIT) && readFramebuffer->getReadColorbuffer() && drawFramebuffer->getFirstColorbuffer()) - { - blitRenderTarget = true; - } - if ((mask & GL_STENCIL_BUFFER_BIT) && readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer()) - { - blitStencil = true; - } - if ((mask & GL_DEPTH_BUFFER_BIT) && readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer()) - { - blitDepth = true; - } - - Rectangle srcRect(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0); - Rectangle dstRect(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0); - if (blitRenderTarget || blitDepth || blitStencil) - { - const Rectangle *scissor = mState.isScissorTestEnabled() ? &mState.getScissor() : NULL; - mRenderer->blitRect(readFramebuffer, srcRect, drawFramebuffer, dstRect, scissor, - blitRenderTarget, blitDepth, blitStencil, filter); - } + return mRenderer->blitFramebuffer(getData(), srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, mask, filter); } void Context::releaseShaderCompiler() @@ -2416,6 +1738,11 @@ void Context::initCaps(GLuint clientVersion) mExtensions.maxSamples = maxSamples; } +Data Context::getData() const +{ + return Data(mClientVersion, mState, mCaps, mTextureCaps, mExtensions, mResourceManager); +} + } extern "C" diff --git a/src/3rdparty/angle/src/libGLESv2/Context.h b/src/3rdparty/angle/src/libGLESv2/Context.h index 1b888aec83a..1e890de3ef2 100644 --- a/src/3rdparty/angle/src/libGLESv2/Context.h +++ b/src/3rdparty/angle/src/libGLESv2/Context.h @@ -13,12 +13,12 @@ #include "common/angleutils.h" #include "common/RefCountObject.h" #include "libGLESv2/Caps.h" +#include "libGLESv2/Constants.h" +#include "libGLESv2/Data.h" #include "libGLESv2/Error.h" #include "libGLESv2/HandleAllocator.h" -#include "libGLESv2/angletypes.h" -#include "libGLESv2/Constants.h" #include "libGLESv2/VertexAttribute.h" -#include "libGLESv2/State.h" +#include "libGLESv2/angletypes.h" #include "angle_gl.h" @@ -50,11 +50,6 @@ class Texture3D; class Texture2DArray; class Framebuffer; class Renderbuffer; -class RenderbufferStorage; -class Colorbuffer; -class Depthbuffer; -class Stencilbuffer; -class DepthStencilbuffer; class FenceNV; class FenceSync; class Query; @@ -68,7 +63,7 @@ class TransformFeedback; class Context { public: - Context(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess); + Context(int clientVersion, const Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess); virtual ~Context(); @@ -86,7 +81,7 @@ class Context GLuint createRenderbuffer(); GLuint createSampler(); GLuint createTransformFeedback(); - GLsync createFenceSync(GLenum condition); + GLsync createFenceSync(); void deleteBuffer(GLuint buffer); void deleteShader(GLuint shader); @@ -115,7 +110,7 @@ class Context void bindArrayBuffer(GLuint buffer); void bindElementArrayBuffer(GLuint buffer); - void bindTexture(GLenum target, GLuint texture); + void bindTexture(GLenum target, GLuint handle); void bindReadFramebuffer(GLuint framebuffer); void bindDrawFramebuffer(GLuint framebuffer); void bindRenderbuffer(GLuint renderbuffer); @@ -130,8 +125,8 @@ class Context void bindPixelPackBuffer(GLuint buffer); void bindPixelUnpackBuffer(GLuint buffer); void useProgram(GLuint program); - void linkProgram(GLuint program); - void setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length); + Error linkProgram(GLuint program); + Error setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length); void bindTransformFeedback(GLuint transformFeedback); Error beginQuery(GLenum target, GLuint query); @@ -139,8 +134,6 @@ class Context void setFramebufferZero(Framebuffer *framebuffer); - void setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples); - void setVertexAttribDivisor(GLuint index, GLuint divisor); void samplerParameteri(GLuint sampler, GLenum pname, GLint param); @@ -183,17 +176,17 @@ class Context bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams); Error clear(GLbitfield mask); - Error clearBufferfv(GLenum buffer, int drawbuffer, const float *values); - Error clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values); - Error clearBufferiv(GLenum buffer, int drawbuffer, const int *values); - Error clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil); + Error clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values); + Error clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values); + Error clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values); + Error clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); Error readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels); Error drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances); Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances, const rx::RangeUI &indexRange); - void sync(bool block); // flush/finish + Error sync(bool block); // flush/finish void recordError(const Error &error); @@ -215,32 +208,21 @@ class Context void getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type); - void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter); + Error blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter); rx::Renderer *getRenderer() { return mRenderer; } State &getState() { return mState; } const State &getState() const { return mState; } + Data getData() const; + void releaseShaderCompiler(); private: DISALLOW_COPY_AND_ASSIGN(Context); - // TODO: std::array may become unavailable using older versions of GCC - typedef std::array FramebufferTextureSerialArray; - - Error applyRenderTarget(GLenum drawMode, bool ignoreViewport); - Error applyState(GLenum drawMode); - Error applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive); - Error applyTextures(ProgramBinary *programBinary, SamplerType shaderType, const FramebufferTextureSerialArray &framebufferSerials, - size_t framebufferSerialCount); - Error applyTextures(ProgramBinary *programBinary); - Error applyUniformBuffers(); - bool applyTransformFeedbackBuffers(); - void markTransformFeedbackUsage(); - void detachBuffer(GLuint buffer); void detachTexture(GLuint texture); void detachFramebuffer(GLuint framebuffer); @@ -249,18 +231,9 @@ class Context void detachTransformFeedback(GLuint transformFeedback); void detachSampler(GLuint sampler); - Error generateSwizzles(ProgramBinary *programBinary, SamplerType type); - Error generateSwizzles(ProgramBinary *programBinary); - - Texture *getIncompleteTexture(GLenum type); - - bool skipDraw(GLenum drawMode); - void initRendererString(); void initExtensionStrings(); - size_t getBoundFramebufferTextureSerials(FramebufferTextureSerialArray *outSerialArray); - void initCaps(GLuint clientVersion); // Caps to use for validation @@ -273,7 +246,6 @@ class Context int mClientVersion; - typedef std::map< GLenum, BindingPointer > TextureMap; TextureMap mZeroTextures; TextureMap mIncompleteTextures; diff --git a/src/3rdparty/angle/src/libGLESv2/Data.cpp b/src/3rdparty/angle/src/libGLESv2/Data.cpp new file mode 100644 index 00000000000..3ddf591d778 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/Data.cpp @@ -0,0 +1,51 @@ +// +// 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. +// + +// Data.cpp: Container class for all GL relevant state, caps and objects + +#include "libGLESv2/Data.h" +#include "libGLESv2/ResourceManager.h" + +namespace gl +{ + +Data::Data(GLint clientVersionIn, const State &stateIn, const Caps &capsIn, + const TextureCapsMap &textureCapsIn, const Extensions &extensionsIn, + const ResourceManager *resourceManagerIn) + : clientVersion(clientVersionIn), + state(&stateIn), + caps(&capsIn), + textureCaps(&textureCapsIn), + extensions(&extensionsIn), + resourceManager(resourceManagerIn) +{} + +Data::~Data() +{ +} + +Data::Data(const Data &other) + : clientVersion(other.clientVersion), + state(other.state), + caps(other.caps), + textureCaps(other.textureCaps), + extensions(other.extensions), + resourceManager(other.resourceManager) +{ +} + +Data &Data::operator=(const Data &other) +{ + clientVersion = other.clientVersion; + state = other.state; + caps = other.caps; + textureCaps = other.textureCaps; + extensions = other.extensions; + resourceManager = other.resourceManager; + return *this; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/Data.h b/src/3rdparty/angle/src/libGLESv2/Data.h new file mode 100644 index 00000000000..9234403e13f --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/Data.h @@ -0,0 +1,38 @@ +// +// 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. +// + +// Data.h: Container class for all GL relevant state, caps and objects + +#ifndef LIBGLESV2_DATA_H_ +#define LIBGLESV2_DATA_H_ + +#include "libGLESv2/State.h" + +namespace gl +{ + +struct Data +{ + public: + Data(GLint clientVersion, const State &state, const Caps &caps, + const TextureCapsMap &textureCaps, const Extensions &extensions, + const ResourceManager *resourceManager); + ~Data(); + + Data(const Data &other); + Data &operator=(const Data &other); + + GLint clientVersion; + const State *state; + const Caps *caps; + const TextureCapsMap *textureCaps; + const Extensions *extensions; + const ResourceManager *resourceManager; +}; + +} + +#endif // LIBGLESV2_DATA_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Fence.cpp b/src/3rdparty/angle/src/libGLESv2/Fence.cpp index ee9a07a5c48..966a327de56 100644 --- a/src/3rdparty/angle/src/libGLESv2/Fence.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Fence.cpp @@ -4,191 +4,113 @@ // found in the LICENSE file. // -// Fence.cpp: Implements the gl::Fence class, which supports the GL_NV_fence extension. - -// Important note on accurate timers in Windows: -// -// QueryPerformanceCounter has a few major issues, including being 10x as expensive to call -// as timeGetTime on laptops and "jumping" during certain hardware events. -// -// See the comments at the top of the Chromium source file "chromium/src/base/time/time_win.cc" -// https://code.google.com/p/chromium/codesearch#chromium/src/base/time/time_win.cc -// -// We still opt to use QPC. In the present and moving forward, most newer systems will not suffer -// from buggy implementations. +// Fence.cpp: Implements the gl::FenceNV and gl::FenceSync classes, which support the GL_NV_fence +// extension and GLES3 sync objects. #include "libGLESv2/Fence.h" #include "libGLESv2/renderer/FenceImpl.h" #include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/main.h" +#include "common/utilities.h" #include "angle_gl.h" namespace gl { -FenceNV::FenceNV(rx::Renderer *renderer) +FenceNV::FenceNV(rx::FenceNVImpl *impl) + : mFence(impl), + mIsSet(false), + mStatus(GL_FALSE), + mCondition(GL_NONE) { - mFence = renderer->createFence(); } FenceNV::~FenceNV() { - delete mFence; + SafeDelete(mFence); } GLboolean FenceNV::isFence() const { // GL_NV_fence spec: // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence. - return (mFence->isSet() ? GL_TRUE : GL_FALSE); + return (mIsSet ? GL_TRUE : GL_FALSE); } -void FenceNV::setFence(GLenum condition) +Error FenceNV::setFence(GLenum condition) { - mFence->set(); + Error error = mFence->set(); + if (error.isError()) + { + return error; + } mCondition = condition; mStatus = GL_FALSE; + mIsSet = true; + + return Error(GL_NO_ERROR); } -GLboolean FenceNV::testFence() +Error FenceNV::testFence(GLboolean *outResult) { // Flush the command buffer by default - bool result = mFence->test(true); - - mStatus = (result ? GL_TRUE : GL_FALSE); - return mStatus; -} - -void FenceNV::finishFence() -{ - ASSERT(mFence->isSet()); - - while (!mFence->test(true)) + Error error = mFence->test(true, &mStatus); + if (error.isError()) { - Sleep(0); + return error; } + + *outResult = mStatus; + return Error(GL_NO_ERROR); } -GLint FenceNV::getFencei(GLenum pname) +Error FenceNV::finishFence() { - ASSERT(mFence->isSet()); + ASSERT(mIsSet); - switch (pname) - { - case GL_FENCE_STATUS_NV: - { - // GL_NV_fence spec: - // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV - // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence. - if (mStatus == GL_TRUE) - { - return GL_TRUE; - } - - mStatus = (mFence->test(false) ? GL_TRUE : GL_FALSE); - return mStatus; - } - - case GL_FENCE_CONDITION_NV: - return mCondition; - - default: UNREACHABLE(); return 0; - } + return mFence->finishFence(&mStatus); } -FenceSync::FenceSync(rx::Renderer *renderer, GLuint id) - : RefCountObject(id) +FenceSync::FenceSync(rx::FenceSyncImpl *impl, GLuint id) + : RefCountObject(id), + mFence(impl), + mCondition(GL_NONE) { - mFence = renderer->createFence(); - - LARGE_INTEGER counterFreqency = { 0 }; - BOOL success = QueryPerformanceFrequency(&counterFreqency); - UNUSED_ASSERTION_VARIABLE(success); - ASSERT(success); - - mCounterFrequency = counterFreqency.QuadPart; } FenceSync::~FenceSync() { - delete mFence; + SafeDelete(mFence); } -void FenceSync::set(GLenum condition) +Error FenceSync::set(GLenum condition) { + Error error = mFence->set(); + if (error.isError()) + { + return error; + } + mCondition = condition; - mFence->set(); + return Error(GL_NO_ERROR); } -GLenum FenceSync::clientWait(GLbitfield flags, GLuint64 timeout) +Error FenceSync::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) { - ASSERT(mFence->isSet()); - - bool flushCommandBuffer = ((flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0); - - if (mFence->test(flushCommandBuffer)) - { - return GL_ALREADY_SIGNALED; - } - - if (mFence->hasError()) - { - return GL_WAIT_FAILED; - } - - if (timeout == 0) - { - return GL_TIMEOUT_EXPIRED; - } - - LARGE_INTEGER currentCounter = { 0 }; - BOOL success = QueryPerformanceCounter(¤tCounter); - UNUSED_ASSERTION_VARIABLE(success); - ASSERT(success); - - LONGLONG timeoutInSeconds = static_cast(timeout) * static_cast(1000000ll); - LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds; - - while (currentCounter.QuadPart < endCounter && !mFence->test(flushCommandBuffer)) - { - Sleep(0); - BOOL success = QueryPerformanceCounter(¤tCounter); - UNUSED_ASSERTION_VARIABLE(success); - ASSERT(success); - } - - if (mFence->hasError()) - { - return GL_WAIT_FAILED; - } - - if (currentCounter.QuadPart >= endCounter) - { - return GL_TIMEOUT_EXPIRED; - } - - return GL_CONDITION_SATISFIED; + ASSERT(mCondition != GL_NONE); + return mFence->clientWait(flags, timeout, outResult); } -void FenceSync::serverWait() +Error FenceSync::serverWait(GLbitfield flags, GLuint64 timeout) { - // Because our API is currently designed to be called from a single thread, we don't need to do - // extra work for a server-side fence. GPU commands issued after the fence is created will always - // be processed after the fence is signaled. + return mFence->serverWait(flags, timeout); } -GLenum FenceSync::getStatus() const +Error FenceSync::getStatus(GLint *outResult) const { - if (mFence->test(false)) - { - // The spec does not specify any way to report errors during the status test (e.g. device lost) - // so we report the fence is unblocked in case of error or signaled. - return GL_SIGNALED; - } - - return GL_UNSIGNALED; + return mFence->getStatus(outResult); } } diff --git a/src/3rdparty/angle/src/libGLESv2/Fence.h b/src/3rdparty/angle/src/libGLESv2/Fence.h index 291edb3de12..fd565e96a68 100644 --- a/src/3rdparty/angle/src/libGLESv2/Fence.h +++ b/src/3rdparty/angle/src/libGLESv2/Fence.h @@ -4,18 +4,21 @@ // found in the LICENSE file. // -// Fence.h: Defines the gl::Fence class, which supports the GL_NV_fence extension. +// Fence.h: Defines the gl::FenceNV and gl::FenceSync classes, which support the GL_NV_fence +// extension and GLES3 sync objects. #ifndef LIBGLESV2_FENCE_H_ #define LIBGLESV2_FENCE_H_ +#include "libGLESv2/Error.h" + #include "common/angleutils.h" #include "common/RefCountObject.h" namespace rx { -class Renderer; -class FenceImpl; +class FenceNVImpl; +class FenceSyncImpl; } namespace gl @@ -24,14 +27,13 @@ namespace gl class FenceNV { public: - explicit FenceNV(rx::Renderer *renderer); + explicit FenceNV(rx::FenceNVImpl *impl); virtual ~FenceNV(); GLboolean isFence() const; - void setFence(GLenum condition); - GLboolean testFence(); - void finishFence(); - GLint getFencei(GLenum pname); + Error setFence(GLenum condition); + Error testFence(GLboolean *outResult); + Error finishFence(); GLboolean getStatus() const { return mStatus; } GLuint getCondition() const { return mCondition; } @@ -39,7 +41,9 @@ class FenceNV private: DISALLOW_COPY_AND_ASSIGN(FenceNV); - rx::FenceImpl *mFence; + rx::FenceNVImpl *mFence; + + bool mIsSet; GLboolean mStatus; GLenum mCondition; @@ -48,21 +52,20 @@ class FenceNV class FenceSync : public RefCountObject { public: - explicit FenceSync(rx::Renderer *renderer, GLuint id); + explicit FenceSync(rx::FenceSyncImpl *impl, GLuint id); virtual ~FenceSync(); - void set(GLenum condition); - GLenum clientWait(GLbitfield flags, GLuint64 timeout); - void serverWait(); - GLenum getStatus() const; + Error set(GLenum condition); + Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult); + Error serverWait(GLbitfield flags, GLuint64 timeout); + Error getStatus(GLint *outResult) const; GLuint getCondition() const { return mCondition; } private: DISALLOW_COPY_AND_ASSIGN(FenceSync); - rx::FenceImpl *mFence; - LONGLONG mCounterFrequency; + rx::FenceSyncImpl *mFence; GLenum mCondition; }; diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp index 5b21433f905..3d57262e3c3 100644 --- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp @@ -16,13 +16,18 @@ #include "libGLESv2/FramebufferAttachment.h" #include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/renderer/RenderTarget.h" +#include "libGLESv2/renderer/RenderbufferImpl.h" +#include "libGLESv2/renderer/Workarounds.h" #include "libGLESv2/renderer/d3d/TextureD3D.h" +#include "libGLESv2/renderer/d3d/RenderbufferD3D.h" #include "common/utilities.h" namespace rx { -RenderTarget *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment) +// TODO: Move these functions, and the D3D-specific header inclusions above, +// to FramebufferD3D. +gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget **outRT) { if (attachment->isTexture()) { @@ -31,14 +36,16 @@ RenderTarget *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment) TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation()); const gl::ImageIndex *index = attachment->getTextureImageIndex(); ASSERT(index); - return textureD3D->getRenderTarget(*index); + return textureD3D->getRenderTarget(*index, outRT); + } + else + { + gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer(); + ASSERT(renderbuffer); + RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation()); + *outRT = renderbufferD3D->getRenderTarget(); + return gl::Error(GL_NO_ERROR); } - - gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer(); - ASSERT(renderbuffer); - - // TODO: cast to RenderbufferD3D - return renderbuffer->getStorage()->getRenderTarget(); } // Note: RenderTarget serials should ideally be in the RenderTargets themselves. @@ -56,9 +63,8 @@ unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment) gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer(); ASSERT(renderbuffer); - - // TODO: cast to RenderbufferD3D - return renderbuffer->getStorage()->getSerial(); + RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation()); + return renderbufferD3D->getRenderTargetSerial(); } } @@ -66,9 +72,8 @@ unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment) namespace gl { -Framebuffer::Framebuffer(rx::Renderer *renderer, GLuint id) - : mRenderer(renderer), - mId(id), +Framebuffer::Framebuffer(GLuint id) + : mId(id), mReadBufferState(GL_COLOR_ATTACHMENT0_EXT), mDepthbuffer(NULL), mStencilbuffer(NULL) @@ -91,124 +96,6 @@ Framebuffer::~Framebuffer() SafeDelete(mStencilbuffer); } -FramebufferAttachment *Framebuffer::createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const -{ - if (handle == 0) - { - return NULL; - } - - gl::Context *context = gl::getContext(); - - switch (type) - { - case GL_NONE: - return NULL; - - case GL_RENDERBUFFER: - return new RenderbufferAttachment(binding, context->getRenderbuffer(handle)); - - case GL_TEXTURE_2D: - { - Texture *texture = context->getTexture(handle); - if (texture && texture->getTarget() == GL_TEXTURE_2D) - { - return new TextureAttachment(binding, texture, ImageIndex::Make2D(level)); - } - else - { - return NULL; - } - } - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - Texture *texture = context->getTexture(handle); - if (texture && texture->getTarget() == GL_TEXTURE_CUBE_MAP) - { - return new TextureAttachment(binding, texture, ImageIndex::MakeCube(type, level)); - } - else - { - return NULL; - } - } - - case GL_TEXTURE_3D: - { - Texture *texture = context->getTexture(handle); - if (texture && texture->getTarget() == GL_TEXTURE_3D) - { - return new TextureAttachment(binding, texture, ImageIndex::Make3D(level, layer)); - } - else - { - return NULL; - } - } - - case GL_TEXTURE_2D_ARRAY: - { - Texture *texture = context->getTexture(handle); - if (texture && texture->getTarget() == GL_TEXTURE_2D_ARRAY) - { - return new TextureAttachment(binding, texture, ImageIndex::Make2DArray(level, layer)); - } - else - { - return NULL; - } - } - - default: - UNREACHABLE(); - return NULL; - } -} - -void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer) -{ - ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); - SafeDelete(mColorbuffers[colorAttachment]); - GLenum binding = colorAttachment + GL_COLOR_ATTACHMENT0; - mColorbuffers[colorAttachment] = createAttachment(binding, type, colorbuffer, level, layer); -} - -void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer) -{ - SafeDelete(mDepthbuffer); - mDepthbuffer = createAttachment(GL_DEPTH_ATTACHMENT, type, depthbuffer, level, layer); -} - -void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer) -{ - SafeDelete(mStencilbuffer); - mStencilbuffer = createAttachment(GL_STENCIL_ATTACHMENT, type, stencilbuffer, level, layer); -} - -void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer) -{ - FramebufferAttachment *attachment = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer); - - SafeDelete(mDepthbuffer); - SafeDelete(mStencilbuffer); - - // ensure this is a legitimate depth+stencil format - if (attachment && attachment->getDepthSize() > 0 && attachment->getStencilSize() > 0) - { - mDepthbuffer = attachment; - - // Make a new attachment object to ensure we do not double-delete - // See angle issue 686 - mStencilbuffer = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer); - } -} - void Framebuffer::detachTexture(GLuint textureId) { for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) @@ -382,14 +269,13 @@ bool Framebuffer::usingExtendedDrawBuffers() const return false; } -GLenum Framebuffer::completeness() const +GLenum Framebuffer::completeness(const gl::Data &data) const { int width = 0; int height = 0; unsigned int colorbufferSize = 0; int samples = -1; bool missingAttachment = true; - GLuint clientVersion = mRenderer->getCurrentClientVersion(); for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { @@ -403,8 +289,7 @@ GLenum Framebuffer::completeness() const } GLenum internalformat = colorbuffer->getInternalFormat(); - // TODO(geofflang): use context's texture caps - const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat); + const TextureCaps &formatCaps = data.textureCaps->get(internalformat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); if (colorbuffer->isTexture()) { @@ -443,7 +328,7 @@ GLenum Framebuffer::completeness() const // in GLES 2.0, all color attachments attachments must have the same number of bitplanes // in GLES 3.0, there is no such restriction - if (clientVersion < 3) + if (data.clientVersion < 3) { if (formatInfo.pixelBytes != colorbufferSize) { @@ -483,14 +368,12 @@ GLenum Framebuffer::completeness() const } GLenum internalformat = mDepthbuffer->getInternalFormat(); - // TODO(geofflang): use context's texture caps - const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat); + const TextureCaps &formatCaps = data.textureCaps->get(internalformat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); if (mDepthbuffer->isTexture()) { // depth texture attachments require OES/ANGLE_depth_texture - // TODO(geofflang): use context's extensions - if (!mRenderer->getRendererExtensions().depthTextures) + if (!data.extensions->depthTextures) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } @@ -538,15 +421,13 @@ GLenum Framebuffer::completeness() const } GLenum internalformat = mStencilbuffer->getInternalFormat(); - // TODO(geofflang): use context's texture caps - const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat); + const TextureCaps &formatCaps = data.textureCaps->get(internalformat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); if (mStencilbuffer->isTexture()) { // texture stencil attachments come along as part // of OES_packed_depth_stencil + OES/ANGLE_depth_texture - // TODO(geofflang): use context's extensions - if (!mRenderer->getRendererExtensions().depthTextures) + if (!data.extensions->depthTextures) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } @@ -602,42 +483,44 @@ GLenum Framebuffer::completeness() const return GL_FRAMEBUFFER_COMPLETE; } -void Framebuffer::invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments) +Error Framebuffer::invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments) { GLuint maxDimension = caps.maxRenderbufferSize; - invalidateSub(caps, numAttachments, attachments, 0, 0, maxDimension, maxDimension); + return invalidateSub(numAttachments, attachments, 0, 0, maxDimension, maxDimension); } -void Framebuffer::invalidateSub(const Caps &caps, GLsizei numAttachments, const GLenum *attachments, - GLint x, GLint y, GLsizei width, GLsizei height) +Error Framebuffer::invalidateSub(GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height) { - ASSERT(completeness() == GL_FRAMEBUFFER_COMPLETE); for (GLsizei attachIndex = 0; attachIndex < numAttachments; ++attachIndex) { GLenum attachmentTarget = attachments[attachIndex]; - gl::FramebufferAttachment *attachment = - (attachmentTarget == GL_DEPTH_STENCIL_ATTACHMENT) ? getDepthOrStencilbuffer() : - getAttachment(attachmentTarget); + FramebufferAttachment *attachment = (attachmentTarget == GL_DEPTH_STENCIL_ATTACHMENT) ? getDepthOrStencilbuffer() + : getAttachment(attachmentTarget); if (attachment) { - rx::RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment); - if (renderTarget) + rx::RenderTarget *renderTarget = NULL; + Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget); + if (error.isError()) { - renderTarget->invalidate(x, y, width, height); + return error; } + + renderTarget->invalidate(x, y, width, height); } } + + return Error(GL_NO_ERROR); } -DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil) - : Framebuffer(renderer, 0) +DefaultFramebuffer::DefaultFramebuffer(rx::RenderbufferImpl *colorbuffer, rx::RenderbufferImpl *depthStencil) + : Framebuffer(0) { - Renderbuffer *colorRenderbuffer = new Renderbuffer(0, colorbuffer); + Renderbuffer *colorRenderbuffer = new Renderbuffer(colorbuffer, 0); mColorbuffers[0] = new RenderbufferAttachment(GL_BACK, colorRenderbuffer); - Renderbuffer *depthStencilBuffer = new Renderbuffer(0, depthStencil); + Renderbuffer *depthStencilBuffer = new Renderbuffer(depthStencil, 0); // Make a new attachment objects to ensure we do not double-delete // See angle issue 686 @@ -648,9 +531,9 @@ DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colo mReadBufferState = GL_BACK; } -int Framebuffer::getSamples() const +int Framebuffer::getSamples(const gl::Data &data) const { - if (completeness() == GL_FRAMEBUFFER_COMPLETE) + if (completeness(data) == GL_FRAMEBUFFER_COMPLETE) { // for a complete framebuffer, all attachments must have the same sample count // in this case return the first nonzero sample size @@ -675,7 +558,7 @@ bool Framebuffer::hasValidDepthStencil() const mDepthbuffer->id() == mStencilbuffer->id()); } -ColorbufferInfo Framebuffer::getColorbuffersForRender() const +ColorbufferInfo Framebuffer::getColorbuffersForRender(const rx::Workarounds &workarounds) const { ColorbufferInfo colorbuffersForRender; @@ -689,18 +572,78 @@ ColorbufferInfo Framebuffer::getColorbuffersForRender() const ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment)); colorbuffersForRender.push_back(colorbuffer); } -#if (ANGLE_MRT_PERF_WORKAROUND == ANGLE_WORKAROUND_DISABLED) - else + else if (!workarounds.mrtPerfWorkaround) { colorbuffersForRender.push_back(NULL); } -#endif } return colorbuffersForRender; } -GLenum DefaultFramebuffer::completeness() const +void Framebuffer::setTextureAttachment(GLenum attachment, Texture *texture, const ImageIndex &imageIndex) +{ + setAttachment(attachment, new TextureAttachment(attachment, texture, imageIndex)); +} + +void Framebuffer::setRenderbufferAttachment(GLenum attachment, Renderbuffer *renderbuffer) +{ + setAttachment(attachment, new RenderbufferAttachment(attachment, renderbuffer)); +} + +void Framebuffer::setNULLAttachment(GLenum attachment) +{ + setAttachment(attachment, NULL); +} + +void Framebuffer::setAttachment(GLenum attachment, FramebufferAttachment *attachmentObj) +{ + if (attachment >= GL_COLOR_ATTACHMENT0 && attachment < (GL_COLOR_ATTACHMENT0 + IMPLEMENTATION_MAX_DRAW_BUFFERS)) + { + size_t colorAttachment = attachment - GL_COLOR_ATTACHMENT0; + SafeDelete(mColorbuffers[colorAttachment]); + mColorbuffers[colorAttachment] = attachmentObj; + } + else if (attachment == GL_DEPTH_ATTACHMENT) + { + SafeDelete(mDepthbuffer); + mDepthbuffer = attachmentObj; + } + else if (attachment == GL_STENCIL_ATTACHMENT) + { + SafeDelete(mStencilbuffer); + mStencilbuffer = attachmentObj; + } + else if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) + { + SafeDelete(mDepthbuffer); + SafeDelete(mStencilbuffer); + + // ensure this is a legitimate depth+stencil format + if (attachmentObj && attachmentObj->getDepthSize() > 0 && attachmentObj->getStencilSize() > 0) + { + mDepthbuffer = attachmentObj; + + // Make a new attachment object to ensure we do not double-delete + // See angle issue 686 + if (attachmentObj->isTexture()) + { + mStencilbuffer = new TextureAttachment(GL_DEPTH_STENCIL_ATTACHMENT, attachmentObj->getTexture(), + *attachmentObj->getTextureImageIndex()); + } + else + { + mStencilbuffer = new RenderbufferAttachment(GL_DEPTH_STENCIL_ATTACHMENT, attachmentObj->getRenderbuffer()); + } + } + } + else + { + UNREACHABLE(); + } +} + +GLenum DefaultFramebuffer::completeness(const gl::Data &) const { // The default framebuffer *must* always be complete, though it may not be // subject to the same rules as application FBOs. ie, it could have 0x0 size. diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h index cc12d229537..d0fe8935ea8 100644 --- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h @@ -10,41 +10,44 @@ #ifndef LIBGLESV2_FRAMEBUFFER_H_ #define LIBGLESV2_FRAMEBUFFER_H_ -#include +#include "libGLESv2/Error.h" #include "common/angleutils.h" #include "common/RefCountObject.h" -#include "constants.h" +#include "Constants.h" + +#include namespace rx { -class Renderer; +class RenderbufferImpl; +struct Workarounds; } namespace gl { class FramebufferAttachment; -class Colorbuffer; -class Depthbuffer; -class Stencilbuffer; -class DepthStencilbuffer; +class Texture; +class Renderbuffer; +struct ImageIndex; struct Caps; +struct Extensions; +class TextureCapsMap; +struct Data; typedef std::vector ColorbufferInfo; class Framebuffer { public: - Framebuffer(rx::Renderer *renderer, GLuint id); - + Framebuffer(GLuint id); virtual ~Framebuffer(); GLuint id() const { return mId; } - void setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer); - void setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer); - void setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer); - void setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer); + void setTextureAttachment(GLenum attachment, Texture *texture, const ImageIndex &imageIndex); + void setRenderbufferAttachment(GLenum attachment, Renderbuffer *renderbuffer); + void setNULLAttachment(GLenum attachment); void detachTexture(GLuint texture); void detachRenderbuffer(GLuint renderbuffer); @@ -66,24 +69,21 @@ class Framebuffer bool isEnabledColorAttachment(unsigned int colorAttachment) const; bool hasEnabledColorAttachment() const; bool hasStencil() const; - int getSamples() const; + int getSamples(const gl::Data &data) const; bool usingExtendedDrawBuffers() const; - virtual GLenum completeness() const; + virtual GLenum completeness(const gl::Data &data) const; bool hasValidDepthStencil() const; - void invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments); - void invalidateSub(const Caps &caps, GLsizei numAttachments, const GLenum *attachments, - GLint x, GLint y, GLsizei width, GLsizei height); + Error invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments); + Error invalidateSub(GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height); // Use this method to retrieve the color buffer map when doing rendering. // It will apply a workaround for poor shader performance on some systems // by compacting the list to skip NULL values. - ColorbufferInfo getColorbuffersForRender() const; + ColorbufferInfo getColorbuffersForRender(const rx::Workarounds &workarounds) const; protected: - rx::Renderer *mRenderer; - GLuint mId; FramebufferAttachment *mColorbuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS]; @@ -96,15 +96,15 @@ class Framebuffer private: DISALLOW_COPY_AND_ASSIGN(Framebuffer); - FramebufferAttachment *createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const; + void setAttachment(GLenum attachment, FramebufferAttachment *attachmentObj); }; class DefaultFramebuffer : public Framebuffer { public: - DefaultFramebuffer(rx::Renderer *Renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil); + DefaultFramebuffer(rx::RenderbufferImpl *colorbuffer, rx::RenderbufferImpl *depthStencil); - virtual GLenum completeness() const; + GLenum completeness(const gl::Data &data) const override; virtual FramebufferAttachment *getAttachment(GLenum attachment) const; private: @@ -118,7 +118,7 @@ namespace rx class RenderTarget; // TODO: place this in FramebufferD3D.h -RenderTarget *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment); +gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget **outRT); unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment); } diff --git a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp index 540ede1cd2a..894884a6d88 100644 --- a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp +++ b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp @@ -187,7 +187,7 @@ GLenum RenderbufferAttachment::getActualFormat() const GLsizei RenderbufferAttachment::getSamples() const { - return mRenderbuffer->getStorage()->getSamples(); + return mRenderbuffer->getSamples(); } GLuint RenderbufferAttachment::id() const diff --git a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h index c18ef7364d7..8d2dafa7eee 100644 --- a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h +++ b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h @@ -16,13 +16,6 @@ #include "angle_gl.h" -namespace rx -{ -class Renderer; -class RenderTarget; -class TextureStorage; -} - namespace gl { class Renderbuffer; diff --git a/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp b/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp index 3522b997e83..b45cd9c1696 100644 --- a/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp +++ b/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp @@ -48,10 +48,101 @@ ImageIndex ImageIndex::Make3D(GLint mipIndex, GLint layerIndex) return ImageIndex(GL_TEXTURE_3D, mipIndex, layerIndex); } +ImageIndex ImageIndex::MakeInvalid() +{ + return ImageIndex(GL_NONE, -1, -1); +} + ImageIndex::ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn) : type(typeIn), mipIndex(mipIndexIn), layerIndex(layerIndexIn) {} +ImageIndexIterator ImageIndexIterator::Make2D(GLint minMip, GLint maxMip) +{ + return ImageIndexIterator(GL_TEXTURE_2D, rx::Range(minMip, maxMip), + rx::Range(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL), NULL); +} + +ImageIndexIterator ImageIndexIterator::MakeCube(GLint minMip, GLint maxMip) +{ + return ImageIndexIterator(GL_TEXTURE_CUBE_MAP, rx::Range(minMip, maxMip), rx::Range(0, 6), NULL); +} + +ImageIndexIterator ImageIndexIterator::Make3D(GLint minMip, GLint maxMip, + GLint minLayer, GLint maxLayer) +{ + return ImageIndexIterator(GL_TEXTURE_3D, rx::Range(minMip, maxMip), rx::Range(minLayer, maxLayer), NULL); +} + +ImageIndexIterator ImageIndexIterator::Make2DArray(GLint minMip, GLint maxMip, + const GLsizei *layerCounts) +{ + return ImageIndexIterator(GL_TEXTURE_2D_ARRAY, rx::Range(minMip, maxMip), + rx::Range(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS), layerCounts); +} + +ImageIndexIterator::ImageIndexIterator(GLenum type, const rx::Range &mipRange, + const rx::Range &layerRange, const GLsizei *layerCounts) + : mType(type), + mMipRange(mipRange), + mLayerRange(layerRange), + mLayerCounts(layerCounts), + mCurrentMip(mipRange.start), + mCurrentLayer(layerRange.start) +{} + +GLint ImageIndexIterator::maxLayer() const +{ + return (mLayerCounts ? static_cast(mLayerCounts[mCurrentMip]) : mLayerRange.end); +} + +ImageIndex ImageIndexIterator::next() +{ + ASSERT(hasNext()); + + ImageIndex value = current(); + + // Iterate layers in the inner loop for now. We can add switchable + // layer or mip iteration if we need it. + + if (mCurrentLayer != ImageIndex::ENTIRE_LEVEL) + { + if (mCurrentLayer < maxLayer()-1) + { + mCurrentLayer++; + } + else if (mCurrentMip < mMipRange.end-1) + { + mCurrentMip++; + mCurrentLayer = mLayerRange.start; + } + } + else if (mCurrentMip < mMipRange.end-1) + { + mCurrentMip++; + mCurrentLayer = mLayerRange.start; + } + + return value; +} + +ImageIndex ImageIndexIterator::current() const +{ + ImageIndex value(mType, mCurrentMip, mCurrentLayer); + + if (mType == GL_TEXTURE_CUBE_MAP) + { + value.type = TextureCubeMap::layerIndexToTarget(mCurrentLayer); + } + + return value; +} + +bool ImageIndexIterator::hasNext() const +{ + return (mCurrentMip < mMipRange.end || mCurrentLayer < maxLayer()); +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/ImageIndex.h b/src/3rdparty/angle/src/libGLESv2/ImageIndex.h index 9f2df88061b..8bb14fd5554 100644 --- a/src/3rdparty/angle/src/libGLESv2/ImageIndex.h +++ b/src/3rdparty/angle/src/libGLESv2/ImageIndex.h @@ -10,6 +10,7 @@ #define LIBGLESV2_IMAGE_INDEX_H_ #include "angle_gl.h" +#include "common/mathutil.h" namespace gl { @@ -20,6 +21,7 @@ struct ImageIndex GLint mipIndex; GLint layerIndex; + ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn); ImageIndex(const ImageIndex &other); ImageIndex &operator=(const ImageIndex &other); @@ -29,11 +31,36 @@ struct ImageIndex static ImageIndex MakeCube(GLenum target, GLint mipIndex); static ImageIndex Make2DArray(GLint mipIndex, GLint layerIndex); static ImageIndex Make3D(GLint mipIndex, GLint layerIndex = ENTIRE_LEVEL); + static ImageIndex MakeInvalid(); static const GLint ENTIRE_LEVEL = static_cast(-1); +}; + +class ImageIndexIterator +{ + public: + static ImageIndexIterator Make2D(GLint minMip, GLint maxMip); + static ImageIndexIterator MakeCube(GLint minMip, GLint maxMip); + static ImageIndexIterator Make3D(GLint minMip, GLint maxMip, GLint minLayer, GLint maxLayer); + static ImageIndexIterator Make2DArray(GLint minMip, GLint maxMip, const GLsizei *layerCounts); + + ImageIndex next(); + ImageIndex current() const; + bool hasNext() const; private: - ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn); + + ImageIndexIterator(GLenum type, const rx::Range &mipRange, + const rx::Range &layerRange, const GLsizei *layerCounts); + + GLint maxLayer() const; + + GLenum mType; + rx::Range mMipRange; + rx::Range mLayerRange; + const GLsizei *mLayerCounts; + GLint mCurrentMip; + GLint mCurrentLayer; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/Program.cpp b/src/3rdparty/angle/src/libGLESv2/Program.cpp index 9bfda09a647..3faa8c56f6f 100644 --- a/src/3rdparty/angle/src/libGLESv2/Program.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Program.cpp @@ -244,7 +244,7 @@ void Program::bindAttributeLocation(GLuint index, const char *name) // Links the HLSL code of the vertex and pixel shader by matching up their varyings, // compiling them into binaries, determining the attribute mappings, and collecting // a list of uniforms -bool Program::link(const Caps &caps) +Error Program::link(const Data &data) { unlink(false); @@ -252,10 +252,15 @@ bool Program::link(const Caps &caps) resetUniformBlockBindings(); mProgramBinary.set(new ProgramBinary(mRenderer->createProgram())); - mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader, - mTransformFeedbackVaryings, mTransformFeedbackBufferMode, caps); + LinkResult result = mProgramBinary->link(data, mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader, + mTransformFeedbackVaryings, mTransformFeedbackBufferMode); + if (result.error.isError()) + { + return result.error; + } - return mLinked; + mLinked = result.linkSuccess; + return gl::Error(GL_NO_ERROR); } int AttributeBindings::getAttributeBinding(const std::string &name) const @@ -303,21 +308,22 @@ ProgramBinary* Program::getProgramBinary() const return mProgramBinary.get(); } -bool Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length) +Error Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length) { unlink(false); mInfoLog.reset(); mProgramBinary.set(new ProgramBinary(mRenderer->createProgram())); - mLinked = mProgramBinary->load(mInfoLog, binaryFormat, binary, length); - - if (!mLinked) + LinkResult result = mProgramBinary->load(mInfoLog, binaryFormat, binary, length); + if (result.error.isError()) { mProgramBinary.set(NULL); + return result.error; } - return mLinked; + mLinked = result.linkSuccess; + return Error(GL_NO_ERROR); } void Program::release() diff --git a/src/3rdparty/angle/src/libGLESv2/Program.h b/src/3rdparty/angle/src/libGLESv2/Program.h index 6528dd11914..b92349eeefb 100644 --- a/src/3rdparty/angle/src/libGLESv2/Program.h +++ b/src/3rdparty/angle/src/libGLESv2/Program.h @@ -29,6 +29,7 @@ class Renderer; namespace gl { struct Caps; +struct Data; class ResourceManager; class Shader; @@ -77,9 +78,9 @@ class Program void bindAttributeLocation(GLuint index, const char *name); - bool link(const Caps &caps); + Error link(const Data &data); bool isLinked(); - bool setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length); + Error setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length); ProgramBinary *getProgramBinary() const; int getInfoLogLength() const; diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp index 3f6d9e0ef9c..6d64b38b566 100644 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp +++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp @@ -23,13 +23,11 @@ #include "libGLESv2/Shader.h" #include "libGLESv2/Program.h" #include "libGLESv2/renderer/ProgramImpl.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/d3d/DynamicHLSL.h" #include "libGLESv2/renderer/d3d/ShaderD3D.h" -#include "libGLESv2/renderer/d3d/VertexDataManager.h" #include "libGLESv2/Context.h" #include "libGLESv2/Buffer.h" #include "common/blocklayout.h" +#include "common/features.h" namespace gl { @@ -37,36 +35,6 @@ namespace gl namespace { -GLenum GetTextureType(GLenum samplerType) -{ - switch (samplerType) - { - case GL_SAMPLER_2D: - case GL_INT_SAMPLER_2D: - case GL_UNSIGNED_INT_SAMPLER_2D: - case GL_SAMPLER_2D_SHADOW: - return GL_TEXTURE_2D; - case GL_SAMPLER_3D: - case GL_INT_SAMPLER_3D: - case GL_UNSIGNED_INT_SAMPLER_3D: - return GL_TEXTURE_3D; - case GL_SAMPLER_CUBE: - case GL_SAMPLER_CUBE_SHADOW: - return GL_TEXTURE_CUBE_MAP; - case GL_INT_SAMPLER_CUBE: - case GL_UNSIGNED_INT_SAMPLER_CUBE: - return GL_TEXTURE_CUBE_MAP; - case GL_SAMPLER_2D_ARRAY: - case GL_INT_SAMPLER_2D_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: - case GL_SAMPLER_2D_ARRAY_SHADOW: - return GL_TEXTURE_2D_ARRAY; - default: UNREACHABLE(); - } - - return GL_TEXTURE_2D; -} - unsigned int ParseAndStripArrayIndex(std::string* name) { unsigned int subscript = GL_INVALID_INDEX; @@ -83,52 +51,6 @@ unsigned int ParseAndStripArrayIndex(std::string* name) return subscript; } -void GetDefaultInputLayoutFromShader(const std::vector &shaderAttributes, VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]) -{ - size_t layoutIndex = 0; - for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) - { - ASSERT(layoutIndex < MAX_VERTEX_ATTRIBS); - - const sh::Attribute &shaderAttr = shaderAttributes[attributeIndex]; - - if (shaderAttr.type != GL_NONE) - { - GLenum transposedType = TransposeMatrixType(shaderAttr.type); - - for (size_t rowIndex = 0; static_cast(rowIndex) < VariableRowCount(transposedType); rowIndex++, layoutIndex++) - { - VertexFormat *defaultFormat = &inputLayout[layoutIndex]; - - defaultFormat->mType = VariableComponentType(transposedType); - defaultFormat->mNormalized = false; - defaultFormat->mPureInteger = (defaultFormat->mType != GL_FLOAT); // note: inputs can not be bool - defaultFormat->mComponents = VariableColumnCount(transposedType); - } - } - } -} - -std::vector GetDefaultOutputLayoutFromShader(const std::vector &shaderOutputVars) -{ - std::vector defaultPixelOutput(1); - - ASSERT(!shaderOutputVars.empty()); - defaultPixelOutput[0] = GL_COLOR_ATTACHMENT0 + shaderOutputVars[0].outputIndex; - - return defaultPixelOutput; -} - -bool IsRowMajorLayout(const sh::InterfaceBlockField &var) -{ - return var.isRowMajorLayout; -} - -bool IsRowMajorLayout(const sh::ShaderVariable &var) -{ - return false; -} - } VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index) @@ -136,47 +58,6 @@ VariableLocation::VariableLocation(const std::string &name, unsigned int element { } -ProgramBinary::VertexExecutable::VertexExecutable(const VertexFormat inputLayout[], - const GLenum signature[], - rx::ShaderExecutable *shaderExecutable) - : mShaderExecutable(shaderExecutable) -{ - for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) - { - mInputs[attributeIndex] = inputLayout[attributeIndex]; - mSignature[attributeIndex] = signature[attributeIndex]; - } -} - -ProgramBinary::VertexExecutable::~VertexExecutable() -{ - SafeDelete(mShaderExecutable); -} - -bool ProgramBinary::VertexExecutable::matchesSignature(const GLenum signature[]) const -{ - for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) - { - if (mSignature[attributeIndex] != signature[attributeIndex]) - { - return false; - } - } - - return true; -} - -ProgramBinary::PixelExecutable::PixelExecutable(const std::vector &outputSignature, rx::ShaderExecutable *shaderExecutable) - : mOutputSignature(outputSignature), - mShaderExecutable(shaderExecutable) -{ -} - -ProgramBinary::PixelExecutable::~PixelExecutable() -{ - SafeDelete(mShaderExecutable); -} - LinkedVarying::LinkedVarying() { } @@ -187,17 +68,17 @@ LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, { } +LinkResult::LinkResult(bool linkSuccess, const Error &error) + : linkSuccess(linkSuccess), + error(error) +{ +} + unsigned int ProgramBinary::mCurrentSerial = 1; ProgramBinary::ProgramBinary(rx::ProgramImpl *impl) : RefCountObject(0), mProgram(impl), - mGeometryExecutable(NULL), - mUsedVertexSamplerRange(0), - mUsedPixelSamplerRange(0), - mUsesPointSize(false), - mShaderVersion(100), - mDirtySamplerMapping(true), mValidated(false), mSerial(issueSerial()) { @@ -220,103 +101,11 @@ unsigned int ProgramBinary::getSerial() const return mSerial; } -int ProgramBinary::getShaderVersion() const -{ - return mShaderVersion; -} - unsigned int ProgramBinary::issueSerial() { return mCurrentSerial++; } -rx::ShaderExecutable *ProgramBinary::getPixelExecutableForFramebuffer(const Framebuffer *fbo) -{ - std::vector outputs; - - const gl::ColorbufferInfo &colorbuffers = fbo->getColorbuffersForRender(); - - for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) - { - const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment]; - - if (colorbuffer) - { - outputs.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding()); - } - else - { - outputs.push_back(GL_NONE); - } - } - - return getPixelExecutableForOutputLayout(outputs); -} - -rx::ShaderExecutable *ProgramBinary::getPixelExecutableForOutputLayout(const std::vector &outputSignature) -{ - for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++) - { - if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature)) - { - return mPixelExecutables[executableIndex]->shaderExecutable(); - } - } - - InfoLog tempInfoLog; - rx::ShaderExecutable *pixelExecutable = mProgram->getPixelExecutableForOutputLayout(tempInfoLog, outputSignature, - mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); - - if (!pixelExecutable) - { - std::vector tempCharBuffer(tempInfoLog.getLength() + 3); - tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]); - ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]); - } - else - { - mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable)); - } - - return pixelExecutable; -} - -rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]) -{ - GLenum signature[MAX_VERTEX_ATTRIBS]; - mProgram->getDynamicHLSL()->getInputLayoutSignature(inputLayout, signature); - - for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++) - { - if (mVertexExecutables[executableIndex]->matchesSignature(signature)) - { - return mVertexExecutables[executableIndex]->shaderExecutable(); - } - } - - InfoLog tempInfoLog; - rx::ShaderExecutable *vertexExecutable = mProgram->getVertexExecutableForInputLayout(tempInfoLog, inputLayout, mShaderAttributes, - mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); - - if (!vertexExecutable) - { - std::vector tempCharBuffer(tempInfoLog.getLength()+3); - tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]); - ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]); - } - else - { - mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, vertexExecutable)); - } - - return vertexExecutable; -} - -rx::ShaderExecutable *ProgramBinary::getGeometryExecutable() const -{ - return mGeometryExecutable; -} - GLuint ProgramBinary::getAttributeLocation(const char *name) { if (name) @@ -343,157 +132,42 @@ int ProgramBinary::getSemanticIndex(int attributeIndex) // Returns one more than the highest sampler index used. GLint ProgramBinary::getUsedSamplerRange(SamplerType type) { - switch (type) - { - case SAMPLER_PIXEL: - return mUsedPixelSamplerRange; - case SAMPLER_VERTEX: - return mUsedVertexSamplerRange; - default: - UNREACHABLE(); - return 0; - } + return mProgram->getUsedSamplerRange(type); } bool ProgramBinary::usesPointSize() const { - return mUsesPointSize; -} - -bool ProgramBinary::usesPointSpriteEmulation() const -{ - return mUsesPointSize && mProgram->getRenderer()->getMajorShaderModel() >= 4; -} - -bool ProgramBinary::usesGeometryShader() const -{ - return usesPointSpriteEmulation(); + return mProgram->usesPointSize(); } GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps) { - GLint logicalTextureUnit = -1; - - switch (type) - { - case SAMPLER_PIXEL: - ASSERT(samplerIndex < caps.maxTextureImageUnits); - if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active) - { - logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit; - } - break; - case SAMPLER_VERTEX: - ASSERT(samplerIndex < caps.maxVertexTextureImageUnits); - if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active) - { - logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit; - } - break; - default: UNREACHABLE(); - } - - if (logicalTextureUnit >= 0 && logicalTextureUnit < static_cast(caps.maxCombinedTextureImageUnits)) - { - return logicalTextureUnit; - } - - return -1; + return mProgram->getSamplerMapping(type, samplerIndex, caps); } -// Returns the texture type for a given Direct3D 9 sampler type and -// index (0-15 for the pixel shader and 0-3 for the vertex shader). GLenum ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex) { - switch (type) - { - case SAMPLER_PIXEL: - ASSERT(samplerIndex < mSamplersPS.size()); - ASSERT(mSamplersPS[samplerIndex].active); - return mSamplersPS[samplerIndex].textureType; - case SAMPLER_VERTEX: - ASSERT(samplerIndex < mSamplersVS.size()); - ASSERT(mSamplersVS[samplerIndex].active); - return mSamplersVS[samplerIndex].textureType; - default: UNREACHABLE(); - } - - return GL_TEXTURE_2D; + return mProgram->getSamplerTextureType(type, samplerIndex); } GLint ProgramBinary::getUniformLocation(std::string name) { - unsigned int subscript = ParseAndStripArrayIndex(&name); - - unsigned int numUniforms = mUniformIndex.size(); - for (unsigned int location = 0; location < numUniforms; location++) - { - if (mUniformIndex[location].name == name) - { - const int index = mUniformIndex[location].index; - const bool isArray = mUniforms[index]->isArray(); - - if ((isArray && mUniformIndex[location].element == subscript) || - (subscript == GL_INVALID_INDEX)) - { - return location; - } - } - } - - return -1; + return mProgram->getUniformLocation(name); } GLuint ProgramBinary::getUniformIndex(std::string name) { - unsigned int subscript = ParseAndStripArrayIndex(&name); - - // The app is not allowed to specify array indices other than 0 for arrays of basic types - if (subscript != 0 && subscript != GL_INVALID_INDEX) - { - return GL_INVALID_INDEX; - } - - unsigned int numUniforms = mUniforms.size(); - for (unsigned int index = 0; index < numUniforms; index++) - { - if (mUniforms[index]->name == name) - { - if (mUniforms[index]->isArray() || subscript == GL_INVALID_INDEX) - { - return index; - } - } - } - - return GL_INVALID_INDEX; + return mProgram->getUniformIndex(name); } GLuint ProgramBinary::getUniformBlockIndex(std::string name) { - unsigned int subscript = ParseAndStripArrayIndex(&name); - - unsigned int numUniformBlocks = mUniformBlocks.size(); - for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++) - { - const UniformBlock &uniformBlock = *mUniformBlocks[blockIndex]; - if (uniformBlock.name == name) - { - const bool arrayElementZero = (subscript == GL_INVALID_INDEX && uniformBlock.elementIndex == 0); - if (subscript == uniformBlock.elementIndex || arrayElementZero) - { - return blockIndex; - } - } - } - - return GL_INVALID_INDEX; + return mProgram->getUniformBlockIndex(name); } UniformBlock *ProgramBinary::getUniformBlockByIndex(GLuint blockIndex) { - ASSERT(blockIndex < mUniformBlocks.size()); - return mUniformBlocks[blockIndex]; + return mProgram->getUniformBlockByIndex(blockIndex); } GLint ProgramBinary::getFragDataLocation(const char *name) const @@ -517,524 +191,129 @@ GLint ProgramBinary::getFragDataLocation(const char *name) const size_t ProgramBinary::getTransformFeedbackVaryingCount() const { - return mTransformFeedbackLinkedVaryings.size(); + return mProgram->getTransformFeedbackLinkedVaryings().size(); } const LinkedVarying &ProgramBinary::getTransformFeedbackVarying(size_t idx) const { - return mTransformFeedbackLinkedVaryings[idx]; + return mProgram->getTransformFeedbackLinkedVaryings()[idx]; } GLenum ProgramBinary::getTransformFeedbackBufferMode() const { - return mTransformFeedbackBufferMode; + return mProgram->getTransformFeedbackBufferMode(); } -template -static inline void SetIfDirty(T *dest, const T& source, bool *dirtyFlag) -{ - ASSERT(dest != NULL); - ASSERT(dirtyFlag != NULL); - - *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0); - *dest = source; +void ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat *v) { + mProgram->setUniform1fv(location, count, v); } -template -void ProgramBinary::setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType) -{ - const int components = VariableComponentCount(targetUniformType); - const GLenum targetBoolType = VariableBoolVectorType(targetUniformType); - - LinkedUniform *targetUniform = getUniformByLocation(location); - - int elementCount = targetUniform->elementCount(); - - count = std::min(elementCount - (int)mUniformIndex[location].element, count); - - if (targetUniform->type == targetUniformType) - { - T *target = reinterpret_cast(targetUniform->data) + mUniformIndex[location].element * 4; - - for (int i = 0; i < count; i++) - { - T *dest = target + (i * 4); - const T *source = v + (i * components); - - for (int c = 0; c < components; c++) - { - SetIfDirty(dest + c, source[c], &targetUniform->dirty); - } - for (int c = components; c < 4; c++) - { - SetIfDirty(dest + c, T(0), &targetUniform->dirty); - } - } - } - else if (targetUniform->type == targetBoolType) - { - GLint *boolParams = reinterpret_cast(targetUniform->data) + mUniformIndex[location].element * 4; - - for (int i = 0; i < count; i++) - { - GLint *dest = boolParams + (i * 4); - const T *source = v + (i * components); - - for (int c = 0; c < components; c++) - { - SetIfDirty(dest + c, (source[c] == static_cast(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty); - } - for (int c = components; c < 4; c++) - { - SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty); - } - } - } - else if (IsSampler(targetUniform->type)) - { - ASSERT(targetUniformType == GL_INT); - - GLint *target = reinterpret_cast(targetUniform->data) + mUniformIndex[location].element * 4; - - bool wasDirty = targetUniform->dirty; - - for (int i = 0; i < count; i++) - { - GLint *dest = target + (i * 4); - const GLint *source = reinterpret_cast(v) + (i * components); - - SetIfDirty(dest + 0, source[0], &targetUniform->dirty); - SetIfDirty(dest + 1, 0, &targetUniform->dirty); - SetIfDirty(dest + 2, 0, &targetUniform->dirty); - SetIfDirty(dest + 3, 0, &targetUniform->dirty); - } - - if (!wasDirty && targetUniform->dirty) - { - mDirtySamplerMapping = true; - } - } - else UNREACHABLE(); +void ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) { + mProgram->setUniform2fv(location, count, v); } -void ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat* v) -{ - setUniform(location, count, v, GL_FLOAT); +void ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) { + mProgram->setUniform3fv(location, count, v); } -void ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) -{ - setUniform(location, count, v, GL_FLOAT_VEC2); +void ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) { + mProgram->setUniform4fv(location, count, v); } -void ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) -{ - setUniform(location, count, v, GL_FLOAT_VEC3); +void ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v) { + mProgram->setUniform1iv(location, count, v); } -void ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) -{ - setUniform(location, count, v, GL_FLOAT_VEC4); +void ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v) { + mProgram->setUniform2iv(location, count, v); } -template -bool transposeMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight) -{ - bool dirty = false; - int copyWidth = std::min(targetHeight, srcWidth); - int copyHeight = std::min(targetWidth, srcHeight); - - for (int x = 0; x < copyWidth; x++) - { - for (int y = 0; y < copyHeight; y++) - { - SetIfDirty(target + (x * targetWidth + y), static_cast(value[y * srcWidth + x]), &dirty); - } - } - // clear unfilled right side - for (int y = 0; y < copyWidth; y++) - { - for (int x = copyHeight; x < targetWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); - } - } - // clear unfilled bottom. - for (int y = copyWidth; y < targetHeight; y++) - { - for (int x = 0; x < targetWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); - } - } - - return dirty; +void ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v) { + mProgram->setUniform3iv(location, count, v); } -template -bool expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight) -{ - bool dirty = false; - int copyWidth = std::min(targetWidth, srcWidth); - int copyHeight = std::min(targetHeight, srcHeight); - - for (int y = 0; y < copyHeight; y++) - { - for (int x = 0; x < copyWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast(value[y * srcWidth + x]), &dirty); - } - } - // clear unfilled right side - for (int y = 0; y < copyHeight; y++) - { - for (int x = copyWidth; x < targetWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); - } - } - // clear unfilled bottom. - for (int y = copyHeight; y < targetHeight; y++) - { - for (int x = 0; x < targetWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); - } - } - - return dirty; +void ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v) { + mProgram->setUniform4iv(location, count, v); } -template -void ProgramBinary::setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType) -{ - LinkedUniform *targetUniform = getUniformByLocation(location); - - int elementCount = targetUniform->elementCount(); - - count = std::min(elementCount - (int)mUniformIndex[location].element, count); - const unsigned int targetMatrixStride = (4 * rows); - GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * targetMatrixStride); - - for (int i = 0; i < count; i++) - { - // Internally store matrices as transposed versions to accomodate HLSL matrix indexing - if (transpose == GL_FALSE) - { - targetUniform->dirty = transposeMatrix(target, value, 4, rows, rows, cols) || targetUniform->dirty; - } - else - { - targetUniform->dirty = expandMatrix(target, value, 4, rows, cols, rows) || targetUniform->dirty; - } - target += targetMatrixStride; - value += cols * rows; - } +void ProgramBinary::setUniform1uiv(GLint location, GLsizei count, const GLuint *v) { + mProgram->setUniform1uiv(location, count, v); } -void ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2); +void ProgramBinary::setUniform2uiv(GLint location, GLsizei count, const GLuint *v) { + mProgram->setUniform2uiv(location, count, v); } -void ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3); +void ProgramBinary::setUniform3uiv(GLint location, GLsizei count, const GLuint *v) { + mProgram->setUniform3uiv(location, count, v); } -void ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4); +void ProgramBinary::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) { + mProgram->setUniform4uiv(location, count, v); } -void ProgramBinary::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3); +void ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + mProgram->setUniformMatrix2fv(location, count, transpose, v); } -void ProgramBinary::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2); +void ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + mProgram->setUniformMatrix3fv(location, count, transpose, v); } -void ProgramBinary::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4); +void ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + mProgram->setUniformMatrix4fv(location, count, transpose, v); } -void ProgramBinary::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2); +void ProgramBinary::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + mProgram->setUniformMatrix2x3fv(location, count, transpose, v); } -void ProgramBinary::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4); +void ProgramBinary::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + mProgram->setUniformMatrix2x4fv(location, count, transpose, v); } -void ProgramBinary::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3); +void ProgramBinary::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + mProgram->setUniformMatrix3x2fv(location, count, transpose, v); } -void ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v) -{ - setUniform(location, count, v, GL_INT); +void ProgramBinary::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + mProgram->setUniformMatrix3x4fv(location, count, transpose, v); } -void ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v) -{ - setUniform(location, count, v, GL_INT_VEC2); +void ProgramBinary::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + mProgram->setUniformMatrix4x2fv(location, count, transpose, v); } -void ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v) -{ - setUniform(location, count, v, GL_INT_VEC3); +void ProgramBinary::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + mProgram->setUniformMatrix4x3fv(location, count, transpose, v); } -void ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v) -{ - setUniform(location, count, v, GL_INT_VEC4); +void ProgramBinary::getUniformfv(GLint location, GLfloat *v) { + mProgram->getUniformfv(location, v); } -void ProgramBinary::setUniform1uiv(GLint location, GLsizei count, const GLuint *v) -{ - setUniform(location, count, v, GL_UNSIGNED_INT); +void ProgramBinary::getUniformiv(GLint location, GLint *v) { + mProgram->getUniformiv(location, v); } -void ProgramBinary::setUniform2uiv(GLint location, GLsizei count, const GLuint *v) -{ - setUniform(location, count, v, GL_UNSIGNED_INT_VEC2); -} - -void ProgramBinary::setUniform3uiv(GLint location, GLsizei count, const GLuint *v) -{ - setUniform(location, count, v, GL_UNSIGNED_INT_VEC3); -} - -void ProgramBinary::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) -{ - setUniform(location, count, v, GL_UNSIGNED_INT_VEC4); -} - -template -void ProgramBinary::getUniformv(GLint location, T *params, GLenum uniformType) -{ - LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index]; - - if (IsMatrixType(targetUniform->type)) - { - const int rows = VariableRowCount(targetUniform->type); - const int cols = VariableColumnCount(targetUniform->type); - transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4 * rows, rows, cols, 4, rows); - } - else if (uniformType == VariableComponentType(targetUniform->type)) - { - unsigned int size = VariableComponentCount(targetUniform->type); - memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(T), - size * sizeof(T)); - } - else - { - unsigned int size = VariableComponentCount(targetUniform->type); - switch (VariableComponentType(targetUniform->type)) - { - case GL_BOOL: - { - GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (unsigned int i = 0; i < size; i++) - { - params[i] = (boolParams[i] == GL_FALSE) ? static_cast(0) : static_cast(1); - } - } - break; - - case GL_FLOAT: - { - GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; - - for (unsigned int i = 0; i < size; i++) - { - params[i] = static_cast(floatParams[i]); - } - } - break; - - case GL_INT: - { - GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (unsigned int i = 0; i < size; i++) - { - params[i] = static_cast(intParams[i]); - } - } - break; - - case GL_UNSIGNED_INT: - { - GLuint *uintParams = (GLuint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (unsigned int i = 0; i < size; i++) - { - params[i] = static_cast(uintParams[i]); - } - } - break; - - default: UNREACHABLE(); - } - } -} - -void ProgramBinary::getUniformfv(GLint location, GLfloat *params) -{ - getUniformv(location, params, GL_FLOAT); -} - -void ProgramBinary::getUniformiv(GLint location, GLint *params) -{ - getUniformv(location, params, GL_INT); -} - -void ProgramBinary::getUniformuiv(GLint location, GLuint *params) -{ - getUniformv(location, params, GL_UNSIGNED_INT); -} - -void ProgramBinary::dirtyAllUniforms() -{ - unsigned int numUniforms = mUniforms.size(); - for (unsigned int index = 0; index < numUniforms; index++) - { - mUniforms[index]->dirty = true; - } +void ProgramBinary::getUniformuiv(GLint location, GLuint *v) { + mProgram->getUniformuiv(location, v); } void ProgramBinary::updateSamplerMapping() { - if (!mDirtySamplerMapping) - { - return; - } - - mDirtySamplerMapping = false; - - // Retrieve sampler uniform values - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) - { - LinkedUniform *targetUniform = mUniforms[uniformIndex]; - - if (targetUniform->dirty) - { - if (IsSampler(targetUniform->type)) - { - int count = targetUniform->elementCount(); - GLint (*v)[4] = reinterpret_cast(targetUniform->data); - - if (targetUniform->isReferencedByFragmentShader()) - { - unsigned int firstIndex = targetUniform->psRegisterIndex; - - for (int i = 0; i < count; i++) - { - unsigned int samplerIndex = firstIndex + i; - - if (samplerIndex < mSamplersPS.size()) - { - ASSERT(mSamplersPS[samplerIndex].active); - mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0]; - } - } - } - - if (targetUniform->isReferencedByVertexShader()) - { - unsigned int firstIndex = targetUniform->vsRegisterIndex; - - for (int i = 0; i < count; i++) - { - unsigned int samplerIndex = firstIndex + i; - - if (samplerIndex < mSamplersVS.size()) - { - ASSERT(mSamplersVS[samplerIndex].active); - mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0]; - } - } - } - } - } - } + return mProgram->updateSamplerMapping(); } // Applies all the uniforms set for this program object to the renderer Error ProgramBinary::applyUniforms() { - updateSamplerMapping(); - - Error error = mProgram->getRenderer()->applyUniforms(*this); - if (error.isError()) - { - return error; - } - - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) - { - mUniforms[uniformIndex]->dirty = false; - } - - return gl::Error(GL_NO_ERROR); + return mProgram->applyUniforms(); } Error ProgramBinary::applyUniformBuffers(const std::vector boundBuffers, const Caps &caps) { - const gl::Buffer *vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS] = {NULL}; - const gl::Buffer *fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS] = {NULL}; - - const unsigned int reservedBuffersInVS = mProgram->getRenderer()->getReservedVertexUniformBuffers(); - const unsigned int reservedBuffersInFS = mProgram->getRenderer()->getReservedFragmentUniformBuffers(); - - ASSERT(boundBuffers.size() == mUniformBlocks.size()); - - for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); uniformBlockIndex++) - { - UniformBlock *uniformBlock = getUniformBlockByIndex(uniformBlockIndex); - gl::Buffer *uniformBuffer = boundBuffers[uniformBlockIndex]; - - ASSERT(uniformBlock && uniformBuffer); - - if (uniformBuffer->getSize() < uniformBlock->dataSize) - { - // undefined behaviour - return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small."); - } - - // Unnecessary to apply an unreferenced standard or shared UBO - if (!uniformBlock->isReferencedByVertexShader() && !uniformBlock->isReferencedByFragmentShader()) - { - continue; - } - - if (uniformBlock->isReferencedByVertexShader()) - { - unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS; - ASSERT(vertexUniformBuffers[registerIndex] == NULL); - ASSERT(registerIndex < caps.maxVertexUniformBlocks); - vertexUniformBuffers[registerIndex] = uniformBuffer; - } - - if (uniformBlock->isReferencedByFragmentShader()) - { - unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS; - ASSERT(fragmentUniformBuffers[registerIndex] == NULL); - ASSERT(registerIndex < caps.maxFragmentUniformBlocks); - fragmentUniformBuffers[registerIndex] = uniformBuffer; - } - } - - return mProgram->getRenderer()->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers); + return mProgram->applyUniformBuffers(boundBuffers, caps); } bool ProgramBinary::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader) @@ -1082,10 +361,10 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shade return true; } -bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length) +LinkResult ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length) { -#ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD - return false; +#if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_DISABLED + return LinkResult(false, Error(GL_NO_ERROR)); #else ASSERT(binaryFormat == mProgram->getBinaryFormat()); @@ -1097,7 +376,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina if (format != mProgram->getBinaryFormat()) { infoLog.append("Invalid program binary format."); - return false; + return LinkResult(false, Error(GL_NO_ERROR)); } int majorVersion = stream.readInt(); @@ -1105,7 +384,7 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION) { infoLog.append("Invalid program binary version."); - return false; + return LinkResult(false, Error(GL_NO_ERROR)); } unsigned char commitString[ANGLE_COMMIT_HASH_SIZE]; @@ -1113,250 +392,38 @@ bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *bina if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0) { infoLog.append("Invalid program binary version."); - return false; + return LinkResult(false, Error(GL_NO_ERROR)); } int compileFlags = stream.readInt(); if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL) { infoLog.append("Mismatched compilation flags."); - return false; + return LinkResult(false, Error(GL_NO_ERROR)); } for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) { stream.readInt(&mLinkedAttribute[i].type); stream.readString(&mLinkedAttribute[i].name); - stream.readInt(&mShaderAttributes[i].type); - stream.readString(&mShaderAttributes[i].name); + stream.readInt(&mProgram->getShaderAttributes()[i].type); + stream.readString(&mProgram->getShaderAttributes()[i].name); stream.readInt(&mSemanticIndex[i]); } initAttributesByLayout(); - const unsigned int psSamplerCount = stream.readInt(); - for (unsigned int i = 0; i < psSamplerCount; ++i) + LinkResult result = mProgram->load(infoLog, &stream); + if (result.error.isError() || !result.linkSuccess) { - Sampler sampler; - stream.readBool(&sampler.active); - stream.readInt(&sampler.logicalTextureUnit); - stream.readInt(&sampler.textureType); - mSamplersPS.push_back(sampler); - } - const unsigned int vsSamplerCount = stream.readInt(); - for (unsigned int i = 0; i < vsSamplerCount; ++i) - { - Sampler sampler; - stream.readBool(&sampler.active); - stream.readInt(&sampler.logicalTextureUnit); - stream.readInt(&sampler.textureType); - mSamplersVS.push_back(sampler); + return result; } - stream.readInt(&mUsedVertexSamplerRange); - stream.readInt(&mUsedPixelSamplerRange); - stream.readBool(&mUsesPointSize); - stream.readInt(&mShaderVersion); - - const unsigned int uniformCount = stream.readInt(); - if (stream.error()) - { - infoLog.append("Invalid program binary."); - return false; - } - - mUniforms.resize(uniformCount); - for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++) - { - GLenum type = stream.readInt(); - GLenum precision = stream.readInt(); - std::string name = stream.readString(); - unsigned int arraySize = stream.readInt(); - int blockIndex = stream.readInt(); - - int offset = stream.readInt(); - int arrayStride = stream.readInt(); - int matrixStride = stream.readInt(); - bool isRowMajorMatrix = stream.readBool(); - - const sh::BlockMemberInfo blockInfo(offset, arrayStride, matrixStride, isRowMajorMatrix); - - LinkedUniform *uniform = new LinkedUniform(type, precision, name, arraySize, blockIndex, blockInfo); - - stream.readInt(&uniform->psRegisterIndex); - stream.readInt(&uniform->vsRegisterIndex); - stream.readInt(&uniform->registerCount); - stream.readInt(&uniform->registerElement); - - mUniforms[uniformIndex] = uniform; - } - - unsigned int uniformBlockCount = stream.readInt(); - if (stream.error()) - { - infoLog.append("Invalid program binary."); - return false; - } - - mUniformBlocks.resize(uniformBlockCount); - for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex) - { - std::string name = stream.readString(); - unsigned int elementIndex = stream.readInt(); - unsigned int dataSize = stream.readInt(); - - UniformBlock *uniformBlock = new UniformBlock(name, elementIndex, dataSize); - - stream.readInt(&uniformBlock->psRegisterIndex); - stream.readInt(&uniformBlock->vsRegisterIndex); - - unsigned int numMembers = stream.readInt(); - uniformBlock->memberUniformIndexes.resize(numMembers); - for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++) - { - stream.readInt(&uniformBlock->memberUniformIndexes[blockMemberIndex]); - } - - mUniformBlocks[uniformBlockIndex] = uniformBlock; - } - - const unsigned int uniformIndexCount = stream.readInt(); - if (stream.error()) - { - infoLog.append("Invalid program binary."); - return false; - } - - mUniformIndex.resize(uniformIndexCount); - for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; uniformIndexIndex++) - { - stream.readString(&mUniformIndex[uniformIndexIndex].name); - stream.readInt(&mUniformIndex[uniformIndexIndex].element); - stream.readInt(&mUniformIndex[uniformIndexIndex].index); - } - - stream.readInt(&mTransformFeedbackBufferMode); - const unsigned int transformFeedbackVaryingCount = stream.readInt(); - mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount); - for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++) - { - LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex]; - - stream.readString(&varying.name); - stream.readInt(&varying.type); - stream.readInt(&varying.size); - stream.readString(&varying.semanticName); - stream.readInt(&varying.semanticIndex); - stream.readInt(&varying.semanticIndexCount); - } - - const unsigned int vertexShaderCount = stream.readInt(); - for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++) - { - VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]; - - for (size_t inputIndex = 0; inputIndex < MAX_VERTEX_ATTRIBS; inputIndex++) - { - VertexFormat *vertexInput = &inputLayout[inputIndex]; - stream.readInt(&vertexInput->mType); - stream.readInt(&vertexInput->mNormalized); - stream.readInt(&vertexInput->mComponents); - stream.readBool(&vertexInput->mPureInteger); - } - - unsigned int vertexShaderSize = stream.readInt(); - const unsigned char *vertexShaderFunction = reinterpret_cast(binary) + stream.offset(); - rx::ShaderExecutable *shaderExecutable = mProgram->getRenderer()->loadExecutable(reinterpret_cast(vertexShaderFunction), - vertexShaderSize, rx::SHADER_VERTEX, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); - if (!shaderExecutable) - { - infoLog.append("Could not create vertex shader."); - return false; - } - - // generated converted input layout - GLenum signature[MAX_VERTEX_ATTRIBS]; - mProgram->getDynamicHLSL()->getInputLayoutSignature(inputLayout, signature); - - // add new binary - mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable)); - - stream.skip(vertexShaderSize); - } - - const size_t pixelShaderCount = stream.readInt(); - for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++) - { - const size_t outputCount = stream.readInt(); - std::vector outputs(outputCount); - for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++) - { - stream.readInt(&outputs[outputIndex]); - } - - const size_t pixelShaderSize = stream.readInt(); - const unsigned char *pixelShaderFunction = reinterpret_cast(binary) + stream.offset(); - rx::Renderer *renderer = mProgram->getRenderer(); - rx::ShaderExecutable *shaderExecutable = renderer->loadExecutable(pixelShaderFunction, pixelShaderSize, - rx::SHADER_PIXEL, mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); - - if (!shaderExecutable) - { - infoLog.append("Could not create pixel shader."); - return false; - } - - // add new binary - mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable)); - - stream.skip(pixelShaderSize); - } - - unsigned int geometryShaderSize = stream.readInt(); - - if (geometryShaderSize > 0) - { - const char *geometryShaderFunction = (const char*) binary + stream.offset(); - rx::Renderer *renderer = mProgram->getRenderer(); - mGeometryExecutable = renderer->loadExecutable(reinterpret_cast(geometryShaderFunction), - geometryShaderSize, rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); - - if (!mGeometryExecutable) - { - infoLog.append("Could not create geometry shader."); - return false; - } - stream.skip(geometryShaderSize); - } - - if (!mProgram->load(infoLog, &stream)) - { - return false; - } - - const char *ptr = (const char*) binary + stream.offset(); - - const GUID *binaryIdentifier = (const GUID *) ptr; - ptr += sizeof(GUID); - - GUID identifier = mProgram->getRenderer()->getAdapterIdentifier(); - if (memcmp(&identifier, binaryIdentifier, sizeof(GUID)) != 0) - { - infoLog.append("Invalid program binary."); - return false; - } - - mProgram->initializeUniformStorage(mUniforms); - - return true; -#endif // #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD + return LinkResult(true, Error(GL_NO_ERROR)); +#endif // #if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_ENABLED } -bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) +Error ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) { if (binaryFormat) { @@ -1375,168 +442,27 @@ bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GL { stream.writeInt(mLinkedAttribute[i].type); stream.writeString(mLinkedAttribute[i].name); - stream.writeInt(mShaderAttributes[i].type); - stream.writeString(mShaderAttributes[i].name); + stream.writeInt(mProgram->getShaderAttributes()[i].type); + stream.writeString(mProgram->getShaderAttributes()[i].name); stream.writeInt(mSemanticIndex[i]); } - stream.writeInt(mSamplersPS.size()); - for (unsigned int i = 0; i < mSamplersPS.size(); ++i) - { - stream.writeInt(mSamplersPS[i].active); - stream.writeInt(mSamplersPS[i].logicalTextureUnit); - stream.writeInt(mSamplersPS[i].textureType); - } - - stream.writeInt(mSamplersVS.size()); - for (unsigned int i = 0; i < mSamplersVS.size(); ++i) - { - stream.writeInt(mSamplersVS[i].active); - stream.writeInt(mSamplersVS[i].logicalTextureUnit); - stream.writeInt(mSamplersVS[i].textureType); - } - - stream.writeInt(mUsedVertexSamplerRange); - stream.writeInt(mUsedPixelSamplerRange); - stream.writeInt(mUsesPointSize); - stream.writeInt(mShaderVersion); - - stream.writeInt(mUniforms.size()); - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex) - { - const LinkedUniform &uniform = *mUniforms[uniformIndex]; - - stream.writeInt(uniform.type); - stream.writeInt(uniform.precision); - stream.writeString(uniform.name); - stream.writeInt(uniform.arraySize); - stream.writeInt(uniform.blockIndex); - - stream.writeInt(uniform.blockInfo.offset); - stream.writeInt(uniform.blockInfo.arrayStride); - stream.writeInt(uniform.blockInfo.matrixStride); - stream.writeInt(uniform.blockInfo.isRowMajorMatrix); - - stream.writeInt(uniform.psRegisterIndex); - stream.writeInt(uniform.vsRegisterIndex); - stream.writeInt(uniform.registerCount); - stream.writeInt(uniform.registerElement); - } - - stream.writeInt(mUniformBlocks.size()); - for (size_t uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); ++uniformBlockIndex) - { - const UniformBlock& uniformBlock = *mUniformBlocks[uniformBlockIndex]; - - stream.writeString(uniformBlock.name); - stream.writeInt(uniformBlock.elementIndex); - stream.writeInt(uniformBlock.dataSize); - - stream.writeInt(uniformBlock.memberUniformIndexes.size()); - for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++) - { - stream.writeInt(uniformBlock.memberUniformIndexes[blockMemberIndex]); - } - - stream.writeInt(uniformBlock.psRegisterIndex); - stream.writeInt(uniformBlock.vsRegisterIndex); - } - - stream.writeInt(mUniformIndex.size()); - for (size_t i = 0; i < mUniformIndex.size(); ++i) - { - stream.writeString(mUniformIndex[i].name); - stream.writeInt(mUniformIndex[i].element); - stream.writeInt(mUniformIndex[i].index); - } - - stream.writeInt(mTransformFeedbackBufferMode); - stream.writeInt(mTransformFeedbackLinkedVaryings.size()); - for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++) - { - const LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i]; - - stream.writeString(varying.name); - stream.writeInt(varying.type); - stream.writeInt(varying.size); - stream.writeString(varying.semanticName); - stream.writeInt(varying.semanticIndex); - stream.writeInt(varying.semanticIndexCount); - } - - stream.writeInt(mVertexExecutables.size()); - for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++) - { - VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex]; - - for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++) - { - const VertexFormat &vertexInput = vertexExecutable->inputs()[inputIndex]; - stream.writeInt(vertexInput.mType); - stream.writeInt(vertexInput.mNormalized); - stream.writeInt(vertexInput.mComponents); - stream.writeInt(vertexInput.mPureInteger); - } - - size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength(); - stream.writeInt(vertexShaderSize); - - const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction(); - stream.writeBytes(vertexBlob, vertexShaderSize); - } - - stream.writeInt(mPixelExecutables.size()); - for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++) - { - PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex]; - - const std::vector outputs = pixelExecutable->outputSignature(); - stream.writeInt(outputs.size()); - for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++) - { - stream.writeInt(outputs[outputIndex]); - } - - size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength(); - stream.writeInt(pixelShaderSize); - - const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction(); - stream.writeBytes(pixelBlob, pixelShaderSize); - } - - size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0; - stream.writeInt(geometryShaderSize); - - if (mGeometryExecutable != NULL && geometryShaderSize > 0) - { - const uint8_t *geometryBlob = mGeometryExecutable->getFunction(); - stream.writeBytes(geometryBlob, geometryShaderSize); - } - - if (!mProgram->save(&stream)) - { - if (length) - { - *length = 0; - } - - return false; - } - - GUID identifier = mProgram->getRenderer()->getAdapterIdentifier(); + mProgram->save(&stream); GLsizei streamLength = stream.length(); const void *streamData = stream.data(); - GLsizei totalLength = streamLength + sizeof(GUID); - if (totalLength > bufSize) + if (streamLength > bufSize) { if (length) { *length = 0; } - return false; + // TODO: This should be moved to the validation layer but computing the size of the binary before saving + // it causes the save to happen twice. It may be possible to write the binary to a separate buffer, validate + // sizes and then copy it. + return Error(GL_INVALID_OPERATION); } if (binary) @@ -1546,129 +472,197 @@ bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GL memcpy(ptr, streamData, streamLength); ptr += streamLength; - memcpy(ptr, &identifier, sizeof(GUID)); - ptr += sizeof(GUID); - - ASSERT(ptr - totalLength == binary); + ASSERT(ptr - streamLength == binary); } if (length) { - *length = totalLength; + *length = streamLength; } - return true; + return Error(GL_NO_ERROR); } GLint ProgramBinary::getLength() { GLint length; - if (save(NULL, NULL, INT_MAX, &length)) - { - return length; - } - else + Error error = save(NULL, NULL, INT_MAX, &length); + if (error.isError()) { return 0; } + + return length; } -bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader, - const std::vector& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps) +LinkResult ProgramBinary::link(const Data &data, InfoLog &infoLog, const AttributeBindings &attributeBindings, + Shader *fragmentShader, Shader *vertexShader, + const std::vector &transformFeedbackVaryings, + GLenum transformFeedbackBufferMode) { if (!fragmentShader || !fragmentShader->isCompiled()) { - return false; + return LinkResult(false, Error(GL_NO_ERROR)); } ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER); if (!vertexShader || !vertexShader->isCompiled()) { - return false; + return LinkResult(false, Error(GL_NO_ERROR)); } ASSERT(vertexShader->getType() == GL_VERTEX_SHADER); reset(); - mSamplersPS.resize(caps.maxTextureImageUnits); - mSamplersVS.resize(caps.maxVertexTextureImageUnits); - - mTransformFeedbackBufferMode = transformFeedbackBufferMode; - - rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); - rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader->getImplementation()); - - mShaderVersion = vertexShaderD3D->getShaderVersion(); - int registers; std::vector linkedVaryings; - if (!mProgram->link(infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, ®isters, &linkedVaryings, &mOutputVariables)) + LinkResult result = mProgram->link(data, infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, transformFeedbackBufferMode, + ®isters, &linkedVaryings, &mOutputVariables); + if (result.error.isError() || !result.linkSuccess) { - return false; + return result; } - mUsesPointSize = vertexShaderD3D->usesPointSize(); - - bool success = true; - if (!linkAttributes(infoLog, attributeBindings, vertexShader)) { - success = false; + return LinkResult(false, Error(GL_NO_ERROR)); } - if (!linkUniforms(infoLog, *vertexShader, *fragmentShader, caps)) + if (!mProgram->linkUniforms(infoLog, *vertexShader, *fragmentShader, *data.caps)) { - success = false; + return LinkResult(false, Error(GL_NO_ERROR)); } - // special case for gl_DepthRange, the only built-in uniform (also a struct) - if (vertexShaderD3D->usesDepthRange() || fragmentShaderD3D->usesDepthRange()) + if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader, *data.caps)) { - const sh::BlockMemberInfo &defaultInfo = sh::BlockMemberInfo::getDefaultBlockInfo(); - - mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0, -1, defaultInfo)); - mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0, -1, defaultInfo)); - mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0, -1, defaultInfo)); - } - - if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader, caps)) - { - success = false; + return LinkResult(false, Error(GL_NO_ERROR)); } if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings, - transformFeedbackBufferMode, &mTransformFeedbackLinkedVaryings, caps)) + transformFeedbackBufferMode, &mProgram->getTransformFeedbackLinkedVaryings(), *data.caps)) { - success = false; + return LinkResult(false, Error(GL_NO_ERROR)); } - if (success) + // TODO: The concept of "executables" is D3D only, and as such this belongs in ProgramD3D. It must be called, + // however, last in this function, so it can't simply be moved to ProgramD3D::link without further shuffling. + result = mProgram->compileProgramExecutables(infoLog, fragmentShader, vertexShader, registers); + if (result.error.isError() || !result.linkSuccess) { - VertexFormat defaultInputLayout[MAX_VERTEX_ATTRIBS]; - GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout); - rx::ShaderExecutable *defaultVertexExecutable = getVertexExecutableForInputLayout(defaultInputLayout); + infoLog.append("Failed to create D3D shaders."); + reset(); + return result; + } - std::vector defaultPixelOutput = GetDefaultOutputLayoutFromShader(mProgram->getPixelShaderKey()); - rx::ShaderExecutable *defaultPixelExecutable = getPixelExecutableForOutputLayout(defaultPixelOutput); + return LinkResult(true, Error(GL_NO_ERROR)); +} - if (usesGeometryShader()) +bool ProgramBinary::linkUniformBlocks(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader, + const gl::Caps &caps) +{ + const std::vector &vertexInterfaceBlocks = vertexShader.getInterfaceBlocks(); + const std::vector &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks(); + + // Check that interface blocks defined in the vertex and fragment shaders are identical + typedef std::map UniformBlockMap; + UniformBlockMap linkedUniformBlocks; + + for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++) + { + const sh::InterfaceBlock &vertexInterfaceBlock = vertexInterfaceBlocks[blockIndex]; + linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock; + } + + for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++) + { + const sh::InterfaceBlock &fragmentInterfaceBlock = fragmentInterfaceBlocks[blockIndex]; + UniformBlockMap::const_iterator entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name); + if (entry != linkedUniformBlocks.end()) { - std::string geometryHLSL = mProgram->getDynamicHLSL()->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D); - mGeometryExecutable = mProgram->getRenderer()->compileToExecutable(infoLog, geometryHLSL.c_str(), - rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - rx::ANGLE_D3D_WORKAROUND_NONE); - } - - if (!defaultVertexExecutable || !defaultPixelExecutable || (usesGeometryShader() && !mGeometryExecutable)) - { - infoLog.append("Failed to create D3D shaders."); - success = false; - reset(); + const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second; + if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock)) + { + return false; + } } } - return success; + for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++) + { + const sh::InterfaceBlock &interfaceBlock = vertexInterfaceBlocks[blockIndex]; + + // Note: shared and std140 layouts are always considered active + if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) + { + if (!mProgram->defineUniformBlock(infoLog, vertexShader, interfaceBlock, caps)) + { + return false; + } + } + } + + for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++) + { + const sh::InterfaceBlock &interfaceBlock = fragmentInterfaceBlocks[blockIndex]; + + // Note: shared and std140 layouts are always considered active + if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) + { + if (!mProgram->defineUniformBlock(infoLog, fragmentShader, interfaceBlock, caps)) + { + return false; + } + } + } + + return true; +} + +bool ProgramBinary::areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, + const sh::InterfaceBlock &fragmentInterfaceBlock) +{ + const char* blockName = vertexInterfaceBlock.name.c_str(); + + // validate blocks for the same member types + if (vertexInterfaceBlock.fields.size() != fragmentInterfaceBlock.fields.size()) + { + infoLog.append("Types for interface block '%s' differ between vertex and fragment shaders", blockName); + return false; + } + + if (vertexInterfaceBlock.arraySize != fragmentInterfaceBlock.arraySize) + { + infoLog.append("Array sizes differ for interface block '%s' between vertex and fragment shaders", blockName); + return false; + } + + if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout) + { + infoLog.append("Layout qualifiers differ for interface block '%s' between vertex and fragment shaders", blockName); + return false; + } + + const unsigned int numBlockMembers = vertexInterfaceBlock.fields.size(); + for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++) + { + const sh::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex]; + const sh::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex]; + + if (vertexMember.name != fragmentMember.name) + { + infoLog.append("Name mismatch for field %d of interface block '%s': (in vertex: '%s', in fragment: '%s')", + blockMemberIndex, blockName, vertexMember.name.c_str(), fragmentMember.name.c_str()); + return false; + } + + std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'"; + if (!gl::ProgramBinary::linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember)) + { + return false; + } + } + + return true; } // Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices @@ -1688,7 +682,7 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location; - mShaderAttributes[attributeIndex] = attribute; + mProgram->getShaderAttributes()[attributeIndex] = attribute; if (location != -1) // Set by glBindAttribLocation or by location layout qualifier { @@ -1708,7 +702,7 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at // In GLSL 3.00, attribute aliasing produces a link error // In GLSL 1.00, attribute aliasing is allowed - if (mShaderVersion >= 300) + if (mProgram->getShaderVersion() >= 300) { if (!linkedAttribute.name.empty()) { @@ -1856,346 +850,6 @@ bool ProgramBinary::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std return true; } -bool ProgramBinary::linkUniforms(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps) -{ - const rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader.getImplementation()); - const rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader.getImplementation()); - - const std::vector &vertexUniforms = vertexShader.getUniforms(); - const std::vector &fragmentUniforms = fragmentShader.getUniforms(); - - // Check that uniforms defined in the vertex and fragment shaders are identical - typedef std::map UniformMap; - UniformMap linkedUniforms; - - for (unsigned int vertexUniformIndex = 0; vertexUniformIndex < vertexUniforms.size(); vertexUniformIndex++) - { - const sh::Uniform &vertexUniform = vertexUniforms[vertexUniformIndex]; - linkedUniforms[vertexUniform.name] = &vertexUniform; - } - - for (unsigned int fragmentUniformIndex = 0; fragmentUniformIndex < fragmentUniforms.size(); fragmentUniformIndex++) - { - const sh::Uniform &fragmentUniform = fragmentUniforms[fragmentUniformIndex]; - UniformMap::const_iterator entry = linkedUniforms.find(fragmentUniform.name); - if (entry != linkedUniforms.end()) - { - const sh::Uniform &vertexUniform = *entry->second; - const std::string &uniformName = "uniform '" + vertexUniform.name + "'"; - if (!linkValidateUniforms(infoLog, uniformName, vertexUniform, fragmentUniform)) - { - return false; - } - } - } - - for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++) - { - const sh::Uniform &uniform = vertexUniforms[uniformIndex]; - - if (uniform.staticUse) - { - defineUniformBase(GL_VERTEX_SHADER, uniform, vertexShaderD3D->getUniformRegister(uniform.name)); - } - } - - for (unsigned int uniformIndex = 0; uniformIndex < fragmentUniforms.size(); uniformIndex++) - { - const sh::Uniform &uniform = fragmentUniforms[uniformIndex]; - - if (uniform.staticUse) - { - defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShaderD3D->getUniformRegister(uniform.name)); - } - } - - if (!indexUniforms(infoLog, caps)) - { - return false; - } - - mProgram->initializeUniformStorage(mUniforms); - - return true; -} - -void ProgramBinary::defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister) -{ - ShShaderOutput outputType = rx::ShaderD3D::getCompilerOutputType(shader); - sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType)); - encoder.skipRegisters(uniformRegister); - - defineUniform(shader, uniform, uniform.name, &encoder); -} - -void ProgramBinary::defineUniform(GLenum shader, const sh::ShaderVariable &uniform, - const std::string &fullName, sh::HLSLBlockEncoder *encoder) -{ - if (uniform.isStruct()) - { - for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++) - { - const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : ""); - - encoder->enterAggregateType(); - - for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++) - { - const sh::ShaderVariable &field = uniform.fields[fieldIndex]; - const std::string &fieldFullName = (fullName + elementString + "." + field.name); - - defineUniform(shader, field, fieldFullName, encoder); - } - - encoder->exitAggregateType(); - } - } - else // Not a struct - { - // Arrays are treated as aggregate types - if (uniform.isArray()) - { - encoder->enterAggregateType(); - } - - LinkedUniform *linkedUniform = getUniformByName(fullName); - - if (!linkedUniform) - { - linkedUniform = new LinkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize, - -1, sh::BlockMemberInfo::getDefaultBlockInfo()); - ASSERT(linkedUniform); - linkedUniform->registerElement = encoder->getCurrentElement(); - mUniforms.push_back(linkedUniform); - } - - ASSERT(linkedUniform->registerElement == encoder->getCurrentElement()); - - if (shader == GL_FRAGMENT_SHADER) - { - linkedUniform->psRegisterIndex = encoder->getCurrentRegister(); - } - else if (shader == GL_VERTEX_SHADER) - { - linkedUniform->vsRegisterIndex = encoder->getCurrentRegister(); - } - else UNREACHABLE(); - - // Advance the uniform offset, to track registers allocation for structs - encoder->encodeType(uniform.type, uniform.arraySize, false); - - // Arrays are treated as aggregate types - if (uniform.isArray()) - { - encoder->exitAggregateType(); - } - } -} - -bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog, const Caps &caps) -{ - ASSERT(IsSampler(uniform.type)); - ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX); - - if (uniform.vsRegisterIndex != GL_INVALID_INDEX) - { - if (!assignSamplers(uniform.vsRegisterIndex, uniform.type, uniform.arraySize, mSamplersVS, - &mUsedVertexSamplerRange)) - { - infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).", - mSamplersVS.size()); - return false; - } - - unsigned int maxVertexVectors = mProgram->getRenderer()->getReservedVertexUniformVectors() + caps.maxVertexUniformVectors; - if (uniform.vsRegisterIndex + uniform.registerCount > maxVertexVectors) - { - infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", - caps.maxVertexUniformVectors); - return false; - } - } - - if (uniform.psRegisterIndex != GL_INVALID_INDEX) - { - if (!assignSamplers(uniform.psRegisterIndex, uniform.type, uniform.arraySize, mSamplersPS, - &mUsedPixelSamplerRange)) - { - infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", - mSamplersPS.size()); - return false; - } - - unsigned int maxFragmentVectors = mProgram->getRenderer()->getReservedFragmentUniformVectors() + caps.maxFragmentUniformVectors; - if (uniform.psRegisterIndex + uniform.registerCount > maxFragmentVectors) - { - infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", - caps.maxFragmentUniformVectors); - return false; - } - } - - return true; -} - -bool ProgramBinary::indexUniforms(InfoLog &infoLog, const Caps &caps) -{ - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) - { - const LinkedUniform &uniform = *mUniforms[uniformIndex]; - - if (IsSampler(uniform.type)) - { - if (!indexSamplerUniform(uniform, infoLog, caps)) - { - return false; - } - } - - for (unsigned int arrayElementIndex = 0; arrayElementIndex < uniform.elementCount(); arrayElementIndex++) - { - mUniformIndex.push_back(VariableLocation(uniform.name, arrayElementIndex, uniformIndex)); - } - } - - return true; -} - -bool ProgramBinary::assignSamplers(unsigned int startSamplerIndex, - GLenum samplerType, - unsigned int samplerCount, - std::vector &outSamplers, - GLuint *outUsedRange) -{ - unsigned int samplerIndex = startSamplerIndex; - - do - { - if (samplerIndex < outSamplers.size()) - { - Sampler& sampler = outSamplers[samplerIndex]; - sampler.active = true; - sampler.textureType = GetTextureType(samplerType); - sampler.logicalTextureUnit = 0; - *outUsedRange = std::max(samplerIndex + 1, *outUsedRange); - } - else - { - return false; - } - - samplerIndex++; - } while (samplerIndex < startSamplerIndex + samplerCount); - - return true; -} - -bool ProgramBinary::areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock) -{ - const char* blockName = vertexInterfaceBlock.name.c_str(); - - // validate blocks for the same member types - if (vertexInterfaceBlock.fields.size() != fragmentInterfaceBlock.fields.size()) - { - infoLog.append("Types for interface block '%s' differ between vertex and fragment shaders", blockName); - return false; - } - - if (vertexInterfaceBlock.arraySize != fragmentInterfaceBlock.arraySize) - { - infoLog.append("Array sizes differ for interface block '%s' between vertex and fragment shaders", blockName); - return false; - } - - if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout) - { - infoLog.append("Layout qualifiers differ for interface block '%s' between vertex and fragment shaders", blockName); - return false; - } - - const unsigned int numBlockMembers = vertexInterfaceBlock.fields.size(); - for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++) - { - const sh::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex]; - const sh::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex]; - - if (vertexMember.name != fragmentMember.name) - { - infoLog.append("Name mismatch for field %d of interface block '%s': (in vertex: '%s', in fragment: '%s')", - blockMemberIndex, blockName, vertexMember.name.c_str(), fragmentMember.name.c_str()); - return false; - } - - std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'"; - if (!linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember)) - { - return false; - } - } - - return true; -} - -bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps) -{ - const std::vector &vertexInterfaceBlocks = vertexShader.getInterfaceBlocks(); - const std::vector &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks(); - - // Check that interface blocks defined in the vertex and fragment shaders are identical - typedef std::map UniformBlockMap; - UniformBlockMap linkedUniformBlocks; - - for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++) - { - const sh::InterfaceBlock &vertexInterfaceBlock = vertexInterfaceBlocks[blockIndex]; - linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock; - } - - for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++) - { - const sh::InterfaceBlock &fragmentInterfaceBlock = fragmentInterfaceBlocks[blockIndex]; - UniformBlockMap::const_iterator entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name); - if (entry != linkedUniformBlocks.end()) - { - const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second; - if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock)) - { - return false; - } - } - } - - for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++) - { - const sh::InterfaceBlock &interfaceBlock = vertexInterfaceBlocks[blockIndex]; - - // Note: shared and std140 layouts are always considered active - if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) - { - if (!defineUniformBlock(infoLog, vertexShader, interfaceBlock, caps)) - { - return false; - } - } - } - - for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++) - { - const sh::InterfaceBlock &interfaceBlock = fragmentInterfaceBlocks[blockIndex]; - - // Note: shared and std140 layouts are always considered active - if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) - { - if (!defineUniformBlock(infoLog, fragmentShader, interfaceBlock, caps)) - { - return false; - } - } - } - - return true; -} - bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector &linkedVaryings, const std::vector &transformFeedbackVaryingNames, GLenum transformFeedbackBufferMode, @@ -2253,142 +907,6 @@ bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, cons return true; } -template -void ProgramBinary::defineUniformBlockMembers(const std::vector &fields, const std::string &prefix, int blockIndex, - sh::BlockLayoutEncoder *encoder, std::vector *blockUniformIndexes, - bool inRowMajorLayout) -{ - for (unsigned int uniformIndex = 0; uniformIndex < fields.size(); uniformIndex++) - { - const VarT &field = fields[uniformIndex]; - const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name); - - if (field.isStruct()) - { - bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field)); - - for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++) - { - encoder->enterAggregateType(); - - const std::string uniformElementName = fieldName + (field.isArray() ? ArrayString(arrayElement) : ""); - defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, encoder, blockUniformIndexes, rowMajorLayout); - - encoder->exitAggregateType(); - } - } - else - { - bool isRowMajorMatrix = (IsMatrixType(field.type) && inRowMajorLayout); - - sh::BlockMemberInfo memberInfo = encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix); - - LinkedUniform *newUniform = new LinkedUniform(field.type, field.precision, fieldName, field.arraySize, - blockIndex, memberInfo); - - // add to uniform list, but not index, since uniform block uniforms have no location - blockUniformIndexes->push_back(mUniforms.size()); - mUniforms.push_back(newUniform); - } - } -} - -bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock, const Caps &caps) -{ - const rx::ShaderD3D* shaderD3D = rx::ShaderD3D::makeShaderD3D(shader.getImplementation()); - - // create uniform block entries if they do not exist - if (getUniformBlockIndex(interfaceBlock.name) == GL_INVALID_INDEX) - { - std::vector blockUniformIndexes; - const unsigned int blockIndex = mUniformBlocks.size(); - - // define member uniforms - sh::BlockLayoutEncoder *encoder = NULL; - - if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD) - { - encoder = new sh::Std140BlockEncoder; - } - else - { - encoder = new sh::HLSLBlockEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED); - } - ASSERT(encoder); - - defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, encoder, &blockUniformIndexes, interfaceBlock.isRowMajorLayout); - - size_t dataSize = encoder->getBlockSize(); - - // create all the uniform blocks - if (interfaceBlock.arraySize > 0) - { - for (unsigned int uniformBlockElement = 0; uniformBlockElement < interfaceBlock.arraySize; uniformBlockElement++) - { - UniformBlock *newUniformBlock = new UniformBlock(interfaceBlock.name, uniformBlockElement, dataSize); - newUniformBlock->memberUniformIndexes = blockUniformIndexes; - mUniformBlocks.push_back(newUniformBlock); - } - } - else - { - UniformBlock *newUniformBlock = new UniformBlock(interfaceBlock.name, GL_INVALID_INDEX, dataSize); - newUniformBlock->memberUniformIndexes = blockUniformIndexes; - mUniformBlocks.push_back(newUniformBlock); - } - } - - if (interfaceBlock.staticUse) - { - // Assign registers to the uniform blocks - const GLuint blockIndex = getUniformBlockIndex(interfaceBlock.name); - const unsigned int elementCount = std::max(1u, interfaceBlock.arraySize); - ASSERT(blockIndex != GL_INVALID_INDEX); - ASSERT(blockIndex + elementCount <= mUniformBlocks.size()); - - unsigned int interfaceBlockRegister = shaderD3D->getInterfaceBlockRegister(interfaceBlock.name); - - for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++) - { - UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement]; - ASSERT(uniformBlock->name == interfaceBlock.name); - - if (!assignUniformBlockRegister(infoLog, uniformBlock, shader.getType(), - interfaceBlockRegister + uniformBlockElement, caps)) - { - return false; - } - } - } - - return true; -} - -bool ProgramBinary::assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps) -{ - if (shader == GL_VERTEX_SHADER) - { - uniformBlock->vsRegisterIndex = registerIndex; - if (registerIndex - mProgram->getRenderer()->getReservedVertexUniformBuffers() >= caps.maxVertexUniformBlocks) - { - infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", caps.maxVertexUniformBlocks); - return false; - } - } - else if (shader == GL_FRAGMENT_SHADER) - { - uniformBlock->psRegisterIndex = registerIndex; - if (registerIndex - mProgram->getRenderer()->getReservedFragmentUniformBuffers() >= caps.maxFragmentUniformBlocks) - { - infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", caps.maxFragmentUniformBlocks); - return false; - } - } - else UNREACHABLE(); - - return true; -} - bool ProgramBinary::isValidated() const { return mValidated; @@ -2464,13 +982,13 @@ GLint ProgramBinary::getActiveAttributeMaxLength() const void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const { - ASSERT(index < mUniforms.size()); // index must be smaller than getActiveUniformCount() + ASSERT(index < mProgram->getUniforms().size()); // index must be smaller than getActiveUniformCount() if (bufsize > 0) { - std::string string = mUniforms[index]->name; + std::string string = mProgram->getUniforms()[index]->name; - if (mUniforms[index]->isArray()) + if (mProgram->getUniforms()[index]->isArray()) { string += "[0]"; } @@ -2484,27 +1002,27 @@ void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *len } } - *size = mUniforms[index]->elementCount(); + *size = mProgram->getUniforms()[index]->elementCount(); - *type = mUniforms[index]->type; + *type = mProgram->getUniforms()[index]->type; } GLint ProgramBinary::getActiveUniformCount() const { - return mUniforms.size(); + return mProgram->getUniforms().size(); } GLint ProgramBinary::getActiveUniformMaxLength() const { int maxLength = 0; - unsigned int numUniforms = mUniforms.size(); + unsigned int numUniforms = mProgram->getUniforms().size(); for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++) { - if (!mUniforms[uniformIndex]->name.empty()) + if (!mProgram->getUniforms()[uniformIndex]->name.empty()) { - int length = (int)(mUniforms[uniformIndex]->name.length() + 1); - if (mUniforms[uniformIndex]->isArray()) + int length = (int)(mProgram->getUniforms()[uniformIndex]->name.length() + 1); + if (mProgram->getUniforms()[uniformIndex]->isArray()) { length += 3; // Counting in "[0]". } @@ -2517,7 +1035,7 @@ GLint ProgramBinary::getActiveUniformMaxLength() const GLint ProgramBinary::getActiveUniformi(GLuint index, GLenum pname) const { - const gl::LinkedUniform& uniform = *mUniforms[index]; + const gl::LinkedUniform& uniform = *mProgram->getUniforms()[index]; switch (pname) { @@ -2540,34 +1058,25 @@ GLint ProgramBinary::getActiveUniformi(GLuint index, GLenum pname) const bool ProgramBinary::isValidUniformLocation(GLint location) const { - ASSERT(rx::IsIntegerCastSafe(mUniformIndex.size())); - return (location >= 0 && location < static_cast(mUniformIndex.size())); + ASSERT(rx::IsIntegerCastSafe(mProgram->getUniformIndices().size())); + return (location >= 0 && location < static_cast(mProgram->getUniformIndices().size())); } LinkedUniform *ProgramBinary::getUniformByLocation(GLint location) const { - ASSERT(location >= 0 && static_cast(location) < mUniformIndex.size()); - return mUniforms[mUniformIndex[location].index]; + return mProgram->getUniformByLocation(location); } LinkedUniform *ProgramBinary::getUniformByName(const std::string &name) const { - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) - { - if (mUniforms[uniformIndex]->name == name) - { - return mUniforms[uniformIndex]; - } - } - - return NULL; + return mProgram->getUniformByName(name); } void ProgramBinary::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const { - ASSERT(uniformBlockIndex < mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount() + ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size()); // index must be smaller than getActiveUniformBlockCount() - const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex]; + const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex]; if (bufSize > 0) { @@ -2590,9 +1099,9 @@ void ProgramBinary::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei void ProgramBinary::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const { - ASSERT(uniformBlockIndex < mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount() + ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size()); // index must be smaller than getActiveUniformBlockCount() - const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex]; + const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex]; switch (pname) { @@ -2625,17 +1134,17 @@ void ProgramBinary::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pna GLuint ProgramBinary::getActiveUniformBlockCount() const { - return mUniformBlocks.size(); + return mProgram->getUniformBlocks().size(); } GLuint ProgramBinary::getActiveUniformBlockMaxLength() const { unsigned int maxLength = 0; - unsigned int numUniformBlocks = mUniformBlocks.size(); + unsigned int numUniformBlocks = mProgram->getUniformBlocks().size(); for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++) { - const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex]; + const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex]; if (!uniformBlock.name.empty()) { const unsigned int length = uniformBlock.name.length() + 1; @@ -2665,88 +1174,7 @@ void ProgramBinary::validate(InfoLog &infoLog, const Caps &caps) bool ProgramBinary::validateSamplers(InfoLog *infoLog, const Caps &caps) { - // if any two active samplers in a program are of different types, but refer to the same - // texture image unit, and this is the current program, then ValidateProgram will fail, and - // DrawArrays and DrawElements will issue the INVALID_OPERATION error. - updateSamplerMapping(); - - std::vector textureUnitTypes(caps.maxCombinedTextureImageUnits, GL_NONE); - - for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i) - { - if (mSamplersPS[i].active) - { - unsigned int unit = mSamplersPS[i].logicalTextureUnit; - - if (unit >= textureUnitTypes.size()) - { - if (infoLog) - { - infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size()); - } - - return false; - } - - if (textureUnitTypes[unit] != GL_NONE) - { - if (mSamplersPS[i].textureType != textureUnitTypes[unit]) - { - if (infoLog) - { - infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit); - } - - return false; - } - } - else - { - textureUnitTypes[unit] = mSamplersPS[i].textureType; - } - } - } - - for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i) - { - if (mSamplersVS[i].active) - { - unsigned int unit = mSamplersVS[i].logicalTextureUnit; - - if (unit >= textureUnitTypes.size()) - { - if (infoLog) - { - infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size()); - } - - return false; - } - - if (textureUnitTypes[unit] != GL_NONE) - { - if (mSamplersVS[i].textureType != textureUnitTypes[unit]) - { - if (infoLog) - { - infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit); - } - - return false; - } - } - else - { - textureUnitTypes[unit] = mSamplersVS[i].textureType; - } - } - } - - return true; -} - -ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D) -{ + return mProgram->validateSamplers(infoLog, caps); } struct AttributeSorter @@ -2795,26 +1223,6 @@ void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MA void ProgramBinary::reset() { - SafeDeleteContainer(mVertexExecutables); - SafeDeleteContainer(mPixelExecutables); - - SafeDelete(mGeometryExecutable); - - mTransformFeedbackBufferMode = GL_NONE; - mTransformFeedbackLinkedVaryings.clear(); - - mSamplersPS.clear(); - mSamplersVS.clear(); - - mUsedVertexSamplerRange = 0; - mUsedPixelSamplerRange = 0; - mUsesPointSize = false; - mShaderVersion = 0; - mDirtySamplerMapping = true; - - SafeDeleteContainer(mUniforms); - SafeDeleteContainer(mUniformBlocks); - mUniformIndex.clear(); mOutputVariables.clear(); mProgram->reset(); diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h index ad470d417b6..3142d66c6df 100644 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h +++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h @@ -24,11 +24,6 @@ #include #include -// TODO(jmadill): place this in workarounds library -#define ANGLE_WORKAROUND_ENABLED 1 -#define ANGLE_WORKAROUND_DISABLED 2 -#define ANGLE_MRT_PERF_WORKAROUND ANGLE_WORKAROUND_ENABLED - namespace sh { class HLSLBlockEncoder; @@ -44,7 +39,6 @@ class HLSLBlockEncoder; namespace rx { class ShaderExecutable; -class Renderer; struct TranslatedAttribute; class UniformStorage; class ProgramImpl; @@ -58,6 +52,7 @@ class InfoLog; class AttributeBindings; class Buffer; class Framebuffer; +struct Data; // Struct used for correlating uniforms/elements of uniform arrays to handles struct VariableLocation @@ -91,6 +86,14 @@ struct LinkedVarying unsigned int semanticIndexCount; }; +struct LinkResult +{ + bool linkSuccess; + Error error; + + LinkResult(bool linkSuccess, const Error &error); +}; + // This is the result of linking a program. It is the state that would be passed to ProgramBinary. class ProgramBinary : public RefCountObject { @@ -101,11 +104,6 @@ class ProgramBinary : public RefCountObject rx::ProgramImpl *getImplementation() { return mProgram; } const rx::ProgramImpl *getImplementation() const { return mProgram; } - rx::ShaderExecutable *getPixelExecutableForFramebuffer(const Framebuffer *fbo); - rx::ShaderExecutable *getPixelExecutableForOutputLayout(const std::vector &outputLayout); - rx::ShaderExecutable *getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]); - rx::ShaderExecutable *getGeometryExecutable() const; - GLuint getAttributeLocation(const char *name); int getSemanticIndex(int attributeIndex); @@ -113,8 +111,6 @@ class ProgramBinary : public RefCountObject GLenum getSamplerTextureType(SamplerType type, unsigned int samplerIndex); GLint getUsedSamplerRange(SamplerType type); bool usesPointSize() const; - bool usesPointSpriteEmulation() const; - bool usesGeometryShader() const; GLint getUniformLocation(std::string name); GLuint getUniformIndex(std::string name); @@ -145,18 +141,17 @@ class ProgramBinary : public RefCountObject void getUniformiv(GLint location, GLint *params); void getUniformuiv(GLint location, GLuint *params); - void dirtyAllUniforms(); - Error applyUniforms(); Error applyUniformBuffers(const std::vector boundBuffers, const Caps &caps); - bool load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length); - bool save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length); + LinkResult load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length); + Error save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length); GLint getLength(); - bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader, - const std::vector& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps); - void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders); + LinkResult link(const Data &data, InfoLog &infoLog, const AttributeBindings &attributeBindings, + Shader *fragmentShader, Shader *vertexShader, + const std::vector &transformFeedbackVaryings, + GLenum transformFeedbackBufferMode); void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const; GLint getActiveAttributeCount() const; @@ -188,30 +183,23 @@ class ProgramBinary : public RefCountObject void updateSamplerMapping(); unsigned int getSerial() const; - int getShaderVersion() const; void initAttributesByLayout(); void sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const; - const std::vector &getUniforms() const { return mUniforms; } - static bool linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader); + static bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform); + static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform); private: DISALLOW_COPY_AND_ASSIGN(ProgramBinary); - struct Sampler - { - Sampler(); - - bool active; - GLint logicalTextureUnit; - GLenum textureType; - }; - void reset(); bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader); + bool linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps); + bool areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, + const sh::InterfaceBlock &fragmentInterfaceBlock); static bool linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, @@ -219,102 +207,21 @@ class ProgramBinary : public RefCountObject const sh::ShaderVariable &fragmentVariable, bool validatePrecision); - static bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform); static bool linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying); - static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform); - bool linkUniforms(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps); - void defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister); - void defineUniform(GLenum shader, const sh::ShaderVariable &uniform, const std::string &fullName, sh::HLSLBlockEncoder *encoder); - bool indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog, const Caps &caps); - bool indexUniforms(InfoLog &infoLog, const Caps &caps); - static bool assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount, - std::vector &outSamplers, GLuint *outUsedRange); - bool areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock); - bool linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps); bool gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector &linkedVaryings, const std::vector &transformFeedbackVaryingNames, GLenum transformFeedbackBufferMode, std::vector *outTransformFeedbackLinkedVaryings, const Caps &caps) const; - template - void defineUniformBlockMembers(const std::vector &fields, const std::string &prefix, int blockIndex, - sh::BlockLayoutEncoder *encoder, std::vector *blockUniformIndexes, - bool inRowMajorLayout); - bool defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock, const Caps &caps); bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps); void defineOutputVariables(Shader *fragmentShader); - template - void setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType); - - template - void setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType); - - template - void getUniformv(GLint location, T *params, GLenum uniformType); - - class VertexExecutable - { - public: - VertexExecutable(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS], - const GLenum signature[MAX_VERTEX_ATTRIBS], - rx::ShaderExecutable *shaderExecutable); - ~VertexExecutable(); - - bool matchesSignature(const GLenum convertedLayout[MAX_VERTEX_ATTRIBS]) const; - - const VertexFormat *inputs() const { return mInputs; } - const GLenum *signature() const { return mSignature; } - rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; } - - private: - VertexFormat mInputs[MAX_VERTEX_ATTRIBS]; - GLenum mSignature[MAX_VERTEX_ATTRIBS]; - rx::ShaderExecutable *mShaderExecutable; - }; - - class PixelExecutable - { - public: - PixelExecutable(const std::vector &outputSignature, rx::ShaderExecutable *shaderExecutable); - ~PixelExecutable(); - - bool matchesSignature(const std::vector &signature) const { return mOutputSignature == signature; } - - const std::vector &outputSignature() const { return mOutputSignature; } - rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; } - - private: - std::vector mOutputSignature; - rx::ShaderExecutable *mShaderExecutable; - }; - rx::ProgramImpl *mProgram; - std::vector mVertexExecutables; - std::vector mPixelExecutables; - - rx::ShaderExecutable *mGeometryExecutable; - sh::Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS]; - sh::Attribute mShaderAttributes[MAX_VERTEX_ATTRIBS]; int mSemanticIndex[MAX_VERTEX_ATTRIBS]; int mAttributesByLayout[MAX_VERTEX_ATTRIBS]; - GLenum mTransformFeedbackBufferMode; - std::vector mTransformFeedbackLinkedVaryings; - - std::vector mSamplersPS; - std::vector mSamplersVS; - GLuint mUsedVertexSamplerRange; - GLuint mUsedPixelSamplerRange; - bool mUsesPointSize; - int mShaderVersion; - bool mDirtySamplerMapping; - - std::vector mUniforms; - std::vector mUniformBlocks; - std::vector mUniformIndex; std::map mOutputVariables; bool mValidated; diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp index 9406fce58df..911a389dfa9 100644 --- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp @@ -4,77 +4,86 @@ // found in the LICENSE file. // -// Renderbuffer.cpp: the gl::Renderbuffer class and its derived classes -// Colorbuffer, Depthbuffer and Stencilbuffer. Implements GL renderbuffer -// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. +// Renderbuffer.cpp: Implements the renderer-agnostic gl::Renderbuffer class, +// GL renderbuffer objects and related functionality. +// [OpenGL ES 2.0.24] section 4.4.3 page 108. #include "libGLESv2/Renderbuffer.h" #include "libGLESv2/Texture.h" #include "libGLESv2/formatutils.h" #include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/d3d/RendererD3D.h" #include "libGLESv2/renderer/RenderTarget.h" +#include "libGLESv2/renderer/RenderbufferImpl.h" #include "common/utilities.h" namespace gl { -unsigned int RenderbufferStorage::mCurrentSerial = 1; - -Renderbuffer::Renderbuffer(GLuint id, RenderbufferStorage *newStorage) +Renderbuffer::Renderbuffer(rx::RenderbufferImpl *impl, GLuint id) : RefCountObject(id), - mStorage(newStorage) + mRenderbuffer(impl) { - ASSERT(mStorage); + ASSERT(mRenderbuffer); + + mWidth = mRenderbuffer->getWidth(); + mHeight = mRenderbuffer->getHeight(); + mInternalFormat = mRenderbuffer->getInternalFormat(); + mActualFormat = mRenderbuffer->getActualFormat(); + mSamples = mRenderbuffer->getSamples(); } Renderbuffer::~Renderbuffer() { - SafeDelete(mStorage); + SafeDelete(mRenderbuffer); } -void Renderbuffer::setStorage(RenderbufferStorage *newStorage) +Error Renderbuffer::setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) { - ASSERT(newStorage); + Error error = mRenderbuffer->setStorage(width, height, internalformat, samples); + if (error.isError()) + { + return error; + } - SafeDelete(mStorage); - mStorage = newStorage; + mWidth = width; + mHeight = height; + mInternalFormat = internalformat; + mSamples = samples; + mActualFormat = mRenderbuffer->getActualFormat(); + + return Error(GL_NO_ERROR); } -RenderbufferStorage *Renderbuffer::getStorage() +rx::RenderbufferImpl *Renderbuffer::getImplementation() { - ASSERT(mStorage); - return mStorage; + ASSERT(mRenderbuffer); + return mRenderbuffer; } GLsizei Renderbuffer::getWidth() const { - ASSERT(mStorage); - return mStorage->getWidth(); + return mWidth; } GLsizei Renderbuffer::getHeight() const { - ASSERT(mStorage); - return mStorage->getHeight(); + return mHeight; } GLenum Renderbuffer::getInternalFormat() const { - ASSERT(mStorage); - return mStorage->getInternalFormat(); + return mInternalFormat; } GLenum Renderbuffer::getActualFormat() const { - ASSERT(mStorage); - return mStorage->getActualFormat(); + return mActualFormat; } GLsizei Renderbuffer::getSamples() const { - ASSERT(mStorage); - return mStorage->getSamples(); + return mSamples; } GLuint Renderbuffer::getRedSize() const @@ -107,176 +116,4 @@ GLuint Renderbuffer::getStencilSize() const return GetInternalFormatInfo(getActualFormat()).stencilBits; } -RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerials(1)) -{ - mWidth = 0; - mHeight = 0; - mInternalFormat = GL_RGBA4; - mActualFormat = GL_RGBA8_OES; - mSamples = 0; -} - -RenderbufferStorage::~RenderbufferStorage() -{ -} - -rx::RenderTarget *RenderbufferStorage::getRenderTarget() -{ - return NULL; -} - -GLsizei RenderbufferStorage::getWidth() const -{ - return mWidth; -} - -GLsizei RenderbufferStorage::getHeight() const -{ - return mHeight; -} - -GLenum RenderbufferStorage::getInternalFormat() const -{ - return mInternalFormat; -} - -GLenum RenderbufferStorage::getActualFormat() const -{ - return mActualFormat; -} - -GLsizei RenderbufferStorage::getSamples() const -{ - return mSamples; -} - -unsigned int RenderbufferStorage::getSerial() const -{ - return mSerial; -} - -unsigned int RenderbufferStorage::issueSerials(unsigned int count) -{ - unsigned int firstSerial = mCurrentSerial; - mCurrentSerial += count; - return firstSerial; -} - -bool RenderbufferStorage::isTexture() const -{ - return false; -} - -unsigned int RenderbufferStorage::getTextureSerial() const -{ - return -1; -} - -Colorbuffer::Colorbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain) -{ - mRenderTarget = renderer->createRenderTarget(swapChain, false); - - if (mRenderTarget) - { - mWidth = mRenderTarget->getWidth(); - mHeight = mRenderTarget->getHeight(); - mInternalFormat = mRenderTarget->getInternalFormat(); - mActualFormat = mRenderTarget->getActualFormat(); - mSamples = mRenderTarget->getSamples(); - } -} - -Colorbuffer::Colorbuffer(rx::Renderer *renderer, int width, int height, GLenum format, GLsizei samples) : mRenderTarget(NULL) -{ - mRenderTarget = renderer->createRenderTarget(width, height, format, samples); - - if (mRenderTarget) - { - mWidth = width; - mHeight = height; - mInternalFormat = format; - mActualFormat = mRenderTarget->getActualFormat(); - mSamples = mRenderTarget->getSamples(); - } -} - -Colorbuffer::~Colorbuffer() -{ - if (mRenderTarget) - { - delete mRenderTarget; - } -} - -rx::RenderTarget *Colorbuffer::getRenderTarget() -{ - return mRenderTarget; -} - -DepthStencilbuffer::DepthStencilbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain) -{ - mDepthStencil = renderer->createRenderTarget(swapChain, true); - if (mDepthStencil) - { - mWidth = mDepthStencil->getWidth(); - mHeight = mDepthStencil->getHeight(); - mInternalFormat = mDepthStencil->getInternalFormat(); - mSamples = mDepthStencil->getSamples(); - mActualFormat = mDepthStencil->getActualFormat(); - } -} - -DepthStencilbuffer::DepthStencilbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples) -{ - - mDepthStencil = renderer->createRenderTarget(width, height, GL_DEPTH24_STENCIL8_OES, samples); - - mWidth = mDepthStencil->getWidth(); - mHeight = mDepthStencil->getHeight(); - mInternalFormat = GL_DEPTH24_STENCIL8_OES; - mActualFormat = mDepthStencil->getActualFormat(); - mSamples = mDepthStencil->getSamples(); -} - -DepthStencilbuffer::~DepthStencilbuffer() -{ - if (mDepthStencil) - { - delete mDepthStencil; - } -} - -rx::RenderTarget *DepthStencilbuffer::getRenderTarget() -{ - return mDepthStencil; -} - -Depthbuffer::Depthbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples) : DepthStencilbuffer(renderer, width, height, samples) -{ - if (mDepthStencil) - { - mInternalFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function - // will expect one of the valid renderbuffer formats for use in - // glRenderbufferStorage - } -} - -Depthbuffer::~Depthbuffer() -{ -} - -Stencilbuffer::Stencilbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples) : DepthStencilbuffer(renderer, width, height, samples) -{ - if (mDepthStencil) - { - mInternalFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function - // will expect one of the valid renderbuffer formats for use in - // glRenderbufferStorage - } -} - -Stencilbuffer::~Stencilbuffer() -{ -} - } diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h index 71bcb0e1f84..e9f12af3ce1 100644 --- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h @@ -4,30 +4,27 @@ // found in the LICENSE file. // -// Renderbuffer.h: Defines the wrapper class gl::Renderbuffer, as well as the -// class hierarchy used to store its contents: RenderbufferStorage, Colorbuffer, -// DepthStencilbuffer, Depthbuffer and Stencilbuffer. Implements GL renderbuffer -// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. +// Renderbuffer.h: Defines the renderer-agnostic container class gl::Renderbuffer. +// Implements GL renderbuffer objects and related functionality. +// [OpenGL ES 2.0.24] section 4.4.3 page 108. #ifndef LIBGLESV2_RENDERBUFFER_H_ #define LIBGLESV2_RENDERBUFFER_H_ #include "angle_gl.h" +#include "libGLESv2/Error.h" + #include "common/angleutils.h" #include "common/RefCountObject.h" namespace rx { -class Renderer; -class SwapChain; -class RenderTarget; -class TextureStorage; +class RenderbufferImpl; } namespace gl { -class RenderbufferStorage; class FramebufferAttachment; // A GL renderbuffer object is usually used as a depth or stencil buffer attachment @@ -38,11 +35,12 @@ class FramebufferAttachment; class Renderbuffer : public RefCountObject { public: - Renderbuffer(GLuint id, RenderbufferStorage *newStorage); + Renderbuffer(rx::RenderbufferImpl *impl, GLuint id); virtual ~Renderbuffer(); - void setStorage(RenderbufferStorage *newStorage); - RenderbufferStorage *getStorage(); + Error setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples); + + rx::RenderbufferImpl *getImplementation(); GLsizei getWidth() const; GLsizei getHeight() const; @@ -57,102 +55,15 @@ class Renderbuffer : public RefCountObject GLuint getStencilSize() const; private: - RenderbufferStorage *mStorage; -}; + DISALLOW_COPY_AND_ASSIGN(Renderbuffer); -// A class derived from RenderbufferStorage is created whenever glRenderbufferStorage -// is called. The specific concrete type depends on whether the internal format is -// colour depth, stencil or packed depth/stencil. -class RenderbufferStorage -{ - public: - RenderbufferStorage(); + rx::RenderbufferImpl *mRenderbuffer; - virtual ~RenderbufferStorage() = 0; - - virtual rx::RenderTarget *getRenderTarget(); - - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLenum getInternalFormat() const; - virtual GLenum getActualFormat() const; - virtual GLsizei getSamples() const; - - virtual unsigned int getSerial() const; - - virtual bool isTexture() const; - virtual unsigned int getTextureSerial() const; - - static unsigned int issueSerials(unsigned int count); - - protected: GLsizei mWidth; GLsizei mHeight; GLenum mInternalFormat; GLenum mActualFormat; GLsizei mSamples; - - private: - DISALLOW_COPY_AND_ASSIGN(RenderbufferStorage); - - const unsigned int mSerial; - - static unsigned int mCurrentSerial; -}; - -class Colorbuffer : public RenderbufferStorage -{ - public: - Colorbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain); - Colorbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples); - - virtual ~Colorbuffer(); - - virtual rx::RenderTarget *getRenderTarget(); - - private: - DISALLOW_COPY_AND_ASSIGN(Colorbuffer); - - rx::RenderTarget *mRenderTarget; -}; - -class DepthStencilbuffer : public RenderbufferStorage -{ - public: - DepthStencilbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain); - DepthStencilbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLsizei samples); - - ~DepthStencilbuffer(); - - virtual rx::RenderTarget *getRenderTarget(); - - protected: - rx::RenderTarget *mDepthStencil; - - private: - DISALLOW_COPY_AND_ASSIGN(DepthStencilbuffer); -}; - -class Depthbuffer : public DepthStencilbuffer -{ - public: - Depthbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLsizei samples); - - virtual ~Depthbuffer(); - - private: - DISALLOW_COPY_AND_ASSIGN(Depthbuffer); -}; - -class Stencilbuffer : public DepthStencilbuffer -{ - public: - Stencilbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLsizei samples); - - virtual ~Stencilbuffer(); - - private: - DISALLOW_COPY_AND_ASSIGN(Stencilbuffer); }; } diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp b/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp index 9121de1750f..38d53cad81e 100644 --- a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp +++ b/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp @@ -21,9 +21,9 @@ namespace gl { ResourceManager::ResourceManager(rx::Renderer *renderer) + : mRenderer(renderer), + mRefCount(1) { - mRefCount = 1; - mRenderer = renderer; } ResourceManager::~ResourceManager() @@ -88,13 +88,13 @@ GLuint ResourceManager::createBuffer() } // Returns an unused shader/program name -GLuint ResourceManager::createShader(GLenum type) +GLuint ResourceManager::createShader(const gl::Data &data, GLenum type) { GLuint handle = mProgramShaderHandleAllocator.allocate(); if (type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER) { - mShaderMap[handle] = new Shader(this, mRenderer->createShader(type), type, handle); + mShaderMap[handle] = new Shader(this, mRenderer->createShader(data, type), type, handle); } else UNREACHABLE(); @@ -146,7 +146,7 @@ GLuint ResourceManager::createFenceSync() { GLuint handle = mFenceSyncHandleAllocator.allocate(); - FenceSync *fenceSync = new FenceSync(mRenderer, handle); + FenceSync *fenceSync = new FenceSync(mRenderer->createFenceSync(), handle); fenceSync->addRef(); mFenceSyncMap[handle] = fenceSync; @@ -295,9 +295,9 @@ Texture *ResourceManager::getTexture(unsigned int handle) } } -Program *ResourceManager::getProgram(unsigned int handle) +Program *ResourceManager::getProgram(unsigned int handle) const { - ProgramMap::iterator program = mProgramMap.find(handle); + ProgramMap::const_iterator program = mProgramMap.find(handle); if (program == mProgramMap.end()) { @@ -403,7 +403,7 @@ void ResourceManager::checkRenderbufferAllocation(GLuint renderbuffer) { if (renderbuffer != 0 && !getRenderbuffer(renderbuffer)) { - Renderbuffer *renderbufferObject = new Renderbuffer(renderbuffer, new Colorbuffer(mRenderer, 0, 0, GL_RGBA4, 0)); + Renderbuffer *renderbufferObject = new Renderbuffer(mRenderer->createRenderbuffer(), renderbuffer); mRenderbufferMap[renderbuffer] = renderbufferObject; renderbufferObject->addRef(); } diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h b/src/3rdparty/angle/src/libGLESv2/ResourceManager.h index 7d53bd48549..acad29b51d5 100644 --- a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h +++ b/src/3rdparty/angle/src/libGLESv2/ResourceManager.h @@ -32,6 +32,7 @@ class Texture; class Renderbuffer; class Sampler; class FenceSync; +struct Data; class ResourceManager { @@ -43,7 +44,7 @@ class ResourceManager void release(); GLuint createBuffer(); - GLuint createShader(GLenum type); + GLuint createShader(const gl::Data &data, GLenum type); GLuint createProgram(); GLuint createTexture(); GLuint createRenderbuffer(); @@ -60,7 +61,7 @@ class ResourceManager Buffer *getBuffer(GLuint handle); Shader *getShader(GLuint handle); - Program *getProgram(GLuint handle); + Program *getProgram(GLuint handle) const; Texture *getTexture(GLuint handle); Renderbuffer *getRenderbuffer(GLuint handle); Sampler *getSampler(GLuint handle); @@ -78,8 +79,8 @@ class ResourceManager private: DISALLOW_COPY_AND_ASSIGN(ResourceManager); - std::size_t mRefCount; rx::Renderer *mRenderer; + std::size_t mRefCount; typedef std::unordered_map BufferMap; BufferMap mBufferMap; diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.cpp b/src/3rdparty/angle/src/libGLESv2/Shader.cpp index e3da2b1a9e7..1cc17a05013 100644 --- a/src/3rdparty/angle/src/libGLESv2/Shader.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Shader.cpp @@ -37,6 +37,7 @@ Shader::Shader(ResourceManager *manager, rx::ShaderImpl *impl, GLenum type, GLui Shader::~Shader() { + SafeDelete(mShader); } GLuint Shader::getHandle() const @@ -117,9 +118,15 @@ void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) getSourceImpl(mShader->getTranslatedSource(), bufSize, length, buffer); } -void Shader::compile() +void Shader::getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const { - mCompiled = mShader->compile(mSource); + std::string debugInfo(mShader->getDebugInfo()); + getSourceImpl(debugInfo, bufSize, length, buffer); +} + +void Shader::compile(const gl::Data &data) +{ + mCompiled = mShader->compile(data, mSource); } void Shader::addRef() diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.h b/src/3rdparty/angle/src/libGLESv2/Shader.h index 7ba3bd165c3..904217dab8c 100644 --- a/src/3rdparty/angle/src/libGLESv2/Shader.h +++ b/src/3rdparty/angle/src/libGLESv2/Shader.h @@ -31,6 +31,7 @@ class ShaderImpl; namespace gl { class ResourceManager; +struct Data; struct PackedVarying : public sh::Varying { @@ -73,8 +74,9 @@ class Shader void getSource(GLsizei bufSize, GLsizei *length, char *buffer) const; int getTranslatedSourceLength() const; void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const; + void getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const; - void compile(); + void compile(const gl::Data &data); bool isCompiled() const { return mCompiled; } void addRef(); diff --git a/src/3rdparty/angle/src/libGLESv2/State.cpp b/src/3rdparty/angle/src/libGLESv2/State.cpp index 3c03b90e56b..b5b62f58483 100644 --- a/src/3rdparty/angle/src/libGLESv2/State.cpp +++ b/src/3rdparty/angle/src/libGLESv2/State.cpp @@ -10,18 +10,20 @@ #include "libGLESv2/Context.h" #include "libGLESv2/Caps.h" -#include "libGLESv2/VertexArray.h" -#include "libGLESv2/Query.h" #include "libGLESv2/Framebuffer.h" #include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/renderer/RenderTarget.h" +#include "libGLESv2/Query.h" +#include "libGLESv2/VertexArray.h" #include "libGLESv2/formatutils.h" +#include "libGLESv2/renderer/RenderTarget.h" namespace gl { State::State() { + mMaxDrawBuffers = 0; + mMaxCombinedTextureImageUnits = 0; } State::~State() @@ -31,7 +33,8 @@ State::~State() void State::initialize(const Caps& caps, GLuint clientVersion) { - mContext = NULL; + mMaxDrawBuffers = caps.maxDrawBuffers; + mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits; setClearColor(0.0f, 0.0f, 0.0f, 0.0f); @@ -111,11 +114,15 @@ void State::initialize(const Caps& caps, GLuint clientVersion) mActiveSampler = 0; const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f }; - for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++) + mVertexAttribCurrentValues.resize(caps.maxVertexAttributes); + for (size_t attribIndex = 0; attribIndex < mVertexAttribCurrentValues.size(); ++attribIndex) { mVertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues); } + mUniformBuffers.resize(caps.maxCombinedUniformBlocks); + mTransformFeedbackBuffers.resize(caps.maxTransformFeedbackSeparateAttributes); + mSamplerTextures[GL_TEXTURE_2D].resize(caps.maxCombinedTextureImageUnits); mSamplerTextures[GL_TEXTURE_CUBE_MAP].resize(caps.maxCombinedTextureImageUnits); if (clientVersion >= 3) @@ -153,12 +160,6 @@ void State::reset() mSamplers[samplerIdx].set(NULL); } - const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f }; - for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++) - { - mVertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues); - } - mArrayBuffer.set(NULL); mRenderbuffer.set(NULL); @@ -170,15 +171,15 @@ void State::reset() } mGenericUniformBuffer.set(NULL); - for (int i = 0; i < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; i++) + mGenericTransformFeedbackBuffer.set(NULL); + for (BufferVector::iterator bufItr = mUniformBuffers.begin(); bufItr != mUniformBuffers.end(); ++bufItr) { - mUniformBuffers[i].set(NULL); + bufItr->set(NULL); } - mGenericTransformFeedbackBuffer.set(NULL); - for (int i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) + for (BufferVector::iterator bufItr = mTransformFeedbackBuffers.begin(); bufItr != mTransformFeedbackBuffers.end(); ++bufItr) { - mTransformFeedbackBuffers[i].set(NULL); + bufItr->set(NULL); } mCopyReadBuffer.set(NULL); @@ -485,7 +486,7 @@ void State::setSampleCoverageParams(GLclampf value, bool invert) mSampleCoverageInvert = invert; } -void State::getSampleCoverageParams(GLclampf *value, bool *invert) +void State::getSampleCoverageParams(GLclampf *value, bool *invert) const { ASSERT(value != NULL && invert != NULL); @@ -612,14 +613,7 @@ void State::setSamplerTexture(GLenum type, Texture *texture) Texture *State::getSamplerTexture(unsigned int sampler, GLenum type) const { - const BindingPointer& binding = mSamplerTextures.at(type)[sampler]; - - if (binding.id() == 0) // Special case: 0 refers to default textures held by Context - { - return NULL; - } - - return binding.get(); + return mSamplerTextures.at(type)[sampler].get(); } GLuint State::getSamplerTextureId(unsigned int sampler, GLenum type) const @@ -627,7 +621,7 @@ GLuint State::getSamplerTextureId(unsigned int sampler, GLenum type) const return mSamplerTextures.at(type)[sampler].id(); } -void State::detachTexture(GLuint texture) +void State::detachTexture(const TextureMap &zeroTextures, GLuint texture) { // Textures have a detach method on State rather than a simple // removeBinding, because the zero/null texture objects are managed @@ -640,13 +634,15 @@ void State::detachTexture(GLuint texture) for (TextureBindingMap::iterator bindingVec = mSamplerTextures.begin(); bindingVec != mSamplerTextures.end(); bindingVec++) { + GLenum textureType = bindingVec->first; TextureBindingVector &textureVector = bindingVec->second; for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++) { BindingPointer &binding = textureVector[textureIdx]; if (binding.id() == texture) { - binding.set(NULL); + // Zero textures are the "default" textures instead of NULL + binding.set(zeroTextures.at(textureType).get()); } } } @@ -667,6 +663,19 @@ void State::detachTexture(GLuint texture) } } +void State::initializeZeroTextures(const TextureMap &zeroTextures) +{ + for (TextureMap::const_iterator i = zeroTextures.begin(); i != zeroTextures.end(); i++) + { + TextureBindingVector &samplerTextureArray = mSamplerTextures[i->first]; + + for (size_t textureUnit = 0; textureUnit < samplerTextureArray.size(); ++textureUnit) + { + samplerTextureArray[textureUnit].set(i->second.get()); + } + } +} + void State::setSamplerBinding(GLuint textureUnit, Sampler *sampler) { mSamplers[textureUnit].set(sampler); @@ -947,14 +956,14 @@ void State::setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintpt GLuint State::getIndexedUniformBufferId(GLuint index) const { - ASSERT(index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS); + ASSERT(static_cast(index) < mUniformBuffers.size()); return mUniformBuffers[index].id(); } Buffer *State::getIndexedUniformBuffer(GLuint index) const { - ASSERT(index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS); + ASSERT(static_cast(index) < mUniformBuffers.size()); return mUniformBuffers[index].get(); } @@ -971,25 +980,30 @@ void State::setIndexedTransformFeedbackBufferBinding(GLuint index, Buffer *buffe GLuint State::getIndexedTransformFeedbackBufferId(GLuint index) const { - ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS); + ASSERT(static_cast(index) < mTransformFeedbackBuffers.size()); return mTransformFeedbackBuffers[index].id(); } Buffer *State::getIndexedTransformFeedbackBuffer(GLuint index) const { - ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS); + ASSERT(static_cast(index) < mTransformFeedbackBuffers.size()); return mTransformFeedbackBuffers[index].get(); } GLuint State::getIndexedTransformFeedbackBufferOffset(GLuint index) const { - ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS); + ASSERT(static_cast(index) < mTransformFeedbackBuffers.size()); return mTransformFeedbackBuffers[index].getOffset(); } +size_t State::getTransformFeedbackBufferIndexRange() const +{ + return mTransformFeedbackBuffers.size(); +} + void State::setCopyReadBufferBinding(Buffer *buffer) { mCopyReadBuffer.set(buffer); @@ -1033,19 +1047,19 @@ void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled) void State::setVertexAttribf(GLuint index, const GLfloat values[4]) { - ASSERT(index < gl::MAX_VERTEX_ATTRIBS); + ASSERT(static_cast(index) < mVertexAttribCurrentValues.size()); mVertexAttribCurrentValues[index].setFloatValues(values); } void State::setVertexAttribu(GLuint index, const GLuint values[4]) { - ASSERT(index < gl::MAX_VERTEX_ATTRIBS); + ASSERT(static_cast(index) < mVertexAttribCurrentValues.size()); mVertexAttribCurrentValues[index].setUnsignedIntValues(values); } void State::setVertexAttribi(GLuint index, const GLint values[4]) { - ASSERT(index < gl::MAX_VERTEX_ATTRIBS); + ASSERT(static_cast(index) < mVertexAttribCurrentValues.size()); mVertexAttribCurrentValues[index].setIntValues(values); } @@ -1062,15 +1076,10 @@ const VertexAttribute &State::getVertexAttribState(unsigned int attribNum) const const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(unsigned int attribNum) const { - ASSERT(attribNum < MAX_VERTEX_ATTRIBS); + ASSERT(static_cast(attribNum) < mVertexAttribCurrentValues.size()); return mVertexAttribCurrentValues[attribNum]; } -const VertexAttribCurrentValueData *State::getVertexAttribCurrentValues() const -{ - return mVertexAttribCurrentValues; -} - const void *State::getVertexAttribPointer(unsigned int attribNum) const { return getVertexArray()->getVertexAttribute(attribNum).pointer; @@ -1180,12 +1189,12 @@ void State::getFloatv(GLenum pname, GLfloat *params) } } -void State::getIntegerv(GLenum pname, GLint *params) +void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) { if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT) { unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0_EXT); - ASSERT(colorAttachment < mContext->getCaps().maxDrawBuffers); + ASSERT(colorAttachment < mMaxDrawBuffers); Framebuffer *framebuffer = mDrawFramebuffer; *params = framebuffer->getDrawBufferState(colorAttachment); return; @@ -1238,12 +1247,12 @@ void State::getIntegerv(GLenum pname, GLint *params) case GL_SAMPLES: { gl::Framebuffer *framebuffer = mDrawFramebuffer; - if (framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE) + if (framebuffer->completeness(data) == GL_FRAMEBUFFER_COMPLETE) { switch (pname) { case GL_SAMPLE_BUFFERS: - if (framebuffer->getSamples() != 0) + if (framebuffer->getSamples(data) != 0) { *params = 1; } @@ -1253,7 +1262,7 @@ void State::getIntegerv(GLenum pname, GLint *params) } break; case GL_SAMPLES: - *params = framebuffer->getSamples(); + *params = framebuffer->getSamples(data); break; } } @@ -1332,19 +1341,19 @@ void State::getIntegerv(GLenum pname, GLint *params) } break; case GL_TEXTURE_BINDING_2D: - ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits); + ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); *params = mSamplerTextures.at(GL_TEXTURE_2D)[mActiveSampler].id(); break; case GL_TEXTURE_BINDING_CUBE_MAP: - ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits); + ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); *params = mSamplerTextures.at(GL_TEXTURE_CUBE_MAP)[mActiveSampler].id(); break; case GL_TEXTURE_BINDING_3D: - ASSERT(mActiveSampler getCaps().maxCombinedTextureImageUnits); + ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); *params = mSamplerTextures.at(GL_TEXTURE_3D)[mActiveSampler].id(); break; case GL_TEXTURE_BINDING_2D_ARRAY: - ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits); + ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); *params = mSamplerTextures.at(GL_TEXTURE_2D_ARRAY)[mActiveSampler].id(); break; case GL_UNIFORM_BUFFER_BINDING: @@ -1376,13 +1385,13 @@ bool State::getIndexedIntegerv(GLenum target, GLuint index, GLint *data) switch (target) { case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: - if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS) + if (static_cast(index) < mTransformFeedbackBuffers.size()) { *data = mTransformFeedbackBuffers[index].id(); } break; case GL_UNIFORM_BUFFER_BINDING: - if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS) + if (static_cast(index) < mUniformBuffers.size()) { *data = mUniformBuffers[index].id(); } @@ -1399,25 +1408,25 @@ bool State::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data) switch (target) { case GL_TRANSFORM_FEEDBACK_BUFFER_START: - if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS) + if (static_cast(index) < mTransformFeedbackBuffers.size()) { *data = mTransformFeedbackBuffers[index].getOffset(); } break; case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: - if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS) + if (static_cast(index) < mTransformFeedbackBuffers.size()) { *data = mTransformFeedbackBuffers[index].getSize(); } break; case GL_UNIFORM_BUFFER_START: - if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS) + if (static_cast(index) < mUniformBuffers.size()) { *data = mUniformBuffers[index].getOffset(); } break; case GL_UNIFORM_BUFFER_SIZE: - if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS) + if (static_cast(index) < mUniformBuffers.size()) { *data = mUniformBuffers[index].getSize(); } @@ -1433,9 +1442,9 @@ bool State::hasMappedBuffer(GLenum target) const { if (target == GL_ARRAY_BUFFER) { - for (unsigned int attribIndex = 0; attribIndex < gl::MAX_VERTEX_ATTRIBS; attribIndex++) + for (size_t attribIndex = 0; attribIndex < mVertexAttribCurrentValues.size(); attribIndex++) { - const gl::VertexAttribute &vertexAttrib = getVertexAttribState(attribIndex); + const gl::VertexAttribute &vertexAttrib = getVertexAttribState(static_cast(attribIndex)); gl::Buffer *boundBuffer = vertexAttrib.buffer.get(); if (vertexAttrib.enabled && boundBuffer && boundBuffer->isMapped()) { diff --git a/src/3rdparty/angle/src/libGLESv2/State.h b/src/3rdparty/angle/src/libGLESv2/State.h index 5f0433136c3..c3e6106bd84 100644 --- a/src/3rdparty/angle/src/libGLESv2/State.h +++ b/src/3rdparty/angle/src/libGLESv2/State.h @@ -25,6 +25,9 @@ class Query; class VertexArray; class Context; struct Caps; +struct Data; + +typedef std::map< GLenum, BindingPointer > TextureMap; class State { @@ -35,8 +38,6 @@ class State void initialize(const Caps& caps, GLuint clientVersion); void reset(); - void setContext(Context *context) { mContext = context; } - // State chunk getters const RasterizerState &getRasterizerState() const; const BlendState &getBlendState() const; @@ -100,7 +101,7 @@ class State bool isSampleCoverageEnabled() const; void setSampleCoverage(bool enabled); void setSampleCoverageParams(GLclampf value, bool invert); - void getSampleCoverageParams(GLclampf *value, bool *invert); + void getSampleCoverageParams(GLclampf *value, bool *invert) const; // Scissor test state toggle & query bool isScissorTestEnabled() const; @@ -133,7 +134,8 @@ class State void setSamplerTexture(GLenum type, Texture *texture); Texture *getSamplerTexture(unsigned int sampler, GLenum type) const; GLuint getSamplerTextureId(unsigned int sampler, GLenum type) const; - void detachTexture(GLuint texture); + void detachTexture(const TextureMap &zeroTextures, GLuint texture); + void initializeZeroTextures(const TextureMap &zeroTextures); // Sampler object binding manipulation void setSamplerBinding(GLuint textureUnit, Sampler *sampler); @@ -199,6 +201,7 @@ class State GLuint getIndexedTransformFeedbackBufferId(GLuint index) const; Buffer *getIndexedTransformFeedbackBuffer(GLuint index) const; GLuint getIndexedTransformFeedbackBufferOffset(GLuint index) const; + size_t getTransformFeedbackBufferIndexRange() const; // GL_COPY_[READ/WRITE]_BUFFER void setCopyReadBufferBinding(Buffer *buffer); @@ -220,7 +223,6 @@ class State bool normalized, bool pureInteger, GLsizei stride, const void *pointer); const VertexAttribute &getVertexAttribState(unsigned int attribNum) const; const VertexAttribCurrentValueData &getVertexAttribCurrentValue(unsigned int attribNum) const; - const VertexAttribCurrentValueData *getVertexAttribCurrentValues() const; const void *getVertexAttribPointer(unsigned int attribNum) const; // Pixel pack state manipulation @@ -238,7 +240,7 @@ class State // State query functions void getBooleanv(GLenum pname, GLboolean *params); void getFloatv(GLenum pname, GLfloat *params); - void getIntegerv(GLenum pname, GLint *params); + void getIntegerv(const gl::Data &data, GLenum pname, GLint *params); bool getIndexedIntegerv(GLenum target, GLuint index, GLint *data); bool getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data); @@ -247,7 +249,9 @@ class State private: DISALLOW_COPY_AND_ASSIGN(State); - Context *mContext; + // Cached values from Context's caps + GLuint mMaxDrawBuffers; + GLuint mMaxCombinedTextureImageUnits; ColorF mColorClearValue; GLclampf mDepthClearValue; @@ -283,7 +287,8 @@ class State GLuint mCurrentProgramId; BindingPointer mCurrentProgramBinary; - VertexAttribCurrentValueData mVertexAttribCurrentValues[MAX_VERTEX_ATTRIBS]; // From glVertexAttrib + typedef std::vector VertexAttribVector; + VertexAttribVector mVertexAttribCurrentValues; // From glVertexAttrib VertexArray *mVertexArray; // Texture and sampler bindings @@ -300,11 +305,12 @@ class State ActiveQueryMap mActiveQueries; BindingPointer mGenericUniformBuffer; - OffsetBindingPointer mUniformBuffers[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS]; + typedef std::vector< OffsetBindingPointer > BufferVector; + BufferVector mUniformBuffers; BindingPointer mTransformFeedback; BindingPointer mGenericTransformFeedbackBuffer; - OffsetBindingPointer mTransformFeedbackBuffers[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; + BufferVector mTransformFeedbackBuffers; BindingPointer mCopyReadBuffer; BindingPointer mCopyWriteBuffer; diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.cpp b/src/3rdparty/angle/src/libGLESv2/Texture.cpp index 3ec492de077..cd4fc4e32a6 100644 --- a/src/3rdparty/angle/src/libGLESv2/Texture.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Texture.cpp @@ -47,11 +47,14 @@ bool IsPointSampled(const gl::SamplerState &samplerState) return (samplerState.magFilter == GL_NEAREST && (samplerState.minFilter == GL_NEAREST || samplerState.minFilter == GL_NEAREST_MIPMAP_NEAREST)); } +unsigned int Texture::mCurrentTextureSerial = 1; + Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target) : RefCountObject(id), mTexture(impl), + mTextureSerial(issueTextureSerial()), mUsage(GL_NONE), - mImmutable(false), + mImmutableLevelCount(0), mTarget(target) { } @@ -72,16 +75,6 @@ void Texture::setUsage(GLenum usage) getImplementation()->setUsage(usage); } -void Texture::getSamplerStateWithNativeOffset(SamplerState *sampler) -{ - *sampler = mSamplerState; - - // Offset the effective base level by the texture storage's top level - rx::TextureStorage *texture = getNativeTexture(); - int topLevel = texture ? texture->getTopLevel() : 0; - sampler->baseLevel = topLevel + mSamplerState.baseLevel; -} - GLenum Texture::getUsage() const { return mUsage; @@ -138,35 +131,35 @@ GLenum Texture::getActualFormat(const ImageIndex &index) const return image->getActualFormat(); } -rx::TextureStorage *Texture::getNativeTexture() +Error Texture::generateMipmaps() { - return getImplementation()->getNativeTexture(); + return getImplementation()->generateMipmaps(); } -void Texture::generateMipmaps() +Error Texture::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) { - getImplementation()->generateMipmaps(); + return mTexture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source); } -void Texture::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) +unsigned int Texture::getTextureSerial() const { - getImplementation()->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source); + return mTextureSerial; } -unsigned int Texture::getTextureSerial() +unsigned int Texture::issueTextureSerial() { - rx::TextureStorage *texture = getNativeTexture(); - return texture ? texture->getTextureSerial() : 0; + return mCurrentTextureSerial++; } bool Texture::isImmutable() const { - return mImmutable; + return (mImmutableLevelCount > 0); } int Texture::immutableLevelCount() { - return (mImmutable ? getNativeTexture()->getLevelCount() : 0); + return mImmutableLevelCount; } int Texture::mipLevels() const @@ -226,11 +219,11 @@ GLenum Texture2D::getActualFormat(GLint level) const return GL_NONE; } -void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) +Error Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { releaseTexImage(); - mTexture->setImage(GL_TEXTURE_2D, level, width, height, 1, internalFormat, format, type, unpack, pixels); + return mTexture->setImage(GL_TEXTURE_2D, level, width, height, 1, internalFormat, format, type, unpack, pixels); } void Texture2D::bindTexImage(egl::Surface *surface) @@ -254,35 +247,44 @@ void Texture2D::releaseTexImage() } } -void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) +Error Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, + const PixelUnpackState &unpack, const void *pixels) { releaseTexImage(); - mTexture->setCompressedImage(GL_TEXTURE_2D, level, format, width, height, 1, imageSize, pixels); + return mTexture->setCompressedImage(GL_TEXTURE_2D, level, format, width, height, 1, imageSize, unpack, pixels); } -void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) +Error Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->subImage(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels); + return mTexture->subImage(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels); } -void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) +Error Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) { - mTexture->subImageCompressed(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels); + return mTexture->subImageCompressed(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels); } -void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) +Error Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, + Framebuffer *source) { releaseTexImage(); - mTexture->copyImage(GL_TEXTURE_2D, level, format, x, y, width, height, source); + return mTexture->copyImage(GL_TEXTURE_2D, level, format, x, y, width, height, source); } -void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +Error Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) { - mImmutable = true; + Error error = mTexture->storage(GL_TEXTURE_2D, levels, internalformat, width, height, 1); + if (error.isError()) + { + return error; + } - mTexture->storage(GL_TEXTURE_2D, levels, internalformat, width, height, 1); + mImmutableLevelCount = levels; + + return Error(GL_NO_ERROR); } // Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85. @@ -359,11 +361,11 @@ bool Texture2D::isDepth(GLint level) const return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } -void Texture2D::generateMipmaps() +Error Texture2D::generateMipmaps() { releaseTexImage(); - mTexture->generateMipmaps(); + return mTexture->generateMipmaps(); } // Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. @@ -467,49 +469,27 @@ GLenum TextureCubeMap::getActualFormat(GLenum target, GLint level) const return GL_NONE; } -void TextureCubeMap::setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) +Error TextureCubeMap::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, width, height, 1, internalFormat, format, type, unpack, pixels); + return mTexture->setImage(target, level, width, height, 1, internalFormat, format, type, unpack, pixels); } -void TextureCubeMap::setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) +Error TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, + GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, width, height, 1, internalFormat, format, type, unpack, pixels); + return mTexture->setCompressedImage(target, level, format, width, height, 1, imageSize, unpack, pixels); } -void TextureCubeMap::setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) +Error TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, width, height, 1, internalFormat, format, type, unpack, pixels); + return mTexture->subImage(target, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels); } -void TextureCubeMap::setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) +Error TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, GLenum format, + GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, width, height, 1, internalFormat, format, type, unpack, pixels); -} - -void TextureCubeMap::setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) -{ - mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, width, height, 1, internalFormat, format, type, unpack, pixels); -} - -void TextureCubeMap::setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) -{ - mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, width, height, 1, internalFormat, format, type, unpack, pixels); -} - -void TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) -{ - mTexture->setCompressedImage(target, level, format, width, height, 1, imageSize, pixels); -} - -void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) -{ - mTexture->subImage(target, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels); -} - -void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) -{ - mTexture->subImageCompressed(target, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels); + return mTexture->subImageCompressed(target, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels); } // Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. @@ -549,16 +529,23 @@ bool TextureCubeMap::isDepth(GLenum target, GLint level) const return GetInternalFormatInfo(getInternalFormat(target, level)).depthBits > 0; } -void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) +Error TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, + GLsizei width, GLsizei height, Framebuffer *source) { - mTexture->copyImage(target, level, format, x, y, width, height, source); + return mTexture->copyImage(target, level, format, x, y, width, height, source); } -void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size) +Error TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size) { - mImmutable = true; + Error error = mTexture->storage(GL_TEXTURE_CUBE_MAP, levels, internalformat, size, size, 1); + if (error.isError()) + { + return error; + } - mTexture->storage(GL_TEXTURE_CUBE_MAP, levels, internalformat, size, size, 1); + mImmutableLevelCount = levels; + + return Error(GL_NO_ERROR); } // Tests for texture sampling completeness @@ -734,31 +721,40 @@ bool Texture3D::isDepth(GLint level) const return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } -void Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) +Error Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setImage(GL_TEXTURE_3D, level, width, height, depth, internalFormat, format, type, unpack, pixels); + return mTexture->setImage(GL_TEXTURE_3D, level, width, height, depth, internalFormat, format, type, unpack, pixels); } -void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) +Error Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, + GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setCompressedImage(GL_TEXTURE_3D, level, format, width, height, depth, imageSize, pixels); + return mTexture->setCompressedImage(GL_TEXTURE_3D, level, format, width, height, depth, imageSize, unpack, pixels); } -void Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) +Error Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->subImage(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels); + return mTexture->subImage(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels); } -void Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) +Error Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, + GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) { - mTexture->subImageCompressed(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels); + return mTexture->subImageCompressed(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, unpack, pixels); } -void Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +Error Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { - mImmutable = true; + Error error = mTexture->storage(GL_TEXTURE_3D, levels, internalformat, width, height, depth); + if (error.isError()) + { + return error; + } - mTexture->storage(GL_TEXTURE_3D, levels, internalformat, width, height, depth); + mImmutableLevelCount = levels; + + return Error(GL_NO_ERROR); } bool Texture3D::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const @@ -892,31 +888,40 @@ bool Texture2DArray::isDepth(GLint level) const return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } -void Texture2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) +Error Texture2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setImage(GL_TEXTURE_2D_ARRAY, level, width, height, depth, internalFormat, format, type, unpack, pixels); + return mTexture->setImage(GL_TEXTURE_2D_ARRAY, level, width, height, depth, internalFormat, format, type, unpack, pixels); } -void Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) +Error Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, + GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setCompressedImage(GL_TEXTURE_2D_ARRAY, level, format, width, height, depth, imageSize, pixels); + return mTexture->setCompressedImage(GL_TEXTURE_2D_ARRAY, level, format, width, height, depth, imageSize, unpack, pixels); } -void Texture2DArray::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) +Error Texture2DArray::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->subImage(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels); + return mTexture->subImage(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels); } -void Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) +Error Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, + GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) { - mTexture->subImageCompressed(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels); + return mTexture->subImageCompressed(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, unpack, pixels); } -void Texture2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +Error Texture2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { - mImmutable = true; + Error error = mTexture->storage(GL_TEXTURE_2D_ARRAY, levels, internalformat, width, height, depth); + if (error.isError()) + { + return error; + } - mTexture->storage(GL_TEXTURE_2D_ARRAY, levels, internalformat, width, height, depth); + mImmutableLevelCount = levels; + + return Error(GL_NO_ERROR); } bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.h b/src/3rdparty/angle/src/libGLESv2/Texture.h index ca5686fde3e..66d4df80158 100644 --- a/src/3rdparty/angle/src/libGLESv2/Texture.h +++ b/src/3rdparty/angle/src/libGLESv2/Texture.h @@ -14,7 +14,7 @@ #include "common/debug.h" #include "common/RefCountObject.h" #include "libGLESv2/angletypes.h" -#include "libGLESv2/constants.h" +#include "libGLESv2/Constants.h" #include "libGLESv2/renderer/TextureImpl.h" #include "libGLESv2/Caps.h" @@ -52,7 +52,6 @@ class Texture : public RefCountObject const SamplerState &getSamplerState() const { return mSamplerState; } SamplerState &getSamplerState() { return mSamplerState; } - void getSamplerStateWithNativeOffset(SamplerState *sampler); void setUsage(GLenum usage); GLenum getUsage() const; @@ -69,15 +68,16 @@ class Texture : public RefCountObject virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const = 0; - rx::TextureStorage *getNativeTexture(); + virtual Error generateMipmaps(); - virtual void generateMipmaps(); - virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); + virtual Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); - unsigned int getTextureSerial(); + // Texture serials provide a unique way of identifying a Texture that isn't a raw pointer. + // "id" is not good enough, as Textures can be deleted, then re-allocated with the same id. + unsigned int getTextureSerial() const; bool isImmutable() const; - int immutableLevelCount(); + GLsizei immutableLevelCount(); rx::TextureImpl *getImplementation() { return mTexture; } const rx::TextureImpl *getImplementation() const { return mTexture; } @@ -86,17 +86,20 @@ class Texture : public RefCountObject protected: int mipLevels() const; + const rx::Image *getBaseLevelImage() const; + static unsigned int issueTextureSerial(); rx::TextureImpl *mTexture; SamplerState mSamplerState; GLenum mUsage; - bool mImmutable; + GLsizei mImmutableLevelCount; GLenum mTarget; - const rx::Image *getBaseLevelImage() const; + const unsigned int mTextureSerial; + static unsigned int mCurrentTextureSerial; private: DISALLOW_COPY_AND_ASSIGN(Texture); @@ -116,18 +119,18 @@ class Texture2D : public Texture bool isCompressed(GLint level) const; bool isDepth(GLint level) const; - void setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels); - void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels); - void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); - void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); + Error setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + Error setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); + Error subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + Error subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); + Error copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); + Error storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const; virtual void bindTexImage(egl::Surface *surface); virtual void releaseTexImage(); - virtual void generateMipmaps(); + virtual Error generateMipmaps(); private: DISALLOW_COPY_AND_ASSIGN(Texture2D); @@ -152,19 +155,12 @@ class TextureCubeMap : public Texture bool isCompressed(GLenum target, GLint level) const; bool isDepth(GLenum target, GLint level) const; - void setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - - void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels); - - void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels); - void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); - void storage(GLsizei levels, GLenum internalformat, GLsizei size); + Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); + Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); + Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); + Error storage(GLsizei levels, GLenum internalformat, GLsizei size); virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const; @@ -195,11 +191,11 @@ class Texture3D : public Texture bool isCompressed(GLint level) const; bool isDepth(GLint level) const; - void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); - void subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); - void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + Error setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + Error setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); + Error subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + Error subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); + Error storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const; @@ -225,11 +221,11 @@ class Texture2DArray : public Texture bool isCompressed(GLint level) const; bool isDepth(GLint level) const; - void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); - void subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); - void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + Error setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + Error setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); + Error subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + Error subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); + Error storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const; diff --git a/src/3rdparty/angle/src/libGLESv2/VertexArray.h b/src/3rdparty/angle/src/libGLESv2/VertexArray.h index 993ba042cfd..a724c0be1cb 100644 --- a/src/3rdparty/angle/src/libGLESv2/VertexArray.h +++ b/src/3rdparty/angle/src/libGLESv2/VertexArray.h @@ -14,14 +14,13 @@ #define LIBGLESV2_VERTEXARRAY_H_ #include "common/RefCountObject.h" -#include "libGLESv2/constants.h" +#include "libGLESv2/Constants.h" #include "libGLESv2/VertexAttribute.h" #include namespace rx { -class Renderer; class VertexArrayImpl; } @@ -44,7 +43,7 @@ class VertexArray void setAttributeState(unsigned int attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type, bool normalized, bool pureInteger, GLsizei stride, const void *pointer); - const VertexAttribute* getVertexAttributes() const { return mVertexAttributes.data(); } + const VertexAttribute* getVertexAttributes() const { return &mVertexAttributes[0]; } Buffer *getElementArrayBuffer() const { return mElementArrayBuffer.get(); } void setElementArrayBuffer(Buffer *buffer); GLuint getElementArrayBufferId() const { return mElementArrayBuffer.id(); } diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp b/src/3rdparty/angle/src/libGLESv2/angletypes.cpp index bb6425df647..5a0cfc5ad95 100644 --- a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp +++ b/src/3rdparty/angle/src/libGLESv2/angletypes.cpp @@ -9,6 +9,10 @@ #include "libGLESv2/angletypes.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/VertexAttribute.h" +#include "libGLESv2/State.h" +#include "libGLESv2/VertexArray.h" + +#include namespace gl { @@ -148,16 +152,16 @@ VertexFormat::VertexFormat(const VertexAttribute &attrib, GLenum currentValueTyp void VertexFormat::GetInputLayout(VertexFormat *inputLayout, ProgramBinary *programBinary, - const VertexAttribute *attributes, - const gl::VertexAttribCurrentValueData *currentValues) + const State &state) { + const VertexAttribute *vertexAttributes = state.getVertexArray()->getVertexAttributes(); for (unsigned int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) { int semanticIndex = programBinary->getSemanticIndex(attributeIndex); if (semanticIndex != -1) { - inputLayout[semanticIndex] = VertexFormat(attributes[attributeIndex], currentValues[attributeIndex].Type); + inputLayout[semanticIndex] = VertexFormat(vertexAttributes[attributeIndex], state.getVertexAttribCurrentValue(attributeIndex).Type); } } } @@ -192,4 +196,15 @@ bool VertexFormat::operator<(const VertexFormat& other) const return mPureInteger < other.mPureInteger; } +bool Box::operator==(const Box &other) const +{ + return (x == other.x && y == other.y && z == other.z && + width == other.width && height == other.height && depth == other.depth); +} + +bool Box::operator!=(const Box &other) const +{ + return !(*this == other); +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.h b/src/3rdparty/angle/src/libGLESv2/angletypes.h index 642a6ec266d..78fe6b0e263 100644 --- a/src/3rdparty/angle/src/libGLESv2/angletypes.h +++ b/src/3rdparty/angle/src/libGLESv2/angletypes.h @@ -9,13 +9,13 @@ #ifndef LIBGLESV2_ANGLETYPES_H_ #define LIBGLESV2_ANGLETYPES_H_ -#include "libGLESv2/constants.h" +#include "libGLESv2/Constants.h" #include "common/RefCountObject.h" -#include namespace gl { class Buffer; +class State; class ProgramBinary; struct VertexAttribute; struct VertexAttribCurrentValueData; @@ -66,6 +66,8 @@ struct Box Box() : x(0), y(0), z(0), width(0), height(0), depth(0) { } Box(int x_in, int y_in, int z_in, int width_in, int height_in, int depth_in) : x(x_in), y(y_in), z(z_in), width(width_in), height(height_in), depth(depth_in) { } + bool operator==(const Box &other) const; + bool operator!=(const Box &other) const; }; struct Extents @@ -230,8 +232,7 @@ struct VertexFormat static void GetInputLayout(VertexFormat *inputLayout, ProgramBinary *programBinary, - const VertexAttribute *attributes, - const gl::VertexAttribCurrentValueData *currentValues); + const State& currentValues); bool operator==(const VertexFormat &other) const; bool operator!=(const VertexFormat &other) const; @@ -251,13 +252,6 @@ enum VertexConversionType VERTEX_CONVERT_BOTH = 3 }; -enum D3DWorkaroundType -{ - ANGLE_D3D_WORKAROUND_NONE, - ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION, - ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION -}; - } #endif // LIBGLESV2_ANGLETYPES_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp index 07f5d47473d..587950a1397 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp @@ -34,13 +34,12 @@ #include "libGLESv2/validationES3.h" #include "libGLESv2/queryconversions.h" - extern "C" { // OpenGL ES 2.0 functions -void __stdcall glActiveTexture(GLenum texture) +void GL_APIENTRY glActiveTexture(GLenum texture) { EVENT("(GLenum texture = 0x%X)", texture); @@ -57,7 +56,7 @@ void __stdcall glActiveTexture(GLenum texture) } } -void __stdcall glAttachShader(GLuint program, GLuint shader) +void GL_APIENTRY glAttachShader(GLuint program, GLuint shader) { EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader); @@ -103,7 +102,7 @@ void __stdcall glAttachShader(GLuint program, GLuint shader) } } -void __stdcall glBeginQueryEXT(GLenum target, GLuint id) +void GL_APIENTRY glBeginQueryEXT(GLenum target, GLuint id) { EVENT("(GLenum target = 0x%X, GLuint %d)", target, id); @@ -124,7 +123,7 @@ void __stdcall glBeginQueryEXT(GLenum target, GLuint id) } } -void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar* name) +void GL_APIENTRY glBindAttribLocation(GLuint program, GLuint index, const GLchar* name) { EVENT("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name); @@ -163,7 +162,7 @@ void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar* } } -void __stdcall glBindBuffer(GLenum target, GLuint buffer) +void GL_APIENTRY glBindBuffer(GLenum target, GLuint buffer) { EVENT("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer); @@ -210,7 +209,7 @@ void __stdcall glBindBuffer(GLenum target, GLuint buffer) } } -void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer) +void GL_APIENTRY glBindFramebuffer(GLenum target, GLuint framebuffer) { EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer); @@ -235,7 +234,7 @@ void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer) } } -void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer) +void GL_APIENTRY glBindRenderbuffer(GLenum target, GLuint renderbuffer) { EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer); @@ -252,7 +251,7 @@ void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer) } } -void __stdcall glBindTexture(GLenum target, GLuint texture) +void GL_APIENTRY glBindTexture(GLenum target, GLuint texture) { EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture); @@ -291,7 +290,7 @@ void __stdcall glBindTexture(GLenum target, GLuint texture) } } -void __stdcall glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +void GL_APIENTRY glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)", red, green, blue, alpha); @@ -304,12 +303,12 @@ void __stdcall glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclamp } } -void __stdcall glBlendEquation(GLenum mode) +void GL_APIENTRY glBlendEquation(GLenum mode) { glBlendEquationSeparate(mode, mode); } -void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) +void GL_APIENTRY glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) { EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha); @@ -348,12 +347,12 @@ void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) } } -void __stdcall glBlendFunc(GLenum sfactor, GLenum dfactor) +void GL_APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor) { glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor); } -void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) +void GL_APIENTRY glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) { EVENT("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)", srcRGB, dstRGB, srcAlpha, dstAlpha); @@ -488,7 +487,7 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha } } -void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) +void GL_APIENTRY glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) { EVENT("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)", target, size, data, usage); @@ -550,7 +549,7 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, } } -void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) +void GL_APIENTRY glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) { EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)", target, offset, size, data); @@ -611,7 +610,7 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, } } -GLenum __stdcall glCheckFramebufferStatus(GLenum target) +GLenum GL_APIENTRY glCheckFramebufferStatus(GLenum target) { EVENT("(GLenum target = 0x%X)", target); @@ -626,13 +625,14 @@ GLenum __stdcall glCheckFramebufferStatus(GLenum target) gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); ASSERT(framebuffer); - return framebuffer->completeness(); + + return framebuffer->completeness(context->getData()); } return 0; } -void __stdcall glClear(GLbitfield mask) +void GL_APIENTRY glClear(GLbitfield mask) { EVENT("(GLbitfield mask = 0x%X)", mask); @@ -640,8 +640,9 @@ void __stdcall glClear(GLbitfield mask) if (context) { gl::Framebuffer *framebufferObject = context->getState().getDrawFramebuffer(); + ASSERT(framebufferObject); - if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE) + if (framebufferObject->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE) { context->recordError(gl::Error(GL_INVALID_FRAMEBUFFER_OPERATION)); return; @@ -662,7 +663,7 @@ void __stdcall glClear(GLbitfield mask) } } -void __stdcall glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +void GL_APIENTRY glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)", red, green, blue, alpha); @@ -674,7 +675,7 @@ void __stdcall glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclamp } } -void __stdcall glClearDepthf(GLclampf depth) +void GL_APIENTRY glClearDepthf(GLclampf depth) { EVENT("(GLclampf depth = %f)", depth); @@ -685,7 +686,7 @@ void __stdcall glClearDepthf(GLclampf depth) } } -void __stdcall glClearStencil(GLint s) +void GL_APIENTRY glClearStencil(GLint s) { EVENT("(GLint s = %d)", s); @@ -696,7 +697,7 @@ void __stdcall glClearStencil(GLint s) } } -void __stdcall glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) +void GL_APIENTRY glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) { EVENT("(GLboolean red = %d, GLboolean green = %u, GLboolean blue = %u, GLboolean alpha = %u)", red, green, blue, alpha); @@ -708,7 +709,7 @@ void __stdcall glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboo } } -void __stdcall glCompileShader(GLuint shader) +void GL_APIENTRY glCompileShader(GLuint shader) { EVENT("(GLuint shader = %d)", shader); @@ -731,11 +732,11 @@ void __stdcall glCompileShader(GLuint shader) } } - shaderObject->compile(); + shaderObject->compile(context->getData()); } } -void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, +void GL_APIENTRY glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) { EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " @@ -771,7 +772,12 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna case GL_TEXTURE_2D: { gl::Texture2D *texture = context->getTexture2D(); - texture->setCompressedImage(level, internalformat, width, height, imageSize, data); + gl::Error error = texture->setCompressedImage(level, internalformat, width, height, imageSize, context->getState().getUnpackState(), data); + if (error.isError()) + { + context->recordError(error); + return; + } } break; @@ -783,7 +789,12 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: { gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data); + gl::Error error = texture->setCompressedImage(target, level, internalformat, width, height, imageSize, context->getState().getUnpackState(), data); + if (error.isError()) + { + context->recordError(error); + return; + } } break; @@ -794,7 +805,7 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna } } -void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, +void GL_APIENTRY glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) { EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " @@ -831,7 +842,12 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs case GL_TEXTURE_2D: { gl::Texture2D *texture = context->getTexture2D(); - texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data); + gl::Error error = texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, context->getState().getUnpackState(), data); + if (error.isError()) + { + context->recordError(error); + return; + } } break; @@ -843,7 +859,12 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: { gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data); + gl::Error error = texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, context->getState().getUnpackState(), data); + if (error.isError()) + { + context->recordError(error); + return; + } } break; @@ -854,7 +875,7 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs } } -void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +void GL_APIENTRY glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, " "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)", @@ -884,7 +905,12 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma case GL_TEXTURE_2D: { gl::Texture2D *texture = context->getTexture2D(); - texture->copyImage(level, internalformat, x, y, width, height, framebuffer); + gl::Error error = texture->copyImage(level, internalformat, x, y, width, height, framebuffer); + if (error.isError()) + { + context->recordError(error); + return; + } } break; @@ -896,7 +922,12 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: { gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer); + gl::Error error = texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer); + if (error.isError()) + { + context->recordError(error); + return; + } } break; @@ -907,7 +938,7 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma } } -void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) +void GL_APIENTRY glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) { EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", @@ -937,7 +968,12 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL case GL_TEXTURE_2D: { gl::Texture2D *texture = context->getTexture2D(); - texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer); + gl::Error error = texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer); + if (error.isError()) + { + context->recordError(error); + return; + } } break; @@ -949,7 +985,12 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: { gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer); + gl::Error error = texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer); + if (error.isError()) + { + context->recordError(error); + return; + } } break; @@ -960,7 +1001,7 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL } } -GLuint __stdcall glCreateProgram(void) +GLuint GL_APIENTRY glCreateProgram(void) { EVENT("()"); @@ -973,7 +1014,7 @@ GLuint __stdcall glCreateProgram(void) return 0; } -GLuint __stdcall glCreateShader(GLenum type) +GLuint GL_APIENTRY glCreateShader(GLenum type) { EVENT("(GLenum type = 0x%X)", type); @@ -995,7 +1036,7 @@ GLuint __stdcall glCreateShader(GLenum type) return 0; } -void __stdcall glCullFace(GLenum mode) +void GL_APIENTRY glCullFace(GLenum mode) { EVENT("(GLenum mode = 0x%X)", mode); @@ -1018,7 +1059,7 @@ void __stdcall glCullFace(GLenum mode) } } -void __stdcall glDeleteBuffers(GLsizei n, const GLuint* buffers) +void GL_APIENTRY glDeleteBuffers(GLsizei n, const GLuint* buffers) { EVENT("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers); @@ -1038,7 +1079,7 @@ void __stdcall glDeleteBuffers(GLsizei n, const GLuint* buffers) } } -void __stdcall glDeleteFencesNV(GLsizei n, const GLuint* fences) +void GL_APIENTRY glDeleteFencesNV(GLsizei n, const GLuint* fences) { EVENT("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences); @@ -1058,7 +1099,7 @@ void __stdcall glDeleteFencesNV(GLsizei n, const GLuint* fences) } } -void __stdcall glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) +void GL_APIENTRY glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) { EVENT("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers); @@ -1081,7 +1122,7 @@ void __stdcall glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) } } -void __stdcall glDeleteProgram(GLuint program) +void GL_APIENTRY glDeleteProgram(GLuint program) { EVENT("(GLuint program = %d)", program); @@ -1111,7 +1152,7 @@ void __stdcall glDeleteProgram(GLuint program) } } -void __stdcall glDeleteQueriesEXT(GLsizei n, const GLuint *ids) +void GL_APIENTRY glDeleteQueriesEXT(GLsizei n, const GLuint *ids) { EVENT("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids); @@ -1131,7 +1172,7 @@ void __stdcall glDeleteQueriesEXT(GLsizei n, const GLuint *ids) } } -void __stdcall glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) +void GL_APIENTRY glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) { EVENT("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers); @@ -1151,7 +1192,7 @@ void __stdcall glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) } } -void __stdcall glDeleteShader(GLuint shader) +void GL_APIENTRY glDeleteShader(GLuint shader) { EVENT("(GLuint shader = %d)", shader); @@ -1181,7 +1222,7 @@ void __stdcall glDeleteShader(GLuint shader) } } -void __stdcall glDeleteTextures(GLsizei n, const GLuint* textures) +void GL_APIENTRY glDeleteTextures(GLsizei n, const GLuint* textures) { EVENT("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures); @@ -1204,7 +1245,7 @@ void __stdcall glDeleteTextures(GLsizei n, const GLuint* textures) } } -void __stdcall glDepthFunc(GLenum func) +void GL_APIENTRY glDepthFunc(GLenum func) { EVENT("(GLenum func = 0x%X)", func); @@ -1231,7 +1272,7 @@ void __stdcall glDepthFunc(GLenum func) } } -void __stdcall glDepthMask(GLboolean flag) +void GL_APIENTRY glDepthMask(GLboolean flag) { EVENT("(GLboolean flag = %u)", flag); @@ -1242,7 +1283,7 @@ void __stdcall glDepthMask(GLboolean flag) } } -void __stdcall glDepthRangef(GLclampf zNear, GLclampf zFar) +void GL_APIENTRY glDepthRangef(GLclampf zNear, GLclampf zFar) { EVENT("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar); @@ -1253,7 +1294,7 @@ void __stdcall glDepthRangef(GLclampf zNear, GLclampf zFar) } } -void __stdcall glDetachShader(GLuint program, GLuint shader) +void GL_APIENTRY glDetachShader(GLuint program, GLuint shader) { EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader); @@ -1302,7 +1343,7 @@ void __stdcall glDetachShader(GLuint program, GLuint shader) } } -void __stdcall glDisable(GLenum cap) +void GL_APIENTRY glDisable(GLenum cap) { EVENT("(GLenum cap = 0x%X)", cap); @@ -1319,7 +1360,7 @@ void __stdcall glDisable(GLenum cap) } } -void __stdcall glDisableVertexAttribArray(GLuint index) +void GL_APIENTRY glDisableVertexAttribArray(GLuint index) { EVENT("(GLuint index = %d)", index); @@ -1336,7 +1377,7 @@ void __stdcall glDisableVertexAttribArray(GLuint index) } } -void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count) +void GL_APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count) { EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count); @@ -1357,7 +1398,7 @@ void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count) } } -void __stdcall glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount) +void GL_APIENTRY glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount) { EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei primcount = %d)", mode, first, count, primcount); @@ -1378,7 +1419,7 @@ void __stdcall glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei coun } } -void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) +void GL_APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) { EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)", mode, count, type, indices); @@ -1401,7 +1442,7 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv } } -void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount) +void GL_APIENTRY glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount) { EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei primcount = %d)", mode, count, type, indices, primcount); @@ -1424,7 +1465,7 @@ void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum t } } -void __stdcall glEnable(GLenum cap) +void GL_APIENTRY glEnable(GLenum cap) { EVENT("(GLenum cap = 0x%X)", cap); @@ -1441,7 +1482,7 @@ void __stdcall glEnable(GLenum cap) } } -void __stdcall glEnableVertexAttribArray(GLuint index) +void GL_APIENTRY glEnableVertexAttribArray(GLuint index) { EVENT("(GLuint index = %d)", index); @@ -1458,7 +1499,7 @@ void __stdcall glEnableVertexAttribArray(GLuint index) } } -void __stdcall glEndQueryEXT(GLenum target) +void GL_APIENTRY glEndQueryEXT(GLenum target) { EVENT("GLenum target = 0x%X)", target); @@ -1479,7 +1520,7 @@ void __stdcall glEndQueryEXT(GLenum target) } } -void __stdcall glFinishFenceNV(GLuint fence) +void GL_APIENTRY glFinishFenceNV(GLuint fence) { EVENT("(GLuint fence = %d)", fence); @@ -1504,29 +1545,39 @@ void __stdcall glFinishFenceNV(GLuint fence) } } -void __stdcall glFinish(void) +void GL_APIENTRY glFinish(void) { EVENT("()"); gl::Context *context = gl::getNonLostContext(); if (context) { - context->sync(true); + gl::Error error = context->sync(true); + if (error.isError()) + { + context->recordError(error); + return; + } } } -void __stdcall glFlush(void) +void GL_APIENTRY glFlush(void) { EVENT("()"); gl::Context *context = gl::getNonLostContext(); if (context) { - context->sync(false); + gl::Error error = context->sync(false); + if (error.isError()) + { + context->recordError(error); + return; + } } } -void __stdcall glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) +void GL_APIENTRY glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) { EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, " "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer); @@ -1548,33 +1599,19 @@ void __stdcall glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenu gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); ASSERT(framebuffer); - if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + if (renderbuffer != 0) { - unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); - framebuffer->setColorbuffer(colorAttachment, GL_RENDERBUFFER, renderbuffer, 0, 0); + gl::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer); + framebuffer->setRenderbufferAttachment(attachment, renderbufferObject); } else { - switch (attachment) - { - case GL_DEPTH_ATTACHMENT: - framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer, 0, 0); - break; - case GL_STENCIL_ATTACHMENT: - framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer, 0, 0); - break; - case GL_DEPTH_STENCIL_ATTACHMENT: - framebuffer->setDepthStencilBuffer(GL_RENDERBUFFER, renderbuffer, 0, 0); - break; - default: - UNREACHABLE(); - break; - } + framebuffer->setNULLAttachment(attachment); } } } -void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +void GL_APIENTRY glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, " "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level); @@ -1587,31 +1624,23 @@ void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum t return; } - if (texture == 0) - { - textarget = GL_NONE; - } - gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); - if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + if (texture != 0) { - const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); - framebuffer->setColorbuffer(colorAttachment, textarget, texture, level, 0); + gl::Texture *textureObj = context->getTexture(texture); + gl::ImageIndex index(textarget, level, gl::ImageIndex::ENTIRE_LEVEL); + framebuffer->setTextureAttachment(attachment, textureObj, index); } else { - switch (attachment) - { - case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level, 0); break; - case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level, 0); break; - case GL_DEPTH_STENCIL_ATTACHMENT: framebuffer->setDepthStencilBuffer(textarget, texture, level, 0); break; - } + framebuffer->setNULLAttachment(attachment); } } } -void __stdcall glFrontFace(GLenum mode) +void GL_APIENTRY glFrontFace(GLenum mode) { EVENT("(GLenum mode = 0x%X)", mode); @@ -1631,7 +1660,7 @@ void __stdcall glFrontFace(GLenum mode) } } -void __stdcall glGenBuffers(GLsizei n, GLuint* buffers) +void GL_APIENTRY glGenBuffers(GLsizei n, GLuint* buffers) { EVENT("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers); @@ -1651,7 +1680,7 @@ void __stdcall glGenBuffers(GLsizei n, GLuint* buffers) } } -void __stdcall glGenerateMipmap(GLenum target) +void GL_APIENTRY glGenerateMipmap(GLenum target) { EVENT("(GLenum target = 0x%X)", target); @@ -1721,11 +1750,16 @@ void __stdcall glGenerateMipmap(GLenum target) } } - texture->generateMipmaps(); + gl::Error error = texture->generateMipmaps(); + if (error.isError()) + { + context->recordError(error); + return; + } } } -void __stdcall glGenFencesNV(GLsizei n, GLuint* fences) +void GL_APIENTRY glGenFencesNV(GLsizei n, GLuint* fences) { EVENT("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences); @@ -1745,7 +1779,7 @@ void __stdcall glGenFencesNV(GLsizei n, GLuint* fences) } } -void __stdcall glGenFramebuffers(GLsizei n, GLuint* framebuffers) +void GL_APIENTRY glGenFramebuffers(GLsizei n, GLuint* framebuffers) { EVENT("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers); @@ -1765,7 +1799,7 @@ void __stdcall glGenFramebuffers(GLsizei n, GLuint* framebuffers) } } -void __stdcall glGenQueriesEXT(GLsizei n, GLuint* ids) +void GL_APIENTRY glGenQueriesEXT(GLsizei n, GLuint* ids) { EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); @@ -1785,7 +1819,7 @@ void __stdcall glGenQueriesEXT(GLsizei n, GLuint* ids) } } -void __stdcall glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) +void GL_APIENTRY glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) { EVENT("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers); @@ -1805,7 +1839,7 @@ void __stdcall glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) } } -void __stdcall glGenTextures(GLsizei n, GLuint* textures) +void GL_APIENTRY glGenTextures(GLsizei n, GLuint* textures) { EVENT("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures); @@ -1825,7 +1859,7 @@ void __stdcall glGenTextures(GLsizei n, GLuint* textures) } } -void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) +void GL_APIENTRY glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) { EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = 0x%0.8p, " "GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)", @@ -1866,7 +1900,7 @@ void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, } } -void __stdcall glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) +void GL_APIENTRY glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) { EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, " "GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)", @@ -1908,7 +1942,7 @@ void __stdcall glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, } } -void __stdcall glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) +void GL_APIENTRY glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) { EVENT("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)", program, maxcount, count, shaders); @@ -1942,7 +1976,7 @@ void __stdcall glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* c } } -GLint __stdcall glGetAttribLocation(GLuint program, const GLchar* name) +GLint GL_APIENTRY glGetAttribLocation(GLuint program, const GLchar* name) { EVENT("(GLuint program = %d, const GLchar* name = %s)", program, name); @@ -1978,7 +2012,7 @@ GLint __stdcall glGetAttribLocation(GLuint program, const GLchar* name) return -1; } -void __stdcall glGetBooleanv(GLenum pname, GLboolean* params) +void GL_APIENTRY glGetBooleanv(GLenum pname, GLboolean* params) { EVENT("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)", pname, params); @@ -2003,7 +2037,7 @@ void __stdcall glGetBooleanv(GLenum pname, GLboolean* params) } } -void __stdcall glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) +void GL_APIENTRY glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); @@ -2056,7 +2090,7 @@ void __stdcall glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params } } -GLenum __stdcall glGetError(void) +GLenum GL_APIENTRY glGetError(void) { EVENT("()"); @@ -2070,7 +2104,7 @@ GLenum __stdcall glGetError(void) return GL_NO_ERROR; } -void __stdcall glGetFenceivNV(GLuint fence, GLenum pname, GLint *params) +void GL_APIENTRY glGetFenceivNV(GLuint fence, GLenum pname, GLint *params) { EVENT("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params); @@ -2094,19 +2128,40 @@ void __stdcall glGetFenceivNV(GLuint fence, GLenum pname, GLint *params) switch (pname) { case GL_FENCE_STATUS_NV: + { + // GL_NV_fence spec: + // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV + // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence. + GLboolean status = GL_TRUE; + if (fenceObject->getStatus() != GL_TRUE) + { + gl::Error error = fenceObject->testFence(&status); + if (error.isError()) + { + context->recordError(error); + return; + } + } + *params = status; + break; + } + case GL_FENCE_CONDITION_NV: - break; + { + *params = fenceObject->getCondition(); + break; + } default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } } - - params[0] = fenceObject->getFencei(pname); } } -void __stdcall glGetFloatv(GLenum pname, GLfloat* params) +void GL_APIENTRY glGetFloatv(GLenum pname, GLfloat* params) { EVENT("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params); @@ -2131,7 +2186,7 @@ void __stdcall glGetFloatv(GLenum pname, GLfloat* params) } } -void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params) +void GL_APIENTRY glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params) { EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, attachment, pname, params); @@ -2214,6 +2269,7 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id(); gl::Framebuffer *framebuffer = context->getFramebuffer(framebufferHandle); + ASSERT(framebuffer); if (framebufferHandle == 0) { @@ -2428,7 +2484,7 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac } } -GLenum __stdcall glGetGraphicsResetStatusEXT(void) +GLenum GL_APIENTRY glGetGraphicsResetStatusEXT(void) { EVENT("()"); @@ -2442,7 +2498,7 @@ GLenum __stdcall glGetGraphicsResetStatusEXT(void) return GL_NO_ERROR; } -void __stdcall glGetIntegerv(GLenum pname, GLint* params) +void GL_APIENTRY glGetIntegerv(GLenum pname, GLint* params) { EVENT("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params); @@ -2468,7 +2524,7 @@ void __stdcall glGetIntegerv(GLenum pname, GLint* params) } } -void __stdcall glGetProgramiv(GLuint program, GLenum pname, GLint* params) +void GL_APIENTRY glGetProgramiv(GLuint program, GLenum pname, GLint* params) { EVENT("(GLuint program = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", program, pname, params); @@ -2552,7 +2608,7 @@ void __stdcall glGetProgramiv(GLuint program, GLenum pname, GLint* params) } } -void __stdcall glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog) +void GL_APIENTRY glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog) { EVENT("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)", program, bufsize, length, infolog); @@ -2578,7 +2634,7 @@ void __stdcall glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* len } } -void __stdcall glGetQueryivEXT(GLenum target, GLenum pname, GLint *params) +void GL_APIENTRY glGetQueryivEXT(GLenum target, GLenum pname, GLint *params) { EVENT("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname, params); @@ -2604,7 +2660,7 @@ void __stdcall glGetQueryivEXT(GLenum target, GLenum pname, GLint *params) } } -void __stdcall glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params) +void GL_APIENTRY glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params) { EVENT("(GLuint id = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", id, pname, params); @@ -2656,7 +2712,7 @@ void __stdcall glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params) } } -void __stdcall glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) +void GL_APIENTRY glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); @@ -2705,7 +2761,7 @@ void __stdcall glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* } } -void __stdcall glGetShaderiv(GLuint shader, GLenum pname, GLint* params) +void GL_APIENTRY glGetShaderiv(GLuint shader, GLenum pname, GLint* params) { EVENT("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params); @@ -2748,7 +2804,7 @@ void __stdcall glGetShaderiv(GLuint shader, GLenum pname, GLint* params) } } -void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog) +void GL_APIENTRY glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog) { EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)", shader, bufsize, length, infolog); @@ -2774,7 +2830,7 @@ void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* lengt } } -void __stdcall glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) +void GL_APIENTRY glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) { EVENT("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)", shadertype, precisiontype, range, precision); @@ -2821,7 +2877,7 @@ void __stdcall glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontyp } } -void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) +void GL_APIENTRY glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) { EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)", shader, bufsize, length, source); @@ -2847,7 +2903,7 @@ void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length } } -void __stdcall glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) +void GL_APIENTRY glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) { EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)", shader, bufsize, length, source); @@ -2869,11 +2925,12 @@ void __stdcall glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, return; } - shaderObject->getTranslatedSource(bufsize, length, source); + // Only returns extra info if ANGLE_GENERATE_SHADER_DEBUG_INFO is defined + shaderObject->getTranslatedSourceWithDebugInfo(bufsize, length, source); } } -const GLubyte* __stdcall glGetString(GLenum name) +const GLubyte* GL_APIENTRY glGetString(GLenum name) { EVENT("(GLenum name = 0x%X)", name); @@ -2919,7 +2976,7 @@ const GLubyte* __stdcall glGetString(GLenum name) } } -void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) +void GL_APIENTRY glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params); @@ -3051,7 +3108,7 @@ void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) } } -void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params) +void GL_APIENTRY glGetTexParameteriv(GLenum target, GLenum pname, GLint* params) { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); @@ -3098,7 +3155,7 @@ void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params) context->recordError(gl::Error(GL_INVALID_ENUM)); return; } - *params = texture->immutableLevelCount(); + *params = static_cast(texture->immutableLevelCount()); break; case GL_TEXTURE_USAGE_ANGLE: *params = texture->getUsage(); @@ -3183,7 +3240,7 @@ void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params) } } -void __stdcall glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params) +void GL_APIENTRY glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params) { EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)", program, location, bufSize, params); @@ -3205,7 +3262,7 @@ void __stdcall glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSiz } } -void __stdcall glGetUniformfv(GLuint program, GLint location, GLfloat* params) +void GL_APIENTRY glGetUniformfv(GLuint program, GLint location, GLfloat* params) { EVENT("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params); @@ -3226,7 +3283,7 @@ void __stdcall glGetUniformfv(GLuint program, GLint location, GLfloat* params) } } -void __stdcall glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params) +void GL_APIENTRY glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params) { EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)", program, location, bufSize, params); @@ -3248,7 +3305,7 @@ void __stdcall glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSiz } } -void __stdcall glGetUniformiv(GLuint program, GLint location, GLint* params) +void GL_APIENTRY glGetUniformiv(GLuint program, GLint location, GLint* params) { EVENT("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params); @@ -3269,7 +3326,7 @@ void __stdcall glGetUniformiv(GLuint program, GLint location, GLint* params) } } -GLint __stdcall glGetUniformLocation(GLuint program, const GLchar* name) +GLint GL_APIENTRY glGetUniformLocation(GLuint program, const GLchar* name) { EVENT("(GLuint program = %d, const GLchar* name = 0x%0.8p)", program, name); @@ -3310,7 +3367,7 @@ GLint __stdcall glGetUniformLocation(GLuint program, const GLchar* name) return -1; } -void __stdcall glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) +void GL_APIENTRY glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) { EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params); @@ -3344,7 +3401,7 @@ void __stdcall glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) } } -void __stdcall glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) +void GL_APIENTRY glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) { EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params); @@ -3380,7 +3437,7 @@ void __stdcall glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) } } -void __stdcall glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer) +void GL_APIENTRY glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer) { EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer); @@ -3403,7 +3460,7 @@ void __stdcall glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** po } } -void __stdcall glHint(GLenum target, GLenum mode) +void GL_APIENTRY glHint(GLenum target, GLenum mode) { EVENT("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode); @@ -3439,7 +3496,7 @@ void __stdcall glHint(GLenum target, GLenum mode) } } -GLboolean __stdcall glIsBuffer(GLuint buffer) +GLboolean GL_APIENTRY glIsBuffer(GLuint buffer) { EVENT("(GLuint buffer = %d)", buffer); @@ -3457,7 +3514,7 @@ GLboolean __stdcall glIsBuffer(GLuint buffer) return GL_FALSE; } -GLboolean __stdcall glIsEnabled(GLenum cap) +GLboolean GL_APIENTRY glIsEnabled(GLenum cap) { EVENT("(GLenum cap = 0x%X)", cap); @@ -3476,7 +3533,7 @@ GLboolean __stdcall glIsEnabled(GLenum cap) return false; } -GLboolean __stdcall glIsFenceNV(GLuint fence) +GLboolean GL_APIENTRY glIsFenceNV(GLuint fence) { EVENT("(GLuint fence = %d)", fence); @@ -3496,7 +3553,7 @@ GLboolean __stdcall glIsFenceNV(GLuint fence) return GL_FALSE; } -GLboolean __stdcall glIsFramebuffer(GLuint framebuffer) +GLboolean GL_APIENTRY glIsFramebuffer(GLuint framebuffer) { EVENT("(GLuint framebuffer = %d)", framebuffer); @@ -3514,7 +3571,7 @@ GLboolean __stdcall glIsFramebuffer(GLuint framebuffer) return GL_FALSE; } -GLboolean __stdcall glIsProgram(GLuint program) +GLboolean GL_APIENTRY glIsProgram(GLuint program) { EVENT("(GLuint program = %d)", program); @@ -3532,7 +3589,7 @@ GLboolean __stdcall glIsProgram(GLuint program) return GL_FALSE; } -GLboolean __stdcall glIsQueryEXT(GLuint id) +GLboolean GL_APIENTRY glIsQueryEXT(GLuint id) { EVENT("(GLuint id = %d)", id); @@ -3545,7 +3602,7 @@ GLboolean __stdcall glIsQueryEXT(GLuint id) return GL_FALSE; } -GLboolean __stdcall glIsRenderbuffer(GLuint renderbuffer) +GLboolean GL_APIENTRY glIsRenderbuffer(GLuint renderbuffer) { EVENT("(GLuint renderbuffer = %d)", renderbuffer); @@ -3563,7 +3620,7 @@ GLboolean __stdcall glIsRenderbuffer(GLuint renderbuffer) return GL_FALSE; } -GLboolean __stdcall glIsShader(GLuint shader) +GLboolean GL_APIENTRY glIsShader(GLuint shader) { EVENT("(GLuint shader = %d)", shader); @@ -3581,7 +3638,7 @@ GLboolean __stdcall glIsShader(GLuint shader) return GL_FALSE; } -GLboolean __stdcall glIsTexture(GLuint texture) +GLboolean GL_APIENTRY glIsTexture(GLuint texture) { EVENT("(GLuint texture = %d)", texture); @@ -3599,7 +3656,7 @@ GLboolean __stdcall glIsTexture(GLuint texture) return GL_FALSE; } -void __stdcall glLineWidth(GLfloat width) +void GL_APIENTRY glLineWidth(GLfloat width) { EVENT("(GLfloat width = %f)", width); @@ -3616,7 +3673,7 @@ void __stdcall glLineWidth(GLfloat width) } } -void __stdcall glLinkProgram(GLuint program) +void GL_APIENTRY glLinkProgram(GLuint program) { EVENT("(GLuint program = %d)", program); @@ -3639,11 +3696,16 @@ void __stdcall glLinkProgram(GLuint program) } } - context->linkProgram(program); + gl::Error error = context->linkProgram(program); + if (error.isError()) + { + context->recordError(error); + return; + } } } -void __stdcall glPixelStorei(GLenum pname, GLint param) +void GL_APIENTRY glPixelStorei(GLenum pname, GLint param) { EVENT("(GLenum pname = 0x%X, GLint param = %d)", pname, param); @@ -3699,7 +3761,7 @@ void __stdcall glPixelStorei(GLenum pname, GLint param) } } -void __stdcall glPolygonOffset(GLfloat factor, GLfloat units) +void GL_APIENTRY glPolygonOffset(GLfloat factor, GLfloat units) { EVENT("(GLfloat factor = %f, GLfloat units = %f)", factor, units); @@ -3710,7 +3772,7 @@ void __stdcall glPolygonOffset(GLfloat factor, GLfloat units) } } -void __stdcall glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, +void GL_APIENTRY glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid *data) { @@ -3742,7 +3804,7 @@ void __stdcall glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, } } -void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, +void GL_APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) { EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, " @@ -3773,7 +3835,7 @@ void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, } } -void __stdcall glReleaseShaderCompiler(void) +void GL_APIENTRY glReleaseShaderCompiler(void) { EVENT("()"); @@ -3785,7 +3847,7 @@ void __stdcall glReleaseShaderCompiler(void) } } -void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) +void GL_APIENTRY glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) { EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", target, samples, internalformat, width, height); @@ -3799,16 +3861,22 @@ void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samp return; } - context->setRenderbufferStorage(width, height, internalformat, samples); + gl::Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer(); + gl::Error error = renderbuffer->setStorage(width, height, internalformat, samples); + if (error.isError()) + { + context->recordError(error); + return; + } } } -void __stdcall glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +void GL_APIENTRY glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) { glRenderbufferStorageMultisampleANGLE(target, 0, internalformat, width, height); } -void __stdcall glSampleCoverage(GLclampf value, GLboolean invert) +void GL_APIENTRY glSampleCoverage(GLclampf value, GLboolean invert) { EVENT("(GLclampf value = %f, GLboolean invert = %u)", value, invert); @@ -3820,7 +3888,7 @@ void __stdcall glSampleCoverage(GLclampf value, GLboolean invert) } } -void __stdcall glSetFenceNV(GLuint fence, GLenum condition) +void GL_APIENTRY glSetFenceNV(GLuint fence, GLenum condition) { EVENT("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition); @@ -3841,11 +3909,16 @@ void __stdcall glSetFenceNV(GLuint fence, GLenum condition) return; } - fenceObject->setFence(condition); + gl::Error error = fenceObject->setFence(condition); + if (error.isError()) + { + context->recordError(error); + return; + } } } -void __stdcall glScissor(GLint x, GLint y, GLsizei width, GLsizei height) +void GL_APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height) { EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); @@ -3862,7 +3935,7 @@ void __stdcall glScissor(GLint x, GLint y, GLsizei width, GLsizei height) } } -void __stdcall glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length) +void GL_APIENTRY glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length) { EVENT("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, " "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)", @@ -3883,7 +3956,7 @@ void __stdcall glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryfor } } -void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length) +void GL_APIENTRY glShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length) { EVENT("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)", shader, count, string, length); @@ -3917,12 +3990,12 @@ void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar* const* } } -void __stdcall glStencilFunc(GLenum func, GLint ref, GLuint mask) +void GL_APIENTRY glStencilFunc(GLenum func, GLint ref, GLuint mask) { glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask); } -void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) +void GL_APIENTRY glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) { EVENT("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask); @@ -3970,12 +4043,12 @@ void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint } } -void __stdcall glStencilMask(GLuint mask) +void GL_APIENTRY glStencilMask(GLuint mask) { glStencilMaskSeparate(GL_FRONT_AND_BACK, mask); } -void __stdcall glStencilMaskSeparate(GLenum face, GLuint mask) +void GL_APIENTRY glStencilMaskSeparate(GLenum face, GLuint mask) { EVENT("(GLenum face = 0x%X, GLuint mask = %d)", face, mask); @@ -4006,12 +4079,12 @@ void __stdcall glStencilMaskSeparate(GLenum face, GLuint mask) } } -void __stdcall glStencilOp(GLenum fail, GLenum zfail, GLenum zpass) +void GL_APIENTRY glStencilOp(GLenum fail, GLenum zfail, GLenum zpass) { glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass); } -void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +void GL_APIENTRY glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) { EVENT("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)", face, fail, zfail, zpass); @@ -4094,7 +4167,7 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu } } -GLboolean __stdcall glTestFenceNV(GLuint fence) +GLboolean GL_APIENTRY glTestFenceNV(GLuint fence) { EVENT("(GLuint fence = %d)", fence); @@ -4115,13 +4188,21 @@ GLboolean __stdcall glTestFenceNV(GLuint fence) return GL_TRUE; } - return fenceObject->testFence(); + GLboolean result; + gl::Error error = fenceObject->testFence(&result); + if (error.isError()) + { + context->recordError(error); + return GL_TRUE; + } + + return result; } return GL_TRUE; } -void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, +void GL_APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels) { EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, " @@ -4150,51 +4231,38 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL case GL_TEXTURE_2D: { gl::Texture2D *texture = context->getTexture2D(); - texture->setImage(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); + gl::Error error = texture->setImage(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); + if (error.isError()) + { + context->recordError(error); + return; + } } break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->setImagePosX(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); - } - break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->setImageNegX(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); - } - break; case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->setImagePosY(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); - } - break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->setImageNegY(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); - } - break; case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->setImagePosZ(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); - } - break; case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: { gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->setImageNegZ(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); + gl::Error error = texture->setImage(target, level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); + if (error.isError()) + { + context->recordError(error); + return; + } } break; + default: UNREACHABLE(); } } } -void __stdcall glTexParameterf(GLenum target, GLenum pname, GLfloat param) +void GL_APIENTRY glTexParameterf(GLenum target, GLenum pname, GLfloat param) { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %f)", target, pname, param); @@ -4238,12 +4306,12 @@ void __stdcall glTexParameterf(GLenum target, GLenum pname, GLfloat param) } } -void __stdcall glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params) +void GL_APIENTRY glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params) { glTexParameterf(target, pname, (GLfloat)*params); } -void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint param) +void GL_APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param); @@ -4287,12 +4355,12 @@ void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint param) } } -void __stdcall glTexParameteriv(GLenum target, GLenum pname, const GLint* params) +void GL_APIENTRY glTexParameteriv(GLenum target, GLenum pname, const GLint* params) { glTexParameteri(target, pname, *params); } -void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +void GL_APIENTRY glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) { EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", target, levels, internalformat, width, height); @@ -4323,14 +4391,24 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf case GL_TEXTURE_2D: { gl::Texture2D *texture2d = context->getTexture2D(); - texture2d->storage(levels, internalformat, width, height); + gl::Error error = texture2d->storage(levels, internalformat, width, height); + if (error.isError()) + { + context->recordError(error); + return; + } } break; case GL_TEXTURE_CUBE_MAP: { gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); - textureCube->storage(levels, internalformat, width); + gl::Error error = textureCube->storage(levels, internalformat, width); + if (error.isError()) + { + context->recordError(error); + return; + } } break; @@ -4341,7 +4419,7 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf } } -void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, +void GL_APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) { EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " @@ -4377,7 +4455,12 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint case GL_TEXTURE_2D: { gl::Texture2D *texture = context->getTexture2D(); - texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getState().getUnpackState(), pixels); + gl::Error error = texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getState().getUnpackState(), pixels); + if (error.isError()) + { + context->recordError(error); + return; + } } break; @@ -4389,7 +4472,12 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: { gl::TextureCubeMap *texture = context->getTextureCubeMap(); - texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getState().getUnpackState(), pixels); + gl::Error error = texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getState().getUnpackState(), pixels); + if (error.isError()) + { + context->recordError(error); + return; + } } break; @@ -4399,12 +4487,12 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint } } -void __stdcall glUniform1f(GLint location, GLfloat x) +void GL_APIENTRY glUniform1f(GLint location, GLfloat x) { glUniform1fv(location, 1, &x); } -void __stdcall glUniform1fv(GLint location, GLsizei count, const GLfloat* v) +void GL_APIENTRY glUniform1fv(GLint location, GLsizei count, const GLfloat* v) { EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); @@ -4421,12 +4509,12 @@ void __stdcall glUniform1fv(GLint location, GLsizei count, const GLfloat* v) } } -void __stdcall glUniform1i(GLint location, GLint x) +void GL_APIENTRY glUniform1i(GLint location, GLint x) { glUniform1iv(location, 1, &x); } -void __stdcall glUniform1iv(GLint location, GLsizei count, const GLint* v) +void GL_APIENTRY glUniform1iv(GLint location, GLsizei count, const GLint* v) { EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); @@ -4443,14 +4531,14 @@ void __stdcall glUniform1iv(GLint location, GLsizei count, const GLint* v) } } -void __stdcall glUniform2f(GLint location, GLfloat x, GLfloat y) +void GL_APIENTRY glUniform2f(GLint location, GLfloat x, GLfloat y) { GLfloat xy[2] = {x, y}; glUniform2fv(location, 1, xy); } -void __stdcall glUniform2fv(GLint location, GLsizei count, const GLfloat* v) +void GL_APIENTRY glUniform2fv(GLint location, GLsizei count, const GLfloat* v) { EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); @@ -4467,14 +4555,14 @@ void __stdcall glUniform2fv(GLint location, GLsizei count, const GLfloat* v) } } -void __stdcall glUniform2i(GLint location, GLint x, GLint y) +void GL_APIENTRY glUniform2i(GLint location, GLint x, GLint y) { GLint xy[2] = {x, y}; glUniform2iv(location, 1, xy); } -void __stdcall glUniform2iv(GLint location, GLsizei count, const GLint* v) +void GL_APIENTRY glUniform2iv(GLint location, GLsizei count, const GLint* v) { EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); @@ -4491,14 +4579,14 @@ void __stdcall glUniform2iv(GLint location, GLsizei count, const GLint* v) } } -void __stdcall glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) +void GL_APIENTRY glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) { GLfloat xyz[3] = {x, y, z}; glUniform3fv(location, 1, xyz); } -void __stdcall glUniform3fv(GLint location, GLsizei count, const GLfloat* v) +void GL_APIENTRY glUniform3fv(GLint location, GLsizei count, const GLfloat* v) { EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); @@ -4515,14 +4603,14 @@ void __stdcall glUniform3fv(GLint location, GLsizei count, const GLfloat* v) } } -void __stdcall glUniform3i(GLint location, GLint x, GLint y, GLint z) +void GL_APIENTRY glUniform3i(GLint location, GLint x, GLint y, GLint z) { GLint xyz[3] = {x, y, z}; glUniform3iv(location, 1, xyz); } -void __stdcall glUniform3iv(GLint location, GLsizei count, const GLint* v) +void GL_APIENTRY glUniform3iv(GLint location, GLsizei count, const GLint* v) { EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); @@ -4539,14 +4627,14 @@ void __stdcall glUniform3iv(GLint location, GLsizei count, const GLint* v) } } -void __stdcall glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +void GL_APIENTRY glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { GLfloat xyzw[4] = {x, y, z, w}; glUniform4fv(location, 1, xyzw); } -void __stdcall glUniform4fv(GLint location, GLsizei count, const GLfloat* v) +void GL_APIENTRY glUniform4fv(GLint location, GLsizei count, const GLfloat* v) { EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); @@ -4563,14 +4651,14 @@ void __stdcall glUniform4fv(GLint location, GLsizei count, const GLfloat* v) } } -void __stdcall glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) +void GL_APIENTRY glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) { GLint xyzw[4] = {x, y, z, w}; glUniform4iv(location, 1, xyzw); } -void __stdcall glUniform4iv(GLint location, GLsizei count, const GLint* v) +void GL_APIENTRY glUniform4iv(GLint location, GLsizei count, const GLint* v) { EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); @@ -4587,7 +4675,7 @@ void __stdcall glUniform4iv(GLint location, GLsizei count, const GLint* v) } } -void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +void GL_APIENTRY glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", location, count, transpose, value); @@ -4605,7 +4693,7 @@ void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean trans } } -void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +void GL_APIENTRY glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", location, count, transpose, value); @@ -4623,7 +4711,7 @@ void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean trans } } -void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +void GL_APIENTRY glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", location, count, transpose, value); @@ -4641,7 +4729,7 @@ void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean trans } } -void __stdcall glUseProgram(GLuint program) +void GL_APIENTRY glUseProgram(GLuint program) { EVENT("(GLuint program = %d)", program); @@ -4674,7 +4762,7 @@ void __stdcall glUseProgram(GLuint program) } } -void __stdcall glValidateProgram(GLuint program) +void GL_APIENTRY glValidateProgram(GLuint program) { EVENT("(GLuint program = %d)", program); @@ -4701,7 +4789,7 @@ void __stdcall glValidateProgram(GLuint program) } } -void __stdcall glVertexAttrib1f(GLuint index, GLfloat x) +void GL_APIENTRY glVertexAttrib1f(GLuint index, GLfloat x) { EVENT("(GLuint index = %d, GLfloat x = %f)", index, x); @@ -4719,7 +4807,7 @@ void __stdcall glVertexAttrib1f(GLuint index, GLfloat x) } } -void __stdcall glVertexAttrib1fv(GLuint index, const GLfloat* values) +void GL_APIENTRY glVertexAttrib1fv(GLuint index, const GLfloat* values) { EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); @@ -4737,7 +4825,7 @@ void __stdcall glVertexAttrib1fv(GLuint index, const GLfloat* values) } } -void __stdcall glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) +void GL_APIENTRY glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) { EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y); @@ -4755,7 +4843,7 @@ void __stdcall glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) } } -void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values) +void GL_APIENTRY glVertexAttrib2fv(GLuint index, const GLfloat* values) { EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); @@ -4773,7 +4861,7 @@ void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values) } } -void __stdcall glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) +void GL_APIENTRY glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) { EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z); @@ -4791,7 +4879,7 @@ void __stdcall glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) } } -void __stdcall glVertexAttrib3fv(GLuint index, const GLfloat* values) +void GL_APIENTRY glVertexAttrib3fv(GLuint index, const GLfloat* values) { EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); @@ -4809,7 +4897,7 @@ void __stdcall glVertexAttrib3fv(GLuint index, const GLfloat* values) } } -void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +void GL_APIENTRY glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w); @@ -4827,7 +4915,7 @@ void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, G } } -void __stdcall glVertexAttrib4fv(GLuint index, const GLfloat* values) +void GL_APIENTRY glVertexAttrib4fv(GLuint index, const GLfloat* values) { EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); @@ -4844,7 +4932,7 @@ void __stdcall glVertexAttrib4fv(GLuint index, const GLfloat* values) } } -void __stdcall glVertexAttribDivisorANGLE(GLuint index, GLuint divisor) +void GL_APIENTRY glVertexAttribDivisorANGLE(GLuint index, GLuint divisor) { EVENT("(GLuint index = %d, GLuint divisor = %d)", index, divisor); @@ -4861,7 +4949,7 @@ void __stdcall glVertexAttribDivisorANGLE(GLuint index, GLuint divisor) } } -void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) +void GL_APIENTRY glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) { EVENT("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, " "GLboolean normalized = %u, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)", @@ -4936,7 +5024,7 @@ void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLbo } } -void __stdcall glViewport(GLint x, GLint y, GLsizei width, GLsizei height) +void GL_APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height) { EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); @@ -4955,7 +5043,7 @@ void __stdcall glViewport(GLint x, GLint y, GLsizei width, GLsizei height) // OpenGL ES 3.0 functions -void __stdcall glReadBuffer(GLenum mode) +void GL_APIENTRY glReadBuffer(GLenum mode) { EVENT("(GLenum mode = 0x%X)", mode); @@ -4973,7 +5061,7 @@ void __stdcall glReadBuffer(GLenum mode) } } -void __stdcall glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices) +void GL_APIENTRY glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices) { EVENT("(GLenum mode = 0x%X, GLuint start = %u, GLuint end = %u, GLsizei count = %d, GLenum type = 0x%X, " "const GLvoid* indices = 0x%0.8p)", mode, start, end, count, type, indices); @@ -4992,7 +5080,7 @@ void __stdcall glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsize } } -void __stdcall glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels) +void GL_APIENTRY glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels) { EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, " "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLenum format = 0x%X, " @@ -5020,14 +5108,24 @@ void __stdcall glTexImage3D(GLenum target, GLint level, GLint internalformat, GL case GL_TEXTURE_3D: { gl::Texture3D *texture = context->getTexture3D(); - texture->setImage(level, width, height, depth, internalformat, format, type, context->getState().getUnpackState(), pixels); + gl::Error error = texture->setImage(level, width, height, depth, internalformat, format, type, context->getState().getUnpackState(), pixels); + if (error.isError()) + { + context->recordError(error); + return; + } } break; case GL_TEXTURE_2D_ARRAY: { gl::Texture2DArray *texture = context->getTexture2DArray(); - texture->setImage(level, width, height, depth, internalformat, format, type, context->getState().getUnpackState(), pixels); + gl::Error error = texture->setImage(level, width, height, depth, internalformat, format, type, context->getState().getUnpackState(), pixels); + if (error.isError()) + { + context->recordError(error); + return; + } } break; @@ -5038,7 +5136,7 @@ void __stdcall glTexImage3D(GLenum target, GLint level, GLint internalformat, GL } } -void __stdcall glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels) +void GL_APIENTRY glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels) { EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, " @@ -5073,14 +5171,24 @@ void __stdcall glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint case GL_TEXTURE_3D: { gl::Texture3D *texture = context->getTexture3D(); - texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getState().getUnpackState(), pixels); + gl::Error error = texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getState().getUnpackState(), pixels); + if (error.isError()) + { + context->recordError(error); + return; + } } break; case GL_TEXTURE_2D_ARRAY: { gl::Texture2DArray *texture = context->getTexture2DArray(); - texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getState().getUnpackState(), pixels); + gl::Error error = texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getState().getUnpackState(), pixels); + if (error.isError()) + { + context->recordError(error); + return; + } } break; @@ -5091,7 +5199,7 @@ void __stdcall glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint } } -void __stdcall glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) +void GL_APIENTRY glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) { EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", @@ -5129,11 +5237,16 @@ void __stdcall glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GL return; } - texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer); + gl::Error error = texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer); + if (error.isError()) + { + context->recordError(error); + return; + } } } -void __stdcall glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) +void GL_APIENTRY glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) { EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, " @@ -5168,14 +5281,24 @@ void __stdcall glCompressedTexImage3D(GLenum target, GLint level, GLenum interna case GL_TEXTURE_3D: { gl::Texture3D *texture = context->getTexture3D(); - texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data); + gl::Error error = texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, context->getState().getUnpackState(), data); + if (error.isError()) + { + context->recordError(error); + return; + } } break; case GL_TEXTURE_2D_ARRAY: { gl::Texture2DArray *texture = context->getTexture2DArray(); - texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data); + gl::Error error = texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, context->getState().getUnpackState(), data); + if (error.isError()) + { + context->recordError(error); + return; + } } break; @@ -5186,7 +5309,7 @@ void __stdcall glCompressedTexImage3D(GLenum target, GLint level, GLenum interna } } -void __stdcall glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data) +void GL_APIENTRY glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data) { EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, " @@ -5233,16 +5356,26 @@ void __stdcall glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffs case GL_TEXTURE_3D: { gl::Texture3D *texture = context->getTexture3D(); - texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, - format, imageSize, data); + gl::Error error = texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, + format, imageSize, context->getState().getUnpackState(), data); + if (error.isError()) + { + context->recordError(error); + return; + } } break; case GL_TEXTURE_2D_ARRAY: { gl::Texture2DArray *texture = context->getTexture2DArray(); - texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, - format, imageSize, data); + gl::Error error = texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, + format, imageSize, context->getState().getUnpackState(), data); + if (error.isError()) + { + context->recordError(error); + return; + } } break; @@ -5253,7 +5386,7 @@ void __stdcall glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffs } } -void __stdcall glGenQueries(GLsizei n, GLuint* ids) +void GL_APIENTRY glGenQueries(GLsizei n, GLuint* ids) { EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); @@ -5279,7 +5412,7 @@ void __stdcall glGenQueries(GLsizei n, GLuint* ids) } } -void __stdcall glDeleteQueries(GLsizei n, const GLuint* ids) +void GL_APIENTRY glDeleteQueries(GLsizei n, const GLuint* ids) { EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); @@ -5305,7 +5438,7 @@ void __stdcall glDeleteQueries(GLsizei n, const GLuint* ids) } } -GLboolean __stdcall glIsQuery(GLuint id) +GLboolean GL_APIENTRY glIsQuery(GLuint id) { EVENT("(GLuint id = %u)", id); @@ -5324,7 +5457,7 @@ GLboolean __stdcall glIsQuery(GLuint id) return GL_FALSE; } -void __stdcall glBeginQuery(GLenum target, GLuint id) +void GL_APIENTRY glBeginQuery(GLenum target, GLuint id) { EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id); @@ -5351,7 +5484,7 @@ void __stdcall glBeginQuery(GLenum target, GLuint id) } } -void __stdcall glEndQuery(GLenum target) +void GL_APIENTRY glEndQuery(GLenum target) { EVENT("(GLenum target = 0x%X)", target); @@ -5378,7 +5511,7 @@ void __stdcall glEndQuery(GLenum target) } } -void __stdcall glGetQueryiv(GLenum target, GLenum pname, GLint* params) +void GL_APIENTRY glGetQueryiv(GLenum target, GLenum pname, GLint* params) { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); @@ -5410,7 +5543,7 @@ void __stdcall glGetQueryiv(GLenum target, GLenum pname, GLint* params) } } -void __stdcall glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params) +void GL_APIENTRY glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params) { EVENT("(GLuint id = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", id, pname, params); @@ -5468,7 +5601,7 @@ void __stdcall glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params) } } -GLboolean __stdcall glUnmapBuffer(GLenum target) +GLboolean GL_APIENTRY glUnmapBuffer(GLenum target) { EVENT("(GLenum target = 0x%X)", target); @@ -5487,7 +5620,7 @@ GLboolean __stdcall glUnmapBuffer(GLenum target) return GL_FALSE; } -void __stdcall glGetBufferPointerv(GLenum target, GLenum pname, GLvoid** params) +void GL_APIENTRY glGetBufferPointerv(GLenum target, GLenum pname, GLvoid** params) { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params); @@ -5504,7 +5637,7 @@ void __stdcall glGetBufferPointerv(GLenum target, GLenum pname, GLvoid** params) } } -void __stdcall glDrawBuffers(GLsizei n, const GLenum* bufs) +void GL_APIENTRY glDrawBuffers(GLsizei n, const GLenum* bufs) { gl::Context *context = gl::getNonLostContext(); if (context) @@ -5519,7 +5652,7 @@ void __stdcall glDrawBuffers(GLsizei n, const GLenum* bufs) } } -void __stdcall glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +void GL_APIENTRY glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", location, count, transpose, value); @@ -5537,7 +5670,7 @@ void __stdcall glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean tra } } -void __stdcall glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +void GL_APIENTRY glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", location, count, transpose, value); @@ -5555,7 +5688,7 @@ void __stdcall glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean tra } } -void __stdcall glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +void GL_APIENTRY glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", location, count, transpose, value); @@ -5573,7 +5706,7 @@ void __stdcall glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean tra } } -void __stdcall glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +void GL_APIENTRY glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", location, count, transpose, value); @@ -5591,7 +5724,7 @@ void __stdcall glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean tra } } -void __stdcall glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +void GL_APIENTRY glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", location, count, transpose, value); @@ -5609,7 +5742,7 @@ void __stdcall glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean tra } } -void __stdcall glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +void GL_APIENTRY glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", location, count, transpose, value); @@ -5627,7 +5760,7 @@ void __stdcall glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean tra } } -void __stdcall glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) +void GL_APIENTRY glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, GLint dstX0 = %d, " "GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, GLbitfield mask = 0x%X, GLenum filter = 0x%X)", @@ -5649,12 +5782,17 @@ void __stdcall glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint sr return; } - context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, - mask, filter); + gl::Error error = context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, + mask, filter); + if (error.isError()) + { + context->recordError(error); + return; + } } } -void __stdcall glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) +void GL_APIENTRY glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) { EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", target, samples, internalformat, width, height); @@ -5674,11 +5812,12 @@ void __stdcall glRenderbufferStorageMultisample(GLenum target, GLsizei samples, return; } - context->setRenderbufferStorage(width, height, internalformat, samples); + gl::Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer(); + renderbuffer->setStorage(width, height, internalformat, samples); } } -void __stdcall glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) +void GL_APIENTRY glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) { EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, GLint layer = %d)", target, attachment, texture, level, layer); @@ -5695,27 +5834,20 @@ void __stdcall glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuin gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); ASSERT(framebuffer); - gl::Texture *textureObject = context->getTexture(texture); - GLenum textarget = textureObject ? textureObject->getTarget() : GL_NONE; - - if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + if (texture != 0) { - const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); - framebuffer->setColorbuffer(colorAttachment, textarget, texture, level, layer); + gl::Texture *textureObject = context->getTexture(texture); + gl::ImageIndex index(textureObject->getTarget(), level, layer); + framebuffer->setTextureAttachment(attachment, textureObject, index); } else { - switch (attachment) - { - case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level, layer); break; - case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level, layer); break; - case GL_DEPTH_STENCIL_ATTACHMENT: framebuffer->setDepthStencilBuffer(textarget, texture, level, layer); break; - } + framebuffer->setNULLAttachment(attachment); } } } -GLvoid* __stdcall glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) +GLvoid* GL_APIENTRY glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) { EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)", target, offset, length, access); @@ -5735,7 +5867,7 @@ GLvoid* __stdcall glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr le return NULL; } -void __stdcall glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) +void GL_APIENTRY glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) { EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length); @@ -5752,7 +5884,7 @@ void __stdcall glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeip } } -void __stdcall glBindVertexArray(GLuint array) +void GL_APIENTRY glBindVertexArray(GLuint array) { EVENT("(GLuint array = %u)", array); @@ -5779,7 +5911,7 @@ void __stdcall glBindVertexArray(GLuint array) } } -void __stdcall glDeleteVertexArrays(GLsizei n, const GLuint* arrays) +void GL_APIENTRY glDeleteVertexArrays(GLsizei n, const GLuint* arrays) { EVENT("(GLsizei n = %d, const GLuint* arrays = 0x%0.8p)", n, arrays); @@ -5808,7 +5940,7 @@ void __stdcall glDeleteVertexArrays(GLsizei n, const GLuint* arrays) } } -void __stdcall glGenVertexArrays(GLsizei n, GLuint* arrays) +void GL_APIENTRY glGenVertexArrays(GLsizei n, GLuint* arrays) { EVENT("(GLsizei n = %d, GLuint* arrays = 0x%0.8p)", n, arrays); @@ -5834,7 +5966,7 @@ void __stdcall glGenVertexArrays(GLsizei n, GLuint* arrays) } } -GLboolean __stdcall glIsVertexArray(GLuint array) +GLboolean GL_APIENTRY glIsVertexArray(GLuint array) { EVENT("(GLuint array = %u)", array); @@ -5860,7 +5992,7 @@ GLboolean __stdcall glIsVertexArray(GLuint array) return GL_FALSE; } -void __stdcall glGetIntegeri_v(GLenum target, GLuint index, GLint* data) +void GL_APIENTRY glGetIntegeri_v(GLenum target, GLuint index, GLint* data) { EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint* data = 0x%0.8p)", target, index, data); @@ -5941,7 +6073,7 @@ void __stdcall glGetIntegeri_v(GLenum target, GLuint index, GLint* data) } } -void __stdcall glBeginTransformFeedback(GLenum primitiveMode) +void GL_APIENTRY glBeginTransformFeedback(GLenum primitiveMode) { EVENT("(GLenum primitiveMode = 0x%X)", primitiveMode); @@ -5986,7 +6118,7 @@ void __stdcall glBeginTransformFeedback(GLenum primitiveMode) } } -void __stdcall glEndTransformFeedback(void) +void GL_APIENTRY glEndTransformFeedback(void) { EVENT("(void)"); @@ -6012,7 +6144,7 @@ void __stdcall glEndTransformFeedback(void) } } -void __stdcall glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) +void GL_APIENTRY glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) { EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u, GLintptr offset = %d, GLsizeiptr size = %d)", target, index, buffer, offset, size); @@ -6090,7 +6222,7 @@ void __stdcall glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLi } } -void __stdcall glBindBufferBase(GLenum target, GLuint index, GLuint buffer) +void GL_APIENTRY glBindBufferBase(GLenum target, GLuint index, GLuint buffer) { EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u)", target, index, buffer); @@ -6146,7 +6278,7 @@ void __stdcall glBindBufferBase(GLenum target, GLuint index, GLuint buffer) } } -void __stdcall glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode) +void GL_APIENTRY glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode) { EVENT("(GLuint program = %u, GLsizei count = %d, const GLchar* const* varyings = 0x%0.8p, GLenum bufferMode = 0x%X)", program, count, varyings, bufferMode); @@ -6195,7 +6327,7 @@ void __stdcall glTransformFeedbackVaryings(GLuint program, GLsizei count, const } } -void __stdcall glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name) +void GL_APIENTRY glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name) { EVENT("(GLuint program = %u, GLuint index = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, " "GLsizei* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)", @@ -6234,7 +6366,7 @@ void __stdcall glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsiz } } -void __stdcall glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) +void GL_APIENTRY glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) { EVENT("(GLuint index = %u, GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid* pointer = 0x%0.8p)", index, size, type, stride, pointer); @@ -6304,7 +6436,7 @@ void __stdcall glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLs } } -void __stdcall glGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params) +void GL_APIENTRY glGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params) { EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params); @@ -6346,7 +6478,7 @@ void __stdcall glGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params) } } -void __stdcall glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params) +void GL_APIENTRY glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params) { EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLuint* params = 0x%0.8p)", index, pname, params); @@ -6388,7 +6520,7 @@ void __stdcall glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params) } } -void __stdcall glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w) +void GL_APIENTRY glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w) { EVENT("(GLuint index = %u, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)", index, x, y, z, w); @@ -6413,7 +6545,7 @@ void __stdcall glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint } } -void __stdcall glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) +void GL_APIENTRY glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) { EVENT("(GLuint index = %u, GLuint x = %u, GLuint y = %u, GLuint z = %u, GLuint w = %u)", index, x, y, z, w); @@ -6438,7 +6570,7 @@ void __stdcall glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GL } } -void __stdcall glVertexAttribI4iv(GLuint index, const GLint* v) +void GL_APIENTRY glVertexAttribI4iv(GLuint index, const GLint* v) { EVENT("(GLuint index = %u, const GLint* v = 0x%0.8p)", index, v); @@ -6461,7 +6593,7 @@ void __stdcall glVertexAttribI4iv(GLuint index, const GLint* v) } } -void __stdcall glVertexAttribI4uiv(GLuint index, const GLuint* v) +void GL_APIENTRY glVertexAttribI4uiv(GLuint index, const GLuint* v) { EVENT("(GLuint index = %u, const GLuint* v = 0x%0.8p)", index, v); @@ -6484,7 +6616,7 @@ void __stdcall glVertexAttribI4uiv(GLuint index, const GLuint* v) } } -void __stdcall glGetUniformuiv(GLuint program, GLint location, GLuint* params) +void GL_APIENTRY glGetUniformuiv(GLuint program, GLint location, GLuint* params) { EVENT("(GLuint program = %u, GLint location = %d, GLuint* params = 0x%0.8p)", program, location, params); @@ -6506,7 +6638,7 @@ void __stdcall glGetUniformuiv(GLuint program, GLint location, GLuint* params) } } -GLint __stdcall glGetFragDataLocation(GLuint program, const GLchar *name) +GLint GL_APIENTRY glGetFragDataLocation(GLuint program, const GLchar *name) { EVENT("(GLuint program = %u, const GLchar *name = 0x%0.8p)", program, name); @@ -6547,30 +6679,30 @@ GLint __stdcall glGetFragDataLocation(GLuint program, const GLchar *name) return 0; } -void __stdcall glUniform1ui(GLint location, GLuint v0) +void GL_APIENTRY glUniform1ui(GLint location, GLuint v0) { glUniform1uiv(location, 1, &v0); } -void __stdcall glUniform2ui(GLint location, GLuint v0, GLuint v1) +void GL_APIENTRY glUniform2ui(GLint location, GLuint v0, GLuint v1) { const GLuint xy[] = { v0, v1 }; glUniform2uiv(location, 1, xy); } -void __stdcall glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) +void GL_APIENTRY glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) { const GLuint xyz[] = { v0, v1, v2 }; glUniform3uiv(location, 1, xyz); } -void __stdcall glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) +void GL_APIENTRY glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) { const GLuint xyzw[] = { v0, v1, v2, v3 }; glUniform4uiv(location, 1, xyzw); } -void __stdcall glUniform1uiv(GLint location, GLsizei count, const GLuint* value) +void GL_APIENTRY glUniform1uiv(GLint location, GLsizei count, const GLuint* value) { EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", location, count, value); @@ -6588,7 +6720,7 @@ void __stdcall glUniform1uiv(GLint location, GLsizei count, const GLuint* value) } } -void __stdcall glUniform2uiv(GLint location, GLsizei count, const GLuint* value) +void GL_APIENTRY glUniform2uiv(GLint location, GLsizei count, const GLuint* value) { EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", location, count, value); @@ -6606,7 +6738,7 @@ void __stdcall glUniform2uiv(GLint location, GLsizei count, const GLuint* value) } } -void __stdcall glUniform3uiv(GLint location, GLsizei count, const GLuint* value) +void GL_APIENTRY glUniform3uiv(GLint location, GLsizei count, const GLuint* value) { EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value)", location, count, value); @@ -6624,7 +6756,7 @@ void __stdcall glUniform3uiv(GLint location, GLsizei count, const GLuint* value) } } -void __stdcall glUniform4uiv(GLint location, GLsizei count, const GLuint* value) +void GL_APIENTRY glUniform4uiv(GLint location, GLsizei count, const GLuint* value) { EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", location, count, value); @@ -6642,7 +6774,7 @@ void __stdcall glUniform4uiv(GLint location, GLsizei count, const GLuint* value) } } -void __stdcall glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) +void GL_APIENTRY glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) { EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint* value = 0x%0.8p)", buffer, drawbuffer, value); @@ -6687,7 +6819,7 @@ void __stdcall glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* val } } -void __stdcall glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value) +void GL_APIENTRY glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value) { EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint* value = 0x%0.8p)", buffer, drawbuffer, value); @@ -6724,7 +6856,7 @@ void __stdcall glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* v } } -void __stdcall glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) +void GL_APIENTRY glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) { EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat* value = 0x%0.8p)", buffer, drawbuffer, value); @@ -6769,7 +6901,7 @@ void __stdcall glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* v } } -void __stdcall glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) +void GL_APIENTRY glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) { EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth, GLint stencil = %d)", buffer, drawbuffer, depth, stencil); @@ -6806,7 +6938,7 @@ void __stdcall glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, G } } -const GLubyte* __stdcall glGetStringi(GLenum name, GLuint index) +const GLubyte* GL_APIENTRY glGetStringi(GLenum name, GLuint index) { EVENT("(GLenum name = 0x%X, GLuint index = %u)", name, index); @@ -6837,7 +6969,7 @@ const GLubyte* __stdcall glGetStringi(GLenum name, GLuint index) return NULL; } -void __stdcall glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) +void GL_APIENTRY glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) { EVENT("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)", readTarget, writeTarget, readOffset, writeOffset, size); @@ -6851,7 +6983,7 @@ void __stdcall glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintp return; } - if (!gl::ValidBufferTarget(context, readTarget) || !gl::ValidBufferTarget(context, readTarget)) + if (!gl::ValidBufferTarget(context, readTarget) || !gl::ValidBufferTarget(context, writeTarget)) { context->recordError(gl::Error(GL_INVALID_ENUM)); return; @@ -6881,7 +7013,7 @@ void __stdcall glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintp return; } - if (readBuffer == writeBuffer && abs(readOffset - writeOffset) < size) + if (readBuffer == writeBuffer && std::abs(readOffset - writeOffset) < size) { context->recordError(gl::Error(GL_INVALID_VALUE)); return; @@ -6900,7 +7032,7 @@ void __stdcall glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintp } } -void __stdcall glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices) +void GL_APIENTRY glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices) { EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLchar* const* uniformNames = 0x%0.8p, GLuint* uniformIndices = 0x%0.8p)", program, uniformCount, uniformNames, uniformIndices); @@ -6954,7 +7086,7 @@ void __stdcall glGetUniformIndices(GLuint program, GLsizei uniformCount, const G } } -void __stdcall glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params) +void GL_APIENTRY glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params) { EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLuint* uniformIndices = 0x%0.8p, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", program, uniformCount, uniformIndices, pname, params); @@ -7034,7 +7166,7 @@ void __stdcall glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const } } -GLuint __stdcall glGetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName) +GLuint GL_APIENTRY glGetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName) { EVENT("(GLuint program = %u, const GLchar* uniformBlockName = 0x%0.8p)", program, uniformBlockName); @@ -7075,7 +7207,7 @@ GLuint __stdcall glGetUniformBlockIndex(GLuint program, const GLchar* uniformBlo return 0; } -void __stdcall glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) +void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) { EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", program, uniformBlockIndex, pname, params); @@ -7134,7 +7266,7 @@ void __stdcall glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockInde } } -void __stdcall glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName) +void GL_APIENTRY glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName) { EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLchar* uniformBlockName = 0x%0.8p)", program, uniformBlockIndex, bufSize, length, uniformBlockName); @@ -7176,7 +7308,7 @@ void __stdcall glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIn } } -void __stdcall glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) +void GL_APIENTRY glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) { EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLuint uniformBlockBinding = %u)", program, uniformBlockIndex, uniformBlockBinding); @@ -7225,7 +7357,7 @@ void __stdcall glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, G } } -void __stdcall glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount) +void GL_APIENTRY glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount) { EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)", mode, first, count, instanceCount); @@ -7244,7 +7376,7 @@ void __stdcall glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GL } } -void __stdcall glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount) +void GL_APIENTRY glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount) { EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei instanceCount = %d)", mode, count, type, indices, instanceCount); @@ -7263,7 +7395,7 @@ void __stdcall glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, } } -GLsync __stdcall glFenceSync(GLenum condition, GLbitfield flags) +GLsync GL_APIENTRY glFenceSync(GLenum condition, GLbitfield flags) { EVENT("(GLenum condition = 0x%X, GLbitfield flags = 0x%X)", condition, flags); @@ -7288,13 +7420,24 @@ GLsync __stdcall glFenceSync(GLenum condition, GLbitfield flags) return 0; } - return context->createFenceSync(condition); + GLsync fenceSync = context->createFenceSync(); + + gl::FenceSync *fenceSyncObject = context->getFenceSync(fenceSync); + gl::Error error = fenceSyncObject->set(condition); + if (error.isError()) + { + context->deleteFenceSync(fenceSync); + context->recordError(error); + return NULL; + } + + return fenceSync; } return NULL; } -GLboolean __stdcall glIsSync(GLsync sync) +GLboolean GL_APIENTRY glIsSync(GLsync sync) { EVENT("(GLsync sync = 0x%0.8p)", sync); @@ -7313,7 +7456,7 @@ GLboolean __stdcall glIsSync(GLsync sync) return GL_FALSE; } -void __stdcall glDeleteSync(GLsync sync) +void GL_APIENTRY glDeleteSync(GLsync sync) { EVENT("(GLsync sync = 0x%0.8p)", sync); @@ -7336,7 +7479,7 @@ void __stdcall glDeleteSync(GLsync sync) } } -GLenum __stdcall glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) +GLenum GL_APIENTRY glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) { EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)", sync, flags, timeout); @@ -7364,13 +7507,21 @@ GLenum __stdcall glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeou return GL_WAIT_FAILED; } - return fenceSync->clientWait(flags, timeout); + GLenum result = GL_WAIT_FAILED; + gl::Error error = fenceSync->clientWait(flags, timeout, &result); + if (error.isError()) + { + context->recordError(error); + return GL_WAIT_FAILED; + } + + return result; } return GL_FALSE; } -void __stdcall glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) +void GL_APIENTRY glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) { EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)", sync, flags, timeout); @@ -7404,11 +7555,15 @@ void __stdcall glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) return; } - fenceSync->serverWait(); + gl::Error error = fenceSync->serverWait(flags, timeout); + if (error.isError()) + { + context->recordError(error); + } } } -void __stdcall glGetInteger64v(GLenum pname, GLint64* params) +void GL_APIENTRY glGetInteger64v(GLenum pname, GLint64* params) { EVENT("(GLenum pname = 0x%X, GLint64* params = 0x%0.8p)", pname, params); @@ -7440,7 +7595,7 @@ void __stdcall glGetInteger64v(GLenum pname, GLint64* params) } } -void __stdcall glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values) +void GL_APIENTRY glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values) { EVENT("(GLsync sync = 0x%0.8p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLint* values = 0x%0.8p)", sync, pname, bufSize, length, values); @@ -7471,10 +7626,20 @@ void __stdcall glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* switch (pname) { case GL_OBJECT_TYPE: values[0] = static_cast(GL_SYNC_FENCE); break; - case GL_SYNC_STATUS: values[0] = static_cast(fenceSync->getStatus()); break; case GL_SYNC_CONDITION: values[0] = static_cast(fenceSync->getCondition()); break; case GL_SYNC_FLAGS: values[0] = 0; break; + case GL_SYNC_STATUS: + { + gl::Error error = fenceSync->getStatus(values); + if (error.isError()) + { + context->recordError(error); + return; + } + break; + } + default: context->recordError(gl::Error(GL_INVALID_ENUM)); return; @@ -7482,7 +7647,7 @@ void __stdcall glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* } } -void __stdcall glGetInteger64i_v(GLenum target, GLuint index, GLint64* data) +void GL_APIENTRY glGetInteger64i_v(GLenum target, GLuint index, GLint64* data) { EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint64* data = 0x%0.8p)", target, index, data); @@ -7558,7 +7723,7 @@ void __stdcall glGetInteger64i_v(GLenum target, GLuint index, GLint64* data) } } -void __stdcall glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params) +void GL_APIENTRY glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params) { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64* params = 0x%0.8p)", target, pname, params); @@ -7618,7 +7783,7 @@ void __stdcall glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64* pa } } -void __stdcall glGenSamplers(GLsizei count, GLuint* samplers) +void GL_APIENTRY glGenSamplers(GLsizei count, GLuint* samplers) { EVENT("(GLsizei count = %d, GLuint* samplers = 0x%0.8p)", count, samplers); @@ -7644,7 +7809,7 @@ void __stdcall glGenSamplers(GLsizei count, GLuint* samplers) } } -void __stdcall glDeleteSamplers(GLsizei count, const GLuint* samplers) +void GL_APIENTRY glDeleteSamplers(GLsizei count, const GLuint* samplers) { EVENT("(GLsizei count = %d, const GLuint* samplers = 0x%0.8p)", count, samplers); @@ -7670,7 +7835,7 @@ void __stdcall glDeleteSamplers(GLsizei count, const GLuint* samplers) } } -GLboolean __stdcall glIsSampler(GLuint sampler) +GLboolean GL_APIENTRY glIsSampler(GLuint sampler) { EVENT("(GLuint sampler = %u)", sampler); @@ -7689,7 +7854,7 @@ GLboolean __stdcall glIsSampler(GLuint sampler) return GL_FALSE; } -void __stdcall glBindSampler(GLuint unit, GLuint sampler) +void GL_APIENTRY glBindSampler(GLuint unit, GLuint sampler) { EVENT("(GLuint unit = %u, GLuint sampler = %u)", unit, sampler); @@ -7718,7 +7883,7 @@ void __stdcall glBindSampler(GLuint unit, GLuint sampler) } } -void __stdcall glSamplerParameteri(GLuint sampler, GLenum pname, GLint param) +void GL_APIENTRY glSamplerParameteri(GLuint sampler, GLenum pname, GLint param) { EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint param = %d)", sampler, pname, param); @@ -7751,12 +7916,12 @@ void __stdcall glSamplerParameteri(GLuint sampler, GLenum pname, GLint param) } } -void __stdcall glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param) +void GL_APIENTRY glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param) { glSamplerParameteri(sampler, pname, *param); } -void __stdcall glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) +void GL_APIENTRY glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) { EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLfloat param = %g)", sampler, pname, param); @@ -7789,12 +7954,12 @@ void __stdcall glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) } } -void __stdcall glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param) +void GL_APIENTRY glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param) { glSamplerParameterf(sampler, pname, *param); } -void __stdcall glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params) +void GL_APIENTRY glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params) { EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", sampler, pname, params); @@ -7822,7 +7987,7 @@ void __stdcall glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* para } } -void __stdcall glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params) +void GL_APIENTRY glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params) { EVENT("(GLuint sample = %ur, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", sampler, pname, params); @@ -7850,7 +8015,7 @@ void __stdcall glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* pa } } -void __stdcall glVertexAttribDivisor(GLuint index, GLuint divisor) +void GL_APIENTRY glVertexAttribDivisor(GLuint index, GLuint divisor) { EVENT("(GLuint index = %u, GLuint divisor = %u)", index, divisor); @@ -7873,7 +8038,7 @@ void __stdcall glVertexAttribDivisor(GLuint index, GLuint divisor) } } -void __stdcall glBindTransformFeedback(GLenum target, GLuint id) +void GL_APIENTRY glBindTransformFeedback(GLenum target, GLuint id) { EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id); @@ -7916,7 +8081,7 @@ void __stdcall glBindTransformFeedback(GLenum target, GLuint id) } } -void __stdcall glDeleteTransformFeedbacks(GLsizei n, const GLuint* ids) +void GL_APIENTRY glDeleteTransformFeedbacks(GLsizei n, const GLuint* ids) { EVENT("(GLsizei n = %d, const GLuint* ids = 0x%0.8p)", n, ids); @@ -7936,7 +8101,7 @@ void __stdcall glDeleteTransformFeedbacks(GLsizei n, const GLuint* ids) } } -void __stdcall glGenTransformFeedbacks(GLsizei n, GLuint* ids) +void GL_APIENTRY glGenTransformFeedbacks(GLsizei n, GLuint* ids) { EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); @@ -7956,7 +8121,7 @@ void __stdcall glGenTransformFeedbacks(GLsizei n, GLuint* ids) } } -GLboolean __stdcall glIsTransformFeedback(GLuint id) +GLboolean GL_APIENTRY glIsTransformFeedback(GLuint id) { EVENT("(GLuint id = %u)", id); @@ -7975,7 +8140,7 @@ GLboolean __stdcall glIsTransformFeedback(GLuint id) return GL_FALSE; } -void __stdcall glPauseTransformFeedback(void) +void GL_APIENTRY glPauseTransformFeedback(void) { EVENT("(void)"); @@ -8002,7 +8167,7 @@ void __stdcall glPauseTransformFeedback(void) } } -void __stdcall glResumeTransformFeedback(void) +void GL_APIENTRY glResumeTransformFeedback(void) { EVENT("(void)"); @@ -8029,7 +8194,7 @@ void __stdcall glResumeTransformFeedback(void) } } -void __stdcall glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary) +void GL_APIENTRY glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary) { EVENT("(GLuint program = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLenum* binaryFormat = 0x%0.8p, GLvoid* binary = 0x%0.8p)", program, bufSize, length, binaryFormat, binary); @@ -8048,7 +8213,7 @@ void __stdcall glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* leng } } -void __stdcall glProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length) +void GL_APIENTRY glProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length) { EVENT("(GLuint program = %u, GLenum binaryFormat = 0x%X, const GLvoid* binary = 0x%0.8p, GLsizei length = %d)", program, binaryFormat, binary, length); @@ -8067,7 +8232,7 @@ void __stdcall glProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid } } -void __stdcall glProgramParameteri(GLuint program, GLenum pname, GLint value) +void GL_APIENTRY glProgramParameteri(GLuint program, GLenum pname, GLint value) { EVENT("(GLuint program = %u, GLenum pname = 0x%X, GLint value = %d)", program, pname, value); @@ -8086,7 +8251,7 @@ void __stdcall glProgramParameteri(GLuint program, GLenum pname, GLint value) } } -void __stdcall glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments) +void GL_APIENTRY glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments) { EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p)", target, numAttachments, attachments); @@ -8106,14 +8271,21 @@ void __stdcall glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, co } gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); - if (framebuffer && framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE) + ASSERT(framebuffer); + + if (framebuffer->completeness(context->getData()) == GL_FRAMEBUFFER_COMPLETE) { - framebuffer->invalidate(context->getCaps(), numAttachments, attachments); + gl::Error error = framebuffer->invalidate(context->getCaps(), numAttachments, attachments); + if (error.isError()) + { + context->recordError(error); + return; + } } } } -void __stdcall glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height) +void GL_APIENTRY glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height) { EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p, GLint x = %d, " "GLint y = %d, GLsizei width = %d, GLsizei height = %d)", @@ -8134,14 +8306,21 @@ void __stdcall glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, } gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); - if (framebuffer && framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE) + ASSERT(framebuffer); + + if (framebuffer->completeness(context->getData()) == GL_FRAMEBUFFER_COMPLETE) { - framebuffer->invalidateSub(context->getCaps(), numAttachments, attachments, x, y, width, height); + gl::Error error = framebuffer->invalidateSub(numAttachments, attachments, x, y, width, height); + if (error.isError()) + { + context->recordError(error); + return; + } } } } -void __stdcall glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +void GL_APIENTRY glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) { EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", target, levels, internalformat, width, height); @@ -8165,14 +8344,24 @@ void __stdcall glTexStorage2D(GLenum target, GLsizei levels, GLenum internalform case GL_TEXTURE_2D: { gl::Texture2D *texture2d = context->getTexture2D(); - texture2d->storage(levels, internalformat, width, height); + gl::Error error = texture2d->storage(levels, internalformat, width, height); + if (error.isError()) + { + context->recordError(error); + return; + } } break; case GL_TEXTURE_CUBE_MAP: { gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); - textureCube->storage(levels, internalformat, width); + gl::Error error = textureCube->storage(levels, internalformat, width); + if (error.isError()) + { + context->recordError(error); + return; + } } break; @@ -8183,7 +8372,7 @@ void __stdcall glTexStorage2D(GLenum target, GLsizei levels, GLenum internalform } } -void __stdcall glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +void GL_APIENTRY glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " "GLsizei height = %d, GLsizei depth = %d)", @@ -8208,14 +8397,24 @@ void __stdcall glTexStorage3D(GLenum target, GLsizei levels, GLenum internalform case GL_TEXTURE_3D: { gl::Texture3D *texture3d = context->getTexture3D(); - texture3d->storage(levels, internalformat, width, height, depth); + gl::Error error = texture3d->storage(levels, internalformat, width, height, depth); + if (error.isError()) + { + context->recordError(error); + return; + } } break; case GL_TEXTURE_2D_ARRAY: { gl::Texture2DArray *texture2darray = context->getTexture2DArray(); - texture2darray->storage(levels, internalformat, width, height, depth); + gl::Error error = texture2darray->storage(levels, internalformat, width, height, depth); + if (error.isError()) + { + context->recordError(error); + return; + } } break; @@ -8225,7 +8424,7 @@ void __stdcall glTexStorage3D(GLenum target, GLsizei levels, GLenum internalform } } -void __stdcall glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params) +void GL_APIENTRY glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params) { EVENT("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, " "GLint* params = 0x%0.8p)", @@ -8281,7 +8480,7 @@ void __stdcall glGetInternalformativ(GLenum target, GLenum internalformat, GLenu // Extension functions -void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, +void GL_APIENTRY glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, " @@ -8299,12 +8498,17 @@ void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLi return; } - context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, - mask, filter); + gl::Error error = context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, + mask, filter); + if (error.isError()) + { + context->recordError(error); + return; + } } } -void __stdcall glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, +void GL_APIENTRY glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels) { EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, " @@ -8315,7 +8519,7 @@ void __stdcall glTexImage3DOES(GLenum target, GLint level, GLenum internalformat UNIMPLEMENTED(); // FIXME } -void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, +void GL_APIENTRY glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary) { EVENT("(GLenum program = 0x%X, bufSize = %d, length = 0x%0.8p, binaryFormat = 0x%0.8p, binary = 0x%0.8p)", @@ -8340,15 +8544,16 @@ void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *l return; } - if (!programBinary->save(binaryFormat, binary, bufSize, length)) + gl::Error error = programBinary->save(binaryFormat, binary, bufSize, length); + if (error.isError()) { - context->recordError(gl::Error(GL_INVALID_OPERATION)); + context->recordError(error); return; } } } -void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat, +void GL_APIENTRY glProgramBinaryOES(GLuint program, GLenum binaryFormat, const void *binary, GLint length) { EVENT("(GLenum program = 0x%X, binaryFormat = 0x%x, binary = 0x%0.8p, length = %d)", @@ -8371,11 +8576,16 @@ void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat, return; } - context->setProgramBinary(program, binaryFormat, binary, length); + gl::Error error = context->setProgramBinary(program, binaryFormat, binary, length); + if (error.isError()) + { + context->recordError(error); + return; + } } } -void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs) +void GL_APIENTRY glDrawBuffersEXT(GLsizei n, const GLenum *bufs) { EVENT("(GLenum n = %d, bufs = 0x%0.8p)", n, bufs); @@ -8388,6 +8598,8 @@ void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs) return; } + ASSERT(context->getState().getDrawFramebuffer()); + if (context->getState().getDrawFramebuffer()->id() == 0) { if (n != 1) @@ -8416,6 +8628,7 @@ void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs) } gl::Framebuffer *framebuffer = context->getState().getDrawFramebuffer(); + ASSERT(framebuffer); for (unsigned int colorAttachment = 0; colorAttachment < static_cast(n); colorAttachment++) { @@ -8429,7 +8642,7 @@ void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs) } } -void __stdcall glGetBufferPointervOES(GLenum target, GLenum pname, void** params) +void GL_APIENTRY glGetBufferPointervOES(GLenum target, GLenum pname, void** params) { EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params); @@ -8461,7 +8674,7 @@ void __stdcall glGetBufferPointervOES(GLenum target, GLenum pname, void** params } } -void * __stdcall glMapBufferOES(GLenum target, GLenum access) +void * GL_APIENTRY glMapBufferOES(GLenum target, GLenum access) { EVENT("(GLenum target = 0x%X, GLbitfield access = 0x%X)", target, access); @@ -8507,7 +8720,7 @@ void * __stdcall glMapBufferOES(GLenum target, GLenum access) return NULL; } -GLboolean __stdcall glUnmapBufferOES(GLenum target) +GLboolean GL_APIENTRY glUnmapBufferOES(GLenum target) { EVENT("(GLenum target = 0x%X)", target); @@ -8543,7 +8756,7 @@ GLboolean __stdcall glUnmapBufferOES(GLenum target) return GL_FALSE; } -void* __stdcall glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) +void* GL_APIENTRY glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) { EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)", target, offset, length, access); @@ -8638,7 +8851,7 @@ void* __stdcall glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr return NULL; } -void __stdcall glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length) +void GL_APIENTRY glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length) { EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length); @@ -8686,7 +8899,7 @@ void __stdcall glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsi } } -__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname) +__eglMustCastToProperFunctionPointerType EGLAPIENTRY glGetProcAddress(const char *procname) { struct Extension { @@ -8744,7 +8957,7 @@ __eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char * // Non-public functions used by EGL -bool __stdcall glBindTexImage(egl::Surface *surface) +bool EGLAPIENTRY glBindTexImage(egl::Surface *surface) { EVENT("(egl::Surface* surface = 0x%0.8p)", surface); diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp index 51447e273af..00f63ae079c 100644 --- a/src/3rdparty/angle/src/libGLESv2/main.cpp +++ b/src/3rdparty/angle/src/libGLESv2/main.cpp @@ -11,24 +11,42 @@ #include "common/tls.h" -#if defined(ANGLE_PLATFORM_WINRT) -__declspec(thread) -#endif -static TLSIndex currentTLS = TLS_OUT_OF_INDEXES; +static TLSIndex currentTLS = TLS_INVALID_INDEX; namespace gl { +// TODO(kbr): figure out how these are going to be managed on +// non-Windows platforms. These routines would need to be exported +// from ANGLE and called cooperatively when users create and destroy +// threads -- or the initialization of the TLS index, and allocation +// of thread-local data, will have to be done lazily. Will have to use +// destructor function with pthread_create_key on POSIX platforms to +// clean up thread-local data. + +// Call this exactly once at process startup. +bool CreateThreadLocalIndex() +{ + currentTLS = CreateTLSIndex(); + if (currentTLS == TLS_INVALID_INDEX) + { + return false; + } + return true; +} + +// Call this exactly once at process shutdown. +void DestroyThreadLocalIndex() +{ + DestroyTLSIndex(currentTLS); + currentTLS = TLS_INVALID_INDEX; +} + +// Call this upon thread startup. Current *AllocateCurrent() { -#if defined(ANGLE_PLATFORM_WINRT) - if (currentTLS == TLS_OUT_OF_INDEXES) - { - currentTLS = CreateTLSIndex(); - } -#endif - ASSERT(currentTLS != TLS_OUT_OF_INDEXES); - if (currentTLS == TLS_OUT_OF_INDEXES) + ASSERT(currentTLS != TLS_INVALID_INDEX); + if (currentTLS == TLS_INVALID_INDEX) { return NULL; } @@ -46,14 +64,9 @@ Current *AllocateCurrent() return current; } +// Call this upon thread shutdown. void DeallocateCurrent() { -#if defined(ANGLE_PLATFORM_WINRT) - if (currentTLS == TLS_OUT_OF_INDEXES) - { - return; - } -#endif Current *current = reinterpret_cast(GetTLSValue(currentTLS)); SafeDelete(current); SetTLSValue(currentTLS, NULL); @@ -61,22 +74,21 @@ void DeallocateCurrent() } -#ifndef QT_OPENGL_ES_2_ANGLE_STATIC - +#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(QT_OPENGL_ES_2_ANGLE_STATIC) extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) { switch (reason) { case DLL_PROCESS_ATTACH: { -#if defined(ANGLE_PLATFORM_WINRT) // On WinRT, don't handle TLS from DllMain - return DisableThreadLibraryCalls(instance); -#endif - currentTLS = CreateTLSIndex(); - if (currentTLS == TLS_OUT_OF_INDEXES) + if (!gl::CreateThreadLocalIndex()) { return FALSE; } + +#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS + gl::InitializeDebugAnnotations(); +#endif } // Fall through to initialize index case DLL_THREAD_ATTACH: @@ -91,9 +103,11 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved break; case DLL_PROCESS_DETACH: { -#if !defined(ANGLE_PLATFORM_WINRT) gl::DeallocateCurrent(); - DestroyTLSIndex(currentTLS); + gl::DestroyThreadLocalIndex(); + +#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS + gl::UninitializeDebugAnnotations(); #endif } break; @@ -103,8 +117,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved return TRUE; } - -#endif // !QT_OPENGL_ES_2_ANGLE_STATIC +#endif // ANGLE_PLATFORM_WINDOWS && !QT_OPENGL_ES_2_ANGLE_STATIC namespace gl { @@ -152,7 +165,7 @@ Context *getNonLostContext() { if (context->isContextLost()) { - gl::error(GL_OUT_OF_MEMORY); + context->recordError(Error(GL_OUT_OF_MEMORY, "Context has been lost.")); return NULL; } else @@ -170,32 +183,4 @@ egl::Display *getDisplay() return current->display; } -// Records an error code -void error(GLenum errorCode) -{ - gl::Context *context = glGetCurrentContext(); - context->recordError(Error(errorCode)); - - switch (errorCode) - { - case GL_INVALID_ENUM: - TRACE("\t! Error generated: invalid enum\n"); - break; - case GL_INVALID_VALUE: - TRACE("\t! Error generated: invalid value\n"); - break; - case GL_INVALID_OPERATION: - TRACE("\t! Error generated: invalid operation\n"); - break; - case GL_OUT_OF_MEMORY: - TRACE("\t! Error generated: out of memory\n"); - break; - case GL_INVALID_FRAMEBUFFER_OPERATION: - TRACE("\t! Error generated: invalid framebuffer operation\n"); - break; - default: UNREACHABLE(); - } } - -} - diff --git a/src/3rdparty/angle/src/libGLESv2/main.h b/src/3rdparty/angle/src/libGLESv2/main.h index c30ad3375c9..dff02787f56 100644 --- a/src/3rdparty/angle/src/libGLESv2/main.h +++ b/src/3rdparty/angle/src/libGLESv2/main.h @@ -14,14 +14,11 @@ #include #include -#ifndef Sleep -#define Sleep(ms) WaitForSingleObjectEx(GetCurrentThread(), ms, FALSE) -#endif - namespace egl { class Display; class Surface; +class AttributeMap; } namespace gl @@ -40,16 +37,6 @@ Context *getContext(); Context *getNonLostContext(); egl::Display *getDisplay(); -void error(GLenum errorCode); - -template -const T &error(GLenum errorCode, const T &returnValue) -{ - error(errorCode); - - return returnValue; -} - } namespace rx @@ -64,11 +51,11 @@ gl::Context *glCreateContext(int clientVersion, const gl::Context *shareContext, 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, EGLNativeDisplayType nativeDisplay, EGLint requestedDisplayType); +rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, const egl::AttributeMap &attribMap); void glDestroyRenderer(rx::Renderer *renderer); -__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname); -bool __stdcall glBindTexImage(egl::Surface *surface); +__eglMustCastToProperFunctionPointerType EGLAPIENTRY glGetProcAddress(const char *procname); +bool EGLAPIENTRY glBindTexImage(egl::Surface *surface); } #endif // LIBGLESV2_MAIN_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h index f0b5f022276..c031effabd6 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h @@ -12,6 +12,8 @@ #include "common/angleutils.h" #include "libGLESv2/Buffer.h" +#include + namespace rx { @@ -21,7 +23,6 @@ class BufferImpl virtual ~BufferImpl() { } virtual gl::Error setData(const void* data, size_t size, GLenum usage) = 0; - virtual void *getData() = 0; virtual gl::Error setSubData(const void* data, size_t size, size_t offset) = 0; virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) = 0; virtual gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) = 0; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h index d54e6becd3e..1dd46785d99 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h @@ -4,29 +4,47 @@ // found in the LICENSE file. // -// FenceImpl.h: Defines the rx::FenceImpl class. +// FenceImpl.h: Defines the rx::FenceNVImpl and rx::FenceSyncImpl classes. #ifndef LIBGLESV2_RENDERER_FENCEIMPL_H_ #define LIBGLESV2_RENDERER_FENCEIMPL_H_ +#include "libGLESv2/Error.h" + #include "common/angleutils.h" +#include "angle_gl.h" + namespace rx { -class FenceImpl +class FenceNVImpl { public: - FenceImpl() { }; - virtual ~FenceImpl() { }; + FenceNVImpl() { }; + virtual ~FenceNVImpl() { }; - virtual bool isSet() const = 0; - virtual void set() = 0; - virtual bool test(bool flushCommandBuffer) = 0; - virtual bool hasError() const = 0; + virtual gl::Error set() = 0; + virtual gl::Error test(bool flushCommandBuffer, GLboolean *outFinished) = 0; + virtual gl::Error finishFence(GLboolean *outFinished) = 0; private: - DISALLOW_COPY_AND_ASSIGN(FenceImpl); + DISALLOW_COPY_AND_ASSIGN(FenceNVImpl); +}; + +class FenceSyncImpl +{ + public: + FenceSyncImpl() { }; + virtual ~FenceSyncImpl() { }; + + virtual gl::Error set() = 0; + virtual gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) = 0; + virtual gl::Error serverWait(GLbitfield flags, GLuint64 timeout) = 0; + virtual gl::Error getStatus(GLint *outResult) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(FenceSyncImpl); }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp index 370b086233e..5b9b75f5626 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp @@ -4,18 +4,20 @@ // found in the LICENSE file. // -// Image.h: Implements the rx::Image class, an abstract base class for the +// Image.h: Implements the rx::Image class, an abstract base class for the // renderer-specific classes which will define the interface to the underlying // surfaces or resources. #include "libGLESv2/renderer/Image.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/main.h" namespace rx { Image::Image() { - mWidth = 0; + mWidth = 0; mHeight = 0; mDepth = 0; mInternalFormat = GL_NONE; @@ -25,4 +27,20 @@ Image::Image() mDirty = false; } +gl::Error Image::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &area, gl::Framebuffer *source) +{ + gl::FramebufferAttachment *colorbuffer = source->getReadColorbuffer(); + ASSERT(colorbuffer); + + RenderTarget *renderTarget = NULL; + gl::Error error = GetAttachmentRenderTarget(colorbuffer, &renderTarget); + if (error.isError()) + { + return error; + } + + ASSERT(renderTarget); + return copy(xoffset, yoffset, zoffset, area, renderTarget); +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image.h b/src/3rdparty/angle/src/libGLESv2/renderer/Image.h index 3bfc6637621..9071a88c671 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Image.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Image.h @@ -4,7 +4,7 @@ // found in the LICENSE file. // -// Image.h: Defines the rx::Image class, an abstract base class for the +// Image.h: Defines the rx::Image class, an abstract base class for the // renderer-specific classes which will define the interface to the underlying // surfaces or resources. @@ -12,18 +12,22 @@ #define LIBGLESV2_RENDERER_IMAGE_H_ #include "common/debug.h" +#include "libGLESv2/Error.h" #include namespace gl { class Framebuffer; +struct Rectangle; +struct ImageIndex; } namespace rx { - -class Renderer; +class RendererD3D; +class RenderTarget; +class TextureStorage; class Image { @@ -43,14 +47,17 @@ class Image void markClean() {mDirty = false;} virtual bool isDirty() const = 0; - virtual bool redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) = 0; + virtual bool redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) = 0; - virtual void loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLint unpackAlignment, GLenum type, const void *input) = 0; - virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - const void *input) = 0; + virtual gl::Error loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLint unpackAlignment, GLenum type, const void *input) = 0; + virtual gl::Error loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + const void *input) = 0; - virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; + gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, gl::Framebuffer *source); + virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source) = 0; + virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, + const gl::ImageIndex &sourceIndex, TextureStorage *source) = 0; protected: GLsizei mWidth; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp index f68ac383de8..d472e1499e3 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp @@ -111,11 +111,7 @@ IndexRangeCache::IndexRange::IndexRange(GLenum typ, intptr_t off, GLsizei c) bool IndexRangeCache::IndexRange::operator<(const IndexRange& rhs) const { -#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); -#endif } IndexRangeCache::IndexBounds::IndexBounds() diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.cpp new file mode 100644 index 00000000000..f9fcad38a46 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.cpp @@ -0,0 +1,146 @@ +// +// 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. +// + +// ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl. + +#include "libGLESv2/renderer/ProgramImpl.h" + +#include "common/utilities.h" +#include "libGLESv2/main.h" + +namespace rx +{ + +namespace +{ + +unsigned int ParseAndStripArrayIndex(std::string* name) +{ + unsigned int subscript = GL_INVALID_INDEX; + + // Strip any trailing array operator and retrieve the subscript + size_t open = name->find_last_of('['); + size_t close = name->find_last_of(']'); + if (open != std::string::npos && close == name->length() - 1) + { + subscript = atoi(name->substr(open + 1).c_str()); + name->erase(open); + } + + return subscript; +} + +} + +ProgramImpl::~ProgramImpl() +{ + // Ensure that reset was called by the inherited class during destruction + ASSERT(mUniformIndex.size() == 0); +} + +gl::LinkedUniform *ProgramImpl::getUniformByLocation(GLint location) const +{ + ASSERT(location >= 0 && static_cast(location) < mUniformIndex.size()); + return mUniforms[mUniformIndex[location].index]; +} + +gl::LinkedUniform *ProgramImpl::getUniformByName(const std::string &name) const +{ + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) + { + if (mUniforms[uniformIndex]->name == name) + { + return mUniforms[uniformIndex]; + } + } + + return NULL; +} + +gl::UniformBlock *ProgramImpl::getUniformBlockByIndex(GLuint blockIndex) const +{ + ASSERT(blockIndex < mUniformBlocks.size()); + return mUniformBlocks[blockIndex]; +} + +GLint ProgramImpl::getUniformLocation(std::string name) +{ + unsigned int subscript = ParseAndStripArrayIndex(&name); + + unsigned int numUniforms = mUniformIndex.size(); + for (unsigned int location = 0; location < numUniforms; location++) + { + if (mUniformIndex[location].name == name) + { + const int index = mUniformIndex[location].index; + const bool isArray = mUniforms[index]->isArray(); + + if ((isArray && mUniformIndex[location].element == subscript) || + (subscript == GL_INVALID_INDEX)) + { + return location; + } + } + } + + return -1; +} + +GLuint ProgramImpl::getUniformIndex(std::string name) +{ + unsigned int subscript = ParseAndStripArrayIndex(&name); + + // The app is not allowed to specify array indices other than 0 for arrays of basic types + if (subscript != 0 && subscript != GL_INVALID_INDEX) + { + return GL_INVALID_INDEX; + } + + unsigned int numUniforms = mUniforms.size(); + for (unsigned int index = 0; index < numUniforms; index++) + { + if (mUniforms[index]->name == name) + { + if (mUniforms[index]->isArray() || subscript == GL_INVALID_INDEX) + { + return index; + } + } + } + + return GL_INVALID_INDEX; +} + +GLuint ProgramImpl::getUniformBlockIndex(std::string name) const +{ + unsigned int subscript = ParseAndStripArrayIndex(&name); + + unsigned int numUniformBlocks = mUniformBlocks.size(); + for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++) + { + const gl::UniformBlock &uniformBlock = *mUniformBlocks[blockIndex]; + if (uniformBlock.name == name) + { + const bool arrayElementZero = (subscript == GL_INVALID_INDEX && uniformBlock.elementIndex == 0); + if (subscript == uniformBlock.elementIndex || arrayElementZero) + { + return blockIndex; + } + } + } + + return GL_INVALID_INDEX; +} + +void ProgramImpl::reset() +{ + SafeDeleteContainer(mUniforms); + mUniformIndex.clear(); + SafeDeleteContainer(mUniformBlocks); + mTransformFeedbackLinkedVaryings.clear(); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h index ba0955fdf8e..6aaa23cf89d 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h @@ -13,44 +13,113 @@ #include "libGLESv2/BinaryStream.h" #include "libGLESv2/Constants.h" #include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/Shader.h" +#include "libGLESv2/renderer/Renderer.h" + +#include namespace rx { -class DynamicHLSL; -class Renderer; - class ProgramImpl { -public: - virtual ~ProgramImpl() { } + public: + ProgramImpl() { } + virtual ~ProgramImpl(); - // TODO: Temporary interfaces to ease migration. Remove soon! - virtual Renderer *getRenderer() = 0; - virtual DynamicHLSL *getDynamicHLSL() = 0; - virtual const std::vector &getPixelShaderKey() = 0; + const std::vector &getUniforms() const { return mUniforms; } + const std::vector &getUniformIndices() const { return mUniformIndex; } + const std::vector &getUniformBlocks() const { return mUniformBlocks; } + const std::vector &getTransformFeedbackLinkedVaryings() const { return mTransformFeedbackLinkedVaryings; } + const sh::Attribute *getShaderAttributes() const { return mShaderAttributes; } + + std::vector &getUniforms() { return mUniforms; } + std::vector &getUniformIndices() { return mUniformIndex; } + std::vector &getUniformBlocks() { return mUniformBlocks; } + std::vector &getTransformFeedbackLinkedVaryings() { return mTransformFeedbackLinkedVaryings; } + sh::Attribute *getShaderAttributes() { return mShaderAttributes; } + + gl::LinkedUniform *getUniformByLocation(GLint location) const; + gl::LinkedUniform *getUniformByName(const std::string &name) const; + gl::UniformBlock *getUniformBlockByIndex(GLuint blockIndex) const; + + GLint getUniformLocation(std::string name); + GLuint getUniformIndex(std::string name); + GLuint getUniformBlockIndex(std::string name) const; + + virtual bool usesPointSize() const = 0; + virtual int getShaderVersion() const = 0; + virtual GLenum getTransformFeedbackBufferMode() const = 0; virtual GLenum getBinaryFormat() = 0; - virtual bool load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0; - virtual bool save(gl::BinaryOutputStream *stream) = 0; + virtual gl::LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0; + virtual gl::Error save(gl::BinaryOutputStream *stream) = 0; - virtual rx::ShaderExecutable *getPixelExecutableForOutputLayout(gl::InfoLog &infoLog, const std::vector &outputSignature, - const std::vector &transformFeedbackLinkedVaryings, - bool separatedOutputBuffers) = 0; - virtual rx::ShaderExecutable *getVertexExecutableForInputLayout(gl::InfoLog &infoLog, - const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], - const sh::Attribute shaderAttributes[], - const std::vector &transformFeedbackLinkedVaryings, - bool separatedOutputBuffers) = 0; + virtual gl::LinkResult link(const gl::Data &data, gl::InfoLog &infoLog, + gl::Shader *fragmentShader, gl::Shader *vertexShader, + const std::vector &transformFeedbackVaryings, + GLenum transformFeedbackBufferMode, + int *registers, std::vector *linkedVaryings, + std::map *outputVariables) = 0; - virtual bool link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, - const std::vector &transformFeedbackVaryings, int *registers, - std::vector *linkedVaryings, std::map *outputVariables) = 0; + virtual void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) = 0; + virtual void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) = 0; + virtual void setUniform3fv(GLint location, GLsizei count, const GLfloat *v) = 0; + virtual void setUniform4fv(GLint location, GLsizei count, const GLfloat *v) = 0; + virtual void setUniform1iv(GLint location, GLsizei count, const GLint *v) = 0; + virtual void setUniform2iv(GLint location, GLsizei count, const GLint *v) = 0; + virtual void setUniform3iv(GLint location, GLsizei count, const GLint *v) = 0; + virtual void setUniform4iv(GLint location, GLsizei count, const GLint *v) = 0; + virtual void setUniform1uiv(GLint location, GLsizei count, const GLuint *v) = 0; + virtual void setUniform2uiv(GLint location, GLsizei count, const GLuint *v) = 0; + virtual void setUniform3uiv(GLint location, GLsizei count, const GLuint *v) = 0; + virtual void setUniform4uiv(GLint location, GLsizei count, const GLuint *v) = 0; + virtual void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; + virtual void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; + virtual void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; + virtual void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; + virtual void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; + virtual void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; + virtual void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; + virtual void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; + virtual void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; - virtual void initializeUniformStorage(const std::vector &uniforms) = 0; + virtual void getUniformfv(GLint location, GLfloat *params) = 0; + virtual void getUniformiv(GLint location, GLint *params) = 0; + virtual void getUniformuiv(GLint location, GLuint *params) = 0; - virtual void reset() = 0; + virtual void reset(); + + // TODO: The following functions are possibly only applicable to D3D backends. The should be carefully evaluated to + // determine if they can be removed from this interface. + virtual GLint getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const = 0; + virtual GLenum getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const = 0; + virtual GLint getUsedSamplerRange(gl::SamplerType type) const = 0; + virtual void updateSamplerMapping() = 0; + virtual bool validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) = 0; + + virtual gl::LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, + int registers) = 0; + + virtual bool linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader, + const gl::Caps &caps) = 0; + virtual bool defineUniformBlock(gl::InfoLog &infoLog, const gl::Shader &shader, const sh::InterfaceBlock &interfaceBlock, + const gl::Caps &caps) = 0; + + virtual gl::Error applyUniforms() = 0; + virtual gl::Error applyUniformBuffers(const std::vector boundBuffers, const gl::Caps &caps) = 0; + virtual bool assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader, + unsigned int registerIndex, const gl::Caps &caps) = 0; + + protected: + DISALLOW_COPY_AND_ASSIGN(ProgramImpl); + + std::vector mUniforms; + std::vector mUniformIndex; + std::vector mUniformBlocks; + std::vector mTransformFeedbackLinkedVaryings; + + sh::Attribute mShaderAttributes[gl::MAX_VERTEX_ATTRIBS]; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.cpp new file mode 100644 index 00000000000..857fdc9dae1 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.cpp @@ -0,0 +1,36 @@ +// +// 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 +// found in the LICENSE file. +// + +// RenderTarget.cpp: Implements serial handling for rx::RenderTarget + +#include "libGLESv2/renderer/RenderTarget.h" + +namespace rx +{ +unsigned int RenderTarget::mCurrentSerial = 1; + +RenderTarget::RenderTarget() + : mSerial(issueSerials(1)) +{ +} + +RenderTarget::~RenderTarget() +{ +} + +unsigned int RenderTarget::getSerial() const +{ + return mSerial; +} + +unsigned int RenderTarget::issueSerials(unsigned int count) +{ + unsigned int firstSerial = mCurrentSerial; + mCurrentSerial += count; + return firstSerial; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h index 44637ec7de9..3bdfb0cc98e 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h @@ -18,28 +18,22 @@ namespace rx class RenderTarget { public: - RenderTarget() - { - mWidth = 0; - mHeight = 0; - mDepth = 0; - mInternalFormat = GL_NONE; - mActualFormat = GL_NONE; - mSamples = 0; - } + RenderTarget(); + virtual ~RenderTarget(); - virtual ~RenderTarget() {}; - - GLsizei getWidth() const { return mWidth; } - GLsizei getHeight() const { return mHeight; } - GLsizei getDepth() const { return mDepth; } - GLenum getInternalFormat() const { return mInternalFormat; } - GLenum getActualFormat() const { return mActualFormat; } - GLsizei getSamples() const { return mSamples; } - gl::Extents getExtents() const { return gl::Extents(mWidth, mHeight, mDepth); } + virtual GLsizei getWidth() const = 0; + virtual GLsizei getHeight() const = 0; + virtual GLsizei getDepth() const = 0; + virtual GLenum getInternalFormat() const = 0; + virtual GLenum getActualFormat() const = 0; + virtual GLsizei getSamples() const = 0; + gl::Extents getExtents() const { return gl::Extents(getWidth(), getHeight(), getDepth()); } virtual void invalidate(GLint x, GLint y, GLsizei width, GLsizei height) = 0; + virtual unsigned int getSerial() const; + static unsigned int issueSerials(unsigned int count); + struct Desc { GLsizei width; GLsizei height; @@ -47,16 +41,11 @@ class RenderTarget GLenum format; }; - protected: - GLsizei mWidth; - GLsizei mHeight; - GLsizei mDepth; - GLenum mInternalFormat; - GLenum mActualFormat; - GLsizei mSamples; - private: DISALLOW_COPY_AND_ASSIGN(RenderTarget); + + const unsigned int mSerial; + static unsigned int mCurrentSerial; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.cpp new file mode 100644 index 00000000000..770ae8e9c6a --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.cpp @@ -0,0 +1,21 @@ +// +// 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. +// + +// RenderbufferImpl.h: Implements the shared methods of the abstract class gl::RenderbufferImpl + +#include "libGLESv2/renderer/RenderbufferImpl.h" + +namespace rx +{ +RenderbufferImpl::RenderbufferImpl() +{ +} + +RenderbufferImpl::~RenderbufferImpl() +{ +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.h new file mode 100644 index 00000000000..52e070f1d3b --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.h @@ -0,0 +1,41 @@ +// +// 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. +// + +// RenderbufferImpl.h: Defines the abstract class gl::RenderbufferImpl + +#ifndef LIBGLESV2_RENDERER_RENDERBUFFERIMPL_H_ +#define LIBGLESV2_RENDERER_RENDERBUFFERIMPL_H_ + +#include "angle_gl.h" + +#include "libGLESv2/Error.h" + +#include "common/angleutils.h" + +namespace rx +{ + +class RenderbufferImpl +{ + public: + RenderbufferImpl(); + virtual ~RenderbufferImpl() = 0; + + virtual gl::Error setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) = 0; + + virtual GLsizei getWidth() const = 0; + virtual GLsizei getHeight() const = 0; + virtual GLenum getInternalFormat() const = 0; + virtual GLenum getActualFormat() const = 0; + virtual GLsizei getSamples() const = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(RenderbufferImpl); +}; + +} + +#endif // LIBGLESV2_RENDERER_RENDERBUFFERIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp index 910d0285f18..df3dae1e383 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp @@ -6,11 +6,12 @@ // Renderer.cpp: Implements EGL dependencies for creating and destroying Renderer instances. -#include "libGLESv2/main.h" -#include "libGLESv2/Program.h" -#include "libGLESv2/renderer/Renderer.h" #include "common/utilities.h" -#include "libGLESv2/Shader.h" +#include "libEGL/AttributeMap.h" +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/Renderer.h" + +#include #if defined (ANGLE_ENABLE_D3D9) #include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" @@ -29,15 +30,12 @@ #define ANGLE_DEFAULT_D3D11 0 #endif -#include - namespace rx { -Renderer::Renderer(egl::Display *display) - : mDisplay(display), - mCapsInitialized(false), - mCurrentClientVersion(2) +Renderer::Renderer() + : mCapsInitialized(false), + mWorkaroundsInitialized(false) { } @@ -78,12 +76,23 @@ const gl::Extensions &Renderer::getRendererExtensions() const return mExtensions; } -typedef Renderer *(*CreateRendererFunction)(egl::Display*, EGLNativeDisplayType, EGLint); +const Workarounds &Renderer::getWorkarounds() const +{ + if (!mWorkaroundsInitialized) + { + mWorkarounds = generateWorkarounds(); + mWorkaroundsInitialized = true; + } + + return mWorkarounds; +} + +typedef Renderer *(*CreateRendererFunction)(egl::Display*, EGLNativeDisplayType, const egl::AttributeMap &); template -Renderer *CreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, EGLint requestedDisplayType) +Renderer *CreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, const egl::AttributeMap &attributes) { - return new RendererType(display, nativeDisplay, requestedDisplayType); + return new RendererType(display, nativeDisplay, attributes); } } @@ -91,15 +100,16 @@ Renderer *CreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDispl extern "C" { -rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, EGLint requestedDisplayType) +rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, const egl::AttributeMap &attribMap) { std::vector rendererCreationFunctions; + EGLint requestedDisplayType = attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE); + # if defined(ANGLE_ENABLE_D3D11) if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || nativeDisplay == EGL_D3D11_ONLY_DISPLAY_ANGLE || - requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE || - requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE) + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE) { rendererCreationFunctions.push_back(rx::CreateRenderer); } @@ -138,7 +148,7 @@ rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativ for (size_t i = 0; i < rendererCreationFunctions.size(); i++) { - rx::Renderer *renderer = rendererCreationFunctions[i](display, nativeDisplay, requestedDisplayType); + rx::Renderer *renderer = rendererCreationFunctions[i](display, nativeDisplay, attribMap); if (renderer->initialize() == EGL_SUCCESS) { return renderer; @@ -155,7 +165,8 @@ rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativ void glDestroyRenderer(rx::Renderer *renderer) { - delete renderer; + ASSERT(renderer); + SafeDelete(renderer); } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h index b2249741abf..b85895a9385 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h @@ -10,10 +10,13 @@ #ifndef LIBGLESV2_RENDERER_RENDERER_H_ #define LIBGLESV2_RENDERER_RENDERER_H_ -#include "libGLESv2/Uniform.h" -#include "libGLESv2/angletypes.h" #include "libGLESv2/Caps.h" #include "libGLESv2/Error.h" +#include "libGLESv2/Uniform.h" +#include "libGLESv2/angletypes.h" +#include "libGLESv2/renderer/Workarounds.h" +#include "common/NativeWindow.h" +#include "common/mathutil.h" #include @@ -32,37 +35,26 @@ class Display; namespace gl { -class InfoLog; -class ProgramBinary; -struct LinkedVarying; -struct VertexAttribute; class Buffer; -class Texture; class Framebuffer; -struct VertexAttribCurrentValueData; +struct Data; } namespace rx { -class TextureStorage; -class VertexBuffer; -class IndexBuffer; class QueryImpl; -class FenceImpl; +class FenceNVImpl; +class FenceSyncImpl; class BufferImpl; class VertexArrayImpl; -class BufferStorage; -struct TranslatedIndexData; class ShaderImpl; class ProgramImpl; -class ShaderExecutable; -class SwapChain; -class RenderTarget; -class Image; -class TextureStorage; -class UniformStorage; class TextureImpl; class TransformFeedbackImpl; +class RenderbufferImpl; +struct TranslatedIndexData; +struct Workarounds; +class SwapChain; struct ConfigDesc { @@ -73,6 +65,110 @@ struct ConfigDesc bool es3Capable; }; +class Renderer +{ + public: + Renderer(); + virtual ~Renderer(); + + virtual EGLint initialize() = 0; + virtual bool resetDevice() = 0; + + virtual int generateConfigs(ConfigDesc **configDescList) = 0; + virtual void deleteConfigs(ConfigDesc *configDescList) = 0; + + virtual gl::Error sync(bool block) = 0; + + virtual gl::Error drawArrays(const gl::Data &data, GLenum mode, + GLint first, GLsizei count, GLsizei instances) = 0; + virtual gl::Error drawElements(const gl::Data &data, GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei instances, + const RangeUI &indexRange) = 0; + + virtual gl::Error clear(const gl::Data &data, GLbitfield mask) = 0; + virtual gl::Error clearBufferfv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLfloat *values) = 0; + virtual gl::Error clearBufferuiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLuint *values) = 0; + virtual gl::Error clearBufferiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLint *values) = 0; + virtual gl::Error clearBufferfi(const gl::Data &data, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) = 0; + + virtual gl::Error readPixels(const gl::Data &data, GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLsizei *bufSize, void* pixels) = 0; + + virtual gl::Error blitFramebuffer(const gl::Data &data, + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) = 0; + + // TODO(jmadill): caps? and virtual for egl::Display + virtual bool getShareHandleSupport() const = 0; + virtual bool getPostSubBufferSupport() const = 0; + + // Shader creation + virtual ShaderImpl *createShader(const gl::Data &data, GLenum type) = 0; + virtual ProgramImpl *createProgram() = 0; + + // Shader operations + virtual void releaseShaderCompiler() = 0; + + // Texture creation + virtual TextureImpl *createTexture(GLenum target) = 0; + + // Renderbuffer creation + virtual RenderbufferImpl *createRenderbuffer() = 0; + virtual RenderbufferImpl *createRenderbuffer(SwapChain *swapChain, bool depth) = 0; + + // Buffer creation + virtual BufferImpl *createBuffer() = 0; + + // Vertex Array creation + virtual VertexArrayImpl *createVertexArray() = 0; + + // Query and Fence creation + virtual QueryImpl *createQuery(GLenum type) = 0; + virtual FenceNVImpl *createFenceNV() = 0; + virtual FenceSyncImpl *createFenceSync() = 0; + + // Transform Feedback creation + virtual TransformFeedbackImpl *createTransformFeedback() = 0; + + // lost device + //TODO(jmadill): investigate if this stuff is necessary in GL + virtual void notifyDeviceLost() = 0; + virtual bool isDeviceLost() = 0; + virtual bool testDeviceLost(bool notify) = 0; + virtual bool testDeviceResettable() = 0; + + virtual DWORD getAdapterVendor() const = 0; + virtual std::string getRendererDescription() const = 0; + virtual GUID getAdapterIdentifier() const = 0; + + // Renderer capabilities (virtual because of egl::Display) + virtual const gl::Caps &getRendererCaps() const; + const gl::TextureCapsMap &getRendererTextureCaps() const; + virtual const gl::Extensions &getRendererExtensions() const; + const Workarounds &getWorkarounds() const; + + // TODO(jmadill): needed by egl::Display, probably should be removed + virtual int getMajorShaderModel() const = 0; + virtual int getMinSwapInterval() const = 0; + virtual int getMaxSwapInterval() const = 0; + virtual bool getLUID(LUID *adapterLuid) const = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(Renderer); + + virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap* outTextureCaps, gl::Extensions *outExtensions) const = 0; + virtual Workarounds generateWorkarounds() const = 0; + + mutable bool mCapsInitialized; + mutable gl::Caps mCaps; + mutable gl::TextureCapsMap mTextureCaps; + mutable gl::Extensions mExtensions; + + mutable bool mWorkaroundsInitialized; + mutable Workarounds mWorkarounds; +}; + struct dx_VertexConstants { float depthRange[4]; @@ -93,176 +189,5 @@ enum ShaderType SHADER_GEOMETRY }; -class Renderer -{ - public: - explicit Renderer(egl::Display *display); - virtual ~Renderer(); - - virtual EGLint initialize() = 0; - virtual bool resetDevice() = 0; - - virtual int generateConfigs(ConfigDesc **configDescList) = 0; - virtual void deleteConfigs(ConfigDesc *configDescList) = 0; - - virtual void sync(bool block) = 0; - - virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0; - - virtual gl::Error generateSwizzle(gl::Texture *texture) = 0; - virtual gl::Error setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler) = 0; - virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0; - - virtual gl::Error setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]) = 0; - - virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState) = 0; - virtual gl::Error setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask) = 0; - virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW) = 0; - - virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled) = 0; - virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, - bool ignoreViewport) = 0; - - virtual gl::Error applyRenderTarget(gl::Framebuffer *frameBuffer) = 0; - virtual gl::Error applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, - bool rasterizerDiscard, bool transformFeedbackActive) = 0; - virtual gl::Error applyUniforms(const gl::ProgramBinary &programBinary) = 0; - virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0; - virtual gl::Error applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], - GLint first, GLsizei count, GLsizei instances) = 0; - virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) = 0; - virtual void applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]) = 0; - - virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) = 0; - virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, - gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) = 0; - - virtual gl::Error clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) = 0; - - virtual void markAllStateDirty() = 0; - - // lost device - virtual void notifyDeviceLost() = 0; - virtual bool isDeviceLost() = 0; - virtual bool testDeviceLost(bool notify) = 0; - virtual bool testDeviceResettable() = 0; - - // Renderer capabilities (virtual because it is used by egl::Display, do not override) - virtual const gl::Caps &getRendererCaps() const; - virtual const gl::TextureCapsMap &getRendererTextureCaps() const; - virtual const gl::Extensions &getRendererExtensions() const; - - virtual DWORD getAdapterVendor() const = 0; - virtual std::string getRendererDescription() const = 0; - virtual GUID getAdapterIdentifier() const = 0; - - virtual unsigned int getReservedVertexUniformVectors() const = 0; - virtual unsigned int getReservedFragmentUniformVectors() const = 0; - virtual unsigned int getReservedVertexUniformBuffers() const = 0; - virtual unsigned int getReservedFragmentUniformBuffers() const = 0; - virtual bool getShareHandleSupport() const = 0; - virtual bool getPostSubBufferSupport() const = 0; - - virtual int getMajorShaderModel() const = 0; - virtual int getMinSwapInterval() const = 0; - virtual int getMaxSwapInterval() const = 0; - - // Pixel operations - virtual bool copyToRenderTarget2D(TextureStorage *dest, TextureStorage *source) = 0; - virtual bool copyToRenderTargetCube(TextureStorage *dest, TextureStorage *source) = 0; - virtual bool copyToRenderTarget3D(TextureStorage *dest, TextureStorage *source) = 0; - virtual bool copyToRenderTarget2DArray(TextureStorage *dest, TextureStorage *source) = 0; - - virtual bool copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) = 0; - virtual bool copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level) = 0; - virtual bool copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) = 0; - virtual bool copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) = 0; - - virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) = 0; - - virtual gl::Error readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) = 0; - - // RenderTarget creation - virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth) = 0; - virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples) = 0; - - // Shader creation - virtual ShaderImpl *createShader(GLenum type) = 0; - virtual ProgramImpl *createProgram() = 0; - - // Shader operations - virtual void releaseShaderCompiler() = 0; - virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers) = 0; - virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, D3DWorkaroundType workaround) = 0; - virtual UniformStorage *createUniformStorage(size_t storageSize) = 0; - - // Image operations - virtual Image *createImage() = 0; - virtual void generateMipmap(Image *dest, Image *source) = 0; - virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain) = 0; - virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) = 0; - virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels) = 0; - virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0; - virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0; - - // Texture creation - virtual TextureImpl *createTexture(GLenum target) = 0; - - // Buffer creation - virtual BufferImpl *createBuffer() = 0; - virtual VertexBuffer *createVertexBuffer() = 0; - virtual IndexBuffer *createIndexBuffer() = 0; - - // Vertex Array creation - virtual VertexArrayImpl *createVertexArray() = 0; - - // Query and Fence creation - virtual QueryImpl *createQuery(GLenum type) = 0; - virtual FenceImpl *createFence() = 0; - - // Transform Feedback creation - virtual TransformFeedbackImpl* createTransformFeedback() = 0; - - // Current GLES client version - void setCurrentClientVersion(int clientVersion) { mCurrentClientVersion = clientVersion; } - int getCurrentClientVersion() const { return mCurrentClientVersion; } - - // Buffer-to-texture and Texture-to-buffer copies - virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const = 0; - virtual bool fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, - GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) = 0; - - virtual bool getLUID(LUID *adapterLuid) const = 0; - virtual rx::VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const = 0; - virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const = 0; - - protected: - egl::Display *mDisplay; - - private: - DISALLOW_COPY_AND_ASSIGN(Renderer); - - virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap* outTextureCaps, gl::Extensions *outExtensions) const = 0; - - mutable bool mCapsInitialized; - mutable gl::Caps mCaps; - mutable gl::TextureCapsMap mTextureCaps; - mutable gl::Extensions mExtensions; - - int mCurrentClientVersion; -}; - } #endif // LIBGLESV2_RENDERER_RENDERER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h index f17195673da..f1a96d74fb2 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h @@ -40,10 +40,21 @@ class ShaderExecutable return mFunctionBuffer.size(); } + const std::string &getDebugInfo() const + { + return mDebugInfo; + } + + void appendDebugInfo(const std::string &info) + { + mDebugInfo += info; + } + private: DISALLOW_COPY_AND_ASSIGN(ShaderExecutable); std::vector mFunctionBuffer; + std::string mDebugInfo; }; class UniformStorage @@ -64,4 +75,4 @@ class UniformStorage } -#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ +#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h index de5d30e6feb..cb0d360f0b2 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h @@ -23,9 +23,10 @@ class ShaderImpl ShaderImpl() { } virtual ~ShaderImpl() { } - virtual bool compile(const std::string &source) = 0; + virtual bool compile(const gl::Data &data, const std::string &source) = 0; virtual const std::string &getInfoLog() const = 0; virtual const std::string &getTranslatedSource() const = 0; + virtual std::string getDebugInfo() const = 0; const std::vector &getVaryings() const { return mVaryings; } const std::vector &getUniforms() const { return mUniforms; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h index 1ec702f2999..1417e0bdf6a 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h @@ -11,28 +11,24 @@ #define LIBGLESV2_RENDERER_SWAPCHAIN_H_ #include "common/angleutils.h" +#include "common/NativeWindow.h" #include "common/platform.h" #include #include -#include + +#if !defined(ANGLE_FORCE_VSYNC_OFF) +#define ANGLE_FORCE_VSYNC_OFF 0 +#endif namespace rx { -enum SwapFlags -{ - SWAP_NORMAL = 0, - SWAP_ROTATE_90 = 1, - SWAP_ROTATE_270 = 2, - SWAP_ROTATE_180 = SWAP_ROTATE_90|SWAP_ROTATE_270, -}; - class SwapChain { public: - SwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) - : mWindow(window), mShareHandle(shareHandle), mBackBufferFormat(backBufferFormat), mDepthBufferFormat(depthBufferFormat) + SwapChain(rx::NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) + : mNativeWindow(nativeWindow), mShareHandle(shareHandle), mBackBufferFormat(backBufferFormat), mDepthBufferFormat(depthBufferFormat) { } @@ -40,13 +36,16 @@ class SwapChain virtual EGLint resize(EGLint backbufferWidth, EGLint backbufferSize) = 0; virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) = 0; - virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint flags) = 0; + virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height) = 0; virtual void recreate() = 0; + GLenum GetBackBufferInternalFormat() const { return mBackBufferFormat; } + GLenum GetDepthBufferInternalFormat() const { return mDepthBufferFormat; } + virtual HANDLE getShareHandle() {return mShareHandle;}; protected: - const EGLNativeWindowType mWindow; // Window that the surface is created for. + rx::NativeWindow mNativeWindow; // Handler for the Window that the surface is created for. const GLenum mBackBufferFormat; const GLenum mDepthBufferFormat; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h index e3cc50d6809..3e662557e4f 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h @@ -10,6 +10,7 @@ #define LIBGLESV2_RENDERER_TEXTUREIMPL_H_ #include "common/angleutils.h" +#include "libGLESv2/Error.h" #include "angle_gl.h" @@ -31,19 +32,12 @@ namespace rx { class Image; -class Renderer; -class TextureStorage; class TextureImpl { public: virtual ~TextureImpl() {}; - // TODO: If this methods could go away that would be ideal; - // TextureStorage should only be necessary for the D3D backend, and as such - // higher level code should not rely on it. - virtual TextureStorage *getNativeTexture() = 0; - // Deprecated in favour of the ImageIndex method virtual Image *getImage(int level, int layer) const = 0; virtual Image *getImage(const gl::ImageIndex &index) const = 0; @@ -51,15 +45,15 @@ class TextureImpl virtual void setUsage(GLenum usage) = 0; - virtual void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; - virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) = 0; - virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; - virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) = 0; - virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; - virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; - virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) = 0; + virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; + virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) = 0; + virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; + virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) = 0; + virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; + virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; + virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) = 0; - virtual void generateMipmaps() = 0; + virtual gl::Error generateMipmaps() = 0; virtual void bindTexImage(egl::Surface *surface) = 0; virtual void releaseTexImage() = 0; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Workarounds.h b/src/3rdparty/angle/src/libGLESv2/renderer/Workarounds.h new file mode 100644 index 00000000000..20a166fb7a0 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Workarounds.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. +// + +// angletypes.h: Workarounds for driver bugs and other issues. + +#ifndef LIBGLESV2_RENDERER_WORKAROUNDS_H_ +#define LIBGLESV2_RENDERER_WORKAROUNDS_H_ + +// TODO(jmadill,zmo,geofflang): make a workarounds library that can operate +// independent of ANGLE's renderer. Workarounds should also be accessible +// outside of the Renderer. + +namespace rx +{ + +enum D3DWorkaroundType +{ + ANGLE_D3D_WORKAROUND_NONE, + ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION, + ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION +}; + +struct Workarounds +{ + Workarounds() + : mrtPerfWorkaround(false), + setDataFasterThanImageUpload(false) + {} + + bool mrtPerfWorkaround; + bool setDataFasterThanImageUpload; +}; + +} + +#endif // LIBGLESV2_RENDERER_WORKAROUNDS_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp index 004223d70f8..aabc9f04e9b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp @@ -6,7 +6,7 @@ // copyimage.cpp: Defines image copying functions -#include "libGLESv2/renderer/copyImage.h" +#include "libGLESv2/renderer/copyimage.h" namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp index a34ef03fb85..dd0d3f52ad4 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp @@ -9,7 +9,6 @@ #include "libGLESv2/renderer/d3d/BufferD3D.h" #include "libGLESv2/renderer/d3d/VertexBuffer.h" #include "libGLESv2/renderer/d3d/IndexBuffer.h" -#include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/main.h" namespace rx @@ -37,6 +36,13 @@ BufferD3D *BufferD3D::makeBufferD3D(BufferImpl *buffer) return static_cast(buffer); } +BufferD3D *BufferD3D::makeFromBuffer(gl::Buffer *buffer) +{ + BufferImpl *impl = buffer->getImplementation(); + ASSERT(impl); + return makeBufferD3D(impl); +} + void BufferD3D::updateSerial() { mSerial = mNextSerial++; @@ -46,11 +52,11 @@ void BufferD3D::initializeStaticData() { if (!mStaticVertexBuffer) { - mStaticVertexBuffer = new rx::StaticVertexBufferInterface(getRenderer()); + mStaticVertexBuffer = new StaticVertexBufferInterface(getRenderer()); } if (!mStaticIndexBuffer) { - mStaticIndexBuffer = new rx::StaticIndexBufferInterface(getRenderer()); + mStaticIndexBuffer = new StaticIndexBufferInterface(getRenderer()); } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h index 44f14cee589..1a1308c545a 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h @@ -12,10 +12,11 @@ #include "libGLESv2/renderer/BufferImpl.h" #include "libGLESv2/angletypes.h" +#include + namespace rx { - -class Renderer; +class RendererD3D; class StaticIndexBufferInterface; class StaticVertexBufferInterface; @@ -26,15 +27,17 @@ class BufferD3D : public BufferImpl virtual ~BufferD3D(); static BufferD3D *makeBufferD3D(BufferImpl *buffer); + static BufferD3D *makeFromBuffer(gl::Buffer *buffer); unsigned int getSerial() const { return mSerial; } + virtual gl::Error getData(const uint8_t **outData) = 0; virtual size_t getSize() const = 0; virtual bool supportsDirectBinding() const = 0; - virtual Renderer* getRenderer() = 0; + virtual RendererD3D *getRenderer() = 0; - rx::StaticVertexBufferInterface *getStaticVertexBuffer() { return mStaticVertexBuffer; } - rx::StaticIndexBufferInterface *getStaticIndexBuffer() { return mStaticIndexBuffer; } + StaticVertexBufferInterface *getStaticVertexBuffer() { return mStaticVertexBuffer; } + StaticIndexBufferInterface *getStaticIndexBuffer() { return mStaticIndexBuffer; } void initializeStaticData(); void invalidateStaticData(); @@ -46,8 +49,8 @@ class BufferD3D : public BufferImpl void updateSerial(); - rx::StaticVertexBufferInterface *mStaticVertexBuffer; - rx::StaticIndexBufferInterface *mStaticIndexBuffer; + StaticVertexBufferInterface *mStaticVertexBuffer; + StaticIndexBufferInterface *mStaticIndexBuffer; unsigned int mUnmodifiedDataUse; }; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp index 13411ebe64a..3d5bfe0cbea 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp @@ -8,10 +8,10 @@ #include "libGLESv2/renderer/d3d/DynamicHLSL.h" #include "libGLESv2/renderer/d3d/ShaderD3D.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/Shader.h" +#include "libGLESv2/renderer/d3d/RendererD3D.h" #include "libGLESv2/Program.h" #include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/Shader.h" #include "libGLESv2/formatutils.h" #include "common/utilities.h" @@ -22,6 +22,9 @@ META_ASSERT(GL_INVALID_INDEX == UINT_MAX); using namespace gl; +namespace rx +{ + namespace { @@ -70,7 +73,7 @@ std::string HLSLTypeString(GLenum type) return HLSLComponentTypeString(gl::VariableComponentType(type), gl::VariableComponentCount(type)); } -const rx::PixelShaderOutputVariable &GetOutputAtLocation(const std::vector &outputVariables, +const PixelShaderOutputVariable &GetOutputAtLocation(const std::vector &outputVariables, unsigned int location) { for (size_t variableIndex = 0; variableIndex < outputVariables.size(); ++variableIndex) @@ -85,15 +88,12 @@ const rx::PixelShaderOutputVariable &GetOutputAtLocation(const std::vector& transformFeedbackVaryings) +int DynamicHLSL::packVaryings(InfoLog &infoLog, VaryingPacking packing, ShaderD3D *fragmentShader, + ShaderD3D *vertexShader, const std::vector &transformFeedbackVaryings) { // TODO (geofflang): Use context's caps const int maxVaryingVectors = mRenderer->getRendererCaps().maxVaryingVectors; @@ -262,6 +262,13 @@ int DynamicHLSL::packVaryings(InfoLog &infoLog, VaryingPacking packing, rx::Shad for (unsigned int feedbackVaryingIndex = 0; feedbackVaryingIndex < transformFeedbackVaryings.size(); feedbackVaryingIndex++) { const std::string &transformFeedbackVarying = transformFeedbackVaryings[feedbackVaryingIndex]; + + if (transformFeedbackVarying == "gl_Position" || transformFeedbackVarying == "gl_PointSize") + { + // do not pack builtin XFB varyings + continue; + } + if (packedVaryings.find(transformFeedbackVarying) == packedVaryings.end()) { bool found = false; @@ -281,7 +288,7 @@ int DynamicHLSL::packVaryings(InfoLog &infoLog, VaryingPacking packing, rx::Shad } } - if (!found && transformFeedbackVarying != "gl_Position" && transformFeedbackVarying != "gl_PointSize") + if (!found) { infoLog.append("Transform feedback varying %s does not exist in the vertex shader.", transformFeedbackVarying.c_str()); return -1; @@ -400,7 +407,7 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &s // data reinterpretation (eg for pure integer->float, float->pure integer) // TODO: issue warning with gl debug info extension, when supported if (IsMatrixType(shaderAttribute.type) || - (mRenderer->getVertexConversionType(vertexFormat) & rx::VERTEX_CONVERT_GPU) != 0) + (mRenderer->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_GPU) != 0) { initHLSL += generateAttributeConversionHLSL(vertexFormat, shaderAttribute); } @@ -639,7 +646,7 @@ void DynamicHLSL::storeBuiltinLinkedVaryings(const SemanticInfo &info, } } -void DynamicHLSL::storeUserLinkedVaryings(const rx::ShaderD3D *vertexShader, +void DynamicHLSL::storeUserLinkedVaryings(const ShaderD3D *vertexShader, std::vector *linkedVaryings) const { const std::string &varyingSemantic = getVaryingSemantic(vertexShader->mUsesPointSize); @@ -662,10 +669,11 @@ void DynamicHLSL::storeUserLinkedVaryings(const rx::ShaderD3D *vertexShader, } } -bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const VaryingPacking packing, - std::string& pixelHLSL, std::string& vertexHLSL, - rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader, - const std::vector& transformFeedbackVaryings, +bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, InfoLog &infoLog, int registers, + const VaryingPacking packing, + std::string &pixelHLSL, std::string &vertexHLSL, + ShaderD3D *fragmentShader, ShaderD3D *vertexShader, + const std::vector &transformFeedbackVaryings, std::vector *linkedVaryings, std::map *programOutputVars, std::vector *outPixelShaderKey, @@ -691,21 +699,17 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const // Write the HLSL input/output declarations const int shaderModel = mRenderer->getMajorShaderModel(); - - // TODO (geofflang): Use context's caps - const int maxVaryingVectors = mRenderer->getRendererCaps().maxVaryingVectors; - const int registersNeeded = registers + (usesFragCoord ? 1 : 0) + (usesPointCoord ? 1 : 0); // Two cases when writing to gl_FragColor and using ESSL 1.0: // - with a 3.0 context, the output color is copied to channel 0 // - with a 2.0 context, the output color is broadcast to all channels - const bool broadcast = (fragmentShader->mUsesFragColor && mRenderer->getCurrentClientVersion() < 3); - const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getRendererCaps().maxDrawBuffers : 1); + const bool broadcast = (fragmentShader->mUsesFragColor && data.clientVersion < 3); + const unsigned int numRenderTargets = (broadcast || usesMRT ? data.caps->maxDrawBuffers : 1); int shaderVersion = vertexShader->getShaderVersion(); - if (registersNeeded > maxVaryingVectors) + if (static_cast(registersNeeded) > data.caps->maxVaryingVectors) { infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord"); return false; @@ -772,7 +776,7 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const for (int row = 0; row < variableRows; row++) { - int r = varying.registerIndex + varying.columnIndex * mRenderer->getRendererCaps().maxVaryingVectors + elementIndex * variableRows + row; + int r = varying.registerIndex + varying.columnIndex * data.caps->maxVaryingVectors + elementIndex * variableRows + row; vertexHLSL += " output.v" + Str(r); vertexHLSL += " = _" + varying.name; @@ -920,7 +924,7 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType)); for (int row = 0; row < variableRows; row++) { - std::string n = Str(varying.registerIndex + varying.columnIndex * mRenderer->getRendererCaps().maxVaryingVectors + elementIndex * variableRows + row); + std::string n = Str(varying.registerIndex + varying.columnIndex * data.caps->maxVaryingVectors + elementIndex * variableRows + row); pixelHLSL += " _" + varying.name; if (varying.isArray()) @@ -966,7 +970,7 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const return true; } -void DynamicHLSL::defineOutputVariables(rx::ShaderD3D *fragmentShader, std::map *programOutputVars) const +void DynamicHLSL::defineOutputVariables(ShaderD3D *fragmentShader, std::map *programOutputVars) const { const std::vector &shaderOutputVars = fragmentShader->getActiveOutputVariables(); @@ -994,14 +998,14 @@ void DynamicHLSL::defineOutputVariables(rx::ShaderD3D *fragmentShader, std::map< } } -std::string DynamicHLSL::generateGeometryShaderHLSL(int registers, rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader) const +std::string DynamicHLSL::generateGeometryShaderHLSL(int registers, ShaderD3D *fragmentShader, ShaderD3D *vertexShader) const { // for now we only handle point sprite emulation ASSERT(vertexShader->mUsesPointSize && mRenderer->getMajorShaderModel() >= 4); return generatePointSpriteHLSL(registers, fragmentShader, vertexShader); } -std::string DynamicHLSL::generatePointSpriteHLSL(int registers, rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader) const +std::string DynamicHLSL::generatePointSpriteHLSL(int registers, ShaderD3D *fragmentShader, ShaderD3D *vertexShader) const { ASSERT(registers >= 0); ASSERT(vertexShader->mUsesPointSize); @@ -1047,7 +1051,7 @@ std::string DynamicHLSL::generatePointSpriteHLSL(int registers, rx::ShaderD3D *f "void main(point GS_INPUT input[1], inout TriangleStream outStream)\n" "{\n" " GS_OUTPUT output = (GS_OUTPUT)0;\n" - " output.gl_Position = input[0].gl_Position;\n"; + " output.gl_Position = input[0].gl_Position;\n" " output.gl_PointSize = input[0].gl_PointSize;\n"; for (int r = 0; r < registers; r++) @@ -1135,7 +1139,7 @@ void DynamicHLSL::getInputLayoutSignature(const VertexFormat inputLayout[], GLen } else { - bool gpuConverted = ((mRenderer->getVertexConversionType(vertexFormat) & rx::VERTEX_CONVERT_GPU) != 0); + bool gpuConverted = ((mRenderer->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_GPU) != 0); signature[inputIndex] = (gpuConverted ? GL_TRUE : GL_FALSE); } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h index f68ed984012..c46bbf6ce01 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h @@ -10,18 +10,13 @@ #define LIBGLESV2_RENDERER_DYNAMIC_HLSL_H_ #include "common/angleutils.h" -#include "libGLESv2/constants.h" +#include "libGLESv2/Constants.h" #include "angle_gl.h" #include #include -namespace rx -{ -class Renderer; -} - namespace sh { struct Attribute; @@ -36,11 +31,12 @@ struct LinkedVarying; struct VertexAttribute; struct VertexFormat; struct PackedVarying; +struct Data; } namespace rx { -class Renderer; +class RendererD3D; class ShaderD3D; typedef const gl::PackedVarying *VaryingPacking[gl::IMPLEMENTATION_MAX_VARYING_VECTORS][4]; @@ -56,30 +52,31 @@ struct PixelShaderOutputVariable class DynamicHLSL { public: - explicit DynamicHLSL(rx::Renderer *const renderer); + explicit DynamicHLSL(RendererD3D *const renderer); - int packVaryings(gl::InfoLog &infoLog, VaryingPacking packing, rx::ShaderD3D *fragmentShader, - rx::ShaderD3D *vertexShader, const std::vector& transformFeedbackVaryings); + int packVaryings(gl::InfoLog &infoLog, VaryingPacking packing, ShaderD3D *fragmentShader, + ShaderD3D *vertexShader, const std::vector& transformFeedbackVaryings); std::string generateVertexShaderForInputLayout(const std::string &sourceShader, const gl::VertexFormat inputLayout[], const sh::Attribute shaderAttributes[]) const; std::string generatePixelShaderForOutputSignature(const std::string &sourceShader, const std::vector &outputVariables, bool usesFragDepth, const std::vector &outputLayout) const; - bool generateShaderLinkHLSL(gl::InfoLog &infoLog, int registers, const VaryingPacking packing, - std::string& pixelHLSL, std::string& vertexHLSL, - rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader, - const std::vector& transformFeedbackVaryings, + bool generateShaderLinkHLSL(const gl::Data &data, gl::InfoLog &infoLog, int registers, + const VaryingPacking packing, + std::string &pixelHLSL, std::string &vertexHLSL, + ShaderD3D *fragmentShader, ShaderD3D *vertexShader, + const std::vector &transformFeedbackVaryings, std::vector *linkedVaryings, std::map *programOutputVars, std::vector *outPixelShaderKey, bool *outUsesFragDepth) const; - std::string generateGeometryShaderHLSL(int registers, rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader) const; + std::string generateGeometryShaderHLSL(int registers, ShaderD3D *fragmentShader, ShaderD3D *vertexShader) const; void getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const; private: DISALLOW_COPY_AND_ASSIGN(DynamicHLSL); - rx::Renderer *const mRenderer; + RendererD3D *const mRenderer; struct SemanticInfo; @@ -88,10 +85,10 @@ class DynamicHLSL bool pixelShader) const; std::string generateVaryingLinkHLSL(const SemanticInfo &info, const std::string &varyingHLSL) const; std::string generateVaryingHLSL(const ShaderD3D *shader) const; - void storeUserLinkedVaryings(const rx::ShaderD3D *vertexShader, std::vector *linkedVaryings) const; + void storeUserLinkedVaryings(const ShaderD3D *vertexShader, std::vector *linkedVaryings) const; void storeBuiltinLinkedVaryings(const SemanticInfo &info, std::vector *linkedVaryings) const; - void defineOutputVariables(rx::ShaderD3D *fragmentShader, std::map *programOutputVars) const; - std::string generatePointSpriteHLSL(int registers, rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader) const; + void defineOutputVariables(ShaderD3D *fragmentShader, std::map *programOutputVars) const; + std::string generatePointSpriteHLSL(int registers, ShaderD3D *fragmentShader, ShaderD3D *vertexShader) const; // Prepend an underscore static std::string decorateVariable(const std::string &name); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp index d0131974eef..776d92b2028 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp @@ -8,34 +8,116 @@ #include "libGLESv2/Program.h" #include "libGLESv2/main.h" +#include "common/features.h" #include "common/utilities.h" -#include "common/platform.h" - -#if defined(__MINGW32__) && !defined(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, - const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages); -typedef HRESULT (WINAPI *pD3DCompile)(const void *data, SIZE_T data_size, const char *filename, - const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, - const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages); - -#endif // __MINGW32__ && !D3DCOMPILER_DLL #ifndef QT_D3DCOMPILER_DLL #define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL #endif +#ifndef D3DCOMPILE_RESERVED16 +#define D3DCOMPILE_RESERVED16 (1 << 16) +#endif +#ifndef D3DCOMPILE_RESERVED17 +#define D3DCOMPILE_RESERVED17 (1 << 17) +#endif + +// Definitions local to the translation unit +namespace +{ + +#ifdef CREATE_COMPILER_FLAG_INFO + #undef CREATE_COMPILER_FLAG_INFO +#endif + +#define CREATE_COMPILER_FLAG_INFO(flag) { flag, #flag } + +struct CompilerFlagInfo +{ + UINT mFlag; + const char *mName; +}; + +CompilerFlagInfo CompilerFlagInfos[] = +{ + // NOTE: The data below is copied from d3dcompiler.h + // If something changes there it should be changed here as well + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_DEBUG), // (1 << 0) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_SKIP_VALIDATION), // (1 << 1) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_SKIP_OPTIMIZATION), // (1 << 2) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PACK_MATRIX_ROW_MAJOR), // (1 << 3) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR), // (1 << 4) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PARTIAL_PRECISION), // (1 << 5) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_FORCE_VS_SOFTWARE_NO_OPT), // (1 << 6) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_FORCE_PS_SOFTWARE_NO_OPT), // (1 << 7) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_NO_PRESHADER), // (1 << 8) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_AVOID_FLOW_CONTROL), // (1 << 9) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PREFER_FLOW_CONTROL), // (1 << 10) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_ENABLE_STRICTNESS), // (1 << 11) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY), // (1 << 12) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_IEEE_STRICTNESS), // (1 << 13) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL0), // (1 << 14) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL1), // 0 + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL2), // ((1 << 14) | (1 << 15)) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL3), // (1 << 15) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_RESERVED16), // (1 << 16) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_RESERVED17), // (1 << 17) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_WARNINGS_ARE_ERRORS) // (1 << 18) +}; + +#undef CREATE_COMPILER_FLAG_INFO + +bool IsCompilerFlagSet(UINT mask, UINT flag) +{ + bool isFlagSet = IsMaskFlagSet(mask, flag); + + switch(flag) + { + case D3DCOMPILE_OPTIMIZATION_LEVEL0: + return isFlagSet && !IsMaskFlagSet(mask, UINT(D3DCOMPILE_OPTIMIZATION_LEVEL3)); + + case D3DCOMPILE_OPTIMIZATION_LEVEL1: + return (mask & D3DCOMPILE_OPTIMIZATION_LEVEL2) == UINT(0); + + case D3DCOMPILE_OPTIMIZATION_LEVEL3: + return isFlagSet && !IsMaskFlagSet(mask, UINT(D3DCOMPILE_OPTIMIZATION_LEVEL0)); + + default: + return isFlagSet; + } +} + +const char *GetCompilerFlagName(UINT mask, size_t flagIx) +{ + const CompilerFlagInfo &flagInfo = CompilerFlagInfos[flagIx]; + if (IsCompilerFlagSet(mask, flagInfo.mFlag)) + { + return flagInfo.mName; + } + + return nullptr; +} + +} namespace rx { +CompileConfig::CompileConfig() + : flags(0), + name() +{ +} + +CompileConfig::CompileConfig(UINT flags, const std::string &name) + : flags(flags), + name(name) +{ +} + HLSLCompiler::HLSLCompiler() : mD3DCompilerModule(NULL), - mD3DCompileFunc(NULL) + mD3DCompileFunc(NULL), + mD3DDisassembleFunc(NULL) { } @@ -46,7 +128,7 @@ HLSLCompiler::~HLSLCompiler() bool HLSLCompiler::initialize() { -#if !defined(ANGLE_PLATFORM_WINRT) +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) #if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES) // Find a D3DCompiler module that had already been loaded based on a predefined list of versions. static const char *d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES; @@ -83,17 +165,32 @@ bool HLSLCompiler::initialize() break; } + if (!mD3DCompilerModule) + { + // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. + mD3DCompilerModule = LoadLibrary(D3DCOMPILER_DLL); + } + if (!mD3DCompilerModule) { ERR("No D3D compiler module found - aborting!\n"); return false; } - mD3DCompileFunc = reinterpret_cast(GetProcAddress(mD3DCompilerModule, "D3DCompile")); + mD3DCompileFunc = reinterpret_cast(GetProcAddress(mD3DCompilerModule, "D3DCompile")); ASSERT(mD3DCompileFunc); + + mD3DDisassembleFunc = reinterpret_cast(GetProcAddress(mD3DCompilerModule, "D3DDisassemble")); + ASSERT(mD3DDisassembleFunc); + #else - mD3DCompileFunc = reinterpret_cast(&D3DCompile); + // D3D Shader compiler is linked already into this module, so the export + // can be directly assigned. + mD3DCompilerModule = NULL; + mD3DCompileFunc = reinterpret_cast(D3DCompile); + mD3DDisassembleFunc = reinterpret_cast(D3DDisassemble); #endif + return mD3DCompileFunc != NULL; } @@ -104,61 +201,133 @@ void HLSLCompiler::release() FreeLibrary(mD3DCompilerModule); mD3DCompilerModule = NULL; mD3DCompileFunc = NULL; + mD3DDisassembleFunc = NULL; } } -ShaderBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, - const UINT optimizationFlags[], const char *flagNames[], int attempts) const +gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile, + const std::vector &configs, const D3D_SHADER_MACRO *overrideMacros, + ID3DBlob **outCompiledBlob, std::string *outDebugInfo) const { -#if !defined(ANGLE_PLATFORM_WINRT) - ASSERT(mD3DCompilerModule && mD3DCompileFunc); +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + ASSERT(mD3DCompilerModule); +#endif + ASSERT(mD3DCompileFunc); + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + if (gl::perfActive()) + { + std::string sourcePath = getTempPath(); + std::string sourceText = FormatString("#line 2 \"%s\"\n\n%s", sourcePath.c_str(), hlsl.c_str()); + writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size()); + } #endif - if (!hlsl) - { - return NULL; - } + const D3D_SHADER_MACRO *macros = overrideMacros ? overrideMacros : NULL; - pD3DCompile compileFunc = reinterpret_cast(mD3DCompileFunc); - for (int i = 0; i < attempts; ++i) + for (size_t i = 0; i < configs.size(); ++i) { ID3DBlob *errorMessage = NULL; ID3DBlob *binary = NULL; - HRESULT result = compileFunc(hlsl, strlen(hlsl), gl::g_fakepath, NULL, NULL, "main", profile, optimizationFlags[i], 0, &binary, &errorMessage); + HRESULT result = mD3DCompileFunc(hlsl.c_str(), hlsl.length(), gl::g_fakepath, macros, NULL, "main", profile.c_str(), + configs[i].flags, 0, &binary, &errorMessage); if (errorMessage) { - const char *message = (const char*)errorMessage->GetBufferPointer(); - - infoLog.appendSanitized(message); - TRACE("\n%s", hlsl); - TRACE("\n%s", message); - + std::string message = reinterpret_cast(errorMessage->GetBufferPointer()); SafeRelease(errorMessage); + + infoLog.appendSanitized(message.c_str()); + TRACE("\n%s", hlsl.c_str()); + TRACE("\n%s", message.c_str()); + + if (message.find("error X3531:") != std::string::npos) // "can't unroll loops marked with loop attribute" + { + macros = NULL; // Disable [loop] and [flatten] + + // Retry without changing compiler flags + i--; + continue; + } } if (SUCCEEDED(result)) { - return (ShaderBlob*)binary; + *outCompiledBlob = binary; + +#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED + (*outDebugInfo) += "// COMPILER INPUT HLSL BEGIN\n\n" + hlsl + "\n// COMPILER INPUT HLSL END\n"; + (*outDebugInfo) += "\n\n// ASSEMBLY BEGIN\n\n"; + (*outDebugInfo) += "// Compiler configuration: " + configs[i].name + "\n// Flags:\n"; + for (size_t fIx = 0; fIx < ArraySize(CompilerFlagInfos); ++fIx) + { + const char *flagName = GetCompilerFlagName(configs[i].flags, fIx); + if (flagName != nullptr) + { + (*outDebugInfo) += std::string("// ") + flagName + "\n"; + } + } + + (*outDebugInfo) += "// Macros:\n"; + if (macros == nullptr) + { + (*outDebugInfo) += "// - : -\n"; + } + else + { + for (const D3D_SHADER_MACRO *mIt = macros; mIt->Name != nullptr; ++mIt) + { + (*outDebugInfo) += std::string("// ") + mIt->Name + " : " + mIt->Definition + "\n"; + } + } + + (*outDebugInfo) += "\n" + disassembleBinary(binary) + "\n// ASSEMBLY END\n"; +#endif + + return gl::Error(GL_NO_ERROR); } else { if (result == E_OUTOFMEMORY) { - return gl::error(GL_OUT_OF_MEMORY, (ShaderBlob*)NULL); + *outCompiledBlob = NULL; + return gl::Error(GL_OUT_OF_MEMORY, "HLSL compiler had an unexpected failure, result: 0x%X.", result); } - infoLog.append("Warning: D3D shader compilation failed with %s flags.", flagNames[i]); + infoLog.append("Warning: D3D shader compilation failed with %s flags.", configs[i].name.c_str()); - if (i + 1 < attempts) + if (i + 1 < configs.size()) { - infoLog.append(" Retrying with %s.\n", flagNames[i + 1]); + infoLog.append(" Retrying with %s.\n", configs[i + 1].name.c_str()); } } } - return NULL; + // None of the configurations succeeded in compiling this shader but the compiler is still intact + *outCompiledBlob = NULL; + return gl::Error(GL_NO_ERROR); +} + +std::string HLSLCompiler::disassembleBinary(ID3DBlob *shaderBinary) const +{ + // Retrieve disassembly + UINT flags = D3D_DISASM_ENABLE_DEFAULT_VALUE_PRINTS | D3D_DISASM_ENABLE_INSTRUCTION_NUMBERING; + ID3DBlob *disassembly = NULL; + pD3DDisassemble disassembleFunc = reinterpret_cast(mD3DDisassembleFunc); + LPCVOID buffer = shaderBinary->GetBufferPointer(); + SIZE_T bufSize = shaderBinary->GetBufferSize(); + HRESULT result = disassembleFunc(buffer, bufSize, flags, "", &disassembly); + + std::string asmSrc; + if (SUCCEEDED(result)) + { + asmSrc = reinterpret_cast(disassembly->GetBufferPointer()); + } + + SafeRelease(disassembly); + + return asmSrc; } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h index 0ce9e44be54..ff56f8035a7 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h @@ -1,7 +1,13 @@ #ifndef LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_ #define LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_ +#include "libGLESv2/Error.h" + #include "common/angleutils.h" +#include "common/platform.h" + +#include +#include namespace gl { @@ -11,8 +17,14 @@ class InfoLog; namespace rx { -typedef void* ShaderBlob; -typedef void(*CompileFuncPtr)(); +struct CompileConfig +{ + UINT flags; + std::string name; + + CompileConfig(); + CompileConfig(UINT flags, const std::string &name); +}; class HLSLCompiler { @@ -23,14 +35,20 @@ class HLSLCompiler bool initialize(); void release(); - ShaderBlob *compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, - const UINT optimizationFlags[], const char *flagNames[], int attempts) const; + // Attempt to compile a HLSL shader using the supplied configurations, may output a NULL compiled blob + // even if no GL errors are returned. + gl::Error compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile, + const std::vector &configs, const D3D_SHADER_MACRO *overrideMacros, + ID3DBlob **outCompiledBlob, std::string *outDebugInfo) const; + + std::string disassembleBinary(ID3DBlob* shaderBinary) const; private: DISALLOW_COPY_AND_ASSIGN(HLSLCompiler); HMODULE mD3DCompilerModule; - CompileFuncPtr mD3DCompileFunc; + pD3DCompile mD3DCompileFunc; + pD3DDisassemble mD3DDisassembleFunc; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp index 0854b968da6..12b919ab5a1 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp @@ -19,8 +19,8 @@ ImageD3D::ImageD3D() ImageD3D *ImageD3D::makeImageD3D(Image *img) { - ASSERT(HAS_DYNAMIC_TYPE(rx::ImageD3D*, img)); - return static_cast(img); + ASSERT(HAS_DYNAMIC_TYPE(ImageD3D*, img)); + return static_cast(img); } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h index 60a6ffdf37e..554ca0cee04 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h @@ -17,6 +17,8 @@ namespace gl { class Framebuffer; +struct ImageIndex; +struct Box; } namespace rx @@ -33,14 +35,11 @@ class ImageD3D : public Image virtual bool isDirty() const = 0; - virtual void setManagedSurface2D(TextureStorage *storage, int level) {}; - virtual void setManagedSurfaceCube(TextureStorage *storage, int face, int level) {}; - virtual void setManagedSurface3D(TextureStorage *storage, int level) {}; - virtual void setManagedSurface2DArray(TextureStorage *storage, int layer, int level) {}; - virtual bool copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0; - virtual bool copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0; - virtual bool copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) = 0; - virtual bool copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height) = 0; + virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); }; + virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level) { return gl::Error(GL_NO_ERROR); }; + virtual gl::Error setManagedSurface3D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); }; + virtual gl::Error setManagedSurface2DArray(TextureStorage *storage, int layer, int level) { return gl::Error(GL_NO_ERROR); }; + virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion) = 0; private: DISALLOW_COPY_AND_ASSIGN(ImageD3D); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp index 1dce1270d8e..aa614f6cc41 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp @@ -8,7 +8,7 @@ // class with derivations, classes that perform graphics API agnostic index buffer operations. #include "libGLESv2/renderer/d3d/IndexBuffer.h" -#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/d3d/RendererD3D.h" namespace rx { @@ -35,7 +35,7 @@ void IndexBuffer::updateSerial() } -IndexBufferInterface::IndexBufferInterface(Renderer *renderer, bool dynamic) : mRenderer(renderer) +IndexBufferInterface::IndexBufferInterface(RendererD3D *renderer, bool dynamic) : mRenderer(renderer) { mIndexBuffer = renderer->createIndexBuffer(); @@ -130,7 +130,7 @@ gl::Error IndexBufferInterface::setBufferSize(unsigned int bufferSize, GLenum in } } -StreamingIndexBufferInterface::StreamingIndexBufferInterface(Renderer *renderer) : IndexBufferInterface(renderer, true) +StreamingIndexBufferInterface::StreamingIndexBufferInterface(RendererD3D *renderer) : IndexBufferInterface(renderer, true) { } @@ -165,7 +165,7 @@ gl::Error StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, G } -StaticIndexBufferInterface::StaticIndexBufferInterface(Renderer *renderer) : IndexBufferInterface(renderer, false) +StaticIndexBufferInterface::StaticIndexBufferInterface(RendererD3D *renderer) : IndexBufferInterface(renderer, false) { } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h index 1bb5ae2c4a2..a34d30bbf37 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h @@ -16,7 +16,7 @@ namespace rx { -class Renderer; +class RendererD3D; class IndexBuffer { @@ -50,7 +50,7 @@ class IndexBuffer class IndexBufferInterface { public: - IndexBufferInterface(Renderer *renderer, bool dynamic); + IndexBufferInterface(RendererD3D *renderer, bool dynamic); virtual ~IndexBufferInterface(); virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) = 0; @@ -76,7 +76,7 @@ class IndexBufferInterface private: DISALLOW_COPY_AND_ASSIGN(IndexBufferInterface); - rx::Renderer *const mRenderer; + RendererD3D *const mRenderer; IndexBuffer* mIndexBuffer; @@ -87,7 +87,7 @@ class IndexBufferInterface class StreamingIndexBufferInterface : public IndexBufferInterface { public: - StreamingIndexBufferInterface(Renderer *renderer); + StreamingIndexBufferInterface(RendererD3D *renderer); ~StreamingIndexBufferInterface(); virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType); @@ -96,7 +96,7 @@ class StreamingIndexBufferInterface : public IndexBufferInterface class StaticIndexBufferInterface : public IndexBufferInterface { public: - explicit StaticIndexBufferInterface(Renderer *renderer); + explicit StaticIndexBufferInterface(RendererD3D *renderer); ~StaticIndexBufferInterface(); virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp index 8d455b4bf3e..eddd9de8873 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp @@ -10,7 +10,7 @@ #include "libGLESv2/renderer/d3d/IndexDataManager.h" #include "libGLESv2/renderer/d3d/BufferD3D.h" #include "libGLESv2/renderer/d3d/IndexBuffer.h" -#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/d3d/RendererD3D.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/main.h" #include "libGLESv2/formatutils.h" @@ -57,7 +57,7 @@ static void ConvertIndices(GLenum sourceType, GLenum destinationType, const void else UNREACHABLE(); } -IndexDataManager::IndexDataManager(Renderer *renderer) +IndexDataManager::IndexDataManager(RendererD3D *renderer) : mRenderer(renderer), mStreamingBufferShort(NULL), mStreamingBufferInt(NULL) @@ -97,7 +97,14 @@ gl::Error IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buf ASSERT(typeInfo.bytes * static_cast(count) + offset <= storage->getSize()); - indices = static_cast(storage->getData()) + offset; + const uint8_t *bufferData = NULL; + gl::Error error = storage->getData(&bufferData); + if (error.isError()) + { + return error; + } + + indices = bufferData + offset; } StaticIndexBufferInterface *staticBuffer = storage ? storage->getStaticIndexBuffer() : NULL; @@ -183,7 +190,16 @@ gl::Error IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buf return error; } - ConvertIndices(type, destinationIndexType, staticBuffer ? storage->getData() : indices, convertCount, output); + const uint8_t *dataPointer = reinterpret_cast(indices); + if (staticBuffer) + { + error = storage->getData(&dataPointer); + if (error.isError()) + { + return error; + } + } + ConvertIndices(type, destinationIndexType, dataPointer, convertCount, output); error = indexBuffer->unmapBuffer(); if (error.isError()) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h index 6d0b89e6d4a..a1aee1588b0 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h @@ -33,7 +33,7 @@ class StaticIndexBufferInterface; class StreamingIndexBufferInterface; class IndexBuffer; class BufferD3D; -class Renderer; +class RendererD3D; struct TranslatedIndexData { @@ -50,7 +50,7 @@ struct TranslatedIndexData class IndexDataManager { public: - explicit IndexDataManager(Renderer *renderer); + explicit IndexDataManager(RendererD3D *renderer); virtual ~IndexDataManager(); gl::Error prepareIndexData(GLenum type, GLsizei count, gl::Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated); @@ -60,7 +60,7 @@ class IndexDataManager DISALLOW_COPY_AND_ASSIGN(IndexDataManager); - Renderer *const mRenderer; + RendererD3D *const mRenderer; StreamingIndexBufferInterface *mStreamingBufferShort; StreamingIndexBufferInterface *mStreamingBufferInt; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp index d7d97cc2bd2..75da78110e7 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp @@ -8,27 +8,163 @@ #include "libGLESv2/renderer/d3d/ProgramD3D.h" +#include "common/features.h" #include "common/utilities.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/FramebufferAttachment.h" +#include "libGLESv2/Program.h" #include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/main.h" #include "libGLESv2/renderer/ShaderExecutable.h" #include "libGLESv2/renderer/d3d/DynamicHLSL.h" +#include "libGLESv2/renderer/d3d/RendererD3D.h" #include "libGLESv2/renderer/d3d/ShaderD3D.h" -#include "libGLESv2/main.h" namespace rx { -ProgramD3D::ProgramD3D(rx::Renderer *renderer) +namespace +{ + +GLenum GetTextureType(GLenum samplerType) +{ + switch (samplerType) + { + case GL_SAMPLER_2D: + case GL_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_SAMPLER_2D_SHADOW: + return GL_TEXTURE_2D; + case GL_SAMPLER_3D: + case GL_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_3D: + return GL_TEXTURE_3D; + case GL_SAMPLER_CUBE: + case GL_SAMPLER_CUBE_SHADOW: + return GL_TEXTURE_CUBE_MAP; + case GL_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + return GL_TEXTURE_CUBE_MAP; + case GL_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_SAMPLER_2D_ARRAY_SHADOW: + return GL_TEXTURE_2D_ARRAY; + default: UNREACHABLE(); + } + + return GL_TEXTURE_2D; +} + +void GetDefaultInputLayoutFromShader(const std::vector &shaderAttributes, gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]) +{ + size_t layoutIndex = 0; + for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) + { + ASSERT(layoutIndex < gl::MAX_VERTEX_ATTRIBS); + + const sh::Attribute &shaderAttr = shaderAttributes[attributeIndex]; + + if (shaderAttr.type != GL_NONE) + { + GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type); + + for (size_t rowIndex = 0; static_cast(rowIndex) < gl::VariableRowCount(transposedType); rowIndex++, layoutIndex++) + { + gl::VertexFormat *defaultFormat = &inputLayout[layoutIndex]; + + defaultFormat->mType = gl::VariableComponentType(transposedType); + defaultFormat->mNormalized = false; + defaultFormat->mPureInteger = (defaultFormat->mType != GL_FLOAT); // note: inputs can not be bool + defaultFormat->mComponents = gl::VariableColumnCount(transposedType); + } + } + } +} + +std::vector GetDefaultOutputLayoutFromShader(const std::vector &shaderOutputVars) +{ + std::vector defaultPixelOutput(1); + + ASSERT(!shaderOutputVars.empty()); + defaultPixelOutput[0] = GL_COLOR_ATTACHMENT0 + shaderOutputVars[0].outputIndex; + + return defaultPixelOutput; +} + +bool IsRowMajorLayout(const sh::InterfaceBlockField &var) +{ + return var.isRowMajorLayout; +} + +bool IsRowMajorLayout(const sh::ShaderVariable &var) +{ + return false; +} + +} + +ProgramD3D::VertexExecutable::VertexExecutable(const gl::VertexFormat inputLayout[], + const GLenum signature[], + ShaderExecutable *shaderExecutable) + : mShaderExecutable(shaderExecutable) +{ + for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) + { + mInputs[attributeIndex] = inputLayout[attributeIndex]; + mSignature[attributeIndex] = signature[attributeIndex]; + } +} + +ProgramD3D::VertexExecutable::~VertexExecutable() +{ + SafeDelete(mShaderExecutable); +} + +bool ProgramD3D::VertexExecutable::matchesSignature(const GLenum signature[]) const +{ + for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) + { + if (mSignature[attributeIndex] != signature[attributeIndex]) + { + return false; + } + } + + return true; +} + +ProgramD3D::PixelExecutable::PixelExecutable(const std::vector &outputSignature, ShaderExecutable *shaderExecutable) + : mOutputSignature(outputSignature), + mShaderExecutable(shaderExecutable) +{ +} + +ProgramD3D::PixelExecutable::~PixelExecutable() +{ + SafeDelete(mShaderExecutable); +} + +ProgramD3D::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D) +{ +} + +ProgramD3D::ProgramD3D(RendererD3D *renderer) : ProgramImpl(), mRenderer(renderer), mDynamicHLSL(NULL), - mVertexWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE), - mPixelWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE), + mGeometryExecutable(NULL), + mVertexWorkarounds(ANGLE_D3D_WORKAROUND_NONE), + mPixelWorkarounds(ANGLE_D3D_WORKAROUND_NONE), + mUsesPointSize(false), mVertexUniformStorage(NULL), - mFragmentUniformStorage(NULL) + mFragmentUniformStorage(NULL), + mUsedVertexSamplerRange(0), + mUsedPixelSamplerRange(0), + mDirtySamplerMapping(true), + mShaderVersion(100) { - mDynamicHLSL = new rx::DynamicHLSL(renderer); + mDynamicHLSL = new DynamicHLSL(renderer); } ProgramD3D::~ProgramD3D() @@ -49,13 +185,344 @@ const ProgramD3D *ProgramD3D::makeProgramD3D(const ProgramImpl *impl) return static_cast(impl); } -bool ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) +bool ProgramD3D::usesPointSpriteEmulation() const { + return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4; +} + +bool ProgramD3D::usesGeometryShader() const +{ + return usesPointSpriteEmulation(); +} + +GLint ProgramD3D::getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const +{ + GLint logicalTextureUnit = -1; + + switch (type) + { + case gl::SAMPLER_PIXEL: + ASSERT(samplerIndex < caps.maxTextureImageUnits); + if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active) + { + logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit; + } + break; + case gl::SAMPLER_VERTEX: + ASSERT(samplerIndex < caps.maxVertexTextureImageUnits); + if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active) + { + logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit; + } + break; + default: UNREACHABLE(); + } + + if (logicalTextureUnit >= 0 && logicalTextureUnit < static_cast(caps.maxCombinedTextureImageUnits)) + { + return logicalTextureUnit; + } + + return -1; +} + +// Returns the texture type for a given Direct3D 9 sampler type and +// index (0-15 for the pixel shader and 0-3 for the vertex shader). +GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const +{ + switch (type) + { + case gl::SAMPLER_PIXEL: + ASSERT(samplerIndex < mSamplersPS.size()); + ASSERT(mSamplersPS[samplerIndex].active); + return mSamplersPS[samplerIndex].textureType; + case gl::SAMPLER_VERTEX: + ASSERT(samplerIndex < mSamplersVS.size()); + ASSERT(mSamplersVS[samplerIndex].active); + return mSamplersVS[samplerIndex].textureType; + default: UNREACHABLE(); + } + + return GL_TEXTURE_2D; +} + +GLint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const +{ + switch (type) + { + case gl::SAMPLER_PIXEL: + return mUsedPixelSamplerRange; + case gl::SAMPLER_VERTEX: + return mUsedVertexSamplerRange; + default: + UNREACHABLE(); + return 0; + } +} + +void ProgramD3D::updateSamplerMapping() +{ + if (!mDirtySamplerMapping) + { + return; + } + + mDirtySamplerMapping = false; + + // Retrieve sampler uniform values + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) + { + gl::LinkedUniform *targetUniform = mUniforms[uniformIndex]; + + if (targetUniform->dirty) + { + if (gl::IsSampler(targetUniform->type)) + { + int count = targetUniform->elementCount(); + GLint (*v)[4] = reinterpret_cast(targetUniform->data); + + if (targetUniform->isReferencedByFragmentShader()) + { + unsigned int firstIndex = targetUniform->psRegisterIndex; + + for (int i = 0; i < count; i++) + { + unsigned int samplerIndex = firstIndex + i; + + if (samplerIndex < mSamplersPS.size()) + { + ASSERT(mSamplersPS[samplerIndex].active); + mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0]; + } + } + } + + if (targetUniform->isReferencedByVertexShader()) + { + unsigned int firstIndex = targetUniform->vsRegisterIndex; + + for (int i = 0; i < count; i++) + { + unsigned int samplerIndex = firstIndex + i; + + if (samplerIndex < mSamplersVS.size()) + { + ASSERT(mSamplersVS[samplerIndex].active); + mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0]; + } + } + } + } + } + } +} + +bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) +{ + // if any two active samplers in a program are of different types, but refer to the same + // texture image unit, and this is the current program, then ValidateProgram will fail, and + // DrawArrays and DrawElements will issue the INVALID_OPERATION error. + updateSamplerMapping(); + + std::vector textureUnitTypes(caps.maxCombinedTextureImageUnits, GL_NONE); + + for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i) + { + if (mSamplersPS[i].active) + { + unsigned int unit = mSamplersPS[i].logicalTextureUnit; + + if (unit >= textureUnitTypes.size()) + { + if (infoLog) + { + infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size()); + } + + return false; + } + + if (textureUnitTypes[unit] != GL_NONE) + { + if (mSamplersPS[i].textureType != textureUnitTypes[unit]) + { + if (infoLog) + { + infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit); + } + + return false; + } + } + else + { + textureUnitTypes[unit] = mSamplersPS[i].textureType; + } + } + } + + for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i) + { + if (mSamplersVS[i].active) + { + unsigned int unit = mSamplersVS[i].logicalTextureUnit; + + if (unit >= textureUnitTypes.size()) + { + if (infoLog) + { + infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size()); + } + + return false; + } + + if (textureUnitTypes[unit] != GL_NONE) + { + if (mSamplersVS[i].textureType != textureUnitTypes[unit]) + { + if (infoLog) + { + infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit); + } + + return false; + } + } + else + { + textureUnitTypes[unit] = mSamplersVS[i].textureType; + } + } + } + + return true; +} + +gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) +{ + stream->readInt(&mShaderVersion); + + const unsigned int psSamplerCount = stream->readInt(); + for (unsigned int i = 0; i < psSamplerCount; ++i) + { + Sampler sampler; + stream->readBool(&sampler.active); + stream->readInt(&sampler.logicalTextureUnit); + stream->readInt(&sampler.textureType); + mSamplersPS.push_back(sampler); + } + const unsigned int vsSamplerCount = stream->readInt(); + for (unsigned int i = 0; i < vsSamplerCount; ++i) + { + Sampler sampler; + stream->readBool(&sampler.active); + stream->readInt(&sampler.logicalTextureUnit); + stream->readInt(&sampler.textureType); + mSamplersVS.push_back(sampler); + } + + stream->readInt(&mUsedVertexSamplerRange); + stream->readInt(&mUsedPixelSamplerRange); + + const unsigned int uniformCount = stream->readInt(); + if (stream->error()) + { + infoLog.append("Invalid program binary."); + return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); + } + + mUniforms.resize(uniformCount); + for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++) + { + GLenum type = stream->readInt(); + GLenum precision = stream->readInt(); + std::string name = stream->readString(); + unsigned int arraySize = stream->readInt(); + int blockIndex = stream->readInt(); + + int offset = stream->readInt(); + int arrayStride = stream->readInt(); + int matrixStride = stream->readInt(); + bool isRowMajorMatrix = stream->readBool(); + + const sh::BlockMemberInfo blockInfo(offset, arrayStride, matrixStride, isRowMajorMatrix); + + gl::LinkedUniform *uniform = new gl::LinkedUniform(type, precision, name, arraySize, blockIndex, blockInfo); + + stream->readInt(&uniform->psRegisterIndex); + stream->readInt(&uniform->vsRegisterIndex); + stream->readInt(&uniform->registerCount); + stream->readInt(&uniform->registerElement); + + mUniforms[uniformIndex] = uniform; + } + + const unsigned int uniformIndexCount = stream->readInt(); + if (stream->error()) + { + infoLog.append("Invalid program binary."); + return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); + } + + mUniformIndex.resize(uniformIndexCount); + for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; uniformIndexIndex++) + { + stream->readString(&mUniformIndex[uniformIndexIndex].name); + stream->readInt(&mUniformIndex[uniformIndexIndex].element); + stream->readInt(&mUniformIndex[uniformIndexIndex].index); + } + + unsigned int uniformBlockCount = stream->readInt(); + if (stream->error()) + { + infoLog.append("Invalid program binary."); + return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); + } + + mUniformBlocks.resize(uniformBlockCount); + for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex) + { + std::string name = stream->readString(); + unsigned int elementIndex = stream->readInt(); + unsigned int dataSize = stream->readInt(); + + gl::UniformBlock *uniformBlock = new gl::UniformBlock(name, elementIndex, dataSize); + + stream->readInt(&uniformBlock->psRegisterIndex); + stream->readInt(&uniformBlock->vsRegisterIndex); + + unsigned int numMembers = stream->readInt(); + uniformBlock->memberUniformIndexes.resize(numMembers); + for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++) + { + stream->readInt(&uniformBlock->memberUniformIndexes[blockMemberIndex]); + } + + mUniformBlocks[uniformBlockIndex] = uniformBlock; + } + + stream->readInt(&mTransformFeedbackBufferMode); + const unsigned int transformFeedbackVaryingCount = stream->readInt(); + mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount); + for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++) + { + gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex]; + + stream->readString(&varying.name); + stream->readInt(&varying.type); + stream->readInt(&varying.size); + stream->readString(&varying.semanticName); + stream->readInt(&varying.semanticIndex); + stream->readInt(&varying.semanticIndexCount); + } + stream->readString(&mVertexHLSL); stream->readInt(&mVertexWorkarounds); stream->readString(&mPixelHLSL); stream->readInt(&mPixelWorkarounds); stream->readBool(&mUsesFragDepth); + stream->readBool(&mUsesPointSize); const size_t pixelShaderKeySize = stream->readInt(); mPixelShaderKey.resize(pixelShaderKeySize); @@ -67,109 +534,513 @@ bool ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex); } - return true; + const unsigned char* binary = reinterpret_cast(stream->data()); + + const unsigned int vertexShaderCount = stream->readInt(); + for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++) + { + gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]; + + for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++) + { + gl::VertexFormat *vertexInput = &inputLayout[inputIndex]; + stream->readInt(&vertexInput->mType); + stream->readInt(&vertexInput->mNormalized); + stream->readInt(&vertexInput->mComponents); + stream->readBool(&vertexInput->mPureInteger); + } + + unsigned int vertexShaderSize = stream->readInt(); + const unsigned char *vertexShaderFunction = binary + stream->offset(); + + ShaderExecutable *shaderExecutable = NULL; + gl::Error error = mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize, + SHADER_VERTEX, + mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), + &shaderExecutable); + if (error.isError()) + { + return gl::LinkResult(false, error); + } + + if (!shaderExecutable) + { + infoLog.append("Could not create vertex shader."); + return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); + } + + // generated converted input layout + GLenum signature[gl::MAX_VERTEX_ATTRIBS]; + getInputLayoutSignature(inputLayout, signature); + + // add new binary + mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable)); + + stream->skip(vertexShaderSize); + } + + const size_t pixelShaderCount = stream->readInt(); + for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++) + { + const size_t outputCount = stream->readInt(); + std::vector outputs(outputCount); + for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++) + { + stream->readInt(&outputs[outputIndex]); + } + + const size_t pixelShaderSize = stream->readInt(); + const unsigned char *pixelShaderFunction = binary + stream->offset(); + ShaderExecutable *shaderExecutable = NULL; + gl::Error error = mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, + mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), + &shaderExecutable); + if (error.isError()) + { + return gl::LinkResult(false, error); + } + + if (!shaderExecutable) + { + infoLog.append("Could not create pixel shader."); + return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); + } + + // add new binary + mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable)); + + stream->skip(pixelShaderSize); + } + + unsigned int geometryShaderSize = stream->readInt(); + + if (geometryShaderSize > 0) + { + const unsigned char *geometryShaderFunction = binary + stream->offset(); + gl::Error error = mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY, + mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), + &mGeometryExecutable); + if (error.isError()) + { + return gl::LinkResult(false, error); + } + + if (!mGeometryExecutable) + { + infoLog.append("Could not create geometry shader."); + return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); + } + stream->skip(geometryShaderSize); + } + + GUID binaryIdentifier = {0}; + stream->readBytes(reinterpret_cast(&binaryIdentifier), sizeof(GUID)); + + GUID identifier = mRenderer->getAdapterIdentifier(); + if (memcmp(&identifier, &binaryIdentifier, sizeof(GUID)) != 0) + { + infoLog.append("Invalid program binary."); + return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); + } + + initializeUniformStorage(); + + return gl::LinkResult(true, gl::Error(GL_NO_ERROR)); } -bool ProgramD3D::save(gl::BinaryOutputStream *stream) +gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) { + stream->writeInt(mShaderVersion); + + stream->writeInt(mSamplersPS.size()); + for (unsigned int i = 0; i < mSamplersPS.size(); ++i) + { + stream->writeInt(mSamplersPS[i].active); + stream->writeInt(mSamplersPS[i].logicalTextureUnit); + stream->writeInt(mSamplersPS[i].textureType); + } + + stream->writeInt(mSamplersVS.size()); + for (unsigned int i = 0; i < mSamplersVS.size(); ++i) + { + stream->writeInt(mSamplersVS[i].active); + stream->writeInt(mSamplersVS[i].logicalTextureUnit); + stream->writeInt(mSamplersVS[i].textureType); + } + + stream->writeInt(mUsedVertexSamplerRange); + stream->writeInt(mUsedPixelSamplerRange); + + stream->writeInt(mUniforms.size()); + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex) + { + const gl::LinkedUniform &uniform = *mUniforms[uniformIndex]; + + stream->writeInt(uniform.type); + stream->writeInt(uniform.precision); + stream->writeString(uniform.name); + stream->writeInt(uniform.arraySize); + stream->writeInt(uniform.blockIndex); + + stream->writeInt(uniform.blockInfo.offset); + stream->writeInt(uniform.blockInfo.arrayStride); + stream->writeInt(uniform.blockInfo.matrixStride); + stream->writeInt(uniform.blockInfo.isRowMajorMatrix); + + stream->writeInt(uniform.psRegisterIndex); + stream->writeInt(uniform.vsRegisterIndex); + stream->writeInt(uniform.registerCount); + stream->writeInt(uniform.registerElement); + } + + stream->writeInt(mUniformIndex.size()); + for (size_t i = 0; i < mUniformIndex.size(); ++i) + { + stream->writeString(mUniformIndex[i].name); + stream->writeInt(mUniformIndex[i].element); + stream->writeInt(mUniformIndex[i].index); + } + + stream->writeInt(mUniformBlocks.size()); + for (size_t uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); ++uniformBlockIndex) + { + const gl::UniformBlock& uniformBlock = *mUniformBlocks[uniformBlockIndex]; + + stream->writeString(uniformBlock.name); + stream->writeInt(uniformBlock.elementIndex); + stream->writeInt(uniformBlock.dataSize); + + stream->writeInt(uniformBlock.memberUniformIndexes.size()); + for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++) + { + stream->writeInt(uniformBlock.memberUniformIndexes[blockMemberIndex]); + } + + stream->writeInt(uniformBlock.psRegisterIndex); + stream->writeInt(uniformBlock.vsRegisterIndex); + } + + stream->writeInt(mTransformFeedbackBufferMode); + stream->writeInt(mTransformFeedbackLinkedVaryings.size()); + for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++) + { + const gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i]; + + stream->writeString(varying.name); + stream->writeInt(varying.type); + stream->writeInt(varying.size); + stream->writeString(varying.semanticName); + stream->writeInt(varying.semanticIndex); + stream->writeInt(varying.semanticIndexCount); + } + stream->writeString(mVertexHLSL); stream->writeInt(mVertexWorkarounds); stream->writeString(mPixelHLSL); stream->writeInt(mPixelWorkarounds); stream->writeInt(mUsesFragDepth); + stream->writeInt(mUsesPointSize); - const std::vector &pixelShaderKey = mPixelShaderKey; + const std::vector &pixelShaderKey = mPixelShaderKey; stream->writeInt(pixelShaderKey.size()); for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); pixelShaderKeyIndex++) { - const rx::PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex]; + const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex]; stream->writeInt(variable.type); stream->writeString(variable.name); stream->writeString(variable.source); stream->writeInt(variable.outputIndex); } - return true; + stream->writeInt(mVertexExecutables.size()); + for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++) + { + VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex]; + + for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++) + { + const gl::VertexFormat &vertexInput = vertexExecutable->inputs()[inputIndex]; + stream->writeInt(vertexInput.mType); + stream->writeInt(vertexInput.mNormalized); + stream->writeInt(vertexInput.mComponents); + stream->writeInt(vertexInput.mPureInteger); + } + + size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength(); + stream->writeInt(vertexShaderSize); + + const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction(); + stream->writeBytes(vertexBlob, vertexShaderSize); + } + + stream->writeInt(mPixelExecutables.size()); + for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++) + { + PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex]; + + const std::vector outputs = pixelExecutable->outputSignature(); + stream->writeInt(outputs.size()); + for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++) + { + stream->writeInt(outputs[outputIndex]); + } + + size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength(); + stream->writeInt(pixelShaderSize); + + const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction(); + stream->writeBytes(pixelBlob, pixelShaderSize); + } + + size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0; + stream->writeInt(geometryShaderSize); + + if (mGeometryExecutable != NULL && geometryShaderSize > 0) + { + const uint8_t *geometryBlob = mGeometryExecutable->getFunction(); + stream->writeBytes(geometryBlob, geometryShaderSize); + } + + GUID binaryIdentifier = mRenderer->getAdapterIdentifier(); + stream->writeBytes(reinterpret_cast(&binaryIdentifier), sizeof(GUID)); + + return gl::Error(GL_NO_ERROR); } -rx::ShaderExecutable *ProgramD3D::getPixelExecutableForOutputLayout(gl::InfoLog &infoLog, const std::vector &outputSignature, - const std::vector &transformFeedbackLinkedVaryings, - bool separatedOutputBuffers) +gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutable **outExecutable) { + std::vector outputs; + + const gl::ColorbufferInfo &colorbuffers = fbo->getColorbuffersForRender(mRenderer->getWorkarounds()); + + for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) + { + const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment]; + + if (colorbuffer) + { + outputs.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding()); + } + else + { + outputs.push_back(GL_NONE); + } + } + + return getPixelExecutableForOutputLayout(outputs, outExecutable); +} + +gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector &outputSignature, ShaderExecutable **outExectuable) +{ + for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++) + { + if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature)) + { + *outExectuable = mPixelExecutables[executableIndex]->shaderExecutable(); + return gl::Error(GL_NO_ERROR); + } + } + std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth, outputSignature); // Generate new pixel executable - rx::ShaderExecutable *pixelExecutable = mRenderer->compileToExecutable(infoLog, finalPixelHLSL.c_str(), rx::SHADER_PIXEL, - transformFeedbackLinkedVaryings, separatedOutputBuffers, - mPixelWorkarounds); + gl::InfoLog tempInfoLog; + ShaderExecutable *pixelExecutable = NULL; + gl::Error error = mRenderer->compileToExecutable(tempInfoLog, finalPixelHLSL, SHADER_PIXEL, + mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), + mPixelWorkarounds, &pixelExecutable); + if (error.isError()) + { + return error; + } - return pixelExecutable; + if (!pixelExecutable) + { + std::vector tempCharBuffer(tempInfoLog.getLength() + 3); + tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]); + ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]); + } + else + { + mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable)); + } + + *outExectuable = pixelExecutable; + return gl::Error(GL_NO_ERROR); } -rx::ShaderExecutable *ProgramD3D::getVertexExecutableForInputLayout(gl::InfoLog &infoLog, - const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], - const sh::Attribute shaderAttributes[], - const std::vector &transformFeedbackLinkedVaryings, - bool separatedOutputBuffers) +gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], ShaderExecutable **outExectuable) { + GLenum signature[gl::MAX_VERTEX_ATTRIBS]; + getInputLayoutSignature(inputLayout, signature); + + for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++) + { + if (mVertexExecutables[executableIndex]->matchesSignature(signature)) + { + *outExectuable = mVertexExecutables[executableIndex]->shaderExecutable(); + return gl::Error(GL_NO_ERROR); + } + } + // Generate new dynamic layout with attribute conversions - std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, shaderAttributes); + std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, mShaderAttributes); // Generate new vertex executable - rx::ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(infoLog, finalVertexHLSL.c_str(), - rx::SHADER_VERTEX, - transformFeedbackLinkedVaryings, separatedOutputBuffers, - mVertexWorkarounds); + gl::InfoLog tempInfoLog; + ShaderExecutable *vertexExecutable = NULL; + gl::Error error = mRenderer->compileToExecutable(tempInfoLog, finalVertexHLSL, SHADER_VERTEX, + mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), + mVertexWorkarounds, &vertexExecutable); + if (error.isError()) + { + return error; + } - return vertexExecutable; + if (!vertexExecutable) + { + std::vector tempCharBuffer(tempInfoLog.getLength()+3); + tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]); + ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]); + } + else + { + mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, vertexExecutable)); + } + + *outExectuable = vertexExecutable; + return gl::Error(GL_NO_ERROR); } -bool ProgramD3D::link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, - const std::vector &transformFeedbackVaryings, int *registers, - std::vector *linkedVaryings, std::map *outputVariables) +gl::LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, + int registers) { - rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); - rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader->getImplementation()); + ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); + ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation()); + + gl::VertexFormat defaultInputLayout[gl::MAX_VERTEX_ATTRIBS]; + GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout); + ShaderExecutable *defaultVertexExecutable = NULL; + gl::Error error = getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable); + if (error.isError()) + { + return gl::LinkResult(false, error); + } + + std::vector defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey()); + ShaderExecutable *defaultPixelExecutable = NULL; + error = getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable); + if (error.isError()) + { + return gl::LinkResult(false, error); + } + + if (usesGeometryShader()) + { + std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D); + + + error = mRenderer->compileToExecutable(infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), + ANGLE_D3D_WORKAROUND_NONE, &mGeometryExecutable); + if (error.isError()) + { + return gl::LinkResult(false, error); + } + } + +#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED + if (usesGeometryShader() && mGeometryExecutable) + { + // Geometry shaders are currently only used internally, so there is no corresponding shader object at the interface level + // For now the geometry shader debug info is pre-pended to the vertex shader, this is a bit of a clutch + vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n"); + vertexShaderD3D->appendDebugInfo(mGeometryExecutable->getDebugInfo()); + vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n"); + } + + if (defaultVertexExecutable) + { + vertexShaderD3D->appendDebugInfo(defaultVertexExecutable->getDebugInfo()); + } + + if (defaultPixelExecutable) + { + fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo()); + } +#endif + + bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable && (!usesGeometryShader() || mGeometryExecutable)); + return gl::LinkResult(linkSuccess, gl::Error(GL_NO_ERROR)); +} + +gl::LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog, + gl::Shader *fragmentShader, gl::Shader *vertexShader, + const std::vector &transformFeedbackVaryings, + GLenum transformFeedbackBufferMode, + int *registers, std::vector *linkedVaryings, + std::map *outputVariables) +{ + ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); + ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation()); + + mSamplersPS.resize(data.caps->maxTextureImageUnits); + mSamplersVS.resize(data.caps->maxVertexTextureImageUnits); + + mTransformFeedbackBufferMode = transformFeedbackBufferMode; mPixelHLSL = fragmentShaderD3D->getTranslatedSource(); mPixelWorkarounds = fragmentShaderD3D->getD3DWorkarounds(); mVertexHLSL = vertexShaderD3D->getTranslatedSource(); mVertexWorkarounds = vertexShaderD3D->getD3DWorkarounds(); + mShaderVersion = vertexShaderD3D->getShaderVersion(); // Map the varyings to the register file - rx::VaryingPacking packing = { NULL }; + VaryingPacking packing = { NULL }; *registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings); if (*registers < 0) { - return false; + return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); } if (!gl::ProgramBinary::linkVaryings(infoLog, fragmentShader, vertexShader)) { - return false; + return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); } - if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, *registers, packing, mPixelHLSL, mVertexHLSL, + if (!mDynamicHLSL->generateShaderLinkHLSL(data, infoLog, *registers, packing, mPixelHLSL, mVertexHLSL, fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings, linkedVaryings, outputVariables, &mPixelShaderKey, &mUsesFragDepth)) { - return false; + return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); } - return true; + mUsesPointSize = vertexShaderD3D->usesPointSize(); + + return gl::LinkResult(true, gl::Error(GL_NO_ERROR)); } -void ProgramD3D::initializeUniformStorage(const std::vector &uniforms) +void ProgramD3D::getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const +{ + mDynamicHLSL->getInputLayoutSignature(inputLayout, signature); +} + +void ProgramD3D::initializeUniformStorage() { // Compute total default block size unsigned int vertexRegisters = 0; unsigned int fragmentRegisters = 0; - for (size_t uniformIndex = 0; uniformIndex < uniforms.size(); uniformIndex++) + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) { - const gl::LinkedUniform &uniform = *uniforms[uniformIndex]; + const gl::LinkedUniform &uniform = *mUniforms[uniformIndex]; if (!gl::IsSampler(uniform.type)) { @@ -188,18 +1059,867 @@ void ProgramD3D::initializeUniformStorage(const std::vector mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u); } +gl::Error ProgramD3D::applyUniforms() +{ + updateSamplerMapping(); + + gl::Error error = mRenderer->applyUniforms(*this, mUniforms); + if (error.isError()) + { + return error; + } + + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) + { + mUniforms[uniformIndex]->dirty = false; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error ProgramD3D::applyUniformBuffers(const std::vector boundBuffers, const gl::Caps &caps) +{ + ASSERT(boundBuffers.size() == mUniformBlocks.size()); + + const gl::Buffer *vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS] = {NULL}; + const gl::Buffer *fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS] = {NULL}; + + const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers(); + const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers(); + + for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); uniformBlockIndex++) + { + gl::UniformBlock *uniformBlock = mUniformBlocks[uniformBlockIndex]; + gl::Buffer *uniformBuffer = boundBuffers[uniformBlockIndex]; + + ASSERT(uniformBlock && uniformBuffer); + + if (uniformBuffer->getSize() < uniformBlock->dataSize) + { + // undefined behaviour + return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small."); + } + + // Unnecessary to apply an unreferenced standard or shared UBO + if (!uniformBlock->isReferencedByVertexShader() && !uniformBlock->isReferencedByFragmentShader()) + { + continue; + } + + if (uniformBlock->isReferencedByVertexShader()) + { + unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS; + ASSERT(vertexUniformBuffers[registerIndex] == NULL); + ASSERT(registerIndex < caps.maxVertexUniformBlocks); + vertexUniformBuffers[registerIndex] = uniformBuffer; + } + + if (uniformBlock->isReferencedByFragmentShader()) + { + unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS; + ASSERT(fragmentUniformBuffers[registerIndex] == NULL); + ASSERT(registerIndex < caps.maxFragmentUniformBlocks); + fragmentUniformBuffers[registerIndex] = uniformBuffer; + } + } + + return mRenderer->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers); +} + +bool ProgramD3D::assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader, + unsigned int registerIndex, const gl::Caps &caps) +{ + if (shader == GL_VERTEX_SHADER) + { + uniformBlock->vsRegisterIndex = registerIndex; + if (registerIndex - mRenderer->getReservedVertexUniformBuffers() >= caps.maxVertexUniformBlocks) + { + infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", caps.maxVertexUniformBlocks); + return false; + } + } + else if (shader == GL_FRAGMENT_SHADER) + { + uniformBlock->psRegisterIndex = registerIndex; + if (registerIndex - mRenderer->getReservedFragmentUniformBuffers() >= caps.maxFragmentUniformBlocks) + { + infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", caps.maxFragmentUniformBlocks); + return false; + } + } + else UNREACHABLE(); + + return true; +} + +void ProgramD3D::dirtyAllUniforms() +{ + unsigned int numUniforms = mUniforms.size(); + for (unsigned int index = 0; index < numUniforms; index++) + { + mUniforms[index]->dirty = true; + } +} + +void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat* v) +{ + setUniform(location, count, v, GL_FLOAT); +} + +void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) +{ + setUniform(location, count, v, GL_FLOAT_VEC2); +} + +void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) +{ + setUniform(location, count, v, GL_FLOAT_VEC3); +} + +void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) +{ + setUniform(location, count, v, GL_FLOAT_VEC4); +} + +void ProgramD3D::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2); +} + +void ProgramD3D::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3); +} + +void ProgramD3D::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4); +} + +void ProgramD3D::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3); +} + +void ProgramD3D::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2); +} + +void ProgramD3D::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4); +} + +void ProgramD3D::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2); +} + +void ProgramD3D::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4); +} + +void ProgramD3D::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3); +} + +void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v) +{ + setUniform(location, count, v, GL_INT); +} + +void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v) +{ + setUniform(location, count, v, GL_INT_VEC2); +} + +void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v) +{ + setUniform(location, count, v, GL_INT_VEC3); +} + +void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v) +{ + setUniform(location, count, v, GL_INT_VEC4); +} + +void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v) +{ + setUniform(location, count, v, GL_UNSIGNED_INT); +} + +void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v) +{ + setUniform(location, count, v, GL_UNSIGNED_INT_VEC2); +} + +void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v) +{ + setUniform(location, count, v, GL_UNSIGNED_INT_VEC3); +} + +void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) +{ + setUniform(location, count, v, GL_UNSIGNED_INT_VEC4); +} + +void ProgramD3D::getUniformfv(GLint location, GLfloat *params) +{ + getUniformv(location, params, GL_FLOAT); +} + +void ProgramD3D::getUniformiv(GLint location, GLint *params) +{ + getUniformv(location, params, GL_INT); +} + +void ProgramD3D::getUniformuiv(GLint location, GLuint *params) +{ + getUniformv(location, params, GL_UNSIGNED_INT); +} + +bool ProgramD3D::linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader, + const gl::Caps &caps) +{ + const ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader.getImplementation()); + const ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader.getImplementation()); + + const std::vector &vertexUniforms = vertexShader.getUniforms(); + const std::vector &fragmentUniforms = fragmentShader.getUniforms(); + + // Check that uniforms defined in the vertex and fragment shaders are identical + typedef std::map UniformMap; + UniformMap linkedUniforms; + + for (unsigned int vertexUniformIndex = 0; vertexUniformIndex < vertexUniforms.size(); vertexUniformIndex++) + { + const sh::Uniform &vertexUniform = vertexUniforms[vertexUniformIndex]; + linkedUniforms[vertexUniform.name] = &vertexUniform; + } + + for (unsigned int fragmentUniformIndex = 0; fragmentUniformIndex < fragmentUniforms.size(); fragmentUniformIndex++) + { + const sh::Uniform &fragmentUniform = fragmentUniforms[fragmentUniformIndex]; + UniformMap::const_iterator entry = linkedUniforms.find(fragmentUniform.name); + if (entry != linkedUniforms.end()) + { + const sh::Uniform &vertexUniform = *entry->second; + const std::string &uniformName = "uniform '" + vertexUniform.name + "'"; + if (!gl::ProgramBinary::linkValidateUniforms(infoLog, uniformName, vertexUniform, fragmentUniform)) + { + return false; + } + } + } + + for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++) + { + const sh::Uniform &uniform = vertexUniforms[uniformIndex]; + + if (uniform.staticUse) + { + defineUniformBase(GL_VERTEX_SHADER, uniform, vertexShaderD3D->getUniformRegister(uniform.name)); + } + } + + for (unsigned int uniformIndex = 0; uniformIndex < fragmentUniforms.size(); uniformIndex++) + { + const sh::Uniform &uniform = fragmentUniforms[uniformIndex]; + + if (uniform.staticUse) + { + defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShaderD3D->getUniformRegister(uniform.name)); + } + } + + if (!indexUniforms(infoLog, caps)) + { + return false; + } + + initializeUniformStorage(); + + // special case for gl_DepthRange, the only built-in uniform (also a struct) + if (vertexShaderD3D->usesDepthRange() || fragmentShaderD3D->usesDepthRange()) + { + const sh::BlockMemberInfo &defaultInfo = sh::BlockMemberInfo::getDefaultBlockInfo(); + + mUniforms.push_back(new gl::LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0, -1, defaultInfo)); + mUniforms.push_back(new gl::LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0, -1, defaultInfo)); + mUniforms.push_back(new gl::LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0, -1, defaultInfo)); + } + + return true; +} + +void ProgramD3D::defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister) +{ + ShShaderOutput outputType = ShaderD3D::getCompilerOutputType(shader); + sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType)); + encoder.skipRegisters(uniformRegister); + + defineUniform(shader, uniform, uniform.name, &encoder); +} + +void ProgramD3D::defineUniform(GLenum shader, const sh::ShaderVariable &uniform, + const std::string &fullName, sh::HLSLBlockEncoder *encoder) +{ + if (uniform.isStruct()) + { + for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++) + { + const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : ""); + + encoder->enterAggregateType(); + + for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++) + { + const sh::ShaderVariable &field = uniform.fields[fieldIndex]; + const std::string &fieldFullName = (fullName + elementString + "." + field.name); + + defineUniform(shader, field, fieldFullName, encoder); + } + + encoder->exitAggregateType(); + } + } + else // Not a struct + { + // Arrays are treated as aggregate types + if (uniform.isArray()) + { + encoder->enterAggregateType(); + } + + gl::LinkedUniform *linkedUniform = getUniformByName(fullName); + + if (!linkedUniform) + { + linkedUniform = new gl::LinkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize, + -1, sh::BlockMemberInfo::getDefaultBlockInfo()); + ASSERT(linkedUniform); + linkedUniform->registerElement = encoder->getCurrentElement(); + mUniforms.push_back(linkedUniform); + } + + ASSERT(linkedUniform->registerElement == encoder->getCurrentElement()); + + if (shader == GL_FRAGMENT_SHADER) + { + linkedUniform->psRegisterIndex = encoder->getCurrentRegister(); + } + else if (shader == GL_VERTEX_SHADER) + { + linkedUniform->vsRegisterIndex = encoder->getCurrentRegister(); + } + else UNREACHABLE(); + + // Advance the uniform offset, to track registers allocation for structs + encoder->encodeType(uniform.type, uniform.arraySize, false); + + // Arrays are treated as aggregate types + if (uniform.isArray()) + { + encoder->exitAggregateType(); + } + } +} + +template +static inline void SetIfDirty(T *dest, const T& source, bool *dirtyFlag) +{ + ASSERT(dest != NULL); + ASSERT(dirtyFlag != NULL); + + *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0); + *dest = source; +} + +template +void ProgramD3D::setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType) +{ + const int components = gl::VariableComponentCount(targetUniformType); + const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType); + + gl::LinkedUniform *targetUniform = getUniformByLocation(location); + + int elementCount = targetUniform->elementCount(); + + count = std::min(elementCount - (int)mUniformIndex[location].element, count); + + if (targetUniform->type == targetUniformType) + { + T *target = reinterpret_cast(targetUniform->data) + mUniformIndex[location].element * 4; + + for (int i = 0; i < count; i++) + { + T *dest = target + (i * 4); + const T *source = v + (i * components); + + for (int c = 0; c < components; c++) + { + SetIfDirty(dest + c, source[c], &targetUniform->dirty); + } + for (int c = components; c < 4; c++) + { + SetIfDirty(dest + c, T(0), &targetUniform->dirty); + } + } + } + else if (targetUniform->type == targetBoolType) + { + GLint *boolParams = reinterpret_cast(targetUniform->data) + mUniformIndex[location].element * 4; + + for (int i = 0; i < count; i++) + { + GLint *dest = boolParams + (i * 4); + const T *source = v + (i * components); + + for (int c = 0; c < components; c++) + { + SetIfDirty(dest + c, (source[c] == static_cast(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty); + } + for (int c = components; c < 4; c++) + { + SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty); + } + } + } + else if (gl::IsSampler(targetUniform->type)) + { + ASSERT(targetUniformType == GL_INT); + + GLint *target = reinterpret_cast(targetUniform->data) + mUniformIndex[location].element * 4; + + bool wasDirty = targetUniform->dirty; + + for (int i = 0; i < count; i++) + { + GLint *dest = target + (i * 4); + const GLint *source = reinterpret_cast(v) + (i * components); + + SetIfDirty(dest + 0, source[0], &targetUniform->dirty); + SetIfDirty(dest + 1, 0, &targetUniform->dirty); + SetIfDirty(dest + 2, 0, &targetUniform->dirty); + SetIfDirty(dest + 3, 0, &targetUniform->dirty); + } + + if (!wasDirty && targetUniform->dirty) + { + mDirtySamplerMapping = true; + } + } + else UNREACHABLE(); +} + +template +bool transposeMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight) +{ + bool dirty = false; + int copyWidth = std::min(targetHeight, srcWidth); + int copyHeight = std::min(targetWidth, srcHeight); + + for (int x = 0; x < copyWidth; x++) + { + for (int y = 0; y < copyHeight; y++) + { + SetIfDirty(target + (x * targetWidth + y), static_cast(value[y * srcWidth + x]), &dirty); + } + } + // clear unfilled right side + for (int y = 0; y < copyWidth; y++) + { + for (int x = copyHeight; x < targetWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); + } + } + // clear unfilled bottom. + for (int y = copyWidth; y < targetHeight; y++) + { + for (int x = 0; x < targetWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); + } + } + + return dirty; +} + +template +bool expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight) +{ + bool dirty = false; + int copyWidth = std::min(targetWidth, srcWidth); + int copyHeight = std::min(targetHeight, srcHeight); + + for (int y = 0; y < copyHeight; y++) + { + for (int x = 0; x < copyWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast(value[y * srcWidth + x]), &dirty); + } + } + // clear unfilled right side + for (int y = 0; y < copyHeight; y++) + { + for (int x = copyWidth; x < targetWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); + } + } + // clear unfilled bottom. + for (int y = copyHeight; y < targetHeight; y++) + { + for (int x = 0; x < targetWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); + } + } + + return dirty; +} + +template +void ProgramD3D::setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType) +{ + gl::LinkedUniform *targetUniform = getUniformByLocation(location); + + int elementCount = targetUniform->elementCount(); + + count = std::min(elementCount - (int)mUniformIndex[location].element, count); + const unsigned int targetMatrixStride = (4 * rows); + GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * targetMatrixStride); + + for (int i = 0; i < count; i++) + { + // Internally store matrices as transposed versions to accomodate HLSL matrix indexing + if (transpose == GL_FALSE) + { + targetUniform->dirty = transposeMatrix(target, value, 4, rows, rows, cols) || targetUniform->dirty; + } + else + { + targetUniform->dirty = expandMatrix(target, value, 4, rows, cols, rows) || targetUniform->dirty; + } + target += targetMatrixStride; + value += cols * rows; + } +} + +template +void ProgramD3D::getUniformv(GLint location, T *params, GLenum uniformType) +{ + gl::LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index]; + + if (gl::IsMatrixType(targetUniform->type)) + { + const int rows = gl::VariableRowCount(targetUniform->type); + const int cols = gl::VariableColumnCount(targetUniform->type); + transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4 * rows, rows, cols, 4, rows); + } + else if (uniformType == gl::VariableComponentType(targetUniform->type)) + { + unsigned int size = gl::VariableComponentCount(targetUniform->type); + memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(T), + size * sizeof(T)); + } + else + { + unsigned int size = gl::VariableComponentCount(targetUniform->type); + switch (gl::VariableComponentType(targetUniform->type)) + { + case GL_BOOL: + { + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; + + for (unsigned int i = 0; i < size; i++) + { + params[i] = (boolParams[i] == GL_FALSE) ? static_cast(0) : static_cast(1); + } + } + break; + + case GL_FLOAT: + { + GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; + + for (unsigned int i = 0; i < size; i++) + { + params[i] = static_cast(floatParams[i]); + } + } + break; + + case GL_INT: + { + GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; + + for (unsigned int i = 0; i < size; i++) + { + params[i] = static_cast(intParams[i]); + } + } + break; + + case GL_UNSIGNED_INT: + { + GLuint *uintParams = (GLuint*)targetUniform->data + mUniformIndex[location].element * 4; + + for (unsigned int i = 0; i < size; i++) + { + params[i] = static_cast(uintParams[i]); + } + } + break; + + default: UNREACHABLE(); + } + } +} + +template +void ProgramD3D::defineUniformBlockMembers(const std::vector &fields, const std::string &prefix, int blockIndex, + sh::BlockLayoutEncoder *encoder, std::vector *blockUniformIndexes, + bool inRowMajorLayout) +{ + for (unsigned int uniformIndex = 0; uniformIndex < fields.size(); uniformIndex++) + { + const VarT &field = fields[uniformIndex]; + const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name); + + if (field.isStruct()) + { + bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field)); + + for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++) + { + encoder->enterAggregateType(); + + const std::string uniformElementName = fieldName + (field.isArray() ? ArrayString(arrayElement) : ""); + defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, encoder, blockUniformIndexes, rowMajorLayout); + + encoder->exitAggregateType(); + } + } + else + { + bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout); + + sh::BlockMemberInfo memberInfo = encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix); + + gl::LinkedUniform *newUniform = new gl::LinkedUniform(field.type, field.precision, fieldName, field.arraySize, + blockIndex, memberInfo); + + // add to uniform list, but not index, since uniform block uniforms have no location + blockUniformIndexes->push_back(mUniforms.size()); + mUniforms.push_back(newUniform); + } + } +} + +bool ProgramD3D::defineUniformBlock(gl::InfoLog &infoLog, const gl::Shader &shader, const sh::InterfaceBlock &interfaceBlock, + const gl::Caps &caps) +{ + const ShaderD3D* shaderD3D = ShaderD3D::makeShaderD3D(shader.getImplementation()); + + // create uniform block entries if they do not exist + if (getUniformBlockIndex(interfaceBlock.name) == GL_INVALID_INDEX) + { + std::vector blockUniformIndexes; + const unsigned int blockIndex = mUniformBlocks.size(); + + // define member uniforms + sh::BlockLayoutEncoder *encoder = NULL; + + if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD) + { + encoder = new sh::Std140BlockEncoder; + } + else + { + encoder = new sh::HLSLBlockEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED); + } + ASSERT(encoder); + + defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, encoder, &blockUniformIndexes, interfaceBlock.isRowMajorLayout); + + size_t dataSize = encoder->getBlockSize(); + + // create all the uniform blocks + if (interfaceBlock.arraySize > 0) + { + for (unsigned int uniformBlockElement = 0; uniformBlockElement < interfaceBlock.arraySize; uniformBlockElement++) + { + gl::UniformBlock *newUniformBlock = new gl::UniformBlock(interfaceBlock.name, uniformBlockElement, dataSize); + newUniformBlock->memberUniformIndexes = blockUniformIndexes; + mUniformBlocks.push_back(newUniformBlock); + } + } + else + { + gl::UniformBlock *newUniformBlock = new gl::UniformBlock(interfaceBlock.name, GL_INVALID_INDEX, dataSize); + newUniformBlock->memberUniformIndexes = blockUniformIndexes; + mUniformBlocks.push_back(newUniformBlock); + } + } + + if (interfaceBlock.staticUse) + { + // Assign registers to the uniform blocks + const GLuint blockIndex = getUniformBlockIndex(interfaceBlock.name); + const unsigned int elementCount = std::max(1u, interfaceBlock.arraySize); + ASSERT(blockIndex != GL_INVALID_INDEX); + ASSERT(blockIndex + elementCount <= mUniformBlocks.size()); + + unsigned int interfaceBlockRegister = shaderD3D->getInterfaceBlockRegister(interfaceBlock.name); + + for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++) + { + gl::UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement]; + ASSERT(uniformBlock->name == interfaceBlock.name); + + if (!assignUniformBlockRegister(infoLog, uniformBlock, shader.getType(), + interfaceBlockRegister + uniformBlockElement, caps)) + { + return false; + } + } + } + + return true; +} + +bool ProgramD3D::assignSamplers(unsigned int startSamplerIndex, + GLenum samplerType, + unsigned int samplerCount, + std::vector &outSamplers, + GLuint *outUsedRange) +{ + unsigned int samplerIndex = startSamplerIndex; + + do + { + if (samplerIndex < outSamplers.size()) + { + Sampler& sampler = outSamplers[samplerIndex]; + sampler.active = true; + sampler.textureType = GetTextureType(samplerType); + sampler.logicalTextureUnit = 0; + *outUsedRange = std::max(samplerIndex + 1, *outUsedRange); + } + else + { + return false; + } + + samplerIndex++; + } while (samplerIndex < startSamplerIndex + samplerCount); + + return true; +} + +bool ProgramD3D::indexSamplerUniform(const gl::LinkedUniform &uniform, gl::InfoLog &infoLog, const gl::Caps &caps) +{ + ASSERT(gl::IsSampler(uniform.type)); + ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX); + + if (uniform.vsRegisterIndex != GL_INVALID_INDEX) + { + if (!assignSamplers(uniform.vsRegisterIndex, uniform.type, uniform.arraySize, mSamplersVS, + &mUsedVertexSamplerRange)) + { + infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).", + mSamplersVS.size()); + return false; + } + + unsigned int maxVertexVectors = mRenderer->getReservedVertexUniformVectors() + caps.maxVertexUniformVectors; + if (uniform.vsRegisterIndex + uniform.registerCount > maxVertexVectors) + { + infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", + caps.maxVertexUniformVectors); + return false; + } + } + + if (uniform.psRegisterIndex != GL_INVALID_INDEX) + { + if (!assignSamplers(uniform.psRegisterIndex, uniform.type, uniform.arraySize, mSamplersPS, + &mUsedPixelSamplerRange)) + { + infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", + mSamplersPS.size()); + return false; + } + + unsigned int maxFragmentVectors = mRenderer->getReservedFragmentUniformVectors() + caps.maxFragmentUniformVectors; + if (uniform.psRegisterIndex + uniform.registerCount > maxFragmentVectors) + { + infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", + caps.maxFragmentUniformVectors); + return false; + } + } + + return true; +} + +bool ProgramD3D::indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps) +{ + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) + { + const gl::LinkedUniform &uniform = *mUniforms[uniformIndex]; + + if (gl::IsSampler(uniform.type)) + { + if (!indexSamplerUniform(uniform, infoLog, caps)) + { + return false; + } + } + + for (unsigned int arrayElementIndex = 0; arrayElementIndex < uniform.elementCount(); arrayElementIndex++) + { + mUniformIndex.push_back(gl::VariableLocation(uniform.name, arrayElementIndex, uniformIndex)); + } + } + + return true; +} + void ProgramD3D::reset() { + ProgramImpl::reset(); + + SafeDeleteContainer(mVertexExecutables); + SafeDeleteContainer(mPixelExecutables); + SafeDelete(mGeometryExecutable); + + mTransformFeedbackBufferMode = GL_NONE; + mVertexHLSL.clear(); - mVertexWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE; + mVertexWorkarounds = ANGLE_D3D_WORKAROUND_NONE; + mShaderVersion = 100; mPixelHLSL.clear(); - mPixelWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE; + mPixelWorkarounds = ANGLE_D3D_WORKAROUND_NONE; mUsesFragDepth = false; mPixelShaderKey.clear(); + mUsesPointSize = false; SafeDelete(mVertexUniformStorage); SafeDelete(mFragmentUniformStorage); + + mSamplersPS.clear(); + mSamplersVS.clear(); + + mUsedVertexSamplerRange = 0; + mUsedPixelSamplerRange = 0; + mDirtySamplerMapping = true; } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h index d645c57daa0..4baab9aa19c 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h @@ -10,6 +10,7 @@ #define LIBGLESV2_RENDERER_PROGRAMD3D_H_ #include "libGLESv2/renderer/ProgramImpl.h" +#include "libGLESv2/renderer/Workarounds.h" #include #include @@ -23,63 +24,194 @@ struct VertexFormat; namespace rx { - +class RendererD3D; class UniformStorage; class ProgramD3D : public ProgramImpl { public: - ProgramD3D(rx::Renderer *renderer); + ProgramD3D(RendererD3D *renderer); virtual ~ProgramD3D(); static ProgramD3D *makeProgramD3D(ProgramImpl *impl); static const ProgramD3D *makeProgramD3D(const ProgramImpl *impl); - Renderer *getRenderer() { return mRenderer; } - DynamicHLSL *getDynamicHLSL() { return mDynamicHLSL; } - const std::vector &getPixelShaderKey() { return mPixelShaderKey; } + const std::vector &getPixelShaderKey() { return mPixelShaderKey; } + int getShaderVersion() const { return mShaderVersion; } + GLenum getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; } + + GLint getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const; + GLenum getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const; + GLint getUsedSamplerRange(gl::SamplerType type) const; + void updateSamplerMapping(); + bool validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps); + + bool usesPointSize() const { return mUsesPointSize; } + bool usesPointSpriteEmulation() const; + bool usesGeometryShader() const; GLenum getBinaryFormat() { return GL_PROGRAM_BINARY_ANGLE; } - bool load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream); - bool save(gl::BinaryOutputStream *stream); + gl::LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream); + gl::Error save(gl::BinaryOutputStream *stream); - ShaderExecutable *getPixelExecutableForOutputLayout(gl::InfoLog &infoLog, const std::vector &outputSignature, - const std::vector &transformFeedbackLinkedVaryings, - bool separatedOutputBuffers); - ShaderExecutable *getVertexExecutableForInputLayout(gl::InfoLog &infoLog, - const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], - const sh::Attribute shaderAttributes[], - const std::vector &transformFeedbackLinkedVaryings, - bool separatedOutputBuffers); + gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutable **outExectuable); + gl::Error getPixelExecutableForOutputLayout(const std::vector &outputLayout, ShaderExecutable **outExectuable); + gl::Error getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], ShaderExecutable **outExectuable); + ShaderExecutable *getGeometryExecutable() const { return mGeometryExecutable; } - bool link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, - const std::vector &transformFeedbackVaryings, int *registers, - std::vector *linkedVaryings, std::map *outputVariables); + gl::LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, + int registers); - // D3D only - void initializeUniformStorage(const std::vector &uniforms); + gl::LinkResult link(const gl::Data &data, gl::InfoLog &infoLog, + gl::Shader *fragmentShader, gl::Shader *vertexShader, + const std::vector &transformFeedbackVaryings, + GLenum transformFeedbackBufferMode, + int *registers, std::vector *linkedVaryings, + std::map *outputVariables); + + void getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const; + + void initializeUniformStorage(); + gl::Error applyUniforms(); + gl::Error applyUniformBuffers(const std::vector boundBuffers, const gl::Caps &caps); + bool assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader, + unsigned int registerIndex, const gl::Caps &caps); + void dirtyAllUniforms(); + + void setUniform1fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform2fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform3fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform4fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform1iv(GLint location, GLsizei count, const GLint *v); + void setUniform2iv(GLint location, GLsizei count, const GLint *v); + void setUniform3iv(GLint location, GLsizei count, const GLint *v); + void setUniform4iv(GLint location, GLsizei count, const GLint *v); + void setUniform1uiv(GLint location, GLsizei count, const GLuint *v); + void setUniform2uiv(GLint location, GLsizei count, const GLuint *v); + void setUniform3uiv(GLint location, GLsizei count, const GLuint *v); + void setUniform4uiv(GLint location, GLsizei count, const GLuint *v); + void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + + void getUniformfv(GLint location, GLfloat *params); + void getUniformiv(GLint location, GLint *params); + void getUniformuiv(GLint location, GLuint *params); const UniformStorage &getVertexUniformStorage() const { return *mVertexUniformStorage; } const UniformStorage &getFragmentUniformStorage() const { return *mFragmentUniformStorage; } + bool linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader, + const gl::Caps &caps); + bool defineUniformBlock(gl::InfoLog &infoLog, const gl::Shader &shader, const sh::InterfaceBlock &interfaceBlock, const gl::Caps &caps); + void reset(); private: DISALLOW_COPY_AND_ASSIGN(ProgramD3D); - Renderer *mRenderer; + class VertexExecutable + { + public: + VertexExecutable(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], + const GLenum signature[gl::MAX_VERTEX_ATTRIBS], + ShaderExecutable *shaderExecutable); + ~VertexExecutable(); + + bool matchesSignature(const GLenum convertedLayout[gl::MAX_VERTEX_ATTRIBS]) const; + + const gl::VertexFormat *inputs() const { return mInputs; } + const GLenum *signature() const { return mSignature; } + ShaderExecutable *shaderExecutable() const { return mShaderExecutable; } + + private: + gl::VertexFormat mInputs[gl::MAX_VERTEX_ATTRIBS]; + GLenum mSignature[gl::MAX_VERTEX_ATTRIBS]; + ShaderExecutable *mShaderExecutable; + }; + + class PixelExecutable + { + public: + PixelExecutable(const std::vector &outputSignature, ShaderExecutable *shaderExecutable); + ~PixelExecutable(); + + bool matchesSignature(const std::vector &signature) const { return mOutputSignature == signature; } + + const std::vector &outputSignature() const { return mOutputSignature; } + ShaderExecutable *shaderExecutable() const { return mShaderExecutable; } + + private: + std::vector mOutputSignature; + ShaderExecutable *mShaderExecutable; + }; + + struct Sampler + { + Sampler(); + + bool active; + GLint logicalTextureUnit; + GLenum textureType; + }; + + void defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister); + void defineUniform(GLenum shader, const sh::ShaderVariable &uniform, const std::string &fullName, + sh::HLSLBlockEncoder *encoder); + bool indexSamplerUniform(const gl::LinkedUniform &uniform, gl::InfoLog &infoLog, const gl::Caps &caps); + bool indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps); + static bool assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount, + std::vector &outSamplers, GLuint *outUsedRange); + + template + void setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType); + + template + void setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType); + + template + void getUniformv(GLint location, T *params, GLenum uniformType); + + template + void defineUniformBlockMembers(const std::vector &fields, const std::string &prefix, int blockIndex, + sh::BlockLayoutEncoder *encoder, std::vector *blockUniformIndexes, + bool inRowMajorLayout); + + RendererD3D *mRenderer; DynamicHLSL *mDynamicHLSL; + std::vector mVertexExecutables; + std::vector mPixelExecutables; + ShaderExecutable *mGeometryExecutable; + std::string mVertexHLSL; - rx::D3DWorkaroundType mVertexWorkarounds; + D3DWorkaroundType mVertexWorkarounds; std::string mPixelHLSL; - rx::D3DWorkaroundType mPixelWorkarounds; + D3DWorkaroundType mPixelWorkarounds; bool mUsesFragDepth; - std::vector mPixelShaderKey; + std::vector mPixelShaderKey; + + bool mUsesPointSize; UniformStorage *mVertexUniformStorage; UniformStorage *mFragmentUniformStorage; + + GLenum mTransformFeedbackBufferMode; + + std::vector mSamplersPS; + std::vector mSamplersVS; + GLuint mUsedVertexSamplerRange; + GLuint mUsedPixelSamplerRange; + bool mDirtySamplerMapping; + + int mShaderVersion; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.cpp new file mode 100644 index 00000000000..cb4af367a2b --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.cpp @@ -0,0 +1,108 @@ +// +// 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. +// + +// RenderbufferD3d.cpp: Implements the RenderbufferD3D class, a specialization of RenderbufferImpl + + +#include "libGLESv2/renderer/d3d/RenderbufferD3D.h" + +#include "libGLESv2/renderer/d3d/RendererD3D.h" +#include "libGLESv2/renderer/RenderTarget.h" + +namespace rx +{ +RenderbufferD3D::RenderbufferD3D(RendererD3D *renderer) : mRenderer(renderer) +{ + mRenderTarget = NULL; +} + +RenderbufferD3D::~RenderbufferD3D() +{ + SafeDelete(mRenderTarget); +} + +RenderbufferD3D *RenderbufferD3D::makeRenderbufferD3D(RenderbufferImpl *renderbuffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(RenderbufferD3D*, renderbuffer)); + return static_cast(renderbuffer); +} + +gl::Error RenderbufferD3D::setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) +{ + // If the renderbuffer parameters are queried, the calling function + // will expect one of the valid renderbuffer formats for use in + // glRenderbufferStorage, but we should create depth and stencil buffers + // as DEPTH24_STENCIL8 + GLenum creationFormat = internalformat; + if (internalformat == GL_DEPTH_COMPONENT16 || internalformat == GL_STENCIL_INDEX8) + { + creationFormat = GL_DEPTH24_STENCIL8_OES; + } + + RenderTarget *newRT = NULL; + gl::Error error = mRenderer->createRenderTarget(width, height, creationFormat, samples, &newRT); + if (error.isError()) + { + return error; + } + + SafeDelete(mRenderTarget); + mRenderTarget = newRT; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error RenderbufferD3D::setStorage(SwapChain *swapChain, bool depth) +{ + RenderTarget *newRT = NULL; + gl::Error error = mRenderer->createRenderTarget(swapChain, depth, &newRT); + if (error.isError()) + { + return error; + } + + SafeDelete(mRenderTarget); + mRenderTarget = newRT; + + return gl::Error(GL_NO_ERROR); +} + +GLsizei RenderbufferD3D::getWidth() const +{ + return (mRenderTarget ? mRenderTarget->getWidth() : 0); +} + +GLsizei RenderbufferD3D::getHeight() const +{ + return (mRenderTarget ? mRenderTarget->getHeight() : 0); +} + +GLenum RenderbufferD3D::getInternalFormat() const +{ + return (mRenderTarget ? mRenderTarget->getInternalFormat() : GL_RGBA4); +} + +GLenum RenderbufferD3D::getActualFormat() const +{ + return (mRenderTarget ? mRenderTarget->getActualFormat() : GL_RGBA4); +} + +GLsizei RenderbufferD3D::getSamples() const +{ + return (mRenderTarget ? mRenderTarget->getSamples() : 0); +} + +RenderTarget *RenderbufferD3D::getRenderTarget() +{ + return mRenderTarget; +} + +unsigned int RenderbufferD3D::getRenderTargetSerial() const +{ + return (mRenderTarget ? mRenderTarget->getSerial() : 0); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.h new file mode 100644 index 00000000000..9440a449f2c --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.h @@ -0,0 +1,51 @@ +// +// 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. +// + +// RenderbufferD3d.h: Defines the RenderbufferD3D class which implements RenderbufferImpl. + +#ifndef LIBGLESV2_RENDERER_RENDERBUFFERD3D_H_ +#define LIBGLESV2_RENDERER_RENDERBUFFERD3D_H_ + +#include "angle_gl.h" + +#include "common/angleutils.h" +#include "libGLESv2/renderer/RenderbufferImpl.h" + +namespace rx +{ +class RendererD3D; +class RenderTarget; +class SwapChain; + +class RenderbufferD3D : public RenderbufferImpl +{ + public: + RenderbufferD3D(RendererD3D *renderer); + virtual ~RenderbufferD3D(); + + static RenderbufferD3D *makeRenderbufferD3D(RenderbufferImpl *renderbuffer); + + virtual gl::Error setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) override; + gl::Error setStorage(SwapChain *swapChain, bool depth); + + virtual GLsizei getWidth() const; + virtual GLsizei getHeight() const; + virtual GLenum getInternalFormat() const; + virtual GLenum getActualFormat() const; + virtual GLsizei getSamples() const; + + RenderTarget *getRenderTarget(); + unsigned int getRenderTargetSerial() const; + + private: + DISALLOW_COPY_AND_ASSIGN(RenderbufferD3D); + + RendererD3D *mRenderer; + RenderTarget *mRenderTarget; +}; +} + +#endif // LIBGLESV2_RENDERER_RENDERBUFFERD3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp new file mode 100644 index 00000000000..97da6da7fdc --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp @@ -0,0 +1,796 @@ +// +// 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. +// + +// RendererD3D.cpp: Implementation of the base D3D Renderer. + +#include "libGLESv2/renderer/d3d/RendererD3D.h" + +#include "libGLESv2/renderer/d3d/IndexDataManager.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/FramebufferAttachment.h" +#include "libGLESv2/ResourceManager.h" +#include "libGLESv2/State.h" +#include "libGLESv2/VertexArray.h" +#include "libGLESv2/formatutils.h" +#include "common/utilities.h" + +namespace rx +{ + +RendererD3D::RendererD3D(egl::Display *display) + : mDisplay(display) +{ +} + +RendererD3D::~RendererD3D() +{ + for (gl::TextureMap::iterator i = mIncompleteTextures.begin(); i != mIncompleteTextures.end(); ++i) + { + i->second.set(NULL); + } + mIncompleteTextures.clear(); +} + +// static +RendererD3D *RendererD3D::makeRendererD3D(Renderer *renderer) +{ + ASSERT(HAS_DYNAMIC_TYPE(RendererD3D*, renderer)); + return static_cast(renderer); +} + +gl::Error RendererD3D::drawElements(const gl::Data &data, + GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei instances, + const RangeUI &indexRange) +{ + ASSERT(data.state->getCurrentProgramId() != 0); + + gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary(); + programBinary->updateSamplerMapping(); + + gl::Error error = generateSwizzles(data); + if (error.isError()) + { + return error; + } + + if (!applyPrimitiveType(mode, count)) + { + return gl::Error(GL_NO_ERROR); + } + + error = applyRenderTarget(data, mode, false); + if (error.isError()) + { + return error; + } + + error = applyState(data, mode); + if (error.isError()) + { + return error; + } + + gl::VertexArray *vao = data.state->getVertexArray(); + TranslatedIndexData indexInfo; + indexInfo.indexRange = indexRange; + error = applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo); + if (error.isError()) + { + return error; + } + + GLsizei vertexCount = indexInfo.indexRange.length() + 1; + error = applyVertexBuffer(*data.state, indexInfo.indexRange.start, vertexCount, instances); + if (error.isError()) + { + return error; + } + + bool transformFeedbackActive = applyTransformFeedbackBuffers(data); + // Transform feedback is not allowed for DrawElements, this error should have been caught at the API validation + // layer. + ASSERT(!transformFeedbackActive); + + error = applyShaders(data, transformFeedbackActive); + if (error.isError()) + { + return error; + } + + error = applyTextures(data); + if (error.isError()) + { + return error; + } + + error = applyUniformBuffers(data); + if (error.isError()) + { + return error; + } + + if (!skipDraw(data, mode)) + { + error = drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error RendererD3D::drawArrays(const gl::Data &data, + GLenum mode, GLint first, + GLsizei count, GLsizei instances) +{ + ASSERT(data.state->getCurrentProgramId() != 0); + + gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary(); + programBinary->updateSamplerMapping(); + + gl::Error error = generateSwizzles(data); + if (error.isError()) + { + return error; + } + + if (!applyPrimitiveType(mode, count)) + { + return gl::Error(GL_NO_ERROR); + } + + error = applyRenderTarget(data, mode, false); + if (error.isError()) + { + return error; + } + + error = applyState(data, mode); + if (error.isError()) + { + return error; + } + + error = applyVertexBuffer(*data.state, first, count, instances); + if (error.isError()) + { + return error; + } + + bool transformFeedbackActive = applyTransformFeedbackBuffers(data); + + error = applyShaders(data, transformFeedbackActive); + if (error.isError()) + { + return error; + } + + error = applyTextures(data); + if (error.isError()) + { + return error; + } + + error = applyUniformBuffers(data); + if (error.isError()) + { + return error; + } + + if (!skipDraw(data, mode)) + { + error = drawArrays(mode, count, instances, transformFeedbackActive); + if (error.isError()) + { + return error; + } + + if (transformFeedbackActive) + { + markTransformFeedbackUsage(data); + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error RendererD3D::generateSwizzles(const gl::Data &data, gl::SamplerType type) +{ + gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary(); + + size_t samplerRange = programBinary->getUsedSamplerRange(type); + + for (size_t i = 0; i < samplerRange; i++) + { + GLenum textureType = programBinary->getSamplerTextureType(type, i); + GLint textureUnit = programBinary->getSamplerMapping(type, i, *data.caps); + if (textureUnit != -1) + { + gl::Texture *texture = data.state->getSamplerTexture(textureUnit, textureType); + ASSERT(texture); + if (texture->getSamplerState().swizzleRequired()) + { + gl::Error error = generateSwizzle(texture); + if (error.isError()) + { + return error; + } + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error RendererD3D::generateSwizzles(const gl::Data &data) +{ + gl::Error error = generateSwizzles(data, gl::SAMPLER_VERTEX); + if (error.isError()) + { + return error; + } + + error = generateSwizzles(data, gl::SAMPLER_PIXEL); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +// Applies the render target surface, depth stencil surface, viewport rectangle and +// scissor rectangle to the renderer +gl::Error RendererD3D::applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport) +{ + const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer(); + ASSERT(framebufferObject && framebufferObject->completeness(data) == GL_FRAMEBUFFER_COMPLETE); + + gl::Error error = applyRenderTarget(framebufferObject); + if (error.isError()) + { + return error; + } + + float nearZ, farZ; + data.state->getDepthRange(&nearZ, &farZ); + setViewport(data.state->getViewport(), nearZ, farZ, drawMode, + data.state->getRasterizerState().frontFace, ignoreViewport); + + setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled()); + + return gl::Error(GL_NO_ERROR); +} + +// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D device +gl::Error RendererD3D::applyState(const gl::Data &data, GLenum drawMode) +{ + const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer(); + int samples = framebufferObject->getSamples(data); + + gl::RasterizerState rasterizer = data.state->getRasterizerState(); + rasterizer.pointDrawMode = (drawMode == GL_POINTS); + rasterizer.multiSample = (samples != 0); + + gl::Error error = setRasterizerState(rasterizer); + if (error.isError()) + { + return error; + } + + unsigned int mask = 0; + if (data.state->isSampleCoverageEnabled()) + { + GLclampf coverageValue; + bool coverageInvert = false; + data.state->getSampleCoverageParams(&coverageValue, &coverageInvert); + if (coverageValue != 0) + { + float threshold = 0.5f; + + for (int i = 0; i < samples; ++i) + { + mask <<= 1; + + if ((i + 1) * coverageValue >= threshold) + { + threshold += 1.0f; + mask |= 1; + } + } + } + + if (coverageInvert) + { + mask = ~mask; + } + } + else + { + mask = 0xFFFFFFFF; + } + error = setBlendState(framebufferObject, data.state->getBlendState(), data.state->getBlendColor(), mask); + if (error.isError()) + { + return error; + } + + error = setDepthStencilState(data.state->getDepthStencilState(), data.state->getStencilRef(), + data.state->getStencilBackRef(), rasterizer.frontFace == GL_CCW); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +bool RendererD3D::applyTransformFeedbackBuffers(const gl::Data &data) +{ + gl::TransformFeedback *curTransformFeedback = data.state->getCurrentTransformFeedback(); + if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) + { + applyTransformFeedbackBuffers(*data.state); + return true; + } + else + { + return false; + } +} + +// Applies the shaders and shader constants to the Direct3D device +gl::Error RendererD3D::applyShaders(const gl::Data &data, bool transformFeedbackActive) +{ + gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary(); + + gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]; + gl::VertexFormat::GetInputLayout(inputLayout, programBinary, *data.state); + + const gl::Framebuffer *fbo = data.state->getDrawFramebuffer(); + + gl::Error error = applyShaders(programBinary, inputLayout, fbo, data.state->getRasterizerState().rasterizerDiscard, transformFeedbackActive); + if (error.isError()) + { + return error; + } + + return programBinary->applyUniforms(); +} + +// For each Direct3D sampler of either the pixel or vertex stage, +// looks up the corresponding OpenGL texture image unit and texture type, +// and sets the texture and its addressing/filtering state (or NULL when inactive). +gl::Error RendererD3D::applyTextures(const gl::Data &data, gl::SamplerType shaderType, + const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount) +{ + gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary(); + + size_t samplerRange = programBinary->getUsedSamplerRange(shaderType); + for (size_t samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++) + { + GLenum textureType = programBinary->getSamplerTextureType(shaderType, samplerIndex); + GLint textureUnit = programBinary->getSamplerMapping(shaderType, samplerIndex, *data.caps); + if (textureUnit != -1) + { + gl::Texture *texture = data.state->getSamplerTexture(textureUnit, textureType); + ASSERT(texture); + gl::SamplerState sampler = texture->getSamplerState(); + + gl::Sampler *samplerObject = data.state->getSampler(textureUnit); + if (samplerObject) + { + samplerObject->getState(&sampler); + } + + // TODO: std::binary_search may become unavailable using older versions of GCC + if (texture->isSamplerComplete(sampler, *data.textureCaps, *data.extensions, data.clientVersion) && + !std::binary_search(framebufferSerials.begin(), framebufferSerials.begin() + framebufferSerialCount, texture->getTextureSerial())) + { + gl::Error error = setSamplerState(shaderType, samplerIndex, texture, sampler); + if (error.isError()) + { + return error; + } + + error = setTexture(shaderType, samplerIndex, texture); + if (error.isError()) + { + return error; + } + } + else + { + // Texture is not sampler complete or it is in use by the framebuffer. Bind the incomplete texture. + gl::Texture *incompleteTexture = getIncompleteTexture(textureType); + gl::Error error = setTexture(shaderType, samplerIndex, incompleteTexture); + if (error.isError()) + { + return error; + } + } + } + else + { + // No texture bound to this slot even though it is used by the shader, bind a NULL texture + gl::Error error = setTexture(shaderType, samplerIndex, NULL); + if (error.isError()) + { + return error; + } + } + } + + // Set all the remaining textures to NULL + size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? data.caps->maxTextureImageUnits + : data.caps->maxVertexTextureImageUnits; + for (size_t samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++) + { + gl::Error error = setTexture(shaderType, samplerIndex, NULL); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error RendererD3D::applyTextures(const gl::Data &data) +{ + FramebufferTextureSerialArray framebufferSerials; + size_t framebufferSerialCount = getBoundFramebufferTextureSerials(data, &framebufferSerials); + + gl::Error error = applyTextures(data, gl::SAMPLER_VERTEX, framebufferSerials, framebufferSerialCount); + if (error.isError()) + { + return error; + } + + error = applyTextures(data, gl::SAMPLER_PIXEL, framebufferSerials, framebufferSerialCount); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error RendererD3D::applyUniformBuffers(const gl::Data &data) +{ + gl::Program *programObject = data.resourceManager->getProgram(data.state->getCurrentProgramId()); + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + + std::vector boundBuffers; + + for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < programBinary->getActiveUniformBlockCount(); uniformBlockIndex++) + { + GLuint blockBinding = programObject->getUniformBlockBinding(uniformBlockIndex); + + if (data.state->getIndexedUniformBuffer(blockBinding)->id() == 0) + { + // undefined behaviour + return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to have a used but unbound uniform buffer."); + } + else + { + gl::Buffer *uniformBuffer = data.state->getIndexedUniformBuffer(blockBinding); + ASSERT(uniformBuffer); + boundBuffers.push_back(uniformBuffer); + } + } + + return programBinary->applyUniformBuffers(boundBuffers, *data.caps); +} + +bool RendererD3D::skipDraw(const gl::Data &data, GLenum drawMode) +{ + if (drawMode == GL_POINTS) + { + // ProgramBinary assumes non-point rendering if gl_PointSize isn't written, + // which affects varying interpolation. Since the value of gl_PointSize is + // undefined when not written, just skip drawing to avoid unexpected results. + if (!data.state->getCurrentProgramBinary()->usesPointSize()) + { + // This is stictly speaking not an error, but developers should be + // notified of risking undefined behavior. + ERR("Point rendering without writing to gl_PointSize."); + + return true; + } + } + else if (gl::IsTriangleMode(drawMode)) + { + if (data.state->getRasterizerState().cullFace && data.state->getRasterizerState().cullMode == GL_FRONT_AND_BACK) + { + return true; + } + } + + return false; +} + +void RendererD3D::markTransformFeedbackUsage(const gl::Data &data) +{ + for (size_t i = 0; i < data.caps->maxTransformFeedbackSeparateAttributes; i++) + { + gl::Buffer *buffer = data.state->getIndexedTransformFeedbackBuffer(i); + if (buffer) + { + buffer->markTransformFeedbackUsage(); + } + } +} + +size_t RendererD3D::getBoundFramebufferTextureSerials(const gl::Data &data, + FramebufferTextureSerialArray *outSerialArray) +{ + size_t serialCount = 0; + + const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer(); + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; i++) + { + gl::FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i); + if (attachment && attachment->isTexture()) + { + gl::Texture *texture = attachment->getTexture(); + (*outSerialArray)[serialCount++] = texture->getTextureSerial(); + } + } + + gl::FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer(); + if (depthStencilAttachment && depthStencilAttachment->isTexture()) + { + gl::Texture *depthStencilTexture = depthStencilAttachment->getTexture(); + (*outSerialArray)[serialCount++] = depthStencilTexture->getTextureSerial(); + } + + std::sort(outSerialArray->begin(), outSerialArray->begin() + serialCount); + + return serialCount; +} + +gl::Texture *RendererD3D::getIncompleteTexture(GLenum type) +{ + if (mIncompleteTextures.find(type) == mIncompleteTextures.end()) + { + const GLubyte color[] = { 0, 0, 0, 255 }; + const gl::PixelUnpackState incompleteUnpackState(1); + + gl::Texture* t = NULL; + switch (type) + { + default: + UNREACHABLE(); + // default falls through to TEXTURE_2D + + case GL_TEXTURE_2D: + { + gl::Texture2D *incomplete2d = new gl::Texture2D(createTexture(GL_TEXTURE_2D), gl::Texture::INCOMPLETE_TEXTURE_ID); + incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); + t = incomplete2d; + } + break; + + case GL_TEXTURE_CUBE_MAP: + { + gl::TextureCubeMap *incompleteCube = new gl::TextureCubeMap(createTexture(GL_TEXTURE_CUBE_MAP), gl::Texture::INCOMPLETE_TEXTURE_ID); + + incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); + incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); + incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); + incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); + incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); + incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); + + t = incompleteCube; + } + break; + + case GL_TEXTURE_3D: + { + gl::Texture3D *incomplete3d = new gl::Texture3D(createTexture(GL_TEXTURE_3D), gl::Texture::INCOMPLETE_TEXTURE_ID); + incomplete3d->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); + + t = incomplete3d; + } + break; + + case GL_TEXTURE_2D_ARRAY: + { + gl::Texture2DArray *incomplete2darray = new gl::Texture2DArray(createTexture(GL_TEXTURE_2D_ARRAY), gl::Texture::INCOMPLETE_TEXTURE_ID); + incomplete2darray->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); + + t = incomplete2darray; + } + break; + } + + mIncompleteTextures[type].set(t); + } + + return mIncompleteTextures[type].get(); +} + +gl::Error RendererD3D::clear(const gl::Data &data, GLbitfield mask) +{ + gl::ClearParameters clearParams = data.state->getClearParameters(mask); + + // Clips the clear to the scissor rectangle but not the viewport + gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true); + if (error.isError()) + { + return error; + } + + return clear(clearParams, data.state->getDrawFramebuffer()); +} + +gl::Error RendererD3D::clearBufferfv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLfloat *values) +{ + // glClearBufferfv can be called to clear the color buffer or depth buffer + gl::ClearParameters clearParams = data.state->getClearParameters(0); + + if (buffer == GL_COLOR) + { + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + clearParams.clearColor[i] = (drawbuffer == static_cast(i)); + } + clearParams.colorFClearValue = gl::ColorF(values[0], values[1], values[2], values[3]); + clearParams.colorClearType = GL_FLOAT; + } + + if (buffer == GL_DEPTH) + { + clearParams.clearDepth = true; + clearParams.depthClearValue = values[0]; + } + + // Clips the clear to the scissor rectangle but not the viewport + gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true); + if (error.isError()) + { + return error; + } + + return clear(clearParams, data.state->getDrawFramebuffer()); +} + +gl::Error RendererD3D::clearBufferuiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLuint *values) +{ + // glClearBufferuiv can only be called to clear a color buffer + gl::ClearParameters clearParams = data.state->getClearParameters(0); + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + clearParams.clearColor[i] = (drawbuffer == static_cast(i)); + } + clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]); + clearParams.colorClearType = GL_UNSIGNED_INT; + + // Clips the clear to the scissor rectangle but not the viewport + gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true); + if (error.isError()) + { + return error; + } + + return clear(clearParams, data.state->getDrawFramebuffer()); +} + +gl::Error RendererD3D::clearBufferiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLint *values) +{ + // glClearBufferiv can be called to clear the color buffer or stencil buffer + gl::ClearParameters clearParams = data.state->getClearParameters(0); + + if (buffer == GL_COLOR) + { + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + clearParams.clearColor[i] = (drawbuffer == static_cast(i)); + } + clearParams.colorIClearValue = gl::ColorI(values[0], values[1], values[2], values[3]); + clearParams.colorClearType = GL_INT; + } + + if (buffer == GL_STENCIL) + { + clearParams.clearStencil = true; + clearParams.stencilClearValue = values[1]; + } + + // Clips the clear to the scissor rectangle but not the viewport + gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true); + if (error.isError()) + { + return error; + } + + return clear(clearParams, data.state->getDrawFramebuffer()); +} + +gl::Error RendererD3D::clearBufferfi(const gl::Data &data, GLenum buffer, GLint drawbuffer, + GLfloat depth, GLint stencil) +{ + if (data.state->isRasterizerDiscardEnabled()) + { + return gl::Error(GL_NO_ERROR); + } + + // glClearBufferfi can only be called to clear a depth stencil buffer + gl::ClearParameters clearParams = data.state->getClearParameters(0); + clearParams.clearDepth = true; + clearParams.depthClearValue = depth; + clearParams.clearStencil = true; + clearParams.stencilClearValue = stencil; + + // Clips the clear to the scissor rectangle but not the viewport + gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true); + if (error.isError()) + { + return error; + } + + return clear(clearParams, data.state->getDrawFramebuffer()); +} + +gl::Error RendererD3D::blitFramebuffer(const gl::Data &data, + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) +{ + const gl::Framebuffer *readFramebuffer = data.state->getReadFramebuffer(); + const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer(); + + bool blitRenderTarget = false; + bool blitDepth = false; + bool blitStencil = false; + if ((mask & GL_COLOR_BUFFER_BIT) && readFramebuffer->getReadColorbuffer() && drawFramebuffer->getFirstColorbuffer()) + { + blitRenderTarget = true; + } + if ((mask & GL_STENCIL_BUFFER_BIT) && readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer()) + { + blitStencil = true; + } + if ((mask & GL_DEPTH_BUFFER_BIT) && readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer()) + { + blitDepth = true; + } + + gl::Rectangle srcRect(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0); + gl::Rectangle dstRect(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0); + if (blitRenderTarget || blitDepth || blitStencil) + { + const gl::Rectangle *scissor = data.state->isScissorTestEnabled() ? &data.state->getScissor() : NULL; + gl::Error error = blitRect(readFramebuffer, srcRect, drawFramebuffer, dstRect, scissor, + blitRenderTarget, blitDepth, blitStencil, filter); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error RendererD3D::readPixels(const gl::Data &data, GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLsizei *bufSize, void* pixels) +{ + const gl::Framebuffer *framebuffer = data.state->getReadFramebuffer(); + + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type); + const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat); + GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, width, data.state->getPackAlignment()); + + return readPixels(framebuffer, x, y, width, height, format, type, outputPitch, data.state->getPackState(), + reinterpret_cast(pixels)); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h new file mode 100644 index 00000000000..99192076677 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h @@ -0,0 +1,195 @@ + +// 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. +// + +// RendererD3D.h: Defines a back-end specific class for the DirectX renderer. + +#ifndef LIBGLESV2_RENDERER_RENDERERD3D_H_ +#define LIBGLESV2_RENDERER_RENDERERD3D_H_ + +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/Data.h" + +//FIXME(jmadill): std::array is currently prohibited by Chromium style guide +#include + +namespace gl +{ +class InfoLog; +struct LinkedVarying; +class Texture; +} + +namespace rx +{ +class TextureStorage; +class VertexBuffer; +class IndexBuffer; +class ShaderExecutable; +class SwapChain; +class RenderTarget; +class Image; +class TextureStorage; +class UniformStorage; + +class RendererD3D : public Renderer +{ + public: + explicit RendererD3D(egl::Display *display); + virtual ~RendererD3D(); + + static RendererD3D *makeRendererD3D(Renderer *renderer); + + gl::Error drawArrays(const gl::Data &data, + GLenum mode, GLint first, + GLsizei count, GLsizei instances) override; + + gl::Error drawElements(const gl::Data &data, + GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei instances, + const RangeUI &indexRange) override; + + gl::Error clear(const gl::Data &data, GLbitfield mask) override; + gl::Error clearBufferfv(const gl::Data &data, GLenum buffer, int drawbuffer, const GLfloat *values) override; + gl::Error clearBufferuiv(const gl::Data &data, GLenum buffer, int drawbuffer, const GLuint *values) override; + gl::Error clearBufferiv(const gl::Data &data, GLenum buffer, int drawbuffer, const GLint *values) override; + gl::Error clearBufferfi(const gl::Data &data, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) override; + + gl::Error readPixels(const gl::Data &data, GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLsizei *bufSize, void* pixels) override; + + gl::Error blitFramebuffer(const gl::Data &data, + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) override; + + // Direct3D Specific methods + virtual SwapChain *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0; + + virtual gl::Error generateSwizzle(gl::Texture *texture) = 0; + virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler) = 0; + virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0; + + virtual gl::Error setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]) = 0; + + virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState) = 0; + virtual gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, + unsigned int sampleMask) = 0; + virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, + int stencilBackRef, bool frontFaceCCW) = 0; + + virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled) = 0; + virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, + bool ignoreViewport) = 0; + + virtual gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) = 0; + virtual gl::Error applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + bool rasterizerDiscard, bool transformFeedbackActive) = 0; + virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector &uniformArray) = 0; + virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0; + virtual gl::Error applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances) = 0; + virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) = 0; + virtual void applyTransformFeedbackBuffers(const gl::State& state) = 0; + + virtual void markAllStateDirty() = 0; + + virtual unsigned int getReservedVertexUniformVectors() const = 0; + virtual unsigned int getReservedFragmentUniformVectors() const = 0; + virtual unsigned int getReservedVertexUniformBuffers() const = 0; + virtual unsigned int getReservedFragmentUniformBuffers() const = 0; + virtual bool getShareHandleSupport() const = 0; + virtual bool getPostSubBufferSupport() const = 0; + + // Pixel operations + virtual gl::Error copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) = 0; + virtual gl::Error copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level) = 0; + virtual gl::Error copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) = 0; + virtual gl::Error copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) = 0; + + virtual gl::Error readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, + GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) = 0; + + // RenderTarget creation + virtual gl::Error createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT) = 0; + virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT) = 0; + + // Shader operations + virtual void releaseShaderCompiler() = 0; + virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, ShaderExecutable **outExecutable) = 0; + virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, D3DWorkaroundType workaround, + ShaderExecutable **outExectuable) = 0; + virtual UniformStorage *createUniformStorage(size_t storageSize) = 0; + + // Image operations + virtual Image *createImage() = 0; + virtual gl::Error generateMipmap(Image *dest, Image *source) = 0; + virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain) = 0; + virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) = 0; + virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels) = 0; + virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0; + virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0; + + // Buffer-to-texture and Texture-to-buffer copies + virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const = 0; + virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) = 0; + + virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const = 0; + virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const = 0; + + virtual VertexBuffer *createVertexBuffer() = 0; + virtual IndexBuffer *createIndexBuffer() = 0; + + protected: + virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) = 0; + virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, + gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) = 0; + virtual gl::Error clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) = 0; + virtual gl::Error blitRect(const gl::Framebuffer *readTarget, const gl::Rectangle &readRect, + const gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, + const gl::Rectangle *scissor, bool blitRenderTarget, + bool blitDepth, bool blitStencil, GLenum filter) = 0; + + egl::Display *mDisplay; + + private: + DISALLOW_COPY_AND_ASSIGN(RendererD3D); + + //FIXME(jmadill): std::array is currently prohibited by Chromium style guide + typedef std::array FramebufferTextureSerialArray; + + gl::Error generateSwizzles(const gl::Data &data, gl::SamplerType type); + gl::Error generateSwizzles(const gl::Data &data); + + gl::Error applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport); + gl::Error applyState(const gl::Data &data, GLenum drawMode); + bool applyTransformFeedbackBuffers(const gl::Data &data); + gl::Error applyShaders(const gl::Data &data, bool transformFeedbackActive); + gl::Error applyTextures(const gl::Data &data, gl::SamplerType shaderType, + const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount); + gl::Error applyTextures(const gl::Data &data); + gl::Error applyUniformBuffers(const gl::Data &data); + + bool skipDraw(const gl::Data &data, GLenum drawMode); + void markTransformFeedbackUsage(const gl::Data &data); + + size_t getBoundFramebufferTextureSerials(const gl::Data &data, + FramebufferTextureSerialArray *outSerialArray); + gl::Texture *getIncompleteTexture(GLenum type); + + gl::TextureMap mIncompleteTextures; +}; + +} + +#endif // LIBGLESV2_RENDERER_RENDERERD3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp index c472113ebac..8a97579e16a 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp @@ -6,13 +6,36 @@ // ShaderD3D.cpp: Defines the rx::ShaderD3D class which implements rx::ShaderImpl. -#include "libGLESv2/renderer/d3d/ShaderD3D.h" -#include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/Shader.h" #include "libGLESv2/main.h" +#include "libGLESv2/renderer/d3d/RendererD3D.h" +#include "libGLESv2/renderer/d3d/ShaderD3D.h" +#include "common/features.h" #include "common/utilities.h" +// Definitions local to the translation unit +namespace +{ + +const char *GetShaderTypeString(GLenum type) +{ + switch (type) + { + case GL_VERTEX_SHADER: + return "VERTEX"; + + case GL_FRAGMENT_SHADER: + return "FRAGMENT"; + + default: + UNREACHABLE(); + return ""; + } +} + +} + namespace rx { @@ -44,13 +67,13 @@ const std::vector *GetShaderVariables(const std::vector *variableLis return variableList; } -ShaderD3D::ShaderD3D(GLenum type, rx::Renderer *renderer) +ShaderD3D::ShaderD3D(const gl::Data &data, GLenum type, RendererD3D *renderer) : mType(type), mRenderer(renderer), mShaderVersion(100) { uncompile(); - initializeCompiler(); + initializeCompiler(data); } ShaderD3D::~ShaderD3D() @@ -69,23 +92,28 @@ const ShaderD3D *ShaderD3D::makeShaderD3D(const ShaderImpl *impl) return static_cast(impl); } +std::string ShaderD3D::getDebugInfo() const +{ + return mDebugInfo + std::string("\n// ") + GetShaderTypeString(mType) + " SHADER END\n"; +} + // Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler) -void ShaderD3D::initializeCompiler() +void ShaderD3D::initializeCompiler(const gl::Data &data) { if (!mFragmentCompiler) { - int result = ShInitialize(); + bool result = ShInitialize(); if (result) { + ShShaderSpec specVersion = (data.clientVersion >= 3) ? SH_GLES3_SPEC : SH_GLES2_SPEC; ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT; ShBuiltInResources resources; ShInitBuiltInResources(&resources); - // TODO(geofflang): use context's caps - const gl::Caps &caps = mRenderer->getRendererCaps(); - const gl::Extensions &extensions = mRenderer->getRendererExtensions(); + const gl::Caps &caps = *data.caps; + const gl::Extensions &extensions = *data.extensions; resources.MaxVertexAttribs = caps.maxVertexAttributes; resources.MaxVertexUniformVectors = caps.maxVertexUniformVectors; @@ -107,8 +135,8 @@ void ShaderD3D::initializeCompiler() resources.MinProgramTexelOffset = caps.minProgramTexelOffset; resources.MaxProgramTexelOffset = caps.maxProgramTexelOffset; - mFragmentCompiler = ShConstructCompiler(GL_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources); - mVertexCompiler = ShConstructCompiler(GL_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources); + mFragmentCompiler = ShConstructCompiler(GL_FRAGMENT_SHADER, specVersion, hlslVersion, &resources); + mVertexCompiler = ShConstructCompiler(GL_VERTEX_SHADER, specVersion, hlslVersion, &resources); } } } @@ -126,7 +154,7 @@ void ShaderD3D::releaseCompiler() void ShaderD3D::parseVaryings(void *compiler) { - if (!mHlsl.empty()) + if (!mHlsl.empty()) { const std::vector *varyings = ShGetVaryings(compiler); ASSERT(varyings); @@ -183,21 +211,25 @@ void ShaderD3D::uncompile() mInterfaceBlocks.clear(); mActiveAttributes.clear(); mActiveOutputVariables.clear(); + mDebugInfo.clear(); } -void ShaderD3D::compileToHLSL(void *compiler, const std::string &source) +void ShaderD3D::compileToHLSL(const gl::Data &data, void *compiler, const std::string &source) { // ensure the compiler is loaded - initializeCompiler(); + initializeCompiler(data); int compileOptions = (SH_OBJECT_CODE | SH_VARIABLES); std::string sourcePath; + +#if !defined (ANGLE_ENABLE_WINDOWS_STORE) if (gl::perfActive()) { sourcePath = getTempPath(); writeFile(sourcePath.c_str(), source.c_str(), source.length()); compileOptions |= SH_LINE_DIRECTIVES; } +#endif int result; if (sourcePath.empty()) @@ -220,25 +252,20 @@ void ShaderD3D::compileToHLSL(void *compiler, const std::string &source) result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH); } - size_t shaderVersion = 100; - ShGetInfo(compiler, SH_SHADER_VERSION, &shaderVersion); + mShaderVersion = ShGetShaderVersion(compiler); - mShaderVersion = static_cast(shaderVersion); - - if (shaderVersion == 300 && mRenderer->getCurrentClientVersion() < 3) + if (mShaderVersion == 300 && data.clientVersion < 3) { mInfoLog = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts"; TRACE("\n%s", mInfoLog.c_str()); } else if (result) { - size_t objCodeLen = 0; - ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen); - - char* outputHLSL = new char[objCodeLen]; - ShGetObjectCode(compiler, outputHLSL); + mHlsl = ShGetObjectCode(compiler); #ifdef _DEBUG + // Prefix hlsl shader with commented out glsl shader + // Useful in diagnostics tools like pix which capture the hlsl shaders std::ostringstream hlslStream; hlslStream << "// GLSL\n"; hlslStream << "//\n"; @@ -254,14 +281,10 @@ void ShaderD3D::compileToHLSL(void *compiler, const std::string &source) curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1); } hlslStream << "\n\n"; - hlslStream << outputHLSL; + hlslStream << mHlsl; mHlsl = hlslStream.str(); -#else - mHlsl = outputHLSL; #endif - SafeDeleteArray(outputHLSL); - mUniforms = *GetShaderVariables(ShGetUniforms(compiler)); for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) @@ -271,7 +294,7 @@ void ShaderD3D::compileToHLSL(void *compiler, const std::string &source) if (uniform.staticUse) { unsigned int index = -1; - bool result = ShGetUniformRegister(compiler, uniform.name.c_str(), &index); + bool result = ShGetUniformRegister(compiler, uniform.name, &index); UNUSED_ASSERTION_VARIABLE(result); ASSERT(result); @@ -288,7 +311,7 @@ void ShaderD3D::compileToHLSL(void *compiler, const std::string &source) if (interfaceBlock.staticUse) { unsigned int index = -1; - bool result = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name.c_str(), &index); + bool result = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name, &index); UNUSED_ASSERTION_VARIABLE(result); ASSERT(result); @@ -298,24 +321,19 @@ void ShaderD3D::compileToHLSL(void *compiler, const std::string &source) } else { - size_t infoLogLen = 0; - ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen); - - char* infoLog = new char[infoLogLen]; - ShGetInfoLog(compiler, infoLog); - mInfoLog = infoLog; + mInfoLog = ShGetInfoLog(compiler); TRACE("\n%s", mInfoLog.c_str()); } } -rx::D3DWorkaroundType ShaderD3D::getD3DWorkarounds() const +D3DWorkaroundType ShaderD3D::getD3DWorkarounds() const { if (mUsesDiscardRewriting) { // ANGLE issue 486: // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization - return rx::ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION; + return ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION; } if (mUsesNestedBreak) @@ -323,10 +341,10 @@ rx::D3DWorkaroundType ShaderD3D::getD3DWorkarounds() const // ANGLE issue 603: // Work-around a D3D9 compiler bug that presents itself when using break in a nested loop, by maximizing optimization // We want to keep the use of ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes precedence - return rx::ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION; + return ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION; } - return rx::ANGLE_D3D_WORKAROUND_NONE; + return ANGLE_D3D_WORKAROUND_NONE; } // true if varying x has a higher priority in packing than y @@ -387,19 +405,16 @@ ShShaderOutput ShaderD3D::getCompilerOutputType(GLenum shader) default: UNREACHABLE(); return SH_HLSL9_OUTPUT; } - size_t outputType = 0; - ShGetInfo(compiler, SH_OUTPUT_TYPE, &outputType); - - return static_cast(outputType); + return ShGetShaderOutputType(compiler); } -bool ShaderD3D::compile(const std::string &source) +bool ShaderD3D::compile(const gl::Data &data, const std::string &source) { uncompile(); void *compiler = getCompiler(); - compileToHLSL(compiler, source); + compileToHLSL(data, compiler, source); if (mType == GL_VERTEX_SHADER) { @@ -420,6 +435,15 @@ bool ShaderD3D::compile(const std::string &source) } } +#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED + mDebugInfo += std::string("// ") + GetShaderTypeString(mType) + " SHADER BEGIN\n"; + mDebugInfo += "\n// GLSL BEGIN\n\n" + source + "\n\n// GLSL END\n\n\n"; + mDebugInfo += "// INITIAL HLSL BEGIN\n\n" + getTranslatedSource() + "\n// INITIAL HLSL END\n\n\n"; + // Successive steps will append more info +#else + mDebugInfo += getTranslatedSource(); +#endif + return !getTranslatedSource().empty(); } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h index 40e64cf36cd..3c9aac2c125 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h @@ -10,6 +10,7 @@ #define LIBGLESV2_RENDERER_SHADERD3D_H_ #include "libGLESv2/renderer/ShaderImpl.h" +#include "libGLESv2/renderer/Workarounds.h" #include "libGLESv2/Shader.h" #include @@ -17,22 +18,23 @@ namespace rx { class DynamicHLSL; -class Renderer; +class RendererD3D; class ShaderD3D : public ShaderImpl { friend class DynamicHLSL; public: - ShaderD3D(GLenum type, rx::Renderer *renderer); + ShaderD3D(const gl::Data &data, GLenum type, RendererD3D *renderer); virtual ~ShaderD3D(); static ShaderD3D *makeShaderD3D(ShaderImpl *impl); static const ShaderD3D *makeShaderD3D(const ShaderImpl *impl); // ShaderImpl implementation - const std::string &getInfoLog() const { return mInfoLog; } - const std::string &getTranslatedSource() const { return mHlsl; } + virtual const std::string &getInfoLog() const { return mInfoLog; } + virtual const std::string &getTranslatedSource() const { return mHlsl; } + virtual std::string getDebugInfo() const; // D3D-specific methods virtual void uncompile(); @@ -40,8 +42,9 @@ class ShaderD3D : public ShaderImpl unsigned int getUniformRegister(const std::string &uniformName) const; unsigned int getInterfaceBlockRegister(const std::string &blockName) const; int getSemanticIndex(const std::string &attributeName) const; + void appendDebugInfo(const std::string &info) { mDebugInfo += info; } - rx::D3DWorkaroundType getD3DWorkarounds() const; + D3DWorkaroundType getD3DWorkarounds() const; int getShaderVersion() const { return mShaderVersion; } bool usesDepthRange() const { return mUsesDepthRange; } bool usesPointSize() const { return mUsesPointSize; } @@ -49,15 +52,15 @@ class ShaderD3D : public ShaderImpl static void releaseCompiler(); static ShShaderOutput getCompilerOutputType(GLenum shader); - virtual bool compile(const std::string &source); + virtual bool compile(const gl::Data &data, const std::string &source); private: DISALLOW_COPY_AND_ASSIGN(ShaderD3D); - void compileToHLSL(void *compiler, const std::string &source); + void compileToHLSL(const gl::Data &data, void *compiler, const std::string &source); void parseVaryings(void *compiler); - void initializeCompiler(); + void initializeCompiler(const gl::Data &data); void parseAttributes(void *compiler); void *getCompiler(); @@ -67,7 +70,7 @@ class ShaderD3D : public ShaderImpl static void *mVertexCompiler; GLenum mType; - rx::Renderer *mRenderer; + RendererD3D *mRenderer; int mShaderVersion; @@ -85,6 +88,7 @@ class ShaderD3D : public ShaderImpl std::string mHlsl; std::string mInfoLog; + std::string mDebugInfo; std::map mUniformRegisterMap; std::map mInterfaceBlockRegisterMap; }; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp index 96c84977cbf..4a67701fdf6 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp @@ -6,9 +6,6 @@ // TextureD3D.cpp: Implementations of the Texture interfaces shared betweeen the D3D backends. -#include "libGLESv2/renderer/d3d/TextureD3D.h" -#include "libGLESv2/renderer/d3d/TextureStorage.h" -#include "libGLESv2/renderer/d3d/ImageD3D.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/Framebuffer.h" #include "libGLESv2/Texture.h" @@ -16,7 +13,11 @@ #include "libGLESv2/formatutils.h" #include "libGLESv2/renderer/BufferImpl.h" #include "libGLESv2/renderer/RenderTarget.h" -#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/d3d/BufferD3D.h" +#include "libGLESv2/renderer/d3d/TextureD3D.h" +#include "libGLESv2/renderer/d3d/TextureStorage.h" +#include "libGLESv2/renderer/d3d/ImageD3D.h" +#include "libGLESv2/renderer/d3d/RendererD3D.h" #include "libEGL/Surface.h" @@ -26,16 +27,51 @@ namespace rx { +namespace +{ + +gl::Error GetUnpackPointer(const gl::PixelUnpackState &unpack, const void *pixels, const uint8_t **pointerOut) +{ + if (unpack.pixelBuffer.id() != 0) + { + // Do a CPU readback here, if we have an unpack buffer bound and the fast GPU path is not supported + gl::Buffer *pixelBuffer = unpack.pixelBuffer.get(); + ptrdiff_t offset = reinterpret_cast(pixels); + + // TODO: this is the only place outside of renderer that asks for a buffers raw data. + // This functionality should be moved into renderer and the getData method of BufferImpl removed. + BufferD3D *bufferD3D = BufferD3D::makeBufferD3D(pixelBuffer->getImplementation()); + ASSERT(bufferD3D); + const uint8_t *bufferData = NULL; + gl::Error error = bufferD3D->getData(&bufferData); + if (error.isError()) + { + return error; + } + + *pointerOut = bufferData + offset; + } + else + { + *pointerOut = static_cast(pixels); + } + + return gl::Error(GL_NO_ERROR); +} + bool IsRenderTargetUsage(GLenum usage) { return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); } -TextureD3D::TextureD3D(Renderer *renderer) +} + +TextureD3D::TextureD3D(RendererD3D *renderer) : mRenderer(renderer), mUsage(GL_NONE), mDirtyImages(true), - mImmutable(false) + mImmutable(false), + mTexStorage(NULL) { } @@ -54,13 +90,12 @@ TextureStorage *TextureD3D::getNativeTexture() // ensure the underlying texture is created initializeStorage(false); - TextureStorage *storage = getBaseLevelStorage(); - if (storage) + if (mTexStorage) { updateStorage(); } - return storage; + return mTexStorage; } GLint TextureD3D::getBaseLevelWidth() const @@ -90,50 +125,79 @@ GLenum TextureD3D::getBaseLevelInternalFormat() const return (baseImage ? baseImage->getInternalFormat() : GL_NONE); } -void TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, Image *image) +bool TextureD3D::shouldUseSetData(const Image *image) const { + if (!mRenderer->getWorkarounds().setDataFasterThanImageUpload) + { + return false; + } + + gl::InternalFormat internalFormat = gl::GetInternalFormatInfo(image->getInternalFormat()); + + // We can only handle full updates for depth-stencil textures, so to avoid complications + // disable them entirely. + if (internalFormat.depthBits > 0 || internalFormat.stencilBits > 0) + { + return false; + } + + // TODO(jmadill): Handle compressed internal formats + return (mTexStorage && !internalFormat.compressed); +} + +gl::Error TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, const gl::ImageIndex &index) +{ + Image *image = getImage(index); + ASSERT(image); + // No-op if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0) { - return; + return gl::Error(GL_NO_ERROR); } // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains. // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components. - const void *pixelData = pixels; - - if (unpack.pixelBuffer.id() != 0) + const uint8_t *pixelData = NULL; + gl::Error error = GetUnpackPointer(unpack, pixels, &pixelData); + if (error.isError()) { - // Do a CPU readback here, if we have an unpack buffer bound and the fast GPU path is not supported - gl::Buffer *pixelBuffer = unpack.pixelBuffer.get(); - ptrdiff_t offset = reinterpret_cast(pixels); - // TODO: setImage/subImage is the only place outside of renderer that asks for a buffers raw data. - // This functionality should be moved into renderer and the getData method of BufferImpl removed. - const void *bufferData = pixelBuffer->getImplementation()->getData(); - pixelData = static_cast(bufferData) + offset; + return error; } if (pixelData != NULL) { - image->loadData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), unpack.alignment, type, pixelData); + gl::Error error(GL_NO_ERROR); + + if (shouldUseSetData(image)) + { + error = mTexStorage->setData(index, image, NULL, type, unpack, pixelData); + } + else + { + error = image->loadData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), unpack.alignment, type, pixelData); + } + + if (error.isError()) + { + return error; + } + mDirtyImages = true; } + + return gl::Error(GL_NO_ERROR); } -bool TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, const gl::ImageIndex &index) +gl::Error TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, const gl::ImageIndex &index) { - const void *pixelData = pixels; - // CPU readback & copy where direct GPU copy is not supported - if (unpack.pixelBuffer.id() != 0) + const uint8_t *pixelData = NULL; + gl::Error error = GetUnpackPointer(unpack, pixels, &pixelData); + if (error.isError()) { - gl::Buffer *pixelBuffer = unpack.pixelBuffer.get(); - ptrdiff_t offset = reinterpret_cast(pixels); - // TODO: setImage/subImage is the only place outside of renderer that asks for a buffers raw data. - // This functionality should be moved into renderer and the getData method of BufferImpl removed. - const void *bufferData = pixelBuffer->getImplementation()->getData(); - pixelData = static_cast(bufferData) + offset; + return error; } if (pixelData != NULL) @@ -141,32 +205,78 @@ bool TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei w Image *image = getImage(index); ASSERT(image); - image->loadData(xoffset, yoffset, zoffset, width, height, depth, unpack.alignment, type, pixelData); + gl::Box region(xoffset, yoffset, zoffset, width, height, depth); + if (shouldUseSetData(image)) + { + return mTexStorage->setData(index, image, ®ion, type, unpack, pixelData); + } + + gl::Error error = image->loadData(xoffset, yoffset, zoffset, width, height, depth, unpack.alignment, + type, pixelData); + if (error.isError()) + { + return error; + } + + error = commitRegion(index, region); + if (error.isError()) + { + return error; + } + mDirtyImages = true; } - return true; + return gl::Error(GL_NO_ERROR); } -void TextureD3D::setCompressedImage(GLsizei imageSize, const void *pixels, Image *image) +gl::Error TextureD3D::setCompressedImage(const gl::PixelUnpackState &unpack, GLsizei imageSize, const void *pixels, Image *image) { - if (pixels != NULL) + // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains. + // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components. + const uint8_t *pixelData = NULL; + gl::Error error = GetUnpackPointer(unpack, pixels, &pixelData); + if (error.isError()) { - image->loadCompressedData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), pixels); + return error; + } + + if (pixelData != NULL) + { + gl::Error error = image->loadCompressedData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), pixelData); + if (error.isError()) + { + return error; + } + mDirtyImages = true; } + + return gl::Error(GL_NO_ERROR); } -bool TextureD3D::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLsizei imageSize, const void *pixels, Image *image) +gl::Error TextureD3D::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels, Image *image) { - if (pixels != NULL) + const uint8_t *pixelData = NULL; + gl::Error error = GetUnpackPointer(unpack, pixels, &pixelData); + if (error.isError()) { - image->loadCompressedData(xoffset, yoffset, zoffset, width, height, depth, pixels); + return error; + } + + if (pixelData != NULL) + { + gl::Error error = image->loadCompressedData(xoffset, yoffset, zoffset, width, height, depth, pixelData); + if (error.isError()) + { + return error; + } + mDirtyImages = true; } - return true; + return gl::Error(GL_NO_ERROR); } bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat) @@ -174,21 +284,28 @@ bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum siz return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat); } -bool TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea, - GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget) +gl::Error TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea, + GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget) { + // No-op if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0) { - return true; + return gl::Error(GL_NO_ERROR); } // In order to perform the fast copy through the shader, we must have the right format, and be able // to create a render target. ASSERT(mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat)); - ptrdiff_t offset = reinterpret_cast(pixels); + uintptr_t offset = reinterpret_cast(pixels); - return mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea); + gl::Error error = mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); } GLint TextureD3D::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const @@ -210,10 +327,192 @@ int TextureD3D::mipLevels() const return gl::log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1; } +TextureStorage *TextureD3D::getStorage() +{ + ASSERT(mTexStorage); + return mTexStorage; +} -TextureD3D_2D::TextureD3D_2D(Renderer *renderer) - : TextureD3D(renderer), - mTexStorage(NULL) +Image *TextureD3D::getBaseLevelImage() const +{ + return getImage(getImageIndex(0, 0)); +} + +gl::Error TextureD3D::generateMipmaps() +{ + GLint mipCount = mipLevels(); + + if (mipCount == 1) + { + return gl::Error(GL_NO_ERROR); // no-op + } + + // Set up proper mipmap chain in our Image array. + initMipmapsImages(); + + // We know that all layers have the same dimension, for the texture to be complete + GLint layerCount = static_cast(getLayerCount(0)); + + // When making mipmaps with the setData workaround enabled, the texture storage has + // the image data already. For non-render-target storage, we have to pull it out into + // an image layer. + if (mRenderer->getWorkarounds().setDataFasterThanImageUpload && mTexStorage) + { + if (!mTexStorage->isRenderTarget()) + { + // Copy from the storage mip 0 to Image mip 0 + for (GLint layer = 0; layer < layerCount; ++layer) + { + gl::ImageIndex srcIndex = getImageIndex(0, layer); + + Image *image = getImage(srcIndex); + gl::Rectangle area(0, 0, image->getWidth(), image->getHeight()); + gl::Error error = image->copy(0, 0, 0, area, srcIndex, mTexStorage); + if (error.isError()) + { + return error; + } + } + } + else + { + gl::Error error = updateStorage(); + if (error.isError()) + { + return error; + } + } + } + + bool renderableStorage = (mTexStorage && mTexStorage->isRenderTarget()); + + for (GLint layer = 0; layer < layerCount; ++layer) + { + for (GLint mip = 1; mip < mipCount; ++mip) + { + ASSERT(getLayerCount(mip) == layerCount); + + gl::ImageIndex sourceIndex = getImageIndex(mip - 1, layer); + gl::ImageIndex destIndex = getImageIndex(mip, layer); + + if (renderableStorage) + { + // GPU-side mipmapping + gl::Error error = mTexStorage->generateMipmap(sourceIndex, destIndex); + if (error.isError()) + { + return error; + } + } + else + { + // CPU-side mipmapping + gl::Error error = mRenderer->generateMipmap(getImage(destIndex), getImage(sourceIndex)); + if (error.isError()) + { + return error; + } + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +bool TextureD3D::isBaseImageZeroSize() const +{ + Image *baseImage = getBaseLevelImage(); + + if (!baseImage || baseImage->getWidth() <= 0) + { + return true; + } + + if (!gl::IsCubemapTextureTarget(baseImage->getTarget()) && baseImage->getHeight() <= 0) + { + return true; + } + + if (baseImage->getTarget() == GL_TEXTURE_3D && baseImage->getDepth() <= 0) + { + return true; + } + + if (baseImage->getTarget() == GL_TEXTURE_2D_ARRAY && getLayerCount(0) <= 0) + { + return true; + } + + return false; +} + +gl::Error TextureD3D::ensureRenderTarget() +{ + gl::Error error = initializeStorage(true); + if (error.isError()) + { + return error; + } + + if (!isBaseImageZeroSize()) + { + ASSERT(mTexStorage); + if (!mTexStorage->isRenderTarget()) + { + TextureStorage *newRenderTargetStorage = NULL; + error = createCompleteStorage(true, &newRenderTargetStorage); + if (error.isError()) + { + return error; + } + + error = mTexStorage->copyToStorage(newRenderTargetStorage); + if (error.isError()) + { + SafeDelete(newRenderTargetStorage); + return error; + } + + error = setCompleteTexStorage(newRenderTargetStorage); + if (error.isError()) + { + SafeDelete(newRenderTargetStorage); + return error; + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +bool TextureD3D::canCreateRenderTargetForImage(const gl::ImageIndex &index) const +{ + Image *image = getImage(index); + bool levelsComplete = (isImageComplete(index) && isImageComplete(getImageIndex(0, 0))); + return (image->isRenderableFormat() && levelsComplete); +} + +gl::Error TextureD3D::commitRegion(const gl::ImageIndex &index, const gl::Box ®ion) +{ + if (mTexStorage) + { + ASSERT(isValidIndex(index)); + Image *image = getImage(index); + ImageD3D *imageD3D = ImageD3D::makeImageD3D(image); + gl::Error error = imageD3D->copyToStorage(mTexStorage, index, region); + if (error.isError()) + { + return error; + } + + image->markClean(); + } + + return gl::Error(GL_NO_ERROR); +} + +TextureD3D_2D::TextureD3D_2D(RendererD3D *renderer) + : TextureD3D(renderer) { for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) { @@ -292,7 +591,9 @@ bool TextureD3D_2D::isDepth(GLint level) const return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } -void TextureD3D_2D::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +gl::Error TextureD3D_2D::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, + GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, + const void *pixels) { ASSERT(target == GL_TEXTURE_2D && depth == 1); @@ -302,142 +603,209 @@ void TextureD3D_2D::setImage(GLenum target, GLint level, GLsizei width, GLsizei redefineImage(level, sizedInternalFormat, width, height); + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + // Attempt a fast gpu copy of the pixel data to the surface if (isFastUnpackable(unpack, sizedInternalFormat) && isLevelComplete(level)) { - gl::ImageIndex index = gl::ImageIndex::Make2D(level); - // Will try to create RT storage if it does not exist - RenderTarget *destRenderTarget = getRenderTarget(index); + RenderTarget *destRenderTarget = NULL; + gl::Error error = getRenderTarget(index, &destRenderTarget); + if (error.isError()) + { + return error; + } + gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1); - if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget)) + error = fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget); + if (error.isError()) { - // Ensure we don't overwrite our newly initialized data - mImageArray[level]->markClean(); - - fastUnpacked = true; + return error; } + + // Ensure we don't overwrite our newly initialized data + mImageArray[level]->markClean(); + + fastUnpacked = true; } if (!fastUnpacked) { - TextureD3D::setImage(unpack, type, pixels, mImageArray[level]); + gl::Error error = TextureD3D::setImage(unpack, type, pixels, index); + if (error.isError()) + { + return error; + } } + + return gl::Error(GL_NO_ERROR); } -void TextureD3D_2D::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) +gl::Error TextureD3D_2D::setCompressedImage(GLenum target, GLint level, GLenum format, + GLsizei width, GLsizei height, GLsizei depth, + GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) { ASSERT(target == GL_TEXTURE_2D && depth == 1); // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly redefineImage(level, format, width, height); - TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[level]); + return TextureD3D::setCompressedImage(unpack, imageSize, pixels, mImageArray[level]); } -void TextureD3D_2D::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +gl::Error TextureD3D_2D::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const void *pixels) { ASSERT(target == GL_TEXTURE_2D && depth == 1 && zoffset == 0); bool fastUnpacked = false; gl::ImageIndex index = gl::ImageIndex::Make2D(level); + gl::Box destArea(xoffset, yoffset, 0, width, height, 1); if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level)) { - RenderTarget *renderTarget = getRenderTarget(index); - gl::Box destArea(xoffset, yoffset, 0, width, height, 1); - - if (renderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, renderTarget)) + RenderTarget *renderTarget = NULL; + gl::Error error = getRenderTarget(index, &renderTarget); + if (error.isError()) { - // Ensure we don't overwrite our newly initialized data - mImageArray[level]->markClean(); - - fastUnpacked = true; + return error; } + + error = fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, renderTarget); + if (error.isError()) + { + return error; + } + + // Ensure we don't overwrite our newly initialized data + mImageArray[level]->markClean(); + + fastUnpacked = true; } - if (!fastUnpacked && TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, index)) + if (!fastUnpacked) { - commitRect(level, xoffset, yoffset, width, height); + return TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, + unpack, pixels, index); } + + return gl::Error(GL_NO_ERROR); } -void TextureD3D_2D::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) +gl::Error TextureD3D_2D::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, + GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) { ASSERT(target == GL_TEXTURE_2D && depth == 1 && zoffset == 0); - if (TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[level])) + gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels, mImageArray[level]); + if (error.isError()) { - commitRect(level, xoffset, yoffset, width, height); + return error; } + + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + gl::Box region(xoffset, yoffset, 0, width, height, 1); + return commitRegion(index, region); } -void TextureD3D_2D::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +gl::Error TextureD3D_2D::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, + gl::Framebuffer *source) { ASSERT(target == GL_TEXTURE_2D); GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, GL_UNSIGNED_BYTE); redefineImage(level, sizedInternalFormat, width, height); - if (!mImageArray[level]->isRenderableFormat()) + gl::Rectangle sourceRect(x, y, width, height); + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + + if (!canCreateRenderTargetForImage(index)) { - mImageArray[level]->copy(0, 0, 0, x, y, width, height, source); + gl::Error error = mImageArray[level]->copy(0, 0, 0, sourceRect, source); + if (error.isError()) + { + return error; + } + mDirtyImages = true; } else { - ensureRenderTarget(); + gl::Error error = ensureRenderTarget(); + if (error.isError()) + { + return error; + } + mImageArray[level]->markClean(); if (width != 0 && height != 0 && isValidLevel(level)) { - gl::Rectangle sourceRect; - sourceRect.x = x; - sourceRect.width = width; - sourceRect.y = y; - sourceRect.height = height; - - mRenderer->copyImage2D(source, sourceRect, format, 0, 0, mTexStorage, level); + gl::Error error = mRenderer->copyImage2D(source, sourceRect, format, 0, 0, mTexStorage, level); + if (error.isError()) + { + return error; + } } } + + return gl::Error(GL_NO_ERROR); } -void TextureD3D_2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +gl::Error TextureD3D_2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) { ASSERT(target == GL_TEXTURE_2D && zoffset == 0); // can only make our texture storage to a render target if level 0 is defined (with a width & height) and // the current level we're copying to is defined (with appropriate format, width & height) - bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0); - if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget)) + gl::Rectangle sourceRect(x, y, width, height); + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + + if (!canCreateRenderTargetForImage(index)) { - mImageArray[level]->copy(xoffset, yoffset, 0, x, y, width, height, source); + gl::Error error = mImageArray[level]->copy(xoffset, yoffset, 0, sourceRect, source); + if (error.isError()) + { + return error; + } + mDirtyImages = true; } else { - ensureRenderTarget(); + gl::Error error = ensureRenderTarget(); + if (error.isError()) + { + return error; + } if (isValidLevel(level)) { - updateStorageLevel(level); + error = updateStorageLevel(level); + if (error.isError()) + { + return error; + } - gl::Rectangle sourceRect; - sourceRect.x = x; - sourceRect.width = width; - sourceRect.y = y; - sourceRect.height = height; - - mRenderer->copyImage2D(source, sourceRect, - gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, - xoffset, yoffset, mTexStorage, level); + error = mRenderer->copyImage2D(source, sourceRect, + gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, + xoffset, yoffset, mTexStorage, level); + if (error.isError()) + { + return error; + } } } + + return gl::Error(GL_NO_ERROR); } -void TextureD3D_2D::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +gl::Error TextureD3D_2D::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { ASSERT(target == GL_TEXTURE_2D && depth == 1); @@ -453,11 +821,20 @@ void TextureD3D_2D::storage(GLenum target, GLsizei levels, GLenum internalformat mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true); } - mImmutable = true; - + // TODO(geofflang): Verify storage creation had no errors bool renderTarget = IsRenderTargetUsage(mUsage); TextureStorage *storage = mRenderer->createTextureStorage2D(internalformat, renderTarget, width, height, levels); - setCompleteTexStorage(storage); + + gl::Error error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + + mImmutable = true; + + return gl::Error(GL_NO_ERROR); } void TextureD3D_2D::bindTexImage(egl::Surface *surface) @@ -489,7 +866,7 @@ void TextureD3D_2D::releaseTexImage() } } -void TextureD3D_2D::generateMipmaps() +void TextureD3D_2D::initMipmapsImages() { // Purge array levels 1 through q and reset them to represent the generated mipmap levels. int levelCount = mipLevels(); @@ -499,42 +876,32 @@ void TextureD3D_2D::generateMipmaps() std::max(getBaseLevelWidth() >> level, 1), std::max(getBaseLevelHeight() >> level, 1)); } - - if (mTexStorage && mTexStorage->isRenderTarget()) - { - mTexStorage->generateMipmaps(); - for (int level = 1; level < levelCount; level++) - { - mImageArray[level]->markClean(); - } - } - else - { - for (int level = 1; level < levelCount; level++) - { - mRenderer->generateMipmap(mImageArray[level], mImageArray[level - 1]); - } - } } unsigned int TextureD3D_2D::getRenderTargetSerial(const gl::ImageIndex &index) { ASSERT(!index.hasLayer()); - return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(index) : 0); + return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0); } -RenderTarget *TextureD3D_2D::getRenderTarget(const gl::ImageIndex &index) +gl::Error TextureD3D_2D::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) { ASSERT(!index.hasLayer()); // ensure the underlying texture is created - if (!ensureRenderTarget()) + gl::Error error = ensureRenderTarget(); + if (error.isError()) { - return NULL; + return error; } - updateStorageLevel(index.mipIndex); - return mTexStorage->getRenderTarget(index); + error = updateStorageLevel(index.mipIndex); + if (error.isError()) + { + return error; + } + + return mTexStorage->getRenderTarget(index, outRT); } bool TextureD3D_2D::isValidLevel(int level) const @@ -586,31 +953,55 @@ bool TextureD3D_2D::isLevelComplete(int level) const return true; } +bool TextureD3D_2D::isImageComplete(const gl::ImageIndex &index) const +{ + return isLevelComplete(index.mipIndex); +} + // Constructs a native texture resource from the texture images -void TextureD3D_2D::initializeStorage(bool renderTarget) +gl::Error TextureD3D_2D::initializeStorage(bool renderTarget) { // Only initialize the first time this texture is used as a render target or shader resource if (mTexStorage) { - return; + return gl::Error(GL_NO_ERROR); } // do not attempt to create storage for nonexistant data if (!isLevelComplete(0)) { - return; + return gl::Error(GL_NO_ERROR); } bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage)); - setCompleteTexStorage(createCompleteStorage(createRenderTarget)); + TextureStorage *storage = NULL; + gl::Error error = createCompleteStorage(createRenderTarget, &storage); + if (error.isError()) + { + return error; + } + + error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + ASSERT(mTexStorage); // flush image data to the storage - updateStorage(); + error = updateStorage(); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); } -TextureStorage *TextureD3D_2D::createCompleteStorage(bool renderTarget) const +gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const { GLsizei width = getBaseLevelWidth(); GLsizei height = getBaseLevelHeight(); @@ -621,26 +1012,35 @@ TextureStorage *TextureD3D_2D::createCompleteStorage(bool renderTarget) const // use existing storage level count, when previously specified by TexStorage*D GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1)); - return mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, levels); + // TODO(geofflang): Determine if the texture creation succeeded + *outTexStorage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, levels); + + return gl::Error(GL_NO_ERROR); } -void TextureD3D_2D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) +gl::Error TextureD3D_2D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) { - SafeDelete(mTexStorage); - mTexStorage = newCompleteTexStorage; - - if (mTexStorage && mTexStorage->isManaged()) + if (newCompleteTexStorage && newCompleteTexStorage->isManaged()) { - for (int level = 0; level < mTexStorage->getLevelCount(); level++) + for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++) { - mImageArray[level]->setManagedSurface2D(mTexStorage, level); + gl::Error error = mImageArray[level]->setManagedSurface2D(newCompleteTexStorage, level); + if (error.isError()) + { + return error; + } } } + SafeDelete(mTexStorage); + mTexStorage = newCompleteTexStorage; + mDirtyImages = true; + + return gl::Error(GL_NO_ERROR); } -void TextureD3D_2D::updateStorage() +gl::Error TextureD3D_2D::updateStorage() { ASSERT(mTexStorage != NULL); GLint storageLevels = mTexStorage->getLevelCount(); @@ -648,54 +1048,34 @@ void TextureD3D_2D::updateStorage() { if (mImageArray[level]->isDirty() && isLevelComplete(level)) { - updateStorageLevel(level); - } - } -} - -bool TextureD3D_2D::ensureRenderTarget() -{ - initializeStorage(true); - - if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0) - { - ASSERT(mTexStorage); - if (!mTexStorage->isRenderTarget()) - { - TextureStorage *newRenderTargetStorage = createCompleteStorage(true); - - if (!mRenderer->copyToRenderTarget2D(newRenderTargetStorage, mTexStorage)) + gl::Error error = updateStorageLevel(level); + if (error.isError()) { - delete newRenderTargetStorage; - return gl::error(GL_OUT_OF_MEMORY, false); + return error; } - - setCompleteTexStorage(newRenderTargetStorage); } } - return (mTexStorage && mTexStorage->isRenderTarget()); + return gl::Error(GL_NO_ERROR); } -TextureStorage *TextureD3D_2D::getBaseLevelStorage() -{ - return mTexStorage; -} - -const ImageD3D *TextureD3D_2D::getBaseLevelImage() const -{ - return mImageArray[0]; -} - -void TextureD3D_2D::updateStorageLevel(int level) +gl::Error TextureD3D_2D::updateStorageLevel(int level) { ASSERT(level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL); ASSERT(isLevelComplete(level)); if (mImageArray[level]->isDirty()) { - commitRect(level, 0, 0, getWidth(level), getHeight(level)); + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1); + gl::Error error = commitRegion(index, region); + if (error.isError()) + { + return error; + } } + + return gl::Error(GL_NO_ERROR); } void TextureD3D_2D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height) @@ -727,22 +1107,25 @@ void TextureD3D_2D::redefineImage(GLint level, GLenum internalformat, GLsizei wi } } -void TextureD3D_2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +gl::ImageIndexIterator TextureD3D_2D::imageIterator() const { - if (isValidLevel(level)) - { - ImageD3D *image = mImageArray[level]; - if (image->copyToStorage2D(mTexStorage, level, xoffset, yoffset, width, height)) - { - image->markClean(); - } - } + return gl::ImageIndexIterator::Make2D(0, mTexStorage->getLevelCount()); } +gl::ImageIndex TextureD3D_2D::getImageIndex(GLint mip, GLint /*layer*/) const +{ + // "layer" does not apply to 2D Textures. + return gl::ImageIndex::Make2D(mip); +} -TextureD3D_Cube::TextureD3D_Cube(Renderer *renderer) - : TextureD3D(renderer), - mTexStorage(NULL) +bool TextureD3D_2D::isValidIndex(const gl::ImageIndex &index) const +{ + return (mTexStorage && index.type == GL_TEXTURE_2D && + index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount()); +} + +TextureD3D_Cube::TextureD3D_Cube(RendererD3D *renderer) + : TextureD3D(renderer) { for (int i = 0; i < 6; i++) { @@ -802,19 +1185,23 @@ bool TextureD3D_Cube::isDepth(GLint level, GLint layer) const return gl::GetInternalFormatInfo(getInternalFormat(level, layer)).depthBits > 0; } -void TextureD3D_Cube::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +gl::Error TextureD3D_Cube::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, + GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, + const void *pixels) { ASSERT(depth == 1); - int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); - redefineImage(faceIndex, level, sizedInternalFormat, width, height); + redefineImage(index.layerIndex, level, sizedInternalFormat, width, height); - TextureD3D::setImage(unpack, type, pixels, mImageArray[faceIndex][level]); + return TextureD3D::setImage(unpack, type, pixels, index); } -void TextureD3D_Cube::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) +gl::Error TextureD3D_Cube::setCompressedImage(GLenum target, GLint level, GLenum format, + GLsizei width, GLsizei height, GLsizei depth, + GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) { ASSERT(depth == 1); @@ -823,101 +1210,129 @@ void TextureD3D_Cube::setCompressedImage(GLenum target, GLint level, GLenum form redefineImage(faceIndex, level, format, width, height); - TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[faceIndex][level]); + return TextureD3D::setCompressedImage(unpack, imageSize, pixels, mImageArray[faceIndex][level]); } -void TextureD3D_Cube::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +gl::Error TextureD3D_Cube::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const void *pixels) { ASSERT(depth == 1 && zoffset == 0); + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); + return TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, index); +} - int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); +gl::Error TextureD3D_Cube::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, + GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) +{ + ASSERT(depth == 1 && zoffset == 0); gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); - if (TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, index)) + + gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels, mImageArray[index.layerIndex][level]); + if (error.isError()) { - commitRect(faceIndex, level, xoffset, yoffset, width, height); + return error; } + + gl::Box region(xoffset, yoffset, 0, width, height, 1); + return commitRegion(index, region); } -void TextureD3D_Cube::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) -{ - ASSERT(depth == 1 && zoffset == 0); - - int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); - - if (TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[faceIndex][level])) - { - commitRect(faceIndex, level, xoffset, yoffset, width, height); - } -} - -void TextureD3D_Cube::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +gl::Error TextureD3D_Cube::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, + GLsizei width, GLsizei height, gl::Framebuffer *source) { int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, GL_UNSIGNED_BYTE); redefineImage(faceIndex, level, sizedInternalFormat, width, height); - if (!mImageArray[faceIndex][level]->isRenderableFormat()) + gl::Rectangle sourceRect(x, y, width, height); + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); + + if (!canCreateRenderTargetForImage(index)) { - mImageArray[faceIndex][level]->copy(0, 0, 0, x, y, width, height, source); + gl::Error error = mImageArray[faceIndex][level]->copy(0, 0, 0, sourceRect, source); + if (error.isError()) + { + return error; + } + mDirtyImages = true; } else { - ensureRenderTarget(); + gl::Error error = ensureRenderTarget(); + if (error.isError()) + { + return error; + } + mImageArray[faceIndex][level]->markClean(); ASSERT(width == height); if (width > 0 && isValidFaceLevel(faceIndex, level)) { - gl::Rectangle sourceRect; - sourceRect.x = x; - sourceRect.width = width; - sourceRect.y = y; - sourceRect.height = height; - - mRenderer->copyImageCube(source, sourceRect, format, 0, 0, mTexStorage, target, level); + error = mRenderer->copyImageCube(source, sourceRect, format, 0, 0, mTexStorage, target, level); + if (error.isError()) + { + return error; + } } } + + return gl::Error(GL_NO_ERROR); } -void TextureD3D_Cube::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +gl::Error TextureD3D_Cube::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) { int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); - // We can only make our texture storage to a render target if the level we're copying *to* is complete - // and the base level is cube-complete. The base level must be cube complete (common case) because we cannot - // rely on the "getBaseLevel*" methods reliably otherwise. - bool canCreateRenderTarget = isFaceLevelComplete(faceIndex, level) && isCubeComplete(); + gl::Rectangle sourceRect(x, y, width, height); + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); - if (!mImageArray[faceIndex][level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget)) + if (!canCreateRenderTargetForImage(index)) { - mImageArray[faceIndex][level]->copy(0, 0, 0, x, y, width, height, source); + gl::Error error =mImageArray[faceIndex][level]->copy(0, 0, 0, sourceRect, source); + if (error.isError()) + { + return error; + } + mDirtyImages = true; } else { - ensureRenderTarget(); + gl::Error error = ensureRenderTarget(); + if (error.isError()) + { + return error; + } if (isValidFaceLevel(faceIndex, level)) { - updateStorageFaceLevel(faceIndex, level); + error = updateStorageFaceLevel(faceIndex, level); + if (error.isError()) + { + return error; + } - gl::Rectangle sourceRect; - sourceRect.x = x; - sourceRect.width = width; - sourceRect.y = y; - sourceRect.height = height; - - mRenderer->copyImageCube(source, sourceRect, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, - xoffset, yoffset, mTexStorage, target, level); + error = mRenderer->copyImageCube(source, sourceRect, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, + xoffset, yoffset, mTexStorage, target, level); + if (error.isError()) + { + return error; + } } } + + return gl::Error(GL_NO_ERROR); } -void TextureD3D_Cube::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +gl::Error TextureD3D_Cube::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { ASSERT(width == height); ASSERT(depth == 1); @@ -939,11 +1354,20 @@ void TextureD3D_Cube::storage(GLenum target, GLsizei levels, GLenum internalform } } - mImmutable = true; - + // TODO(geofflang): Verify storage creation had no errors bool renderTarget = IsRenderTargetUsage(mUsage); TextureStorage *storage = mRenderer->createTextureStorageCube(internalformat, renderTarget, width, levels); - setCompleteTexStorage(storage); + + gl::Error error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + + mImmutable = true; + + return gl::Error(GL_NO_ERROR); } // Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. @@ -984,7 +1408,7 @@ void TextureD3D_Cube::releaseTexImage() } -void TextureD3D_Cube::generateMipmaps() +void TextureD3D_Cube::initMipmapsImages() { // Purge array levels 1 through q and reset them to represent the generated mipmap levels. int levelCount = mipLevels(); @@ -996,74 +1420,76 @@ void TextureD3D_Cube::generateMipmaps() redefineImage(faceIndex, level, mImageArray[faceIndex][0]->getInternalFormat(), faceLevelSize, faceLevelSize); } } - - if (mTexStorage && mTexStorage->isRenderTarget()) - { - mTexStorage->generateMipmaps(); - - for (int faceIndex = 0; faceIndex < 6; faceIndex++) - { - for (int level = 1; level < levelCount; level++) - { - mImageArray[faceIndex][level]->markClean(); - } - } - } - else - { - for (int faceIndex = 0; faceIndex < 6; faceIndex++) - { - for (int level = 1; level < levelCount; level++) - { - mRenderer->generateMipmap(mImageArray[faceIndex][level], mImageArray[faceIndex][level - 1]); - } - } - } } unsigned int TextureD3D_Cube::getRenderTargetSerial(const gl::ImageIndex &index) { - return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(index) : 0); + return (ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0); } -RenderTarget *TextureD3D_Cube::getRenderTarget(const gl::ImageIndex &index) +gl::Error TextureD3D_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) { ASSERT(gl::IsCubemapTextureTarget(index.type)); // ensure the underlying texture is created - if (!ensureRenderTarget()) + gl::Error error = ensureRenderTarget(); + if (error.isError()) { - return NULL; + return error; } - updateStorageFaceLevel(index.layerIndex, index.mipIndex); - return mTexStorage->getRenderTarget(index); + error = updateStorageFaceLevel(index.layerIndex, index.mipIndex); + if (error.isError()) + { + return error; + } + + return mTexStorage->getRenderTarget(index, outRT); } -void TextureD3D_Cube::initializeStorage(bool renderTarget) +gl::Error TextureD3D_Cube::initializeStorage(bool renderTarget) { // Only initialize the first time this texture is used as a render target or shader resource if (mTexStorage) { - return; + return gl::Error(GL_NO_ERROR); } // do not attempt to create storage for nonexistant data if (!isFaceLevelComplete(0, 0)) { - return; + return gl::Error(GL_NO_ERROR); } bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage)); - setCompleteTexStorage(createCompleteStorage(createRenderTarget)); + TextureStorage *storage = NULL; + gl::Error error = createCompleteStorage(createRenderTarget, &storage); + if (error.isError()) + { + return error; + } + + error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + ASSERT(mTexStorage); // flush image data to the storage - updateStorage(); + error = updateStorage(); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); } -TextureStorage *TextureD3D_Cube::createCompleteStorage(bool renderTarget) const +gl::Error TextureD3D_Cube::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const { GLsizei size = getBaseLevelWidth(); @@ -1072,29 +1498,37 @@ TextureStorage *TextureD3D_Cube::createCompleteStorage(bool renderTarget) const // use existing storage level count, when previously specified by TexStorage*D GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(size, size, 1)); - return mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), renderTarget, size, levels); + // TODO (geofflang): detect if storage creation succeeded + *outTexStorage = mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), renderTarget, size, levels); + + return gl::Error(GL_NO_ERROR); } -void TextureD3D_Cube::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) +gl::Error TextureD3D_Cube::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) { - SafeDelete(mTexStorage); - mTexStorage = newCompleteTexStorage; - - if (mTexStorage && mTexStorage->isManaged()) + if (newCompleteTexStorage && newCompleteTexStorage->isManaged()) { for (int faceIndex = 0; faceIndex < 6; faceIndex++) { - for (int level = 0; level < mTexStorage->getLevelCount(); level++) + for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++) { - mImageArray[faceIndex][level]->setManagedSurfaceCube(mTexStorage, faceIndex, level); + gl::Error error = mImageArray[faceIndex][level]->setManagedSurfaceCube(newCompleteTexStorage, faceIndex, level); + if (error.isError()) + { + return error; + } } } } + SafeDelete(mTexStorage); + mTexStorage = newCompleteTexStorage; + mDirtyImages = true; + return gl::Error(GL_NO_ERROR); } -void TextureD3D_Cube::updateStorage() +gl::Error TextureD3D_Cube::updateStorage() { ASSERT(mTexStorage != NULL); GLint storageLevels = mTexStorage->getLevelCount(); @@ -1104,46 +1538,16 @@ void TextureD3D_Cube::updateStorage() { if (mImageArray[face][level]->isDirty() && isFaceLevelComplete(face, level)) { - updateStorageFaceLevel(face, level); + gl::Error error = updateStorageFaceLevel(face, level); + if (error.isError()) + { + return error; + } } } } -} -bool TextureD3D_Cube::ensureRenderTarget() -{ - initializeStorage(true); - - if (getBaseLevelWidth() > 0) - { - ASSERT(mTexStorage); - if (!mTexStorage->isRenderTarget()) - { - TextureStorage *newRenderTargetStorage = createCompleteStorage(true); - - if (!mRenderer->copyToRenderTargetCube(newRenderTargetStorage, mTexStorage)) - { - delete newRenderTargetStorage; - return gl::error(GL_OUT_OF_MEMORY, false); - } - - setCompleteTexStorage(newRenderTargetStorage); - } - } - - return (mTexStorage && mTexStorage->isRenderTarget()); -} - -TextureStorage *TextureD3D_Cube::getBaseLevelStorage() -{ - return mTexStorage; -} - -const ImageD3D *TextureD3D_Cube::getBaseLevelImage() const -{ - // Note: if we are not cube-complete, there is no single base level image that can describe all - // cube faces, so this method is only well-defined for a cube-complete base level. - return mImageArray[0][0]; + return gl::Error(GL_NO_ERROR); } bool TextureD3D_Cube::isValidFaceLevel(int faceIndex, int level) const @@ -1191,15 +1595,29 @@ bool TextureD3D_Cube::isFaceLevelComplete(int faceIndex, int level) const return true; } -void TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level) +bool TextureD3D_Cube::isImageComplete(const gl::ImageIndex &index) const +{ + return isFaceLevelComplete(index.layerIndex, index.mipIndex); +} + +gl::Error TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level) { ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL); ImageD3D *image = mImageArray[faceIndex][level]; if (image->isDirty()) { - commitRect(faceIndex, level, 0, 0, image->getWidth(), image->getHeight()); + GLenum faceTarget = gl::TextureCubeMap::layerIndexToTarget(faceIndex); + gl::ImageIndex index = gl::ImageIndex::MakeCube(faceTarget, level); + gl::Box region(0, 0, 0, image->getWidth(), image->getHeight(), 1); + gl::Error error = commitRegion(index, region); + if (error.isError()) + { + return error; + } } + + return gl::Error(GL_NO_ERROR); } void TextureD3D_Cube::redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height) @@ -1235,20 +1653,25 @@ void TextureD3D_Cube::redefineImage(int faceIndex, GLint level, GLenum internalf } } -void TextureD3D_Cube::commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +gl::ImageIndexIterator TextureD3D_Cube::imageIterator() const { - if (isValidFaceLevel(faceIndex, level)) - { - ImageD3D *image = mImageArray[faceIndex][level]; - if (image->copyToStorageCube(mTexStorage, faceIndex, level, xoffset, yoffset, width, height)) - image->markClean(); - } + return gl::ImageIndexIterator::MakeCube(0, mTexStorage->getLevelCount()); } +gl::ImageIndex TextureD3D_Cube::getImageIndex(GLint mip, GLint layer) const +{ + // The "layer" of the image index corresponds to the cube face + return gl::ImageIndex::MakeCube(gl::TextureCubeMap::layerIndexToTarget(layer), mip); +} -TextureD3D_3D::TextureD3D_3D(Renderer *renderer) - : TextureD3D(renderer), - mTexStorage(NULL) +bool TextureD3D_Cube::isValidIndex(const gl::ImageIndex &index) const +{ + return (mTexStorage && gl::IsCubemapTextureTarget(index.type) && + index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount()); +} + +TextureD3D_3D::TextureD3D_3D(RendererD3D *renderer) + : TextureD3D(renderer) { for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) { @@ -1327,7 +1750,9 @@ bool TextureD3D_3D::isDepth(GLint level) const return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } -void TextureD3D_3D::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +gl::Error TextureD3D_3D::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, + GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, + const void *pixels) { ASSERT(target == GL_TEXTURE_3D); GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); @@ -1336,40 +1761,60 @@ void TextureD3D_3D::setImage(GLenum target, GLint level, GLsizei width, GLsizei bool fastUnpacked = false; + gl::ImageIndex index = gl::ImageIndex::Make3D(level); + // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer if (isFastUnpackable(unpack, sizedInternalFormat)) { // Will try to create RT storage if it does not exist - gl::ImageIndex index = gl::ImageIndex::Make3D(level); - RenderTarget *destRenderTarget = getRenderTarget(index); + RenderTarget *destRenderTarget = NULL; + gl::Error error = getRenderTarget(index, &destRenderTarget); + if (error.isError()) + { + return error; + } + gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), getDepth(level)); - if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget)) + error = fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget); + if (error.isError()) { - // Ensure we don't overwrite our newly initialized data - mImageArray[level]->markClean(); - - fastUnpacked = true; + return error; } + + // Ensure we don't overwrite our newly initialized data + mImageArray[level]->markClean(); + + fastUnpacked = true; } if (!fastUnpacked) { - TextureD3D::setImage(unpack, type, pixels, mImageArray[level]); + gl::Error error = TextureD3D::setImage(unpack, type, pixels, index); + if (error.isError()) + { + return error; + } } + + return gl::Error(GL_NO_ERROR); } -void TextureD3D_3D::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) +gl::Error TextureD3D_3D::setCompressedImage(GLenum target, GLint level, GLenum format, + GLsizei width, GLsizei height,GLsizei depth, + GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) { ASSERT(target == GL_TEXTURE_3D); // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly redefineImage(level, format, width, height, depth); - TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[level]); + return TextureD3D::setCompressedImage(unpack, imageSize, pixels, mImageArray[level]); } -void TextureD3D_3D::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +gl::Error TextureD3D_3D::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const void *pixels) { ASSERT(target == GL_TEXTURE_3D); @@ -1380,74 +1825,108 @@ void TextureD3D_3D::subImage(GLenum target, GLint level, GLint xoffset, GLint yo // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer if (isFastUnpackable(unpack, getInternalFormat(level))) { - RenderTarget *destRenderTarget = getRenderTarget(index); - gl::Box destArea(xoffset, yoffset, zoffset, width, height, depth); - - if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, destRenderTarget)) + RenderTarget *destRenderTarget = NULL; + gl::Error error = getRenderTarget(index, &destRenderTarget); + if (error.isError()) { - // Ensure we don't overwrite our newly initialized data - mImageArray[level]->markClean(); - - fastUnpacked = true; + return error; } + + gl::Box destArea(xoffset, yoffset, zoffset, width, height, depth); + error = fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, destRenderTarget); + if (error.isError()) + { + return error; + } + + // Ensure we don't overwrite our newly initialized data + mImageArray[level]->markClean(); + + fastUnpacked = true; } - if (!fastUnpacked && TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels, index)) + if (!fastUnpacked) { - commitRect(level, xoffset, yoffset, zoffset, width, height, depth); + return TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, depth, format, type, + unpack, pixels, index); } + + return gl::Error(GL_NO_ERROR); } -void TextureD3D_3D::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) +gl::Error TextureD3D_3D::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, + GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) { ASSERT(target == GL_TEXTURE_3D); - if (TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels, mImageArray[level])) + gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, depth, + format, imageSize, unpack, pixels, mImageArray[level]); + if (error.isError()) { - commitRect(level, xoffset, yoffset, zoffset, width, height, depth); + return error; } + + gl::ImageIndex index = gl::ImageIndex::Make3D(level); + gl::Box region(xoffset, yoffset, zoffset, width, height, depth); + return commitRegion(index, region); } -void TextureD3D_3D::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +gl::Error TextureD3D_3D::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, + GLsizei width, GLsizei height, gl::Framebuffer *source) { UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, "Copying 3D textures is unimplemented."); } -void TextureD3D_3D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +gl::Error TextureD3D_3D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) { ASSERT(target == GL_TEXTURE_3D); - // can only make our texture storage to a render target if level 0 is defined (with a width & height) and - // the current level we're copying to is defined (with appropriate format, width & height) - bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0); + gl::Rectangle sourceRect(x, y, width, height); + gl::ImageIndex index = gl::ImageIndex::Make3D(level); - if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget)) + if (canCreateRenderTargetForImage(index)) { - mImageArray[level]->copy(xoffset, yoffset, zoffset, x, y, width, height, source); + gl::Error error = mImageArray[level]->copy(xoffset, yoffset, zoffset, sourceRect, source); + if (error.isError()) + { + return error; + } + mDirtyImages = true; } else { - ensureRenderTarget(); + gl::Error error = ensureRenderTarget(); + if (error.isError()) + { + return error; + } if (isValidLevel(level)) { - updateStorageLevel(level); + error = updateStorageLevel(level); + if (error.isError()) + { + return error; + } - gl::Rectangle sourceRect; - sourceRect.x = x; - sourceRect.width = width; - sourceRect.y = y; - sourceRect.height = height; - - mRenderer->copyImage3D(source, sourceRect, - gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, - xoffset, yoffset, zoffset, mTexStorage, level); + error = mRenderer->copyImage3D(source, sourceRect, + gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, + xoffset, yoffset, zoffset, mTexStorage, level); + if (error.isError()) + { + return error; + } } } + + return gl::Error(GL_NO_ERROR); } -void TextureD3D_3D::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +gl::Error TextureD3D_3D::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { ASSERT(target == GL_TEXTURE_3D); @@ -1464,11 +1943,20 @@ void TextureD3D_3D::storage(GLenum target, GLsizei levels, GLenum internalformat mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, GL_NONE, 0, 0, 0, true); } - mImmutable = true; - + // TODO(geofflang): Verify storage creation had no errors bool renderTarget = IsRenderTargetUsage(mUsage); TextureStorage *storage = mRenderer->createTextureStorage3D(internalformat, renderTarget, width, height, depth, levels); - setCompleteTexStorage(storage); + + gl::Error error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + + mImmutable = true; + + return gl::Error(GL_NO_ERROR); } void TextureD3D_3D::bindTexImage(egl::Surface *surface) @@ -1482,7 +1970,7 @@ void TextureD3D_3D::releaseTexImage() } -void TextureD3D_3D::generateMipmaps() +void TextureD3D_3D::initMipmapsImages() { // Purge array levels 1 through q and reset them to represent the generated mipmap levels. int levelCount = mipLevels(); @@ -1493,74 +1981,85 @@ void TextureD3D_3D::generateMipmaps() std::max(getBaseLevelHeight() >> level, 1), std::max(getBaseLevelDepth() >> level, 1)); } - - if (mTexStorage && mTexStorage->isRenderTarget()) - { - mTexStorage->generateMipmaps(); - - for (int level = 1; level < levelCount; level++) - { - mImageArray[level]->markClean(); - } - } - else - { - for (int level = 1; level < levelCount; level++) - { - mRenderer->generateMipmap(mImageArray[level], mImageArray[level - 1]); - } - } } unsigned int TextureD3D_3D::getRenderTargetSerial(const gl::ImageIndex &index) { - return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(index) : 0); + return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0); } -RenderTarget *TextureD3D_3D::getRenderTarget(const gl::ImageIndex &index) +gl::Error TextureD3D_3D::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) { // ensure the underlying texture is created - if (!ensureRenderTarget()) + gl::Error error = ensureRenderTarget(); + if (error.isError()) { - return NULL; + return error; } if (index.hasLayer()) { - updateStorage(); + error = updateStorage(); + if (error.isError()) + { + return error; + } } else { - updateStorageLevel(index.mipIndex); + error = updateStorageLevel(index.mipIndex); + if (error.isError()) + { + return error; + } } - return mTexStorage->getRenderTarget(index); + return mTexStorage->getRenderTarget(index, outRT); } -void TextureD3D_3D::initializeStorage(bool renderTarget) +gl::Error TextureD3D_3D::initializeStorage(bool renderTarget) { // Only initialize the first time this texture is used as a render target or shader resource if (mTexStorage) { - return; + return gl::Error(GL_NO_ERROR); } // do not attempt to create storage for nonexistant data if (!isLevelComplete(0)) { - return; + return gl::Error(GL_NO_ERROR); } bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); - setCompleteTexStorage(createCompleteStorage(createRenderTarget)); + TextureStorage *storage = NULL; + gl::Error error = createCompleteStorage(createRenderTarget, &storage); + if (error.isError()) + { + return error; + } + + error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + ASSERT(mTexStorage); // flush image data to the storage - updateStorage(); + error = updateStorage(); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); } -TextureStorage *TextureD3D_3D::createCompleteStorage(bool renderTarget) const +gl::Error TextureD3D_3D::createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const { GLsizei width = getBaseLevelWidth(); GLsizei height = getBaseLevelHeight(); @@ -1572,10 +2071,13 @@ TextureStorage *TextureD3D_3D::createCompleteStorage(bool renderTarget) const // use existing storage level count, when previously specified by TexStorage*D GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, depth)); - return mRenderer->createTextureStorage3D(internalFormat, renderTarget, width, height, depth, levels); + // TODO: Verify creation of the storage succeeded + *outStorage = mRenderer->createTextureStorage3D(internalFormat, renderTarget, width, height, depth, levels); + + return gl::Error(GL_NO_ERROR); } -void TextureD3D_3D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) +gl::Error TextureD3D_3D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) { SafeDelete(mTexStorage); mTexStorage = newCompleteTexStorage; @@ -1583,9 +2085,11 @@ void TextureD3D_3D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) // We do not support managed 3D storage, as that is D3D9/ES2-only ASSERT(!mTexStorage->isManaged()); + + return gl::Error(GL_NO_ERROR); } -void TextureD3D_3D::updateStorage() +gl::Error TextureD3D_3D::updateStorage() { ASSERT(mTexStorage != NULL); GLint storageLevels = mTexStorage->getLevelCount(); @@ -1593,43 +2097,15 @@ void TextureD3D_3D::updateStorage() { if (mImageArray[level]->isDirty() && isLevelComplete(level)) { - updateStorageLevel(level); - } - } -} - -bool TextureD3D_3D::ensureRenderTarget() -{ - initializeStorage(true); - - if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0 && getBaseLevelDepth() > 0) - { - ASSERT(mTexStorage); - if (!mTexStorage->isRenderTarget()) - { - TextureStorage *newRenderTargetStorage = createCompleteStorage(true); - - if (!mRenderer->copyToRenderTarget3D(newRenderTargetStorage, mTexStorage)) + gl::Error error = updateStorageLevel(level); + if (error.isError()) { - delete newRenderTargetStorage; - return gl::error(GL_OUT_OF_MEMORY, false); + return error; } - - setCompleteTexStorage(newRenderTargetStorage); } } - return (mTexStorage && mTexStorage->isRenderTarget()); -} - -TextureStorage *TextureD3D_3D::getBaseLevelStorage() -{ - return mTexStorage; -} - -const ImageD3D *TextureD3D_3D::getBaseLevelImage() const -{ - return mImageArray[0]; + return gl::Error(GL_NO_ERROR); } bool TextureD3D_3D::isValidLevel(int level) const @@ -1685,15 +2161,28 @@ bool TextureD3D_3D::isLevelComplete(int level) const return true; } -void TextureD3D_3D::updateStorageLevel(int level) +bool TextureD3D_3D::isImageComplete(const gl::ImageIndex &index) const +{ + return isLevelComplete(index.mipIndex); +} + +gl::Error TextureD3D_3D::updateStorageLevel(int level) { ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL); ASSERT(isLevelComplete(level)); if (mImageArray[level]->isDirty()) { - commitRect(level, 0, 0, 0, getWidth(level), getHeight(level), getDepth(level)); + gl::ImageIndex index = gl::ImageIndex::Make3D(level); + gl::Box region(0, 0, 0, getWidth(level), getHeight(level), getDepth(level)); + gl::Error error = commitRegion(index, region); + if (error.isError()) + { + return error; + } } + + return gl::Error(GL_NO_ERROR); } void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) @@ -1727,22 +2216,26 @@ void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, GLsizei wi } } -void TextureD3D_3D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) +gl::ImageIndexIterator TextureD3D_3D::imageIterator() const { - if (isValidLevel(level)) - { - ImageD3D *image = mImageArray[level]; - if (image->copyToStorage3D(mTexStorage, level, xoffset, yoffset, zoffset, width, height, depth)) - { - image->markClean(); - } - } + return gl::ImageIndexIterator::Make3D(0, mTexStorage->getLevelCount(), + gl::ImageIndex::ENTIRE_LEVEL, gl::ImageIndex::ENTIRE_LEVEL); } +gl::ImageIndex TextureD3D_3D::getImageIndex(GLint mip, GLint /*layer*/) const +{ + // The "layer" here does not apply to 3D images. We use one Image per mip. + return gl::ImageIndex::Make3D(mip); +} -TextureD3D_2DArray::TextureD3D_2DArray(Renderer *renderer) - : TextureD3D(renderer), - mTexStorage(NULL) +bool TextureD3D_3D::isValidIndex(const gl::ImageIndex &index) const +{ + return (mTexStorage && index.type == GL_TEXTURE_3D && + index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount()); +} + +TextureD3D_2DArray::TextureD3D_2DArray(RendererD3D *renderer) + : TextureD3D(renderer) { for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level) { @@ -1791,11 +2284,6 @@ GLsizei TextureD3D_2DArray::getHeight(GLint level) const return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getHeight() : 0; } -GLsizei TextureD3D_2DArray::getLayers(GLint level) const -{ - return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mLayerCounts[level] : 0; -} - GLenum TextureD3D_2DArray::getInternalFormat(GLint level) const { return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getInternalFormat() : GL_NONE; @@ -1806,7 +2294,9 @@ bool TextureD3D_2DArray::isDepth(GLint level) const return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } -void TextureD3D_2DArray::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +gl::Error TextureD3D_2DArray::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, + GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, + const void *pixels) { ASSERT(target == GL_TEXTURE_2D_ARRAY); @@ -1820,11 +2310,20 @@ void TextureD3D_2DArray::setImage(GLenum target, GLint level, GLsizei width, GLs for (int i = 0; i < depth; i++) { const void *layerPixels = pixels ? (reinterpret_cast(pixels) + (inputDepthPitch * i)) : NULL; - TextureD3D::setImage(unpack, type, layerPixels, mImageArray[level][i]); + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i); + gl::Error error = TextureD3D::setImage(unpack, type, layerPixels, index); + if (error.isError()) + { + return error; + } } + + return gl::Error(GL_NO_ERROR); } -void TextureD3D_2DArray::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) +gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target, GLint level, GLenum format, + GLsizei width, GLsizei height, GLsizei depth, + GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) { ASSERT(target == GL_TEXTURE_2D_ARRAY); @@ -1837,11 +2336,19 @@ void TextureD3D_2DArray::setCompressedImage(GLenum target, GLint level, GLenum f for (int i = 0; i < depth; i++) { const void *layerPixels = pixels ? (reinterpret_cast(pixels) + (inputDepthPitch * i)) : NULL; - TextureD3D::setCompressedImage(imageSize, layerPixels, mImageArray[level][i]); + gl::Error error = TextureD3D::setCompressedImage(unpack, imageSize, layerPixels, mImageArray[level][i]); + if (error.isError()) + { + return error; + } } + + return gl::Error(GL_NO_ERROR); } -void TextureD3D_2DArray::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +gl::Error TextureD3D_2DArray::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const void *pixels) { ASSERT(target == GL_TEXTURE_2D_ARRAY); @@ -1854,14 +2361,20 @@ void TextureD3D_2DArray::subImage(GLenum target, GLint level, GLint xoffset, GLi const void *layerPixels = pixels ? (reinterpret_cast(pixels) + (inputDepthPitch * i)) : NULL; gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer); - if (TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, 1, format, type, unpack, layerPixels, index)) + gl::Error error = TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, 1, format, type, + unpack, layerPixels, index); + if (error.isError()) { - commitRect(level, xoffset, yoffset, layer, width, height); + return error; } } + + return gl::Error(GL_NO_ERROR); } -void TextureD3D_2DArray::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) +gl::Error TextureD3D_2DArray::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, GLenum format, + GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) { ASSERT(target == GL_TEXTURE_2D_ARRAY); @@ -1873,52 +2386,75 @@ void TextureD3D_2DArray::subImageCompressed(GLenum target, GLint level, GLint xo int layer = zoffset + i; const void *layerPixels = pixels ? (reinterpret_cast(pixels) + (inputDepthPitch * i)) : NULL; - if (TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, 1, format, imageSize, layerPixels, mImageArray[level][layer])) + gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, 1, format, imageSize, unpack, layerPixels, mImageArray[level][layer]); + if (error.isError()) { - commitRect(level, xoffset, yoffset, layer, width, height); + return error; + } + + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer); + gl::Box region(xoffset, yoffset, 0, width, height, 1); + error = commitRegion(index, region); + if (error.isError()) + { + return error; } } + + return gl::Error(GL_NO_ERROR); } -void TextureD3D_2DArray::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +gl::Error TextureD3D_2DArray::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) { UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, "Copying 2D array textures is unimplemented."); } -void TextureD3D_2DArray::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +gl::Error TextureD3D_2DArray::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) { ASSERT(target == GL_TEXTURE_2D_ARRAY); - // can only make our texture storage to a render target if level 0 is defined (with a width & height) and - // the current level we're copying to is defined (with appropriate format, width & height) - bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0); + gl::Rectangle sourceRect(x, y, width, height); + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, zoffset); - if (!mImageArray[level][0]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget)) + if (canCreateRenderTargetForImage(index)) { - mImageArray[level][zoffset]->copy(xoffset, yoffset, 0, x, y, width, height, source); + gl::Error error = mImageArray[level][zoffset]->copy(xoffset, yoffset, 0, sourceRect, source); + if (error.isError()) + { + return error; + } + mDirtyImages = true; } else { - ensureRenderTarget(); + gl::Error error = ensureRenderTarget(); + if (error.isError()) + { + return error; + } if (isValidLevel(level)) { - updateStorageLevel(level); + error = updateStorageLevel(level); + if (error.isError()) + { + return error; + } - gl::Rectangle sourceRect; - sourceRect.x = x; - sourceRect.width = width; - sourceRect.y = y; - sourceRect.height = height; - - mRenderer->copyImage2DArray(source, sourceRect, gl::GetInternalFormatInfo(getInternalFormat(0)).format, - xoffset, yoffset, zoffset, mTexStorage, level); + error = mRenderer->copyImage2DArray(source, sourceRect, gl::GetInternalFormatInfo(getInternalFormat(0)).format, + xoffset, yoffset, zoffset, mTexStorage, level); + if (error.isError()) + { + return error; + } } } + return gl::Error(GL_NO_ERROR); } -void TextureD3D_2DArray::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +gl::Error TextureD3D_2DArray::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { ASSERT(target == GL_TEXTURE_2D_ARRAY); @@ -1945,11 +2481,20 @@ void TextureD3D_2DArray::storage(GLenum target, GLsizei levels, GLenum internalf } } - mImmutable = true; - + // TODO(geofflang): Verify storage creation had no errors bool renderTarget = IsRenderTargetUsage(mUsage); TextureStorage *storage = mRenderer->createTextureStorage2DArray(internalformat, renderTarget, width, height, depth, levels); - setCompleteTexStorage(storage); + + gl::Error error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + + mImmutable = true; + + return gl::Error(GL_NO_ERROR); } void TextureD3D_2DArray::bindTexImage(egl::Surface *surface) @@ -1963,7 +2508,7 @@ void TextureD3D_2DArray::releaseTexImage() } -void TextureD3D_2DArray::generateMipmaps() +void TextureD3D_2DArray::initMipmapsImages() { int baseWidth = getBaseLevelWidth(); int baseHeight = getBaseLevelHeight(); @@ -1976,76 +2521,78 @@ void TextureD3D_2DArray::generateMipmaps() { redefineImage(level, baseFormat, std::max(baseWidth >> level, 1), std::max(baseHeight >> level, 1), baseDepth); } - - if (mTexStorage && mTexStorage->isRenderTarget()) - { - mTexStorage->generateMipmaps(); - - for (int level = 1; level < levelCount; level++) - { - for (int layer = 0; layer < mLayerCounts[level]; layer++) - { - mImageArray[level][layer]->markClean(); - } - } - } - else - { - for (int level = 1; level < levelCount; level++) - { - for (int layer = 0; layer < mLayerCounts[level]; layer++) - { - mRenderer->generateMipmap(mImageArray[level][layer], mImageArray[level - 1][layer]); - } - } - } } unsigned int TextureD3D_2DArray::getRenderTargetSerial(const gl::ImageIndex &index) { - return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(index) : 0); + return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0); } -RenderTarget *TextureD3D_2DArray::getRenderTarget(const gl::ImageIndex &index) +gl::Error TextureD3D_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) { // ensure the underlying texture is created - if (!ensureRenderTarget()) + gl::Error error = ensureRenderTarget(); + if (error.isError()) { - return NULL; + return error; } - updateStorageLevel(index.mipIndex); - return mTexStorage->getRenderTarget(index); + error = updateStorageLevel(index.mipIndex); + if (error.isError()) + { + return error; + } + + return mTexStorage->getRenderTarget(index, outRT); } -void TextureD3D_2DArray::initializeStorage(bool renderTarget) +gl::Error TextureD3D_2DArray::initializeStorage(bool renderTarget) { // Only initialize the first time this texture is used as a render target or shader resource if (mTexStorage) { - return; + return gl::Error(GL_NO_ERROR); } // do not attempt to create storage for nonexistant data if (!isLevelComplete(0)) { - return; + return gl::Error(GL_NO_ERROR); } bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); - setCompleteTexStorage(createCompleteStorage(createRenderTarget)); + TextureStorage *storage = NULL; + gl::Error error = createCompleteStorage(createRenderTarget, &storage); + if (error.isError()) + { + return error; + } + + error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + ASSERT(mTexStorage); // flush image data to the storage - updateStorage(); + error = updateStorage(); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); } -TextureStorage *TextureD3D_2DArray::createCompleteStorage(bool renderTarget) const +gl::Error TextureD3D_2DArray::createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const { GLsizei width = getBaseLevelWidth(); GLsizei height = getBaseLevelHeight(); - GLsizei depth = getLayers(0); + GLsizei depth = getLayerCount(0); GLenum internalFormat = getBaseLevelInternalFormat(); ASSERT(width > 0 && height > 0 && depth > 0); @@ -2053,10 +2600,13 @@ TextureStorage *TextureD3D_2DArray::createCompleteStorage(bool renderTarget) con // use existing storage level count, when previously specified by TexStorage*D GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1)); - return mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, width, height, depth, levels); + // TODO(geofflang): Verify storage creation succeeds + *outStorage = mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, width, height, depth, levels); + + return gl::Error(GL_NO_ERROR); } -void TextureD3D_2DArray::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) +gl::Error TextureD3D_2DArray::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) { SafeDelete(mTexStorage); mTexStorage = newCompleteTexStorage; @@ -2064,9 +2614,11 @@ void TextureD3D_2DArray::setCompleteTexStorage(TextureStorage *newCompleteTexSto // We do not support managed 2D array storage, as managed storage is ES2/D3D9 only ASSERT(!mTexStorage->isManaged()); + + return gl::Error(GL_NO_ERROR); } -void TextureD3D_2DArray::updateStorage() +gl::Error TextureD3D_2DArray::updateStorage() { ASSERT(mTexStorage != NULL); GLint storageLevels = mTexStorage->getLevelCount(); @@ -2074,43 +2626,15 @@ void TextureD3D_2DArray::updateStorage() { if (isLevelComplete(level)) { - updateStorageLevel(level); - } - } -} - -bool TextureD3D_2DArray::ensureRenderTarget() -{ - initializeStorage(true); - - if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0 && getLayers(0) > 0) - { - ASSERT(mTexStorage); - if (!mTexStorage->isRenderTarget()) - { - TextureStorage *newRenderTargetStorage = createCompleteStorage(true); - - if (!mRenderer->copyToRenderTarget2DArray(newRenderTargetStorage, mTexStorage)) + gl::Error error = updateStorageLevel(level); + if (error.isError()) { - delete newRenderTargetStorage; - return gl::error(GL_OUT_OF_MEMORY, false); + return error; } - - setCompleteTexStorage(newRenderTargetStorage); } } - return (mTexStorage && mTexStorage->isRenderTarget()); -} - -const ImageD3D *TextureD3D_2DArray::getBaseLevelImage() const -{ - return (mLayerCounts[0] > 0 ? mImageArray[0][0] : NULL); -} - -TextureStorage *TextureD3D_2DArray::getBaseLevelStorage() -{ - return mTexStorage; + return gl::Error(GL_NO_ERROR); } bool TextureD3D_2DArray::isValidLevel(int level) const @@ -2129,7 +2653,7 @@ bool TextureD3D_2DArray::isLevelComplete(int level) const GLsizei width = getBaseLevelWidth(); GLsizei height = getBaseLevelHeight(); - GLsizei layers = getLayers(0); + GLsizei layers = getLayerCount(0); if (width <= 0 || height <= 0 || layers <= 0) { @@ -2156,7 +2680,7 @@ bool TextureD3D_2DArray::isLevelComplete(int level) const return false; } - if (getLayers(level) != layers) + if (getLayerCount(level) != layers) { return false; } @@ -2164,7 +2688,12 @@ bool TextureD3D_2DArray::isLevelComplete(int level) const return true; } -void TextureD3D_2DArray::updateStorageLevel(int level) +bool TextureD3D_2DArray::isImageComplete(const gl::ImageIndex &index) const +{ + return isLevelComplete(index.mipIndex); +} + +gl::Error TextureD3D_2DArray::updateStorageLevel(int level) { ASSERT(level >= 0 && level < (int)ArraySize(mLayerCounts)); ASSERT(isLevelComplete(level)); @@ -2174,9 +2703,17 @@ void TextureD3D_2DArray::updateStorageLevel(int level) ASSERT(mImageArray[level] != NULL && mImageArray[level][layer] != NULL); if (mImageArray[level][layer]->isDirty()) { - commitRect(level, 0, 0, layer, getWidth(level), getHeight(level)); + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer); + gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1); + gl::Error error = commitRegion(index, region); + if (error.isError()) + { + return error; + } } } + + return gl::Error(GL_NO_ERROR); } void TextureD3D_2DArray::deleteImages() @@ -2198,7 +2735,7 @@ void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, GLsiz // If there currently is a corresponding storage texture image, it has these parameters const int storageWidth = std::max(1, getBaseLevelWidth() >> level); const int storageHeight = std::max(1, getBaseLevelHeight() >> level); - const int storageDepth = getLayers(0); + const int storageDepth = getLayerCount(0); const GLenum storageFormat = getBaseLevelInternalFormat(); for (int layer = 0; layer < mLayerCounts[level]; layer++) @@ -2245,16 +2782,32 @@ void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, GLsiz } } -void TextureD3D_2DArray::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint layerTarget, GLsizei width, GLsizei height) +gl::ImageIndexIterator TextureD3D_2DArray::imageIterator() const { - if (isValidLevel(level) && layerTarget < getLayers(level)) + return gl::ImageIndexIterator::Make2DArray(0, mTexStorage->getLevelCount(), mLayerCounts); +} + +gl::ImageIndex TextureD3D_2DArray::getImageIndex(GLint mip, GLint layer) const +{ + return gl::ImageIndex::Make2DArray(mip, layer); +} + +bool TextureD3D_2DArray::isValidIndex(const gl::ImageIndex &index) const +{ + // Check for having a storage and the right type of index + if (!mTexStorage || index.type != GL_TEXTURE_2D_ARRAY) { - ImageD3D *image = mImageArray[level][layerTarget]; - if (image->copyToStorage2DArray(mTexStorage, level, xoffset, yoffset, layerTarget, width, height)) - { - image->markClean(); - } + return false; } + + // Check the mip index + if (index.mipIndex < 0 || index.mipIndex >= mTexStorage->getLevelCount()) + { + return false; + } + + // Check the layer index + return (!index.hasLayer() || (index.layerIndex >= 0 && index.layerIndex < mLayerCounts[index.mipIndex])); } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h index 41c73180de8..083a6335b9e 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h @@ -11,7 +11,7 @@ #include "libGLESv2/renderer/TextureImpl.h" #include "libGLESv2/angletypes.h" -#include "libGLESv2/constants.h" +#include "libGLESv2/Constants.h" namespace gl { @@ -23,19 +23,19 @@ namespace rx class Image; class ImageD3D; -class Renderer; +class RendererD3D; class RenderTarget; class TextureStorage; class TextureD3D : public TextureImpl { public: - TextureD3D(Renderer *renderer); + TextureD3D(RendererD3D *renderer); virtual ~TextureD3D(); static TextureD3D *makeTextureD3D(TextureImpl *texture); - virtual TextureStorage *getNativeTexture(); + TextureStorage *getNativeTexture(); virtual void setUsage(GLenum usage) { mUsage = usage; } bool hasDirtyImages() const { return mDirtyImages; } @@ -48,45 +48,68 @@ class TextureD3D : public TextureImpl bool isImmutable() const { return mImmutable; } - virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index) = 0; + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) = 0; virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index) = 0; + // Returns an iterator over all "Images" for this particular Texture. + virtual gl::ImageIndexIterator imageIterator() const = 0; + + // Returns an ImageIndex for a particular "Image". 3D Textures do not have images for + // slices of their depth texures, so 3D textures ignore the layer parameter. + virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const = 0; + virtual bool isValidIndex(const gl::ImageIndex &index) const = 0; + + virtual gl::Error generateMipmaps(); + TextureStorage *getStorage(); + Image *getBaseLevelImage() const; + protected: - void setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, Image *image); - bool subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, const gl::ImageIndex &index); - void setCompressedImage(GLsizei imageSize, const void *pixels, Image *image); - bool subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLsizei imageSize, const void *pixels, Image *image); + gl::Error setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, const gl::ImageIndex &index); + gl::Error subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, const gl::ImageIndex &index); + gl::Error setCompressedImage(const gl::PixelUnpackState &unpack, GLsizei imageSize, const void *pixels, Image *image); + gl::Error subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels, Image *image); bool isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat); - bool fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea, - GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget); + gl::Error fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea, + GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget); GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const; int mipLevels() const; + virtual void initMipmapsImages() = 0; + bool isBaseImageZeroSize() const; + virtual bool isImageComplete(const gl::ImageIndex &index) const = 0; - Renderer *mRenderer; + bool canCreateRenderTargetForImage(const gl::ImageIndex &index) const; + virtual gl::Error ensureRenderTarget(); + + virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const = 0; + virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage) = 0; + gl::Error commitRegion(const gl::ImageIndex &index, const gl::Box ®ion); + + RendererD3D *mRenderer; GLenum mUsage; bool mDirtyImages; bool mImmutable; + TextureStorage *mTexStorage; private: DISALLOW_COPY_AND_ASSIGN(TextureD3D); - virtual void initializeStorage(bool renderTarget) = 0; + virtual gl::Error initializeStorage(bool renderTarget) = 0; - virtual void updateStorage() = 0; - virtual TextureStorage *getBaseLevelStorage() = 0; - virtual const ImageD3D *getBaseLevelImage() const = 0; + virtual gl::Error updateStorage() = 0; + + bool shouldUseSetData(const Image *image) const; }; class TextureD3D_2D : public TextureD3D { public: - TextureD3D_2D(Renderer *renderer); + TextureD3D_2D(RendererD3D *renderer); virtual ~TextureD3D_2D(); virtual Image *getImage(int level, int layer) const; @@ -99,50 +122,49 @@ class TextureD3D_2D : public TextureD3D GLenum getActualFormat(GLint level) const; bool isDepth(GLint level) const; - virtual void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); - virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); - virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); + virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); + virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); virtual void bindTexImage(egl::Surface *surface); virtual void releaseTexImage(); - virtual void generateMipmaps(); - - virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); + virtual gl::ImageIndexIterator imageIterator() const; + virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const; + virtual bool isValidIndex(const gl::ImageIndex &index) const; + private: DISALLOW_COPY_AND_ASSIGN(TextureD3D_2D); - virtual void initializeStorage(bool renderTarget); - TextureStorage *createCompleteStorage(bool renderTarget) const; - void setCompleteTexStorage(TextureStorage *newCompleteTexStorage); + virtual gl::Error initializeStorage(bool renderTarget); + virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const; + virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage); - virtual void updateStorage(); - bool ensureRenderTarget(); - virtual TextureStorage *getBaseLevelStorage(); - virtual const ImageD3D *getBaseLevelImage() const; + virtual gl::Error updateStorage(); + virtual void initMipmapsImages(); bool isValidLevel(int level) const; bool isLevelComplete(int level) const; + virtual bool isImageComplete(const gl::ImageIndex &index) const; - void updateStorageLevel(int level); + gl::Error updateStorageLevel(int level); void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height); - void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - TextureStorage *mTexStorage; ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; }; class TextureD3D_Cube : public TextureD3D { public: - TextureD3D_Cube(Renderer *renderer); + TextureD3D_Cube(RendererD3D *renderer); virtual ~TextureD3D_Cube(); virtual Image *getImage(int level, int layer) const; @@ -156,51 +178,49 @@ class TextureD3D_Cube : public TextureD3D GLenum getInternalFormat(GLint level, GLint layer) const; bool isDepth(GLint level, GLint layer) const; - virtual void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); - virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); - virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); + virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); + virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); virtual void bindTexImage(egl::Surface *surface); virtual void releaseTexImage(); - virtual void generateMipmaps(); - - virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); + virtual gl::ImageIndexIterator imageIterator() const; + virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const; + virtual bool isValidIndex(const gl::ImageIndex &index) const; + private: DISALLOW_COPY_AND_ASSIGN(TextureD3D_Cube); - virtual void initializeStorage(bool renderTarget); - TextureStorage *createCompleteStorage(bool renderTarget) const; - void setCompleteTexStorage(TextureStorage *newCompleteTexStorage); + virtual gl::Error initializeStorage(bool renderTarget); + virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const; + virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage); - virtual void updateStorage(); - bool ensureRenderTarget(); - virtual TextureStorage *getBaseLevelStorage(); - virtual const ImageD3D *getBaseLevelImage() const; + virtual gl::Error updateStorage(); + virtual void initMipmapsImages(); bool isValidFaceLevel(int faceIndex, int level) const; bool isFaceLevelComplete(int faceIndex, int level) const; bool isCubeComplete() const; - void updateStorageFaceLevel(int faceIndex, int level); + virtual bool isImageComplete(const gl::ImageIndex &index) const; + gl::Error updateStorageFaceLevel(int faceIndex, int level); void redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height); - void commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); ImageD3D *mImageArray[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - - TextureStorage *mTexStorage; }; class TextureD3D_3D : public TextureD3D { public: - TextureD3D_3D(Renderer *renderer); + TextureD3D_3D(RendererD3D *renderer); virtual ~TextureD3D_3D(); virtual Image *getImage(int level, int layer) const; @@ -213,50 +233,48 @@ class TextureD3D_3D : public TextureD3D GLenum getInternalFormat(GLint level) const; bool isDepth(GLint level) const; - virtual void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); - virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); - virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); + virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); + virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); virtual void bindTexImage(egl::Surface *surface); virtual void releaseTexImage(); - virtual void generateMipmaps(); - - virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); + virtual gl::ImageIndexIterator imageIterator() const; + virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const; + virtual bool isValidIndex(const gl::ImageIndex &index) const; + private: DISALLOW_COPY_AND_ASSIGN(TextureD3D_3D); - virtual void initializeStorage(bool renderTarget); - TextureStorage *createCompleteStorage(bool renderTarget) const; - void setCompleteTexStorage(TextureStorage *newCompleteTexStorage); + virtual gl::Error initializeStorage(bool renderTarget); + virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const; + virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage); - virtual void updateStorage(); - bool ensureRenderTarget(); - virtual TextureStorage *getBaseLevelStorage(); - virtual const ImageD3D *getBaseLevelImage() const; + virtual gl::Error updateStorage(); + virtual void initMipmapsImages(); bool isValidLevel(int level) const; bool isLevelComplete(int level) const; - void updateStorageLevel(int level); + virtual bool isImageComplete(const gl::ImageIndex &index) const; + gl::Error updateStorageLevel(int level); void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); - void commitRect(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - - TextureStorage *mTexStorage; }; class TextureD3D_2DArray : public TextureD3D { public: - TextureD3D_2DArray(Renderer *renderer); + TextureD3D_2DArray(RendererD3D *renderer); virtual ~TextureD3D_2DArray(); virtual Image *getImage(int level, int layer) const; @@ -265,45 +283,44 @@ class TextureD3D_2DArray : public TextureD3D GLsizei getWidth(GLint level) const; GLsizei getHeight(GLint level) const; - GLsizei getLayers(GLint level) const; GLenum getInternalFormat(GLint level) const; bool isDepth(GLint level) const; - virtual void setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); - virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); - virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); + virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); + virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); + virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); virtual void bindTexImage(egl::Surface *surface); virtual void releaseTexImage(); - virtual void generateMipmaps(); - - virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); + virtual gl::ImageIndexIterator imageIterator() const; + virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const; + virtual bool isValidIndex(const gl::ImageIndex &index) const; + private: DISALLOW_COPY_AND_ASSIGN(TextureD3D_2DArray); - virtual void initializeStorage(bool renderTarget); - TextureStorage *createCompleteStorage(bool renderTarget) const; - void setCompleteTexStorage(TextureStorage *newCompleteTexStorage); + virtual gl::Error initializeStorage(bool renderTarget); + virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const; + virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage); - virtual void updateStorage(); - bool ensureRenderTarget(); - virtual TextureStorage *getBaseLevelStorage(); - virtual const ImageD3D *getBaseLevelImage() const; + virtual gl::Error updateStorage(); + virtual void initMipmapsImages(); bool isValidLevel(int level) const; bool isLevelComplete(int level) const; - void updateStorageLevel(int level); + virtual bool isImageComplete(const gl::ImageIndex &index) const; + gl::Error updateStorageLevel(int level); void deleteImages(); void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); - void commitRect(GLint level, GLint xoffset, GLint yoffset, GLint layerTarget, GLsizei width, GLsizei height); // Storing images as an array of single depth textures since D3D11 treats each array level of a // Texture2D object as a separate subresource. Each layer would have to be looped over @@ -311,8 +328,6 @@ class TextureD3D_2DArray : public TextureD3D // sense for the Image class to not have to worry about layer subresource as well as mip subresources. GLsizei mLayerCounts[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; ImageD3D **mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - - TextureStorage *mTexStorage; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp index dedd266c09c..320b74b8edd 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp @@ -8,6 +8,7 @@ #include "libGLESv2/renderer/d3d/TextureStorage.h" #include "libGLESv2/renderer/d3d/TextureD3D.h" +#include "libGLESv2/renderer/RenderTarget.h" #include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/Renderbuffer.h" #include "libGLESv2/Texture.h" @@ -18,17 +19,14 @@ namespace rx { -unsigned int TextureStorage::mCurrentTextureSerial = 1; - TextureStorage::TextureStorage() - : mTextureSerial(issueTextureSerial()), - mFirstRenderTargetSerial(0), + : mFirstRenderTargetSerial(0), mRenderTargetSerialsLayerStride(0) {} void TextureStorage::initializeSerials(unsigned int rtSerialsToReserve, unsigned int rtSerialsLayerStride) { - mFirstRenderTargetSerial = gl::RenderbufferStorage::issueSerials(rtSerialsToReserve); + mFirstRenderTargetSerial = RenderTarget::issueSerials(rtSerialsToReserve); mRenderTargetSerialsLayerStride = rtSerialsLayerStride; } @@ -38,14 +36,4 @@ unsigned int TextureStorage::getRenderTargetSerial(const gl::ImageIndex &index) return mFirstRenderTargetSerial + static_cast(index.mipIndex) + layerOffset; } -unsigned int TextureStorage::getTextureSerial() const -{ - return mTextureSerial; -} - -unsigned int TextureStorage::issueTextureSerial() -{ - return mCurrentTextureSerial++; -} - } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h index 9cc2c2977b2..da92be3c741 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h @@ -9,20 +9,26 @@ #ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ #define LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ +#include "libGLESv2/Error.h" + #include "common/debug.h" +#include "libGLESv2/Error.h" #include +#include namespace gl { struct ImageIndex; +struct Box; +struct PixelUnpackState; } namespace rx { -class Renderer; class SwapChain; class RenderTarget; +class Image; class TextureStorage { @@ -35,8 +41,12 @@ class TextureStorage virtual bool isManaged() const = 0; virtual int getLevelCount() const = 0; - virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index) = 0; - virtual void generateMipmaps() = 0; + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) = 0; + virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) = 0; + + virtual gl::Error copyToStorage(TextureStorage *destStorage) = 0; + virtual gl::Error setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixelData) = 0; unsigned int getRenderTargetSerial(const gl::ImageIndex &index) const; unsigned int getTextureSerial() const; @@ -47,11 +57,6 @@ class TextureStorage private: DISALLOW_COPY_AND_ASSIGN(TextureStorage); - const unsigned int mTextureSerial; - static unsigned int issueTextureSerial(); - - static unsigned int mCurrentTextureSerial; - unsigned int mFirstRenderTargetSerial; unsigned int mRenderTargetSerialsLayerStride; }; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp index 4f85eb94fa7..73f0c79e192 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp @@ -9,7 +9,7 @@ #include "libGLESv2/renderer/d3d/VertexBuffer.h" #include "libGLESv2/renderer/d3d/BufferD3D.h" -#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/d3d/RendererD3D.h" #include "libGLESv2/VertexAttribute.h" #include "common/mathutil.h" @@ -38,7 +38,7 @@ unsigned int VertexBuffer::getSerial() const return mSerial; } -VertexBufferInterface::VertexBufferInterface(rx::Renderer *renderer, bool dynamic) : mRenderer(renderer) +VertexBufferInterface::VertexBufferInterface(RendererD3D *renderer, bool dynamic) : mRenderer(renderer) { mDynamic = dynamic; mWritePosition = 0; @@ -127,7 +127,7 @@ gl::Error VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute mWritePosition += spaceRequired; // Align to 16-byte boundary - mWritePosition = rx::roundUp(mWritePosition, 16u); + mWritePosition = roundUp(mWritePosition, 16u); return gl::Error(GL_NO_ERROR); } @@ -153,7 +153,7 @@ gl::Error VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &a mReservedSpace += requiredSpace; // Align to 16-byte boundary - mReservedSpace = rx::roundUp(mReservedSpace, 16u); + mReservedSpace = roundUp(mReservedSpace, 16u); return gl::Error(GL_NO_ERROR); } @@ -197,7 +197,7 @@ bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &att return !requiresConversion && isAligned; } -StreamingVertexBufferInterface::StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize) : VertexBufferInterface(renderer, true) +StreamingVertexBufferInterface::StreamingVertexBufferInterface(RendererD3D *renderer, std::size_t initialSize) : VertexBufferInterface(renderer, true) { setBufferSize(initialSize); } @@ -231,7 +231,7 @@ gl::Error StreamingVertexBufferInterface::reserveSpace(unsigned int size) return gl::Error(GL_NO_ERROR); } -StaticVertexBufferInterface::StaticVertexBufferInterface(rx::Renderer *renderer) : VertexBufferInterface(renderer, false) +StaticVertexBufferInterface::StaticVertexBufferInterface(RendererD3D *renderer) : VertexBufferInterface(renderer, false) { } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h index fa747d9cb43..4b40818f8ef 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h @@ -26,7 +26,7 @@ struct VertexAttribCurrentValueData; namespace rx { -class Renderer; +class RendererD3D; class VertexBuffer { @@ -60,7 +60,7 @@ class VertexBuffer class VertexBufferInterface { public: - VertexBufferInterface(rx::Renderer *renderer, bool dynamic); + VertexBufferInterface(RendererD3D *renderer, bool dynamic); virtual ~VertexBufferInterface(); gl::Error reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances); @@ -90,7 +90,7 @@ class VertexBufferInterface private: DISALLOW_COPY_AND_ASSIGN(VertexBufferInterface); - rx::Renderer *const mRenderer; + RendererD3D *const mRenderer; VertexBuffer* mVertexBuffer; @@ -102,7 +102,7 @@ class VertexBufferInterface class StreamingVertexBufferInterface : public VertexBufferInterface { public: - StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize); + StreamingVertexBufferInterface(RendererD3D *renderer, std::size_t initialSize); ~StreamingVertexBufferInterface(); protected: @@ -112,7 +112,7 @@ class StreamingVertexBufferInterface : public VertexBufferInterface class StaticVertexBufferInterface : public VertexBufferInterface { public: - explicit StaticVertexBufferInterface(rx::Renderer *renderer); + explicit StaticVertexBufferInterface(RendererD3D *renderer); ~StaticVertexBufferInterface(); gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp index 7034b78eabc..8d3df31c8b1 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp @@ -14,6 +14,7 @@ #include "libGLESv2/Buffer.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/VertexAttribute.h" +#include "libGLESv2/State.h" namespace { @@ -51,7 +52,7 @@ static int StreamingBufferElementCount(const gl::VertexAttribute &attrib, int ve return vertexDrawCount; } -VertexDataManager::VertexDataManager(Renderer *renderer) : mRenderer(renderer) +VertexDataManager::VertexDataManager(RendererD3D *renderer) : mRenderer(renderer) { for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { @@ -82,8 +83,8 @@ VertexDataManager::~VertexDataManager() } } -gl::Error VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], const gl::VertexAttribCurrentValueData currentValues[], - gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances) +gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint start, GLsizei count, + TranslatedAttribute *translated, GLsizei instances) { if (!mStreamingBuffer) { @@ -93,20 +94,22 @@ gl::Error VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs // Invalidate static buffers that don't contain matching attributes for (int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) { - translated[attributeIndex].active = (programBinary->getSemanticIndex(attributeIndex) != -1); + translated[attributeIndex].active = (state.getCurrentProgramBinary()->getSemanticIndex(attributeIndex) != -1); + const gl::VertexAttribute &curAttrib = state.getVertexAttribState(attributeIndex); - if (translated[attributeIndex].active && attribs[attributeIndex].enabled) + if (translated[attributeIndex].active && curAttrib.enabled) { - invalidateMatchingStaticData(attribs[attributeIndex], currentValues[attributeIndex]); + invalidateMatchingStaticData(curAttrib, state.getVertexAttribCurrentValue(attributeIndex)); } } // Reserve the required space in the buffers for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { - if (translated[i].active && attribs[i].enabled) + const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i); + if (translated[i].active && curAttrib.enabled) { - gl::Error error = reserveSpaceForAttrib(attribs[i], currentValues[i], count, instances); + gl::Error error = reserveSpaceForAttrib(curAttrib, state.getVertexAttribCurrentValue(i), count, instances); if (error.isError()) { return error; @@ -117,12 +120,14 @@ gl::Error VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs // Perform the vertex data translations for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { + const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i); if (translated[i].active) { - if (attribs[i].enabled) + if (curAttrib.enabled) { - gl::Error error = storeAttribute(attribs[i], currentValues[i], &translated[i], - start, count, instances); + gl::Error error = storeAttribute(curAttrib, state.getVertexAttribCurrentValue(i), + &translated[i], start, count, instances); + if (error.isError()) { return error; @@ -135,7 +140,7 @@ gl::Error VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mRenderer, CONSTANT_VERTEX_BUFFER_SIZE); } - gl::Error error = storeCurrentValue(attribs[i], currentValues[i], &translated[i], + gl::Error error = storeCurrentValue(curAttrib, state.getVertexAttribCurrentValue(i), &translated[i], &mCurrentValue[i], &mCurrentValueOffsets[i], mCurrentValueBuffer[i]); if (error.isError()) @@ -148,14 +153,15 @@ gl::Error VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { - if (translated[i].active && attribs[i].enabled) + const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i); + if (translated[i].active && curAttrib.enabled) { - gl::Buffer *buffer = attribs[i].buffer.get(); + gl::Buffer *buffer = curAttrib.buffer.get(); if (buffer) { BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation()); - bufferImpl->promoteStaticUsage(count * ComputeVertexAttributeTypeSize(attribs[i])); + bufferImpl->promoteStaticUsage(count * ComputeVertexAttributeTypeSize(curAttrib)); } } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h index 77287222464..64ef653221f 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h @@ -16,8 +16,9 @@ namespace gl { -struct VertexAttribute; class ProgramBinary; +class State; +struct VertexAttribute; struct VertexAttribCurrentValueData; } @@ -26,7 +27,7 @@ namespace rx class BufferD3D; class StreamingVertexBufferInterface; class VertexBuffer; -class Renderer; +class RendererD3D; struct TranslatedAttribute { @@ -49,11 +50,11 @@ struct TranslatedAttribute class VertexDataManager { public: - VertexDataManager(rx::Renderer *renderer); + VertexDataManager(RendererD3D *renderer); virtual ~VertexDataManager(); - gl::Error prepareVertexData(const gl::VertexAttribute attribs[], const gl::VertexAttribCurrentValueData currentValues[], - gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *outAttribs, GLsizei instances); + gl::Error prepareVertexData(const gl::State &state, GLint start, GLsizei count, + TranslatedAttribute *outAttribs, GLsizei instances); private: DISALLOW_COPY_AND_ASSIGN(VertexDataManager); @@ -80,7 +81,7 @@ class VertexDataManager size_t *cachedOffset, StreamingVertexBufferInterface *buffer); - rx::Renderer *const mRenderer; + RendererD3D *const mRenderer; StreamingVertexBufferInterface *mStreamingBuffer; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp index d43e65ea78a..06aea9befe6 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp @@ -172,7 +172,7 @@ static void Write3DVertices(const gl::Box &sourceArea, const gl::Extents &source *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; } -Blit11::Blit11(rx::Renderer11 *renderer) +Blit11::Blit11(Renderer11 *renderer) : mRenderer(renderer), mBlitShaderMap(compareBlitParameters), mSwizzleShaderMap(compareSwizzleParameters), mVertexBuffer(NULL), mPointSampler(NULL), mLinearSampler(NULL), mScissorEnabledRasterizerState(NULL), mScissorDisabledRasterizerState(NULL), mDepthStencilState(NULL), @@ -209,7 +209,7 @@ Blit11::Blit11(rx::Renderer11 *renderer) pointSamplerDesc.BorderColor[2] = 0.0f; pointSamplerDesc.BorderColor[3] = 0.0f; pointSamplerDesc.MinLOD = 0.0f; - pointSamplerDesc.MaxLOD = mRenderer->isLevel9() ? FLT_MAX : 0.0f; + pointSamplerDesc.MaxLOD = mRenderer->isLevel9() ? D3D11_FLOAT32_MAX : 0.0f; result = device->CreateSamplerState(&pointSamplerDesc, &mPointSampler); ASSERT(SUCCEEDED(result)); @@ -228,7 +228,7 @@ Blit11::Blit11(rx::Renderer11 *renderer) linearSamplerDesc.BorderColor[2] = 0.0f; linearSamplerDesc.BorderColor[3] = 0.0f; linearSamplerDesc.MinLOD = 0.0f; - linearSamplerDesc.MaxLOD = mRenderer->isLevel9() ? FLT_MAX : 0.0f; + linearSamplerDesc.MaxLOD = mRenderer->isLevel9() ? D3D11_FLOAT32_MAX : 0.0f; result = device->CreateSamplerState(&linearSamplerDesc, &mLinearSampler); ASSERT(SUCCEEDED(result)); @@ -468,8 +468,7 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderT deviceContext->GSSetShader(shader.mGeometryShader, NULL, 0); // Unset the currently bound shader resource to avoid conflicts - ID3D11ShaderResourceView *const nullSRV = NULL; - deviceContext->PSSetShaderResources(0, 1, &nullSRV); + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); // Apply render target mRenderer->setOneTimeRenderTarget(dest); @@ -485,7 +484,7 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderT deviceContext->RSSetViewports(1, &viewport); // Apply textures - deviceContext->PSSetShaderResources(0, 1, &source); + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, source); // Apply samplers deviceContext->PSSetSamplers(0, 1, &mPointSampler); @@ -494,7 +493,7 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderT deviceContext->Draw(drawCount, 0); // Unbind textures and render targets and vertex buffer - deviceContext->PSSetShaderResources(0, 1, &nullSRV); + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); mRenderer->unapplyRenderTargets(); @@ -507,9 +506,9 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderT return gl::Error(GL_NO_ERROR); } -bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor, GLenum destFormat, GLenum filter) +gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor, GLenum destFormat, GLenum filter) { HRESULT result; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); @@ -531,7 +530,7 @@ bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &source if (i == mBlitShaderMap.end()) { UNREACHABLE(); - return false; + return gl::Error(GL_OUT_OF_MEMORY, "Could not find appropriate shader for internal texture blit."); } const Shader& shader = i->second; @@ -541,8 +540,7 @@ bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &source result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { - ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result); - return false; + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer for texture copy, HRESULT: 0x%X.", result); } UINT stride = 0; @@ -587,8 +585,7 @@ bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &source deviceContext->GSSetShader(shader.mGeometryShader, NULL, 0); // Unset the currently bound shader resource to avoid conflicts - ID3D11ShaderResourceView *const nullSRV = NULL; - deviceContext->PSSetShaderResources(0, 1, &nullSRV); + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); // Apply render target mRenderer->setOneTimeRenderTarget(dest); @@ -604,7 +601,7 @@ bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &source deviceContext->RSSetViewports(1, &viewport); // Apply textures - deviceContext->PSSetShaderResources(0, 1, &source); + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, source); // Apply samplers ID3D11SamplerState *sampler = NULL; @@ -612,7 +609,10 @@ bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &source { case GL_NEAREST: sampler = mPointSampler; break; case GL_LINEAR: sampler = mLinearSampler; break; - default: UNREACHABLE(); return false; + + default: + UNREACHABLE(); + return gl::Error(GL_OUT_OF_MEMORY, "Internal error, unknown blit filter mode."); } deviceContext->PSSetSamplers(0, 1, &sampler); @@ -620,7 +620,7 @@ bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &source deviceContext->Draw(drawCount, 0); // Unbind textures and render targets and vertex buffer - deviceContext->PSSetShaderResources(0, 1, &nullSRV); + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); mRenderer->unapplyRenderTargets(); @@ -630,21 +630,21 @@ bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &source mRenderer->markAllStateDirty(); - return true; + return gl::Error(GL_NO_ERROR); } -bool Blit11::copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor) +gl::Error Blit11::copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor) { return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize, dest, destSubresource, destArea, destSize, scissor, true); } -bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor) +gl::Error Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor) { HRESULT result; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); @@ -654,8 +654,7 @@ bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceAr result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { - ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result); - return false; + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer for texture copy, HRESULT: 0x%X.", result); } UINT stride = 0; @@ -700,8 +699,7 @@ bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceAr deviceContext->GSSetShader(NULL, NULL, 0); // Unset the currently bound shader resource to avoid conflicts - ID3D11ShaderResourceView *const nullSRV = NULL; - deviceContext->PSSetShaderResources(0, 1, &nullSRV); + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); // Apply render target deviceContext->OMSetRenderTargets(0, NULL, dest); @@ -717,7 +715,7 @@ bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceAr deviceContext->RSSetViewports(1, &viewport); // Apply textures - deviceContext->PSSetShaderResources(0, 1, &source); + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, source); // Apply samplers deviceContext->PSSetSamplers(0, 1, &mPointSampler); @@ -726,7 +724,7 @@ bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceAr deviceContext->Draw(drawCount, 0); // Unbind textures and render targets and vertex buffer - deviceContext->PSSetShaderResources(0, 1, &nullSRV); + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); mRenderer->unapplyRenderTargets(); @@ -736,21 +734,21 @@ bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceAr mRenderer->markAllStateDirty(); - return true; + return gl::Error(GL_NO_ERROR); } -bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor) +gl::Error Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor) { return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize, dest, destSubresource, destArea, destSize, scissor, false); } -bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor, bool stencilOnly) +gl::Error Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor, bool stencilOnly) { ID3D11Device *device = mRenderer->getDevice(); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); @@ -764,7 +762,7 @@ bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubreso { SafeRelease(sourceStaging); SafeRelease(destStaging); - return false; + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal staging textures for depth stencil blit."); } DXGI_FORMAT format = GetTextureFormat(source); @@ -785,23 +783,23 @@ bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubreso dxgiFormatInfo.depthBits % 8 == 0); } - D3D11_MAPPED_SUBRESOURCE sourceMapping, destMapping; - deviceContext->Map(sourceStaging, 0, D3D11_MAP_READ, 0, &sourceMapping); - deviceContext->Map(destStaging, 0, D3D11_MAP_WRITE, 0, &destMapping); - - if (!sourceMapping.pData || !destMapping.pData) + D3D11_MAPPED_SUBRESOURCE sourceMapping; + HRESULT result = deviceContext->Map(sourceStaging, 0, D3D11_MAP_READ, 0, &sourceMapping); + if (FAILED(result)) { - if (!sourceMapping.pData) - { - deviceContext->Unmap(sourceStaging, 0); - } - if (!destMapping.pData) - { - deviceContext->Unmap(destStaging, 0); - } SafeRelease(sourceStaging); SafeRelease(destStaging); - return false; + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal source staging texture for depth stencil blit, HRESULT: 0x%X.", result); + } + + D3D11_MAPPED_SUBRESOURCE destMapping; + result = deviceContext->Map(destStaging, 0, D3D11_MAP_WRITE, 0, &destMapping); + if (FAILED(result)) + { + deviceContext->Unmap(sourceStaging, 0); + SafeRelease(sourceStaging); + SafeRelease(destStaging); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal destination staging texture for depth stencil blit, HRESULT: 0x%X.", result); } gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height); @@ -880,7 +878,7 @@ bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubreso SafeRelease(sourceStaging); SafeRelease(destStaging); - return true; + return gl::Error(GL_NO_ERROR); } bool Blit11::compareBlitParameters(const Blit11::BlitParameters &a, const Blit11::BlitParameters &b) @@ -1001,12 +999,12 @@ void Blit11::buildShaderMap() add3DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI, "Blit11 3D I RGBA pixel shader" )); add3DBlitShaderToMap(GL_BGRA_EXT, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D BGRA pixel shader" )); add3DBlitShaderToMap(GL_RGB, false, d3d11::CompilePS(device, g_PS_PassthroughRGB3D, "Blit11 3D RGB pixel shader" )); - add3DBlitShaderToMap(GL_RG, false, d3d11::CompilePS(device, g_PS_PassthroughRG3D, "Blit11 3D RG pixel shader" )); add3DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB3DUI, "Blit11 3D RGB UI pixel shader" )); add3DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB3DI, "Blit11 3D RGB I pixel shader" )); - add3DBlitShaderToMap(GL_RED, false, d3d11::CompilePS(device, g_PS_PassthroughR3D, "Blit11 3D R pixel shader" )); + add3DBlitShaderToMap(GL_RG, false, d3d11::CompilePS(device, g_PS_PassthroughRG3D, "Blit11 3D RG pixel shader" )); add3DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG3DUI, "Blit11 3D RG UI pixel shader" )); add3DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG3DI, "Blit11 3D RG I pixel shader" )); + add3DBlitShaderToMap(GL_RED, false, d3d11::CompilePS(device, g_PS_PassthroughR3D, "Blit11 3D R pixel shader" )); add3DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR3DUI, "Blit11 3D R UI pixel shader" )); add3DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR3DI, "Blit11 3D R I pixel shader" )); add3DBlitShaderToMap(GL_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D alpha pixel shader" )); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h index d6a0b795f49..821fa9d0cc2 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h @@ -19,12 +19,6 @@ namespace rx { class Renderer11; -enum Filter -{ - Point, - Linear, -}; - class Blit11 { public: @@ -34,24 +28,24 @@ class Blit11 gl::Error swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size, GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); - bool copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor, GLenum destFormat, GLenum filter); + gl::Error copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor, GLenum destFormat, GLenum filter); - bool copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor); - - bool copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor); - - bool copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + gl::Error copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, const gl::Rectangle *scissor); + gl::Error copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor); + + gl::Error copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor); + private: - rx::Renderer11 *mRenderer; + Renderer11 *mRenderer; struct BlitParameters { @@ -60,9 +54,9 @@ class Blit11 bool m3DBlit; }; - bool copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor, bool stencilOnly); + gl::Error copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor, bool stencilOnly); static bool compareBlitParameters(const BlitParameters &a, const BlitParameters &b); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp index ecd4d4672b0..5aab37938f1 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp @@ -86,7 +86,7 @@ class Buffer11::BufferStorage11 virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset, size_t size, size_t destOffset) = 0; - virtual bool resize(size_t size, bool preserveData) = 0; + virtual gl::Error resize(size_t size, bool preserveData) = 0; virtual void *map(size_t offset, size_t length, GLbitfield access) = 0; virtual void unmap() = 0; @@ -112,17 +112,17 @@ class Buffer11::NativeBuffer11 : public Buffer11::BufferStorage11 virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset, size_t size, size_t destOffset); - virtual bool resize(size_t size, bool preserveData); + virtual gl::Error resize(size_t size, bool preserveData); virtual void *map(size_t offset, size_t length, GLbitfield access); virtual void unmap(); - bool setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset); + gl::Error setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset); private: ID3D11Buffer *mNativeBuffer; - static void fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize); + static void fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer11 *renderer, BufferUsage usage, unsigned int bufferSize); }; // Pack storage represents internal storage for pack buffers. We implement pack buffers @@ -135,7 +135,7 @@ class Buffer11::PackStorage11 : public Buffer11::BufferStorage11 virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset, size_t size, size_t destOffset); - virtual bool resize(size_t size, bool preserveData); + virtual gl::Error resize(size_t size, bool preserveData); virtual void *map(size_t offset, size_t length, GLbitfield access); virtual void unmap(); @@ -144,7 +144,7 @@ class Buffer11::PackStorage11 : public Buffer11::BufferStorage11 private: - void flushQueuedPackCommand(); + gl::Error flushQueuedPackCommand(); ID3D11Texture2D *mStagingTexture; DXGI_FORMAT mTextureFormat; @@ -195,14 +195,14 @@ gl::Error Buffer11::setData(const void *data, size_t size, GLenum usage) return error; } -void *Buffer11::getData() +gl::Error Buffer11::getData(const uint8_t **outData) { NativeBuffer11 *stagingBuffer = getStagingBuffer(); if (!stagingBuffer) { // Out-of-memory - return NULL; + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get internal staging buffer."); } if (stagingBuffer->getDataRevision() > mResolvedDataRevision) @@ -211,7 +211,7 @@ void *Buffer11::getData() { if (!mResolvedData.resize(stagingBuffer->getSize())) { - return gl::error(GL_OUT_OF_MEMORY, (void*)NULL); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize data resolve buffer."); } } @@ -221,7 +221,7 @@ void *Buffer11::getData() HRESULT result = context->Map(stagingBuffer->getNativeBuffer(), 0, D3D11_MAP_READ, 0, &mappedResource); if (FAILED(result)) { - return gl::error(GL_OUT_OF_MEMORY, (void*)NULL); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer, result: 0x%X.", result); } memcpy(mResolvedData.data(), mappedResource.pData, stagingBuffer->getSize()); @@ -238,13 +238,14 @@ void *Buffer11::getData() { if (!mResolvedData.resize(mSize)) { - return gl::error(GL_OUT_OF_MEMORY, (void*)NULL); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize data resolve buffer."); } } ASSERT(mResolvedData.size() >= mSize); - return mResolvedData.data(); + *outData = mResolvedData.data(); + return gl::Error(GL_NO_ERROR); } gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset) @@ -265,15 +266,17 @@ gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset) if (stagingBuffer->getSize() < requiredSize) { bool preserveData = (offset > 0); - if (!stagingBuffer->resize(requiredSize, preserveData)) + gl::Error error = stagingBuffer->resize(requiredSize, preserveData); + if (error.isError()) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal staging buffer."); + return error; } } - if (!stagingBuffer->setData(D3D11_MAP_WRITE, reinterpret_cast(data), size, offset)) + gl::Error error = stagingBuffer->setData(D3D11_MAP_WRITE, reinterpret_cast(data), size, offset); + if (error.isError()) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to set data on internal staging buffer."); + return error; } stagingBuffer->setDataRevision(stagingBuffer->getDataRevision() + 1); @@ -411,7 +414,7 @@ void Buffer11::markBufferUsage() } } -Renderer* Buffer11::getRenderer() +RendererD3D* Buffer11::getRenderer() { return mRenderer; } @@ -527,7 +530,7 @@ Buffer11::BufferStorage11 *Buffer11::getBufferStorage(BufferUsage usage) // resize buffer if (directBuffer->getSize() < mSize) { - if (!directBuffer->resize(mSize, true)) + if (directBuffer->resize(mSize, true).isError()) { // Out of memory error return NULL; @@ -667,6 +670,9 @@ bool Buffer11::NativeBuffer11::copyFromStorage(BufferStorage11 *source, size_t s // Offset bounds are validated at the API layer ASSERT(sourceOffset + size <= destOffset + mBufferSize); memcpy(destPointer, sourcePointer, size); + + context->Unmap(mNativeBuffer, 0); + source->unmap(); } else { @@ -689,7 +695,7 @@ bool Buffer11::NativeBuffer11::copyFromStorage(BufferStorage11 *source, size_t s return createBuffer; } -bool Buffer11::NativeBuffer11::resize(size_t size, bool preserveData) +gl::Error Buffer11::NativeBuffer11::resize(size_t size, bool preserveData) { ID3D11Device *device = mRenderer->getDevice(); ID3D11DeviceContext *context = mRenderer->getDeviceContext(); @@ -702,7 +708,7 @@ bool Buffer11::NativeBuffer11::resize(size_t size, bool preserveData) if (FAILED(result)) { - return gl::error(GL_OUT_OF_MEMORY, false); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer, result: 0x%X.", result); } if (mNativeBuffer && preserveData) @@ -727,10 +733,10 @@ bool Buffer11::NativeBuffer11::resize(size_t size, bool preserveData) mBufferSize = bufferDesc.ByteWidth; - return true; + return gl::Error(GL_NO_ERROR); } -void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, +void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer11 *renderer, BufferUsage usage, unsigned int bufferSize) { bufferDesc->ByteWidth = bufferSize; @@ -748,7 +754,7 @@ void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Ren case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK: bufferDesc->Usage = D3D11_USAGE_DEFAULT; bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER; - if (!static_cast(renderer)->isLevel9()) + if (!renderer->isLevel9()) bufferDesc->BindFlags |= D3D11_BIND_STREAM_OUTPUT; bufferDesc->CPUAccessFlags = 0; break; @@ -797,7 +803,7 @@ void *Buffer11::NativeBuffer11::map(size_t offset, size_t length, GLbitfield acc return static_cast(mappedResource.pData) + offset; } -bool Buffer11::NativeBuffer11::setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset) +gl::Error Buffer11::NativeBuffer11::setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset) { ID3D11DeviceContext *context = mRenderer->getDeviceContext(); @@ -805,7 +811,7 @@ bool Buffer11::NativeBuffer11::setData(D3D11_MAP mapMode, const uint8_t *data, s HRESULT result = context->Map(mNativeBuffer, 0, mapMode, 0, &mappedResource); if (FAILED(result)) { - return gl::error(GL_OUT_OF_MEMORY, false); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer, result: 0x%X.", result); } uint8_t *offsetBufferPointer = reinterpret_cast(mappedResource.pData) + offset; @@ -813,7 +819,7 @@ bool Buffer11::NativeBuffer11::setData(D3D11_MAP mapMode, const uint8_t *data, s context->Unmap(mNativeBuffer, 0); - return true; + return gl::Error(GL_NO_ERROR); } void Buffer11::NativeBuffer11::unmap() @@ -847,18 +853,18 @@ bool Buffer11::PackStorage11::copyFromStorage(BufferStorage11 *source, size_t so return false; } -bool Buffer11::PackStorage11::resize(size_t size, bool preserveData) +gl::Error Buffer11::PackStorage11::resize(size_t size, bool preserveData) { if (size != mBufferSize) { if (!mMemoryBuffer.resize(size)) { - return false; + return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer storage."); } mBufferSize = size; } - return true; + return gl::Error(GL_NO_ERROR); } void *Buffer11::PackStorage11::map(size_t offset, size_t length, GLbitfield access) @@ -869,7 +875,12 @@ void *Buffer11::PackStorage11::map(size_t offset, size_t length, GLbitfield acce // and if D3D packs the staging texture memory identically to how we would fill // the pack buffer according to the current pack state. - flushQueuedPackCommand(); + gl::Error error = flushQueuedPackCommand(); + if (error.isError()) + { + return NULL; + } + mDataModified = (mDataModified || (access & GL_MAP_WRITE_BIT) != 0); return mMemoryBuffer.data() + offset; @@ -882,7 +893,12 @@ void Buffer11::PackStorage11::unmap() gl::Error Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms) { - flushQueuedPackCommand(); + gl::Error error = flushQueuedPackCommand(); + if (error.isError()) + { + return error; + } + mQueuedPackCommand = new PackPixelsParams(params); D3D11_TEXTURE2D_DESC textureDesc; @@ -947,15 +963,21 @@ gl::Error Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT s return gl::Error(GL_NO_ERROR); } -void Buffer11::PackStorage11::flushQueuedPackCommand() +gl::Error Buffer11::PackStorage11::flushQueuedPackCommand() { ASSERT(mMemoryBuffer.size() > 0); if (mQueuedPackCommand) { - mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data()); + gl::Error error = mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data()); SafeDelete(mQueuedPackCommand); + if (error.isError()) + { + return error; + } } + + return gl::Error(GL_NO_ERROR); } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h index 5f24fb4e2de..1c06bbf88aa 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h @@ -47,7 +47,7 @@ typedef size_t DataRevision; class Buffer11 : public BufferD3D { public: - Buffer11(rx::Renderer11 *renderer); + Buffer11(Renderer11 *renderer); virtual ~Buffer11(); static Buffer11 *makeBuffer11(BufferImpl *buffer); @@ -60,11 +60,11 @@ class Buffer11 : public BufferD3D // BufferD3D implementation virtual size_t getSize() const { return mSize; } virtual bool supportsDirectBinding() const; - virtual Renderer* getRenderer(); + RendererD3D *getRenderer() override; // BufferImpl implementation virtual gl::Error setData(const void* data, size_t size, GLenum usage); - virtual void *getData(); + gl::Error getData(const uint8_t **outData) override; virtual gl::Error setSubData(const void* data, size_t size, size_t offset); virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); virtual gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr); @@ -78,7 +78,7 @@ class Buffer11 : public BufferD3D class NativeBuffer11; class PackStorage11; - rx::Renderer11 *mRenderer; + Renderer11 *mRenderer; size_t mSize; BufferStorage11 *mMappedStorage; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp index 765d34fd3f7..7185a05506b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp @@ -104,7 +104,7 @@ Clear11::Clear11(Renderer11 *renderer) rsDesc.DepthBias = 0; rsDesc.DepthBiasClamp = 0.0f; rsDesc.SlopeScaledDepthBias = 0.0f; - rsDesc.DepthClipEnable = mRenderer->isLevel9(); + rsDesc.DepthClipEnable = renderer->isLevel9(); rsDesc.ScissorEnable = FALSE; rsDesc.MultisampleEnable = FALSE; rsDesc.AntialiasedLineEnable = FALSE; @@ -119,7 +119,6 @@ Clear11::Clear11(Renderer11 *renderer) memset(&mIntClearShader, 0, sizeof(ClearShader)); return; } - mUintClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_UINT, g_VS_ClearUint, g_PS_ClearUint ); mIntClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_SINT, g_VS_ClearSint, g_PS_ClearSint ); } @@ -154,7 +153,7 @@ Clear11::~Clear11() SafeRelease(mRasterizerState); } -gl::Error Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) +gl::Error Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) { // First determine if a scissored clear is needed, this will always require drawing a quad. // @@ -217,10 +216,11 @@ gl::Error Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl:: gl::FramebufferAttachment *attachment = frameBuffer->getColorbuffer(colorAttachment); if (attachment) { - RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(attachment); - if (!renderTarget) + RenderTarget11 *renderTarget = NULL; + gl::Error error = d3d11::GetAttachmentRenderTarget(attachment, &renderTarget); + if (error.isError()) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null."); + return error; } const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat()); @@ -290,10 +290,11 @@ gl::Error Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl:: gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer(); if (attachment) { - RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(attachment); - if (!renderTarget) + RenderTarget11 *renderTarget = NULL; + gl::Error error = d3d11::GetAttachmentRenderTarget(attachment, &renderTarget); + if (error.isError()) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null."); + return error; } const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat()); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h index be8e187c40e..a7e8fea56af 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h @@ -32,7 +32,7 @@ class Clear11 ~Clear11(); // Clears the framebuffer with the supplied clear parameters, assumes that the framebuffer is currently applied. - gl::Error clearFramebuffer(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); + gl::Error clearFramebuffer(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer); private: Renderer11 *mRenderer; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp index a841b528625..f44d9340566 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp @@ -4,67 +4,229 @@ // found in the LICENSE file. // -// Fence11.cpp: Defines the rx::Fence11 class which implements rx::FenceImpl. +// Fence11.cpp: Defines the rx::FenceNV11 and rx::FenceSync11 classes which implement rx::FenceNVImpl and rx::FenceSyncImpl. #include "libGLESv2/renderer/d3d/d3d11/Fence11.h" #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" #include "libGLESv2/main.h" +#include "common/utilities.h" + namespace rx { -Fence11::Fence11(rx::Renderer11 *renderer) -{ - mRenderer = renderer; - mQuery = NULL; -} +// +// Template helpers for set and test operations. +// -Fence11::~Fence11() +template +gl::Error FenceSetHelper(FenceClass *fence) { - SafeRelease(mQuery); -} - -bool Fence11::isSet() const -{ - return mQuery != NULL; -} - -void Fence11::set() -{ - if (!mQuery) + if (!fence->mQuery) { D3D11_QUERY_DESC queryDesc; queryDesc.Query = D3D11_QUERY_EVENT; queryDesc.MiscFlags = 0; - if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery))) + HRESULT result = fence->mRenderer->getDevice()->CreateQuery(&queryDesc, &fence->mQuery); + if (FAILED(result)) { - return gl::error(GL_OUT_OF_MEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.", result); } } - mRenderer->getDeviceContext()->End(mQuery); + fence->mRenderer->getDeviceContext()->End(fence->mQuery); + return gl::Error(GL_NO_ERROR); } -bool Fence11::test(bool flushCommandBuffer) +template +gl::Error FenceTestHelper(FenceClass *fence, bool flushCommandBuffer, GLboolean *outFinished) { - ASSERT(mQuery); + ASSERT(fence->mQuery); UINT getDataFlags = (flushCommandBuffer ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH); - HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, getDataFlags); + HRESULT result = fence->mRenderer->getDeviceContext()->GetData(fence->mQuery, NULL, 0, getDataFlags); - if (mRenderer->isDeviceLost()) + if (FAILED(result)) { - return gl::error(GL_OUT_OF_MEMORY, true); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get query data, result: 0x%X.", result); + } + else if (fence->mRenderer->isDeviceLost()) + { + return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while querying result of an event query."); } ASSERT(result == S_OK || result == S_FALSE); - return (result == S_OK); + *outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE); + return gl::Error(GL_NO_ERROR); } -bool Fence11::hasError() const +// +// FenceNV11 +// + +FenceNV11::FenceNV11(Renderer11 *renderer) + : FenceNVImpl(), + mRenderer(renderer), + mQuery(NULL) { - return mRenderer->isDeviceLost(); } +FenceNV11::~FenceNV11() +{ + SafeRelease(mQuery); } + +gl::Error FenceNV11::set() +{ + return FenceSetHelper(this); +} + +gl::Error FenceNV11::test(bool flushCommandBuffer, GLboolean *outFinished) +{ + return FenceTestHelper(this, flushCommandBuffer, outFinished); +} + +gl::Error FenceNV11::finishFence(GLboolean *outFinished) +{ + ASSERT(outFinished); + + while (*outFinished != GL_TRUE) + { + gl::Error error = test(true, outFinished); + if (error.isError()) + { + return error; + } + + Sleep(0); + } + + return gl::Error(GL_NO_ERROR); +} + +// +// FenceSync11 +// + +// Important note on accurate timers in Windows: +// +// QueryPerformanceCounter has a few major issues, including being 10x as expensive to call +// as timeGetTime on laptops and "jumping" during certain hardware events. +// +// See the comments at the top of the Chromium source file "chromium/src/base/time/time_win.cc" +// https://code.google.com/p/chromium/codesearch#chromium/src/base/time/time_win.cc +// +// We still opt to use QPC. In the present and moving forward, most newer systems will not suffer +// from buggy implementations. + +FenceSync11::FenceSync11(Renderer11 *renderer) + : FenceSyncImpl(), + mRenderer(renderer), + mQuery(NULL) +{ + LARGE_INTEGER counterFreqency = { 0 }; + BOOL success = QueryPerformanceFrequency(&counterFreqency); + UNUSED_ASSERTION_VARIABLE(success); + ASSERT(success); + + mCounterFrequency = counterFreqency.QuadPart; +} + +FenceSync11::~FenceSync11() +{ + SafeRelease(mQuery); +} + +gl::Error FenceSync11::set() +{ + return FenceSetHelper(this); +} + +gl::Error FenceSync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) +{ + ASSERT(outResult); + + bool flushCommandBuffer = ((flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0); + + GLboolean result = GL_FALSE; + gl::Error error = FenceTestHelper(this, flushCommandBuffer, &result); + if (error.isError()) + { + *outResult = GL_WAIT_FAILED; + return error; + } + + if (result == GL_TRUE) + { + *outResult = GL_ALREADY_SIGNALED; + return gl::Error(GL_NO_ERROR); + } + + if (timeout == 0) + { + *outResult = GL_TIMEOUT_EXPIRED; + return gl::Error(GL_NO_ERROR); + } + + LARGE_INTEGER currentCounter = { 0 }; + BOOL success = QueryPerformanceCounter(¤tCounter); + UNUSED_ASSERTION_VARIABLE(success); + ASSERT(success); + + LONGLONG timeoutInSeconds = static_cast(timeout) * static_cast(1000000ll); + LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds; + + while (currentCounter.QuadPart < endCounter && !result) + { + Sleep(0); + BOOL success = QueryPerformanceCounter(¤tCounter); + UNUSED_ASSERTION_VARIABLE(success); + ASSERT(success); + + error = FenceTestHelper(this, flushCommandBuffer, &result); + if (error.isError()) + { + *outResult = GL_WAIT_FAILED; + return error; + } + } + + if (currentCounter.QuadPart >= endCounter) + { + *outResult = GL_TIMEOUT_EXPIRED; + } + else + { + *outResult = GL_CONDITION_SATISFIED; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error FenceSync11::serverWait(GLbitfield flags, GLuint64 timeout) +{ + // Because our API is currently designed to be called from a single thread, we don't need to do + // extra work for a server-side fence. GPU commands issued after the fence is created will always + // be processed after the fence is signaled. + return gl::Error(GL_NO_ERROR); +} + +gl::Error FenceSync11::getStatus(GLint *outResult) +{ + GLboolean result = GL_FALSE; + gl::Error error = FenceTestHelper(this, false, &result); + if (error.isError()) + { + // The spec does not specify any way to report errors during the status test (e.g. device lost) + // so we report the fence is unblocked in case of error or signaled. + *outResult = GL_SIGNALED; + + return error; + } + + *outResult = (result ? GL_SIGNALED : GL_UNSIGNALED); + return gl::Error(GL_NO_ERROR); +} + +} // namespace rx diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h index 50c76217764..1223a53b90a 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h @@ -4,10 +4,10 @@ // found in the LICENSE file. // -// Fence11.h: Defines the rx::Fence11 class which implements rx::FenceImpl. +// Fence11.h: Defines the rx::FenceNV11 and rx::FenceSync11 classes which implement rx::FenceNVImpl and rx::FenceSyncImpl. -#ifndef LIBGLESV2_RENDERER_Fence11_H_ -#define LIBGLESV2_RENDERER_Fence11_H_ +#ifndef LIBGLESV2_RENDERER_FENCE11_H_ +#define LIBGLESV2_RENDERER_FENCE11_H_ #include "libGLESv2/renderer/FenceImpl.h" @@ -15,24 +15,48 @@ namespace rx { class Renderer11; -class Fence11 : public FenceImpl +class FenceNV11 : public FenceNVImpl { public: - explicit Fence11(rx::Renderer11 *renderer); - virtual ~Fence11(); + explicit FenceNV11(Renderer11 *renderer); + virtual ~FenceNV11(); - bool isSet() const; - void set(); - bool test(bool flushCommandBuffer); - bool hasError() const; + gl::Error set(); + gl::Error test(bool flushCommandBuffer, GLboolean *outFinished); + gl::Error finishFence(GLboolean *outFinished); private: - DISALLOW_COPY_AND_ASSIGN(Fence11); + DISALLOW_COPY_AND_ASSIGN(FenceNV11); - rx::Renderer11 *mRenderer; + template friend gl::Error FenceSetHelper(T *fence); + template friend gl::Error FenceTestHelper(T *fence, bool flushCommandBuffer, GLboolean *outFinished); + + Renderer11 *mRenderer; ID3D11Query *mQuery; }; +class FenceSync11 : public FenceSyncImpl +{ + public: + explicit FenceSync11(Renderer11 *renderer); + virtual ~FenceSync11(); + + gl::Error set(); + gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult); + gl::Error serverWait(GLbitfield flags, GLuint64 timeout); + gl::Error getStatus(GLint *outResult); + + private: + DISALLOW_COPY_AND_ASSIGN(FenceSync11); + + template friend gl::Error FenceSetHelper(T *fence); + template friend gl::Error FenceTestHelper(T *fence, bool flushCommandBuffer, GLboolean *outFinished); + + Renderer11 *mRenderer; + ID3D11Query *mQuery; + LONGLONG mCounterFrequency; +}; + } #endif // LIBGLESV2_RENDERER_FENCE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp index 7536713af4d..e6f3e906833 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp @@ -9,6 +9,7 @@ #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" #include "libGLESv2/renderer/d3d/d3d11/Image11.h" +#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" #include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h" #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" @@ -22,15 +23,16 @@ namespace rx { Image11::Image11() + : mRenderer(NULL), + mDXGIFormat(DXGI_FORMAT_UNKNOWN), + mStagingTexture(NULL), + mStagingSubresource(0), + mRecoverFromStorage(false), + mAssociatedStorage(NULL), + mAssociatedImageIndex(gl::ImageIndex::MakeInvalid()), + mRecoveredFromStorageCount(0) + { - mStagingTexture = NULL; - mRenderer = NULL; - mDXGIFormat = DXGI_FORMAT_UNKNOWN; - mRecoverFromStorage = false; - mAssociatedStorage = NULL; - mAssociatedStorageLevel = 0; - mAssociatedStorageLayerTarget = 0; - mRecoveredFromStorageCount = 0; } Image11::~Image11() @@ -41,11 +43,11 @@ Image11::~Image11() Image11 *Image11::makeImage11(Image *img) { - ASSERT(HAS_DYNAMIC_TYPE(rx::Image11*, img)); - return static_cast(img); + ASSERT(HAS_DYNAMIC_TYPE(Image11*, img)); + return static_cast(img); } -void Image11::generateMipmap(Image11 *dest, Image11 *src) +gl::Error Image11::generateMipmap(Image11 *dest, Image11 *src) { ASSERT(src->getDXGIFormat() == dest->getDXGIFormat()); ASSERT(src->getWidth() == 1 || src->getWidth() / 2 == dest->getWidth()); @@ -55,21 +57,18 @@ void Image11::generateMipmap(Image11 *dest, Image11 *src) ASSERT(dxgiFormatInfo.mipGenerationFunction != NULL); D3D11_MAPPED_SUBRESOURCE destMapped; - HRESULT destMapResult = dest->map(D3D11_MAP_WRITE, &destMapped); - if (FAILED(destMapResult)) + gl::Error error = dest->map(D3D11_MAP_WRITE, &destMapped); + if (error.isError()) { - ERR("Failed to map destination image for mip map generation. HRESULT:0x%X", destMapResult); - return; + return error; } D3D11_MAPPED_SUBRESOURCE srcMapped; - HRESULT srcMapResult = src->map(D3D11_MAP_READ, &srcMapped); - if (FAILED(srcMapResult)) + error = src->map(D3D11_MAP_READ, &srcMapped); + if (error.isError()) { - ERR("Failed to map source image for mip map generation. HRESULT:0x%X", srcMapResult); - dest->unmap(); - return; + return error; } const uint8_t *sourceData = reinterpret_cast(srcMapped.pData); @@ -83,6 +82,8 @@ void Image11::generateMipmap(Image11 *dest, Image11 *src) src->unmap(); dest->markDirty(); + + return gl::Error(GL_NO_ERROR); } bool Image11::isDirty() const @@ -99,32 +100,10 @@ bool Image11::isDirty() const return mDirty; } -bool Image11::copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +gl::Error Image11::copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion) { - TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage); - return copyToStorageImpl(storage11, level, 0, xoffset, yoffset, width, height); -} + TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(storage); -bool Image11::copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) -{ - TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage); - return copyToStorageImpl(storage11, level, face, xoffset, yoffset, width, height); -} - -bool Image11::copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) -{ - TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage); - return copyToStorageImpl(storage11, level, 0, xoffset, yoffset, width, height); -} - -bool Image11::copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint arrayLayer, GLsizei width, GLsizei height) -{ - TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage); - return copyToStorageImpl(storage11, level, arrayLayer, xoffset, yoffset, width, height); -} - -bool Image11::copyToStorageImpl(TextureStorage11 *storage11, int level, int layerTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) -{ // If an app's behavior results in an Image11 copying its data to/from to a TextureStorage multiple times, // then we should just keep the staging texture around to prevent the copying from impacting perf. // We allow the Image11 to copy its data to/from TextureStorage once. @@ -134,23 +113,38 @@ bool Image11::copyToStorageImpl(TextureStorage11 *storage11, int level, int laye if (attemptToReleaseStagingTexture) { // If another image is relying on this Storage for its data, then we must let it recover its data before we overwrite it. - storage11->releaseAssociatedImage(level, layerTarget, this); + gl::Error error = storage11->releaseAssociatedImage(index, this); + if (error.isError()) + { + return error; + } } - bool updateSubresourceSuccess = storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, layerTarget, xoffset, yoffset, 0, width, height, 1); + ID3D11Resource *stagingTexture = NULL; + unsigned int stagingSubresourceIndex = 0; + gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex); + if (error.isError()) + { + return error; + } + + error = storage11->updateSubresourceLevel(stagingTexture, stagingSubresourceIndex, index, region); + if (error.isError()) + { + return error; + } // Once the image data has been copied into the Storage, we can release it locally. - if (attemptToReleaseStagingTexture && updateSubresourceSuccess) + if (attemptToReleaseStagingTexture) { - storage11->associateImage(this, level, layerTarget); + storage11->associateImage(this, index); releaseStagingTexture(); mRecoverFromStorage = true; mAssociatedStorage = storage11; - mAssociatedStorageLevel = level; - mAssociatedStorageLayerTarget = layerTarget; + mAssociatedImageIndex = index; } - return updateSubresourceSuccess; + return gl::Error(GL_NO_ERROR); } bool Image11::isAssociatedStorageValid(TextureStorage11* textureStorage) const @@ -158,13 +152,17 @@ bool Image11::isAssociatedStorageValid(TextureStorage11* textureStorage) const return (mAssociatedStorage == textureStorage); } -bool Image11::recoverFromAssociatedStorage() +gl::Error Image11::recoverFromAssociatedStorage() { if (mRecoverFromStorage) { - createStagingTexture(); + gl::Error error = createStagingTexture(); + if (error.isError()) + { + return error; + } - bool textureStorageCorrect = mAssociatedStorage->isAssociatedImageValid(mAssociatedStorageLevel, mAssociatedStorageLayerTarget, this); + bool textureStorageCorrect = mAssociatedStorage->isAssociatedImageValid(mAssociatedImageIndex, this); // This means that the cached TextureStorage has been modified after this Image11 released its copy of its data. // This should not have happened. The TextureStorage should have told this Image11 to recover its data before it was overwritten. @@ -173,17 +171,21 @@ bool Image11::recoverFromAssociatedStorage() if (textureStorageCorrect) { // CopySubResource from the Storage to the Staging texture - mAssociatedStorage->copySubresourceLevel(mStagingTexture, mStagingSubresource, mAssociatedStorageLevel, mAssociatedStorageLayerTarget, 0, 0, 0, mWidth, mHeight, mDepth); + gl::Box region(0, 0, 0, mWidth, mHeight, mDepth); + error = mAssociatedStorage->copySubresourceLevel(mStagingTexture, mStagingSubresource, mAssociatedImageIndex, region); + if (error.isError()) + { + return error; + } + mRecoveredFromStorageCount += 1; } // Reset all the recovery parameters, even if the texture storage association is broken. disassociateStorage(); - - return textureStorageCorrect; } - return false; + return gl::Error(GL_NO_ERROR); } void Image11::disassociateStorage() @@ -191,16 +193,15 @@ void Image11::disassociateStorage() if (mRecoverFromStorage) { // Make the texturestorage release the Image11 too - mAssociatedStorage->disassociateImage(mAssociatedStorageLevel, mAssociatedStorageLayerTarget, this); + mAssociatedStorage->disassociateImage(mAssociatedImageIndex, this); mRecoverFromStorage = false; mAssociatedStorage = NULL; - mAssociatedStorageLevel = 0; - mAssociatedStorageLayerTarget = 0; + mAssociatedImageIndex = gl::ImageIndex::MakeInvalid(); } } -bool Image11::redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) +bool Image11::redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) { if (mWidth != width || mHeight != height || @@ -227,7 +228,7 @@ bool Image11::redefine(Renderer *renderer, GLenum target, GLenum internalformat, mActualFormat = dxgiFormatInfo.internalFormat; mRenderable = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); - SafeRelease(mStagingTexture); + releaseStagingTexture(); mDirty = (formatInfo.dataInitializerFunction != NULL); return true; @@ -247,8 +248,8 @@ DXGI_FORMAT Image11::getDXGIFormat() const // Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input // into the target pixel rectangle. -void Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLint unpackAlignment, GLenum type, const void *input) +gl::Error Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLint unpackAlignment, GLenum type, const void *input) { const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); GLsizei inputRowPitch = formatInfo.computeRowPitch(type, width, unpackAlignment); @@ -261,11 +262,10 @@ void Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei widt LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(type); D3D11_MAPPED_SUBRESOURCE mappedImage; - HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); - if (FAILED(result)) + gl::Error error = map(D3D11_MAP_WRITE, &mappedImage); + if (error.isError()) { - ERR("Could not map image for loading."); - return; + return error; } uint8_t* offsetMappedData = (reinterpret_cast(mappedImage.pData) + (yoffset * mappedImage.RowPitch + xoffset * outputPixelSize + zoffset * mappedImage.DepthPitch)); @@ -274,10 +274,12 @@ void Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei widt offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); unmap(); + + return gl::Error(GL_NO_ERROR); } -void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - const void *input) +gl::Error Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + const void *input) { const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, width, 1); @@ -295,11 +297,10 @@ void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GL LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(GL_UNSIGNED_BYTE); D3D11_MAPPED_SUBRESOURCE mappedImage; - HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); - if (FAILED(result)) + gl::Error error = map(D3D11_MAP_WRITE, &mappedImage); + if (error.isError()) { - ERR("Could not map image for loading."); - return; + return error; } uint8_t* offsetMappedData = reinterpret_cast(mappedImage.pData) + ((yoffset / outputBlockHeight) * mappedImage.RowPitch + @@ -311,81 +312,130 @@ void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GL offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); unmap(); + + return gl::Error(GL_NO_ERROR); } -void Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source) { - gl::FramebufferAttachment *colorbuffer = source->getReadColorbuffer(); + RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(source); + ASSERT(sourceRenderTarget->getTexture()); - if (colorbuffer && colorbuffer->getActualFormat() == mActualFormat) + UINT subresourceIndex = sourceRenderTarget->getSubresourceIndex(); + ID3D11Texture2D *sourceTexture2D = d3d11::DynamicCastComObject(sourceRenderTarget->getTexture()); + + if (!sourceTexture2D) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the ID3D11Texture2D from the source RenderTarget."); + } + + gl::Error error = copy(xoffset, yoffset, zoffset, sourceArea, sourceTexture2D, subresourceIndex); + + SafeRelease(sourceTexture2D); + + return error; +} + +gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, const gl::ImageIndex &sourceIndex, TextureStorage *source) +{ + TextureStorage11 *sourceStorage11 = TextureStorage11::makeTextureStorage11(source); + + UINT subresourceIndex = sourceStorage11->getSubresourceIndex(sourceIndex); + ID3D11Resource *resource = NULL; + gl::Error error = sourceStorage11->getResource(&resource); + if (error.isError()) + { + return error; + } + + ID3D11Texture2D *sourceTexture2D = d3d11::DynamicCastComObject(resource); + + if (!sourceTexture2D) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the ID3D11Texture2D from the source TextureStorage."); + } + + error = copy(xoffset, yoffset, zoffset, sourceArea, sourceTexture2D, subresourceIndex); + + SafeRelease(sourceTexture2D); + + return error; +} + +gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, ID3D11Texture2D *source, UINT sourceSubResource) +{ + D3D11_TEXTURE2D_DESC textureDesc; + source->GetDesc(&textureDesc); + + if (textureDesc.Format == mDXGIFormat) { // No conversion needed-- use copyback fastpath - ID3D11Texture2D *colorBufferTexture = NULL; - unsigned int subresourceIndex = 0; - - if (mRenderer->getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture)) + ID3D11Resource *stagingTexture = NULL; + unsigned int stagingSubresourceIndex = 0; + gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex); + if (error.isError()) { - D3D11_TEXTURE2D_DESC textureDesc; - colorBufferTexture->GetDesc(&textureDesc); + return error; + } - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - ID3D11Texture2D* srcTex = NULL; - if (textureDesc.SampleDesc.Count > 1) + UINT subresourceAfterResolve = sourceSubResource; + + ID3D11Texture2D* srcTex = NULL; + if (textureDesc.SampleDesc.Count > 1) + { + D3D11_TEXTURE2D_DESC resolveDesc; + resolveDesc.Width = textureDesc.Width; + resolveDesc.Height = textureDesc.Height; + resolveDesc.MipLevels = 1; + resolveDesc.ArraySize = 1; + resolveDesc.Format = textureDesc.Format; + resolveDesc.SampleDesc.Count = 1; + resolveDesc.SampleDesc.Quality = 0; + resolveDesc.Usage = D3D11_USAGE_DEFAULT; + resolveDesc.BindFlags = 0; + resolveDesc.CPUAccessFlags = 0; + resolveDesc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex); + if (FAILED(result)) { - D3D11_TEXTURE2D_DESC resolveDesc; - resolveDesc.Width = textureDesc.Width; - resolveDesc.Height = textureDesc.Height; - resolveDesc.MipLevels = 1; - resolveDesc.ArraySize = 1; - resolveDesc.Format = textureDesc.Format; - resolveDesc.SampleDesc.Count = 1; - resolveDesc.SampleDesc.Quality = 0; - resolveDesc.Usage = D3D11_USAGE_DEFAULT; - resolveDesc.BindFlags = 0; - resolveDesc.CPUAccessFlags = 0; - resolveDesc.MiscFlags = 0; - - HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex); - if (FAILED(result)) - { - ERR("Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result); - return; - } - - deviceContext->ResolveSubresource(srcTex, 0, colorBufferTexture, subresourceIndex, textureDesc.Format); - subresourceIndex = 0; - } - else - { - srcTex = colorBufferTexture; - srcTex->AddRef(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result); } - D3D11_BOX srcBox; - srcBox.left = x; - srcBox.right = x + width; - srcBox.top = y; - srcBox.bottom = y + height; - srcBox.front = 0; - srcBox.back = 1; + deviceContext->ResolveSubresource(srcTex, 0, source, sourceSubResource, textureDesc.Format); + subresourceAfterResolve = 0; + } + else + { + srcTex = source; + } - deviceContext->CopySubresourceRegion(mStagingTexture, 0, xoffset, yoffset, zoffset, srcTex, subresourceIndex, &srcBox); + D3D11_BOX srcBox; + srcBox.left = sourceArea.x; + srcBox.right = sourceArea.x + sourceArea.width; + srcBox.top = sourceArea.y; + srcBox.bottom = sourceArea.y + sourceArea.height; + srcBox.front = 0; + srcBox.back = 1; + deviceContext->CopySubresourceRegion(stagingTexture, stagingSubresourceIndex, xoffset, yoffset, zoffset, srcTex, subresourceAfterResolve, &srcBox); + + if (textureDesc.SampleDesc.Count > 1) + { SafeRelease(srcTex); - SafeRelease(colorBufferTexture); } } else { // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels D3D11_MAPPED_SUBRESOURCE mappedImage; - HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); - if (FAILED(result)) + gl::Error error = map(D3D11_MAP_WRITE, &mappedImage); + if (error.isError()) { - ERR("Failed to map texture for Image11::copy, HRESULT: 0x%X.", result); - return; + return error; } // determine the offset coordinate into the destination buffer @@ -394,17 +444,32 @@ void Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); - mRenderer->readPixels(source, x, y, width, height, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset); + error = mRenderer->readTextureData(source, sourceSubResource, sourceArea, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset); unmap(); + + if (error.isError()) + { + return error; + } } + + mDirty = true; + + return gl::Error(GL_NO_ERROR); } -ID3D11Resource *Image11::getStagingTexture() +gl::Error Image11::getStagingTexture(ID3D11Resource **outStagingTexture, unsigned int *outSubresourceIndex) { - createStagingTexture(); + gl::Error error = createStagingTexture(); + if (error.isError()) + { + return error; + } - return mStagingTexture; + *outStagingTexture = mStagingTexture; + *outSubresourceIndex = mStagingSubresource; + return gl::Error(GL_NO_ERROR); } void Image11::releaseStagingTexture() @@ -412,149 +477,149 @@ void Image11::releaseStagingTexture() SafeRelease(mStagingTexture); } -unsigned int Image11::getStagingSubresource() -{ - createStagingTexture(); - - return mStagingSubresource; -} - -void Image11::createStagingTexture() +gl::Error Image11::createStagingTexture() { if (mStagingTexture) { - return; + return gl::Error(GL_NO_ERROR); } + ASSERT(mWidth > 0 && mHeight > 0 && mDepth > 0); + const DXGI_FORMAT dxgiFormat = getDXGIFormat(); - if (mWidth > 0 && mHeight > 0 && mDepth > 0) + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + int lodOffset = 1; + GLsizei width = mWidth; + GLsizei height = mHeight; + + // adjust size if needed for compressed textures + d3d11::MakeValidSize(false, dxgiFormat, &width, &height, &lodOffset); + + if (mTarget == GL_TEXTURE_3D) { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; + ID3D11Texture3D *newTexture = NULL; - int lodOffset = 1; - GLsizei width = mWidth; - GLsizei height = mHeight; + D3D11_TEXTURE3D_DESC desc; + desc.Width = width; + desc.Height = height; + desc.Depth = mDepth; + desc.MipLevels = lodOffset + 1; + desc.Format = dxgiFormat; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; - // adjust size if needed for compressed textures - d3d11::MakeValidSize(false, dxgiFormat, &width, &height, &lodOffset); - - if (mTarget == GL_TEXTURE_3D) + if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL) { - ID3D11Texture3D *newTexture = NULL; + std::vector initialData; + std::vector< std::vector > textureData; + d3d11::GenerateInitialTextureData(mInternalFormat, width, height, mDepth, + lodOffset + 1, &initialData, &textureData); - D3D11_TEXTURE3D_DESC desc; - desc.Width = width; - desc.Height = height; - desc.Depth = mDepth; - desc.MipLevels = lodOffset + 1; - desc.Format = dxgiFormat; - desc.Usage = D3D11_USAGE_STAGING; - desc.BindFlags = 0; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; - desc.MiscFlags = 0; - - if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL) - { - std::vector initialData; - std::vector< std::vector > textureData; - d3d11::GenerateInitialTextureData(mInternalFormat, width, height, mDepth, - lodOffset + 1, &initialData, &textureData); - - result = device->CreateTexture3D(&desc, initialData.data(), &newTexture); - } - else - { - result = device->CreateTexture3D(&desc, NULL, &newTexture); - } - - if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - ERR("Creating image failed."); - return gl::error(GL_OUT_OF_MEMORY); - } - - mStagingTexture = newTexture; - mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); - } - else if (mTarget == GL_TEXTURE_2D || mTarget == GL_TEXTURE_2D_ARRAY || mTarget == GL_TEXTURE_CUBE_MAP) - { - ID3D11Texture2D *newTexture = NULL; - - D3D11_TEXTURE2D_DESC desc; - desc.Width = width; - desc.Height = height; - desc.MipLevels = lodOffset + 1; - desc.ArraySize = 1; - desc.Format = dxgiFormat; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_STAGING; - desc.BindFlags = 0; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; - desc.MiscFlags = 0; - - if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL) - { - std::vector initialData; - std::vector< std::vector > textureData; - d3d11::GenerateInitialTextureData(mInternalFormat, width, height, 1, - lodOffset + 1, &initialData, &textureData); - - result = device->CreateTexture2D(&desc, initialData.data(), &newTexture); - } - else - { - result = device->CreateTexture2D(&desc, NULL, &newTexture); - } - - if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - ERR("Creating image failed."); - return gl::error(GL_OUT_OF_MEMORY); - } - - mStagingTexture = newTexture; - mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); + result = device->CreateTexture3D(&desc, initialData.data(), &newTexture); } else { - UNREACHABLE(); + result = device->CreateTexture3D(&desc, NULL, &newTexture); } + + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create staging texture, result: 0x%X.", result); + } + + mStagingTexture = newTexture; + mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); + } + else if (mTarget == GL_TEXTURE_2D || mTarget == GL_TEXTURE_2D_ARRAY || mTarget == GL_TEXTURE_CUBE_MAP) + { + ID3D11Texture2D *newTexture = NULL; + + D3D11_TEXTURE2D_DESC desc; + desc.Width = width; + desc.Height = height; + desc.MipLevels = lodOffset + 1; + desc.ArraySize = 1; + desc.Format = dxgiFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + + if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL) + { + std::vector initialData; + std::vector< std::vector > textureData; + d3d11::GenerateInitialTextureData(mInternalFormat, width, height, 1, + lodOffset + 1, &initialData, &textureData); + + result = device->CreateTexture2D(&desc, initialData.data(), &newTexture); + } + else + { + result = device->CreateTexture2D(&desc, NULL, &newTexture); + } + + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create staging texture, result: 0x%X.", result); + } + + mStagingTexture = newTexture; + mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); + } + else + { + UNREACHABLE(); } mDirty = false; + return gl::Error(GL_NO_ERROR); } -HRESULT Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) +gl::Error Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) { - createStagingTexture(); - // We must recover from the TextureStorage if necessary, even for D3D11_MAP_WRITE. - recoverFromAssociatedStorage(); - - HRESULT result = E_FAIL; - - if (mStagingTexture) + gl::Error error = recoverFromAssociatedStorage(); + if (error.isError()) { - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - result = deviceContext->Map(mStagingTexture, mStagingSubresource, mapType, 0, map); - - // this can fail if the device is removed (from TDR) - if (d3d11::isDeviceLostError(result)) - { - mRenderer->notifyDeviceLost(); - } - else if (SUCCEEDED(result)) - { - mDirty = true; - } + return error; } - return result; + ID3D11Resource *stagingTexture = NULL; + unsigned int subresourceIndex = 0; + error = getStagingTexture(&stagingTexture, &subresourceIndex); + if (error.isError()) + { + return error; + } + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + ASSERT(mStagingTexture); + HRESULT result = deviceContext->Map(stagingTexture, subresourceIndex, mapType, 0, map); + + // this can fail if the device is removed (from TDR) + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + } + else if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map staging texture, result: 0x%X.", result); + } + + mDirty = true; + + return gl::Error(GL_NO_ERROR); } void Image11::unmap() diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h index a76a61f0363..a936e6d7b24 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h @@ -11,6 +11,7 @@ #define LIBGLESV2_RENDERER_IMAGE11_H_ #include "libGLESv2/renderer/d3d/ImageD3D.h" +#include "libGLESv2/ImageIndex.h" #include "common/debug.h" @@ -21,7 +22,6 @@ class Framebuffer; namespace rx { -class Renderer; class Renderer11; class TextureStorage11; @@ -33,42 +33,41 @@ class Image11 : public ImageD3D static Image11 *makeImage11(Image *img); - static void generateMipmap(Image11 *dest, Image11 *src); + static gl::Error generateMipmap(Image11 *dest, Image11 *src); virtual bool isDirty() const; - virtual bool copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - virtual bool copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - virtual bool copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); - virtual bool copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint arrayLayer, GLsizei width, GLsizei height); + virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion); - virtual bool redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease); + bool redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) override; DXGI_FORMAT getDXGIFormat() const; - - virtual void loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLint unpackAlignment, GLenum type, const void *input); - virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - const void *input); - virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual gl::Error loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLint unpackAlignment, GLenum type, const void *input); + virtual gl::Error loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + const void *input); - bool recoverFromAssociatedStorage(); + virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source); + virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, + const gl::ImageIndex &sourceIndex, TextureStorage *source); + + gl::Error recoverFromAssociatedStorage(); bool isAssociatedStorageValid(TextureStorage11* textureStorage) const; void disassociateStorage(); protected: - HRESULT map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map); + gl::Error map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map); void unmap(); private: DISALLOW_COPY_AND_ASSIGN(Image11); - bool copyToStorageImpl(TextureStorage11 *storage11, int level, int layerTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + gl::Error copyToStorageImpl(TextureStorage11 *storage11, const gl::ImageIndex &index, const gl::Box ®ion); + gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, ID3D11Texture2D *source, UINT sourceSubResource); - ID3D11Resource *getStagingTexture(); - unsigned int getStagingSubresource(); - void createStagingTexture(); + gl::Error getStagingTexture(ID3D11Resource **outStagingTexture, unsigned int *outSubresourceIndex); + gl::Error createStagingTexture(); void releaseStagingTexture(); Renderer11 *mRenderer; @@ -79,8 +78,7 @@ class Image11 : public ImageD3D bool mRecoverFromStorage; TextureStorage11 *mAssociatedStorage; - int mAssociatedStorageLevel; - int mAssociatedStorageLayerTarget; + gl::ImageIndex mAssociatedImageIndex; unsigned int mRecoveredFromStorageCount; }; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h index f7c2b38e7e6..3351df5ec13 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h @@ -40,7 +40,7 @@ class IndexBuffer11 : public IndexBuffer private: DISALLOW_COPY_AND_ASSIGN(IndexBuffer11); - rx::Renderer11 *const mRenderer; + Renderer11 *const mRenderer; ID3D11Buffer *mBuffer; unsigned int mBufferSize; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp index d835e4fa684..ff90a6a69a1 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp @@ -12,6 +12,7 @@ #include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" #include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h" #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "libGLESv2/renderer/d3d/ProgramD3D.h" #include "libGLESv2/renderer/d3d/VertexDataManager.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/VertexAttribute.h" @@ -137,7 +138,16 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl { gl::VertexFormat shaderInputLayout[gl::MAX_VERTEX_ATTRIBS]; GetInputLayout(attributes, shaderInputLayout); - ShaderExecutable11 *shader = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutableForInputLayout(shaderInputLayout)); + ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary->getImplementation()); + + ShaderExecutable *shader = NULL; + gl::Error error = programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader); + if (error.isError()) + { + return error; + } + + ShaderExecutable *shader11 = ShaderExecutable11::makeShaderExecutable11(shader); D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS]; for (unsigned int j = 0; j < ilKey.elementCount; ++j) @@ -145,7 +155,7 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl descs[j] = ilKey.elements[j].desc; } - HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader->getFunction(), shader->getLength(), &inputLayout); + HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader11->getFunction(), shader11->getLength(), &inputLayout); if (FAILED(result)) { return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal input layout, HRESULT: 0x%08x", result); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp index a4e84f91c20..6a3d3475ee4 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp @@ -33,12 +33,38 @@ namespace rx PixelTransfer11::PixelTransfer11(Renderer11 *renderer) : mRenderer(renderer), + mResourcesLoaded(false), mBufferToTextureVS(NULL), mBufferToTextureGS(NULL), mParamsConstantBuffer(NULL), mCopyRasterizerState(NULL), mCopyDepthStencilState(NULL) { +} + +PixelTransfer11::~PixelTransfer11() +{ + for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++) + { + SafeRelease(shaderMapIt->second); + } + + mBufferToTexturePSMap.clear(); + + SafeRelease(mBufferToTextureVS); + SafeRelease(mBufferToTextureGS); + SafeRelease(mParamsConstantBuffer); + SafeRelease(mCopyRasterizerState); + SafeRelease(mCopyDepthStencilState); +} + +gl::Error PixelTransfer11::loadResources() +{ + if (mResourcesLoaded) + { + return gl::Error(GL_NO_ERROR); + } + HRESULT result = S_OK; ID3D11Device *device = mRenderer->getDevice(); @@ -56,6 +82,10 @@ PixelTransfer11::PixelTransfer11(Renderer11 *renderer) result = device->CreateRasterizerState(&rasterDesc, &mCopyRasterizerState); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer rasterizer state, result: 0x%X.", result); + } D3D11_DEPTH_STENCIL_DESC depthStencilDesc; depthStencilDesc.DepthEnable = true; @@ -75,9 +105,13 @@ PixelTransfer11::PixelTransfer11(Renderer11 *renderer) result = device->CreateDepthStencilState(&depthStencilDesc, &mCopyDepthStencilState); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer depth stencil state, result: 0x%X.", result); + } D3D11_BUFFER_DESC constantBufferDesc = { 0 }; - constantBufferDesc.ByteWidth = rx::roundUp(sizeof(CopyShaderParams), 32u); + constantBufferDesc.ByteWidth = roundUp(sizeof(CopyShaderParams), 32u); constantBufferDesc.Usage = D3D11_USAGE_DYNAMIC; constantBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; constantBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; @@ -86,34 +120,39 @@ PixelTransfer11::PixelTransfer11(Renderer11 *renderer) result = device->CreateBuffer(&constantBufferDesc, NULL, &mParamsConstantBuffer); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer constant buffer, result: 0x%X.", result); + } d3d11::SetDebugName(mParamsConstantBuffer, "PixelTransfer11 constant buffer"); + // init shaders + mBufferToTextureVS = d3d11::CompileVS(device, g_VS_BufferToTexture, "BufferToTexture VS"); + if (!mBufferToTextureVS) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture vertex shader."); + } + + if (!mRenderer->isLevel9()) + { + mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS"); + if (!mBufferToTextureGS) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture geometry shader."); + } + } + + gl::Error error = buildShaderMap(); + if (error.isError()) + { + return error; + } + StructZero(&mParamsData); - // init shaders - if (mRenderer->isLevel9()) - return; + mResourcesLoaded = true; - mBufferToTextureVS = d3d11::CompileVS(device, g_VS_BufferToTexture, "BufferToTexture VS"); - mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS"); - - buildShaderMap(); -} - -PixelTransfer11::~PixelTransfer11() -{ - for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++) - { - SafeRelease(shaderMapIt->second); - } - - mBufferToTexturePSMap.clear(); - - SafeRelease(mBufferToTextureVS); - SafeRelease(mBufferToTextureGS); - SafeRelease(mParamsConstantBuffer); - SafeRelease(mCopyRasterizerState); - SafeRelease(mCopyDepthStencilState); + return gl::Error(GL_NO_ERROR); } void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat, @@ -138,17 +177,20 @@ void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, cons parametersOut->PositionScale[1] = -2.0f / static_cast(destSize.height); } -bool PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, - GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) +gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) { + gl::Error error = loadResources(); + if (error.isError()) + { + return error; + } + gl::Extents destSize = destRenderTarget->getExtents(); - if (destArea.x < 0 || destArea.x + destArea.width > destSize.width || - destArea.y < 0 || destArea.y + destArea.height > destSize.height || - destArea.z < 0 || destArea.z + destArea.depth > destSize.depth ) - { - return false; - } + ASSERT(destArea.x >= 0 && destArea.x + destArea.width <= destSize.width && + destArea.y >= 0 && destArea.y + destArea.height <= destSize.height && + destArea.z >= 0 && destArea.z + destArea.depth <= destSize.depth ); const gl::Buffer &sourceBuffer = *unpack.pixelBuffer.get(); @@ -177,7 +219,6 @@ bool PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, un ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - ID3D11ShaderResourceView *nullSRV = NULL; ID3D11Buffer *nullBuffer = NULL; UINT zero = 0; @@ -187,7 +228,7 @@ bool PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, un deviceContext->VSSetShader(mBufferToTextureVS, NULL, 0); deviceContext->GSSetShader(geometryShader, NULL, 0); deviceContext->PSSetShader(pixelShader, NULL, 0); - deviceContext->PSSetShaderResources(0, 1, &bufferSRV); + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, bufferSRV); deviceContext->IASetInputLayout(NULL); deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); @@ -220,21 +261,32 @@ bool PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, un deviceContext->Draw(numPixels, 0); // Unbind textures and render targets and vertex buffer - deviceContext->PSSetShaderResources(0, 1, &nullSRV); + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); deviceContext->VSSetConstantBuffers(0, 1, &nullBuffer); mRenderer->markAllStateDirty(); - return true; + return gl::Error(GL_NO_ERROR); } -void PixelTransfer11::buildShaderMap() +gl::Error PixelTransfer11::buildShaderMap() { ID3D11Device *device = mRenderer->getDevice(); mBufferToTexturePSMap[GL_FLOAT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4F, "BufferToTexture RGBA ps"); mBufferToTexturePSMap[GL_INT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4I, "BufferToTexture RGBA-I ps"); mBufferToTexturePSMap[GL_UNSIGNED_INT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4UI, "BufferToTexture RGBA-UI ps"); + + // Check that all the shaders were created successfully + for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++) + { + if (shaderMapIt->second == NULL) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture pixel shader."); + } + } + + return gl::Error(GL_NO_ERROR); } ID3D11PixelShader *PixelTransfer11::findBufferToTexturePS(GLenum internalFormat) const diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h index ed1a3ae1d0a..29552140bba 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h @@ -11,6 +11,8 @@ #ifndef LIBGLESV2_PIXELTRANSFER11_H_ #define LIBGLESV2_PIXELTRANSFER11_H_ +#include "libGLESv2/Error.h" + #include "common/platform.h" #include @@ -38,15 +40,13 @@ class PixelTransfer11 explicit PixelTransfer11(Renderer11 *renderer); ~PixelTransfer11(); - static bool supportsBufferToTextureCopy(GLenum internalFormat); - // unpack: the source buffer is stored in the unpack state, and buffer strides // offset: the start of the data within the unpack buffer // destRenderTarget: individual slice/layer of a target texture // destinationFormat/sourcePixelsType: determines shaders + shader parameters // destArea: the sub-section of destRenderTarget to copy to - bool copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, - GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); + gl::Error copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); private: @@ -65,11 +65,13 @@ class PixelTransfer11 static void setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat, const gl::PixelUnpackState &unpack, unsigned int offset, CopyShaderParams *parametersOut); - void buildShaderMap(); + gl::Error loadResources(); + gl::Error buildShaderMap(); ID3D11PixelShader *findBufferToTexturePS(GLenum internalFormat) const; Renderer11 *mRenderer; + bool mResourcesLoaded; std::map mBufferToTexturePSMap; ID3D11VertexShader *mBufferToTextureVS; ID3D11GeometryShader *mBufferToTextureGS; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp index 7109be3e288..17ab1f8ab3c 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp @@ -10,13 +10,14 @@ #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" #include "libGLESv2/main.h" +#include "common/utilities.h" #include namespace rx { -Query11::Query11(rx::Renderer11 *renderer, GLenum type) +Query11::Query11(Renderer11 *renderer, GLenum type) : QueryImpl(type), mResult(0), mQueryFinished(false), diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h index 822f2542eec..f9ff467873e 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h @@ -18,7 +18,7 @@ class Renderer11; class Query11 : public QueryImpl { public: - Query11(rx::Renderer11 *renderer, GLenum type); + Query11(Renderer11 *renderer, GLenum type); virtual ~Query11(); virtual gl::Error begin(); @@ -35,7 +35,7 @@ class Query11 : public QueryImpl bool mQueryFinished; - rx::Renderer11 *mRenderer; + Renderer11 *mRenderer; ID3D11Query *mQuery; }; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp index 71b931f27ee..ab4f60bd988 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp @@ -38,11 +38,14 @@ const unsigned int RenderStateCache::kMaxRasterizerStates = 4096; const unsigned int RenderStateCache::kMaxDepthStencilStates = 4096; const unsigned int RenderStateCache::kMaxSamplerStates = 4096; -RenderStateCache::RenderStateCache() : mDevice(NULL), mCounter(0), - mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates), - mRasterizerStateCache(kMaxRasterizerStates, hashRasterizerState, compareRasterizerStates), - mDepthStencilStateCache(kMaxDepthStencilStates, hashDepthStencilState, compareDepthStencilStates), - mSamplerStateCache(kMaxSamplerStates, hashSamplerState, compareSamplerStates) +RenderStateCache::RenderStateCache(Renderer11 *renderer) + : mRenderer(renderer), + mDevice(NULL), + mCounter(0), + mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates), + mRasterizerStateCache(kMaxRasterizerStates, hashRasterizerState, compareRasterizerStates), + mDepthStencilStateCache(kMaxDepthStencilStates, hashDepthStencilState, compareDepthStencilStates), + mSamplerStateCache(kMaxSamplerStates, hashSamplerState, compareSamplerStates) { } @@ -89,7 +92,7 @@ gl::Error RenderStateCache::getBlendState(const gl::Framebuffer *framebuffer, co bool mrt = false; - const gl::ColorbufferInfo &colorbuffers = framebuffer->getColorbuffersForRender(); + const gl::ColorbufferInfo &colorbuffers = framebuffer->getColorbuffersForRender(mRenderer->getWorkarounds()); BlendStateKey key = { 0 }; key.blendState = blendState; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h index d5471a3061e..dfd1d84265c 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h @@ -28,7 +28,7 @@ class Renderer11; class RenderStateCache { public: - RenderStateCache(); + RenderStateCache(Renderer11 *renderer); virtual ~RenderStateCache(); void initialize(ID3D11Device *device); @@ -42,6 +42,7 @@ class RenderStateCache private: DISALLOW_COPY_AND_ASSIGN(RenderStateCache); + Renderer11 *mRenderer; unsigned long long mCounter; // Blend state cache diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp index 3041f21faa6..aff34534921 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp @@ -10,6 +10,7 @@ #include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h" #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" #include "libGLESv2/main.h" @@ -176,246 +177,10 @@ static unsigned int getDSVSubresourceIndex(ID3D11Resource *resource, ID3D11Depth return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); } -RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Resource *resource, - ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth) -{ - mRenderer = Renderer11::makeRenderer11(renderer); - - mTexture = resource; - if (mTexture) - { - mTexture->AddRef(); - } - - mRenderTarget = rtv; - if (mRenderTarget) - { - mRenderTarget->AddRef(); - } - - mDepthStencil = NULL; - - mShaderResource = srv; - if (mShaderResource) - { - mShaderResource->AddRef(); - } - - mSubresourceIndex = 0; - - if (mRenderTarget && mTexture) - { - D3D11_RENDER_TARGET_VIEW_DESC desc; - mRenderTarget->GetDesc(&desc); - - unsigned int mipLevels, samples; - getTextureProperties(mTexture, &mipLevels, &samples); - - mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget); - mWidth = width; - mHeight = height; - mDepth = depth; - mSamples = samples; - - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format); - mInternalFormat = dxgiFormatInfo.internalFormat; - mActualFormat = dxgiFormatInfo.internalFormat; - } -} - -RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Resource *resource, - ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth) -{ - mRenderer = Renderer11::makeRenderer11(renderer); - - mTexture = resource; - if (mTexture) - { - mTexture->AddRef(); - } - - mRenderTarget = NULL; - - mDepthStencil = dsv; - if (mDepthStencil) - { - mDepthStencil->AddRef(); - } - - mShaderResource = srv; - if (mShaderResource) - { - mShaderResource->AddRef(); - } - - mSubresourceIndex = 0; - - if (mDepthStencil && mTexture) - { - D3D11_DEPTH_STENCIL_VIEW_DESC desc; - mDepthStencil->GetDesc(&desc); - - unsigned int mipLevels, samples; - getTextureProperties(mTexture, &mipLevels, &samples); - - mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil); - mWidth = width; - mHeight = height; - mDepth = depth; - mSamples = samples; - - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format); - mInternalFormat = dxgiFormatInfo.internalFormat; - mActualFormat = dxgiFormatInfo.internalFormat; - } -} - -RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples) -{ - mRenderer = Renderer11::makeRenderer11(renderer); - mTexture = NULL; - mRenderTarget = NULL; - mDepthStencil = NULL; - mShaderResource = NULL; - - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(formatInfo.texFormat); - - const gl::TextureCaps &textureCaps = mRenderer->getRendererTextureCaps().get(internalFormat); - GLuint supportedSamples = textureCaps.getNearestSamples(samples); - - if (width > 0 && height > 0) - { - // Create texture resource - D3D11_TEXTURE2D_DESC desc; - desc.Width = width; - desc.Height = height; - desc.MipLevels = 1; - desc.ArraySize = 1; - desc.Format = formatInfo.texFormat; - desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - - // If a rendertarget or depthstencil format exists for this texture format, - // we'll flag it to allow binding that way. Shader resource views are a little - // more complicated. - bool bindRTV = false, bindDSV = false, bindSRV = false; - bindRTV = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); - bindDSV = (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN); - if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) - { - // Multisample targets flagged for binding as depth stencil cannot also be - // flagged for binding as SRV, so make certain not to add the SRV flag for - // these targets. - bindSRV = !(formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN && desc.SampleDesc.Count > 1); - } - - desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) | - (bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) | - (bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0); - - ID3D11Device *device = mRenderer->getDevice(); - ID3D11Texture2D *texture = NULL; - HRESULT result = device->CreateTexture2D(&desc, NULL, &texture); - mTexture = texture; - - if (result == E_OUTOFMEMORY) - { - gl::error(GL_OUT_OF_MEMORY); - return; - } - ASSERT(SUCCEEDED(result)); - - if (bindSRV) - { - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = formatInfo.srvFormat; - srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS; - srvDesc.Texture2D.MostDetailedMip = 0; - srvDesc.Texture2D.MipLevels = 1; - result = device->CreateShaderResourceView(mTexture, &srvDesc, &mShaderResource); - - if (result == E_OUTOFMEMORY) - { - SafeRelease(mTexture); - gl::error(GL_OUT_OF_MEMORY); - return; - } - ASSERT(SUCCEEDED(result)); - } - - if (bindDSV) - { - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = formatInfo.dsvFormat; - dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS; - dsvDesc.Texture2D.MipSlice = 0; - dsvDesc.Flags = 0; - result = device->CreateDepthStencilView(mTexture, &dsvDesc, &mDepthStencil); - - if (result == E_OUTOFMEMORY) - { - SafeRelease(mTexture); - SafeRelease(mShaderResource); - gl::error(GL_OUT_OF_MEMORY); - return; - } - ASSERT(SUCCEEDED(result)); - } - - if (bindRTV) - { - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = formatInfo.rtvFormat; - rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS; - rtvDesc.Texture2D.MipSlice = 0; - result = device->CreateRenderTargetView(mTexture, &rtvDesc, &mRenderTarget); - - if (result == E_OUTOFMEMORY) - { - SafeRelease(mTexture); - SafeRelease(mShaderResource); - SafeRelease(mDepthStencil); - gl::error(GL_OUT_OF_MEMORY); - return; - } - ASSERT(SUCCEEDED(result)); - - if (formatInfo.dataInitializerFunction != NULL) - { - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - - const float clearValues[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; - context->ClearRenderTargetView(mRenderTarget, clearValues); - } - } - } - - - mWidth = width; - mHeight = height; - mDepth = 1; - mInternalFormat = internalFormat; - mSamples = supportedSamples; - mActualFormat = dxgiFormatInfo.internalFormat; - mSubresourceIndex = D3D11CalcSubresource(0, 0, 1); -} - -RenderTarget11::~RenderTarget11() -{ - SafeRelease(mTexture); - SafeRelease(mRenderTarget); - SafeRelease(mDepthStencil); - SafeRelease(mShaderResource); -} - RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTarget *target) { - ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget11*, target)); - return static_cast(target); + ASSERT(HAS_DYNAMIC_TYPE(RenderTarget11*, target)); + return static_cast(target); } void RenderTarget11::invalidate(GLint x, GLint y, GLsizei width, GLsizei height) @@ -423,29 +188,217 @@ void RenderTarget11::invalidate(GLint x, GLint y, GLsizei width, GLsizei height) // Currently a no-op } -ID3D11Resource *RenderTarget11::getTexture() const +TextureRenderTarget11::TextureRenderTarget11(ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, + GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples) + : mWidth(width), + mHeight(height), + mDepth(depth), + mInternalFormat(internalFormat), + mActualFormat(internalFormat), + mSamples(samples), + mSubresourceIndex(0), + mTexture(resource), + mRenderTarget(rtv), + mDepthStencil(NULL), + mShaderResource(srv) +{ + if (mTexture) + { + mTexture->AddRef(); + } + + if (mRenderTarget) + { + mRenderTarget->AddRef(); + } + + if (mShaderResource) + { + mShaderResource->AddRef(); + } + + if (mRenderTarget && mTexture) + { + mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget); + + D3D11_RENDER_TARGET_VIEW_DESC desc; + mRenderTarget->GetDesc(&desc); + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format); + mActualFormat = dxgiFormatInfo.internalFormat; + } +} + +TextureRenderTarget11::TextureRenderTarget11(ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, + GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples) + : mWidth(width), + mHeight(height), + mDepth(depth), + mInternalFormat(internalFormat), + mActualFormat(internalFormat), + mSamples(samples), + mSubresourceIndex(0), + mTexture(resource), + mRenderTarget(NULL), + mDepthStencil(dsv), + mShaderResource(srv) +{ + if (mTexture) + { + mTexture->AddRef(); + } + + if (mDepthStencil) + { + mDepthStencil->AddRef(); + } + + if (mShaderResource) + { + mShaderResource->AddRef(); + } + + if (mDepthStencil && mTexture) + { + mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil); + + D3D11_DEPTH_STENCIL_VIEW_DESC desc; + mDepthStencil->GetDesc(&desc); + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format); + mActualFormat = dxgiFormatInfo.internalFormat; + } +} + +TextureRenderTarget11::~TextureRenderTarget11() +{ + SafeRelease(mTexture); + SafeRelease(mRenderTarget); + SafeRelease(mDepthStencil); + SafeRelease(mShaderResource); +} + +ID3D11Resource *TextureRenderTarget11::getTexture() const { return mTexture; } -ID3D11RenderTargetView *RenderTarget11::getRenderTargetView() const +ID3D11RenderTargetView *TextureRenderTarget11::getRenderTargetView() const { return mRenderTarget; } -ID3D11DepthStencilView *RenderTarget11::getDepthStencilView() const +ID3D11DepthStencilView *TextureRenderTarget11::getDepthStencilView() const { return mDepthStencil; } -ID3D11ShaderResourceView *RenderTarget11::getShaderResourceView() const +ID3D11ShaderResourceView *TextureRenderTarget11::getShaderResourceView() const { return mShaderResource; } -unsigned int RenderTarget11::getSubresourceIndex() const +GLsizei TextureRenderTarget11::getWidth() const +{ + return mWidth; +} + +GLsizei TextureRenderTarget11::getHeight() const +{ + return mHeight; +} + +GLsizei TextureRenderTarget11::getDepth() const +{ + return mDepth; +} + +GLenum TextureRenderTarget11::getInternalFormat() const +{ + return mInternalFormat; +} + +GLenum TextureRenderTarget11::getActualFormat() const +{ + return mActualFormat; +} + +GLsizei TextureRenderTarget11::getSamples() const +{ + return mSamples; +} + +unsigned int TextureRenderTarget11::getSubresourceIndex() const { return mSubresourceIndex; } + +SurfaceRenderTarget11::SurfaceRenderTarget11(SwapChain11 *swapChain, bool depth) + : mSwapChain(swapChain), + mDepth(depth) +{ + ASSERT(mSwapChain); +} + +SurfaceRenderTarget11::~SurfaceRenderTarget11() +{ +} + +GLsizei SurfaceRenderTarget11::getWidth() const +{ + return mSwapChain->getWidth(); +} + +GLsizei SurfaceRenderTarget11::getHeight() const +{ + return mSwapChain->getHeight(); +} + +GLsizei SurfaceRenderTarget11::getDepth() const +{ + return 1; +} + +GLenum SurfaceRenderTarget11::getInternalFormat() const +{ + return (mDepth ? mSwapChain->GetDepthBufferInternalFormat() : mSwapChain->GetBackBufferInternalFormat()); +} + +GLenum SurfaceRenderTarget11::getActualFormat() const +{ + return d3d11::GetDXGIFormatInfo(d3d11::GetTextureFormatInfo(getInternalFormat()).texFormat).internalFormat; +} + +GLsizei SurfaceRenderTarget11::getSamples() const +{ + // Our EGL surfaces do not support multisampling. + return 0; +} + +ID3D11Resource *SurfaceRenderTarget11::getTexture() const +{ + return (mDepth ? mSwapChain->getDepthStencilTexture() : mSwapChain->getOffscreenTexture()); +} + +ID3D11RenderTargetView *SurfaceRenderTarget11::getRenderTargetView() const +{ + return (mDepth ? NULL : mSwapChain->getRenderTarget()); +} + +ID3D11DepthStencilView *SurfaceRenderTarget11::getDepthStencilView() const +{ + return (mDepth ? mSwapChain->getDepthStencil() : NULL); +} + +ID3D11ShaderResourceView *SurfaceRenderTarget11::getShaderResourceView() const +{ + return (mDepth ? mSwapChain->getDepthStencilShaderResource() : mSwapChain->getRenderTargetShaderResource()); +} + +unsigned int SurfaceRenderTarget11::getSubresourceIndex() const +{ + return 0; +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h index 82182957afb..c7babdda3f4 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h @@ -14,39 +14,95 @@ namespace rx { -class Renderer; -class Renderer11; +class SwapChain11; class RenderTarget11 : public RenderTarget { public: - // RenderTarget11 takes ownership of any D3D11 resources it is given and will AddRef them - RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth); - RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth); - RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples); - virtual ~RenderTarget11(); + RenderTarget11() { } + virtual ~RenderTarget11() { } static RenderTarget11 *makeRenderTarget11(RenderTarget *renderTarget); - virtual void invalidate(GLint x, GLint y, GLsizei width, GLsizei height); + void invalidate(GLint x, GLint y, GLsizei width, GLsizei height) override; - ID3D11Resource *getTexture() const; - ID3D11RenderTargetView *getRenderTargetView() const; - ID3D11DepthStencilView *getDepthStencilView() const; - ID3D11ShaderResourceView *getShaderResourceView() const; + virtual ID3D11Resource *getTexture() const = 0; + virtual ID3D11RenderTargetView *getRenderTargetView() const = 0; + virtual ID3D11DepthStencilView *getDepthStencilView() const = 0; + virtual ID3D11ShaderResourceView *getShaderResourceView() const = 0; - unsigned int getSubresourceIndex() const; + virtual unsigned int getSubresourceIndex() const = 0; private: DISALLOW_COPY_AND_ASSIGN(RenderTarget11); +}; + +class TextureRenderTarget11 : public RenderTarget11 +{ + public: + // TextureRenderTarget11 takes ownership of any D3D11 resources it is given and will AddRef them + TextureRenderTarget11(ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, + GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples); + TextureRenderTarget11(ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, + GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples); + virtual ~TextureRenderTarget11(); + + GLsizei getWidth() const override; + GLsizei getHeight() const override; + GLsizei getDepth() const override; + GLenum getInternalFormat() const override; + GLenum getActualFormat() const override; + GLsizei getSamples() const override; + + ID3D11Resource *getTexture() const override; + ID3D11RenderTargetView *getRenderTargetView() const override; + ID3D11DepthStencilView *getDepthStencilView() const override; + ID3D11ShaderResourceView *getShaderResourceView() const override; + + unsigned int getSubresourceIndex() const override; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureRenderTarget11); + + GLsizei mWidth; + GLsizei mHeight; + GLsizei mDepth; + GLenum mInternalFormat; + GLenum mActualFormat; + GLsizei mSamples; unsigned int mSubresourceIndex; ID3D11Resource *mTexture; ID3D11RenderTargetView *mRenderTarget; ID3D11DepthStencilView *mDepthStencil; ID3D11ShaderResourceView *mShaderResource; +}; - Renderer11 *mRenderer; +class SurfaceRenderTarget11 : public RenderTarget11 +{ + public: + SurfaceRenderTarget11(SwapChain11 *swapChain, bool depth); + virtual ~SurfaceRenderTarget11(); + + GLsizei getWidth() const override; + GLsizei getHeight() const override; + GLsizei getDepth() const override; + GLenum getInternalFormat() const override; + GLenum getActualFormat() const override; + GLsizei getSamples() const override; + + ID3D11Resource *getTexture() const override; + ID3D11RenderTargetView *getRenderTargetView() const override; + ID3D11DepthStencilView *getDepthStencilView() const override; + ID3D11ShaderResourceView *getShaderResourceView() const override; + + unsigned int getSubresourceIndex() const override; + + private: + DISALLOW_COPY_AND_ASSIGN(SurfaceRenderTarget11); + + SwapChain11 *mSwapChain; + bool mDepth; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp index b29b2ef9109..e6d7f3025b9 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp @@ -6,12 +6,12 @@ // Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer. -#include "common/platform.h" #include "libGLESv2/main.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/FramebufferAttachment.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/Framebuffer.h" +#include "libGLESv2/State.h" #include "libGLESv2/renderer/d3d/ProgramD3D.h" #include "libGLESv2/renderer/d3d/ShaderD3D.h" #include "libGLESv2/renderer/d3d/TextureD3D.h" @@ -36,10 +36,12 @@ #include "libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h" #include "libGLESv2/renderer/d3d/d3d11/VertexArray11.h" #include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" +#include "libGLESv2/renderer/d3d/RenderbufferD3D.h" #include "libEGL/Display.h" #include "common/utilities.h" +#include "common/tls.h" #include @@ -59,6 +61,9 @@ namespace rx { + +namespace +{ static const DXGI_FORMAT RenderTargetFormats[] = { DXGI_FORMAT_B8G8R8A8_UNORM, @@ -77,10 +82,22 @@ enum MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16 }; -Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay) - : Renderer(display), +// Does *not* increment the resource ref count!! +ID3D11Resource *GetSRVResource(ID3D11ShaderResourceView *srv) +{ + ID3D11Resource *resource = NULL; + ASSERT(srv); + srv->GetResource(&resource); + resource->Release(); + return resource; +} + +} + +Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, const egl::AttributeMap &attributes) + : RendererD3D(display), mDc(hDc), - mRequestedDisplay(requestedDisplay) + mStateCache(this) { mVertexDataManager = NULL; mIndexDataManager = NULL; @@ -112,6 +129,50 @@ Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, EGLint r mAppliedGeometryShader = NULL; mCurPointGeometryShader = NULL; mAppliedPixelShader = NULL; + + EGLint requestedMajorVersion = attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE); + EGLint requestedMinorVersion = attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE); + + if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11) + { + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0); + } + } + + if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 10) + { + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_1); + } + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_0); + } + } + +#if !defined(ANGLE_ENABLE_D3D9) + if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9) + { + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); + } + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 2) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2); + } + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1); + } + } +#endif + + mDriverType = (attributes.get(EGL_PLATFORM_ANGLE_USE_WARP_ANGLE, EGL_FALSE) == EGL_TRUE) ? D3D_DRIVER_TYPE_WARP + : D3D_DRIVER_TYPE_HARDWARE; } Renderer11::~Renderer11() @@ -121,8 +182,8 @@ Renderer11::~Renderer11() Renderer11 *Renderer11::makeRenderer11(Renderer *renderer) { - ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer11*, renderer)); - return static_cast(renderer); + ASSERT(HAS_DYNAMIC_TYPE(Renderer11*, renderer)); + return static_cast(renderer); } #ifndef __d3d11_1_h__ @@ -136,7 +197,7 @@ EGLint Renderer11::initialize() return EGL_NOT_INITIALIZED; } -#if !defined(ANGLE_PLATFORM_WINRT) +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); @@ -157,33 +218,14 @@ EGLint Renderer11::initialize() } #endif - D3D_FEATURE_LEVEL featureLevels[] = - { - 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 - }; - - D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_HARDWARE; - if (mRequestedDisplay == EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE) - { - driverType = D3D_DRIVER_TYPE_WARP; - } - HRESULT result = S_OK; - #ifdef _DEBUG result = D3D11CreateDevice(NULL, - driverType, + mDriverType, NULL, D3D11_CREATE_DEVICE_DEBUG, - featureLevels, - ArraySize(featureLevels), + mAvailableFeatureLevels.data(), + mAvailableFeatureLevels.size(), D3D11_SDK_VERSION, &mDevice, &mFeatureLevel, @@ -198,11 +240,11 @@ EGLint Renderer11::initialize() #endif { result = D3D11CreateDevice(NULL, - driverType, + mDriverType, NULL, 0, - featureLevels, - ArraySize(featureLevels), + mAvailableFeatureLevels.data(), + mAvailableFeatureLevels.size(), D3D11_SDK_VERSION, &mDevice, &mFeatureLevel, @@ -215,7 +257,18 @@ EGLint Renderer11::initialize() } } -#if !ANGLE_SKIP_DXGI_1_2_CHECK && !defined(ANGLE_PLATFORM_WINRT) +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED"); + if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1")) + { + ID3D10Multithread *multithread; + result = mDevice->QueryInterface(IID_PPV_ARGS(&multithread)); + ASSERT(SUCCEEDED(result)); + result = multithread->SetMultithreadProtected(true); + ASSERT(SUCCEEDED(result)); + multithread->Release(); + } +#if !ANGLE_SKIP_DXGI_1_2_CHECK // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required. // The easiest way to check is to query for a IDXGIDevice2. bool requireDXGI1_2 = false; @@ -244,13 +297,10 @@ EGLint Renderer11::initialize() SafeRelease(dxgiDevice2); } #endif - -#if !defined(ANGLE_PLATFORM_WINRT) - IDXGIDevice *dxgiDevice = NULL; -#else - IDXGIDevice1 *dxgiDevice = NULL; #endif - result = mDevice->QueryInterface(IID_PPV_ARGS(&dxgiDevice)); + + IDXGIDevice *dxgiDevice = NULL; + result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); if (FAILED(result)) { @@ -281,9 +331,9 @@ EGLint Renderer11::initialize() } // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log -#if !defined(__MINGW32__) && defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG) +#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG) ID3D11InfoQueue *infoQueue; - result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue); + result = mDevice->QueryInterface(IID_ID3D11InfoQueue, (void **)&infoQueue); if (SUCCEEDED(result)) { @@ -301,19 +351,6 @@ EGLint Renderer11::initialize() } #endif -#if !defined(ANGLE_PLATFORM_WINRT) - static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED"); - if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1")) - { - ID3D10Multithread *multithread; - result = mDevice->QueryInterface(IID_PPV_ARGS(&multithread)); - ASSERT(SUCCEEDED(result)); - result = multithread->SetMultithreadProtected(true); - ASSERT(SUCCEEDED(result)); - multithread->Release(); - } -#endif - initializeDevice(); return EGL_SUCCESS; @@ -394,7 +431,7 @@ void Renderer11::deleteConfigs(ConfigDesc *configDescList) delete [] (configDescList); } -void Renderer11::sync(bool block) +gl::Error Renderer11::sync(bool block) { if (block) { @@ -408,6 +445,10 @@ void Renderer11::sync(bool block) result = mDevice->CreateQuery(&queryDesc, &mSyncQuery); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.", result); + } } mDeviceContext->End(mSyncQuery); @@ -416,13 +457,17 @@ void Renderer11::sync(bool block) do { result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result); + } // Keep polling, but allow other threads to do something useful first Sleep(0); if (testDeviceLost(true)) { - return; + return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while waiting for sync."); } } while (result == S_FALSE); @@ -431,22 +476,26 @@ void Renderer11::sync(bool block) { mDeviceContext->Flush(); } + + return gl::Error(GL_NO_ERROR); } -SwapChain *Renderer11::createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) +SwapChain *Renderer11::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) { - return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat); + return new SwapChain11(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat); } gl::Error Renderer11::generateSwizzle(gl::Texture *texture) { if (texture) { - TextureStorage *texStorage = texture->getNativeTexture(); + TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation()); + ASSERT(textureD3D); + + TextureStorage *texStorage = textureD3D->getNativeTexture(); if (texStorage) { TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage); - gl::Error error = storage11->generateSwizzles(texture->getSamplerState().swizzleRed, texture->getSamplerState().swizzleGreen, texture->getSamplerState().swizzleBlue, @@ -461,16 +510,21 @@ gl::Error Renderer11::generateSwizzle(gl::Texture *texture) return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState) +gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &samplerStateParam) { + // Make sure to add the level offset for our tiny compressed texture workaround + TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation()); + gl::SamplerState samplerStateInternal = samplerStateParam; + samplerStateInternal.baseLevel += textureD3D->getNativeTexture()->getTopLevel(); + if (type == gl::SAMPLER_PIXEL) { ASSERT(static_cast(index) < getRendererCaps().maxTextureImageUnits); - if (mForceSetPixelSamplerStates[index] || memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0) + if (mForceSetPixelSamplerStates[index] || memcmp(&samplerStateInternal, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0) { ID3D11SamplerState *dxSamplerState = NULL; - gl::Error error = mStateCache.getSamplerState(samplerState, &dxSamplerState); + gl::Error error = mStateCache.getSamplerState(samplerStateInternal, &dxSamplerState); if (error.isError()) { return error; @@ -479,7 +533,7 @@ gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, const gl: ASSERT(dxSamplerState != NULL); mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState); - mCurPixelSamplerStates[index] = samplerState; + mCurPixelSamplerStates[index] = samplerStateInternal; } mForceSetPixelSamplerStates[index] = false; @@ -488,10 +542,10 @@ gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, const gl: { ASSERT(static_cast(index) < getRendererCaps().maxVertexTextureImageUnits); - if (mForceSetVertexSamplerStates[index] || memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0) + if (mForceSetVertexSamplerStates[index] || memcmp(&samplerStateInternal, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0) { ID3D11SamplerState *dxSamplerState = NULL; - gl::Error error = mStateCache.getSamplerState(samplerState, &dxSamplerState); + gl::Error error = mStateCache.getSamplerState(samplerStateInternal, &dxSamplerState); if (error.isError()) { return error; @@ -500,7 +554,7 @@ gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, const gl: ASSERT(dxSamplerState != NULL); mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState); - mCurVertexSamplerStates[index] = samplerState; + mCurVertexSamplerStates[index] = samplerStateInternal; } mForceSetVertexSamplerStates[index] = false; @@ -513,50 +567,36 @@ gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, const gl: gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture) { ID3D11ShaderResourceView *textureSRV = NULL; - bool forceSetTexture = false; if (texture) { - TextureD3D* textureImpl = TextureD3D::makeTextureD3D(texture->getImplementation()); + TextureD3D *textureImpl = TextureD3D::makeTextureD3D(texture->getImplementation()); TextureStorage *texStorage = textureImpl->getNativeTexture(); ASSERT(texStorage != NULL); TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage); - gl::SamplerState samplerState; - texture->getSamplerStateWithNativeOffset(&samplerState); - textureSRV = storage11->getSRV(samplerState); + + // Make sure to add the level offset for our tiny compressed texture workaround + gl::SamplerState samplerState = texture->getSamplerState(); + samplerState.baseLevel += storage11->getTopLevel(); + + gl::Error error = storage11->getSRV(samplerState, &textureSRV); + if (error.isError()) + { + return error; + } // If we get NULL back from getSRV here, something went wrong in the texture class and we're unexpectedly // missing the shader resource view ASSERT(textureSRV != NULL); - forceSetTexture = textureImpl->hasDirtyImages(); textureImpl->resetDirty(); } - if (type == gl::SAMPLER_PIXEL) - { - ASSERT(static_cast(index) < getRendererCaps().maxTextureImageUnits); + ASSERT((type == gl::SAMPLER_PIXEL && static_cast(index) < getRendererCaps().maxTextureImageUnits) || + (type == gl::SAMPLER_VERTEX && static_cast(index) < getRendererCaps().maxVertexTextureImageUnits)); - if (forceSetTexture || mCurPixelSRVs[index] != textureSRV) - { - mDeviceContext->PSSetShaderResources(index, 1, &textureSRV); - } - - mCurPixelSRVs[index] = textureSRV; - } - else if (type == gl::SAMPLER_VERTEX) - { - ASSERT(static_cast(index) < getRendererCaps().maxVertexTextureImageUnits); - - if (forceSetTexture || mCurVertexSRVs[index] != textureSRV) - { - mDeviceContext->VSSetShaderResources(index, 1, &textureSRV); - } - - mCurVertexSRVs[index] = textureSRV; - } - else UNREACHABLE(); + setShaderResource(type, index, textureSRV); return gl::Error(GL_NO_ERROR); } @@ -631,7 +671,7 @@ gl::Error Renderer11::setRasterizerState(const gl::RasterizerState &rasterState) return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, +gl::Error Renderer11::setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, unsigned int sampleMask) { if (mForceSetBlendState || @@ -831,7 +871,22 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count) return count >= minCount; } -gl::Error Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) +void Renderer11::unsetSRVsWithResource(gl::SamplerType samplerType, const ID3D11Resource *resource) +{ + std::vector ¤tSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); + + for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex) + { + ID3D11ShaderResourceView *srv = currentSRVs[resourceIndex]; + + if (srv && GetSRVResource(srv) == resource) + { + setShaderResource(samplerType, static_cast(resourceIndex), NULL); + } + } +} + +gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer) { // Get the color render buffer and serial // Also extract the render target dimensions and view @@ -842,7 +897,7 @@ gl::Error Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; bool missingColorRenderTarget = true; - const gl::ColorbufferInfo &colorbuffers = framebuffer->getColorbuffersForRender(); + const gl::ColorbufferInfo &colorbuffers = framebuffer->getColorbuffersForRender(getWorkarounds()); for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) { @@ -863,17 +918,16 @@ gl::Error Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) renderTargetSerials[colorAttachment] = GetAttachmentSerial(colorbuffer); // Extract the render target dimensions and view - RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer); - if (!renderTarget) + RenderTarget11 *renderTarget = NULL; + gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &renderTarget); + if (error.isError()) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal render target pointer unexpectedly null."); + return error; } + ASSERT(renderTarget); framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView(); - if (!framebufferRTVs[colorAttachment]) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null."); - } + ASSERT(framebufferRTVs[colorAttachment]); if (missingColorRenderTarget) { @@ -883,8 +937,12 @@ gl::Error Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) missingColorRenderTarget = false; } - // TODO: Detect if this color buffer is already bound as a texture and unbind it first to prevent - // D3D11 warnings. +#if !defined(NDEBUG) + // Unbind render target SRVs from the shader here to prevent D3D11 warnings. + ID3D11Resource *renderTargetResource = renderTarget->getTexture(); + unsetSRVsWithResource(gl::SAMPLER_VERTEX, renderTargetResource); + unsetSRVsWithResource(gl::SAMPLER_PIXEL, renderTargetResource); +#endif } } @@ -905,19 +963,17 @@ gl::Error Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) ID3D11DepthStencilView* framebufferDSV = NULL; if (depthStencil) { - RenderTarget11 *depthStencilRenderTarget = d3d11::GetAttachmentRenderTarget(depthStencil); - if (!depthStencilRenderTarget) + RenderTarget11 *depthStencilRenderTarget = NULL; + gl::Error error = d3d11::GetAttachmentRenderTarget(depthStencil, &depthStencilRenderTarget); + if (error.isError()) { SafeRelease(framebufferRTVs); - return gl::Error(GL_OUT_OF_MEMORY, "Internal render target pointer unexpectedly null."); + return error; } + ASSERT(depthStencilRenderTarget); framebufferDSV = depthStencilRenderTarget->getDepthStencilView(); - if (!framebufferDSV) - { - SafeRelease(framebufferRTVs); - return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null."); - } + ASSERT(framebufferDSV); // If there is no render buffer, the width, height and format values come from // the depth stencil @@ -964,17 +1020,16 @@ gl::Error Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], - GLint first, GLsizei count, GLsizei instances) +gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances) { TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; - gl::Error error = mVertexDataManager->prepareVertexData(vertexAttributes, currentValues, programBinary, first, count, attributes, instances); + gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, attributes, instances); if (error.isError()) { return error; } - return mInputLayoutCache.applyVertexBuffers(attributes, programBinary); + return mInputLayoutCache.applyVertexBuffers(attributes, state.getCurrentProgramBinary()); } gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) @@ -1011,28 +1066,25 @@ gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elemen return gl::Error(GL_NO_ERROR); } -void Renderer11::applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]) +void Renderer11::applyTransformFeedbackBuffers(const gl::State& state) { - ID3D11Buffer* d3dBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; - UINT d3dOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; + size_t numXFBBindings = state.getTransformFeedbackBufferIndexRange(); + ASSERT(numXFBBindings <= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS); + bool requiresUpdate = false; - for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) + for (size_t i = 0; i < numXFBBindings; i++) { - if (transformFeedbackBuffers[i]) + gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i); + GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i); + ID3D11Buffer *d3dBuffer = NULL; + if (curXFBBuffer) { - Buffer11 *storage = Buffer11::makeBuffer11(transformFeedbackBuffers[i]->getImplementation()); - ID3D11Buffer *buffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); - - d3dBuffers[i] = buffer; - d3dOffsets[i] = (mAppliedTFBuffers[i] != buffer) ? static_cast(offsets[i]) : -1; - } - else - { - d3dBuffers[i] = NULL; - d3dOffsets[i] = 0; + Buffer11 *storage = Buffer11::makeBuffer11(curXFBBuffer->getImplementation()); + d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); } - if (d3dBuffers[i] != mAppliedTFBuffers[i] || offsets[i] != mAppliedTFOffsets[i]) + // TODO: mAppliedTFBuffers and friends should also be kept in a vector. + if (d3dBuffer != mAppliedTFBuffers[i] || curXFBOffset != mAppliedTFOffsets[i]) { requiresUpdate = true; } @@ -1040,12 +1092,29 @@ void Renderer11::applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuff if (requiresUpdate) { - mDeviceContext->SOSetTargets(ArraySize(d3dBuffers), d3dBuffers, d3dOffsets); - for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) + for (size_t i = 0; i < numXFBBindings; ++i) { - mAppliedTFBuffers[i] = d3dBuffers[i]; - mAppliedTFOffsets[i] = offsets[i]; + gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i); + GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i); + + if (curXFBBuffer) + { + Buffer11 *storage = Buffer11::makeBuffer11(curXFBBuffer->getImplementation()); + ID3D11Buffer *d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); + + mCurrentD3DOffsets[i] = (mAppliedTFBuffers[i] != d3dBuffer && mAppliedTFOffsets[i] != curXFBOffset) ? + static_cast(curXFBOffset) : -1; + mAppliedTFBuffers[i] = d3dBuffer; + } + else + { + mAppliedTFBuffers[i] = NULL; + mCurrentD3DOffsets[i] = 0; + } + mAppliedTFOffsets[i] = curXFBOffset; } + + mDeviceContext->SOSetTargets(numXFBBindings, mAppliedTFBuffers, mCurrentD3DOffsets); } } @@ -1129,7 +1198,6 @@ gl::Error Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, cons return gl::Error(GL_NO_ERROR); } } - template static void fillLineLoopIndices(GLenum type, GLsizei count, const GLvoid *indices, T *data) { @@ -1213,10 +1281,17 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind // Get the raw indices for an indexed draw if (type != GL_NONE && elementArrayBuffer) { - gl::Buffer *indexBuffer = elementArrayBuffer; - BufferImpl *storage = indexBuffer->getImplementation(); + BufferD3D *storage = BufferD3D::makeFromBuffer(elementArrayBuffer); intptr_t offset = reinterpret_cast(indices); - indices = static_cast(storage->getData()) + offset; + + const uint8_t *bufferData = NULL; + gl::Error error = storage->getData(&bufferData); + if (error.isError()) + { + return error; + } + + indices = bufferData + offset; } // TODO: some level 9 hardware supports 32-bit indices; test and store support instead @@ -1291,10 +1366,17 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * // Get the raw indices for an indexed draw if (type != GL_NONE && elementArrayBuffer) { - gl::Buffer *indexBuffer = elementArrayBuffer; - BufferImpl *storage = indexBuffer->getImplementation(); + BufferD3D *storage = BufferD3D::makeFromBuffer(elementArrayBuffer); intptr_t offset = reinterpret_cast(indices); - indices = static_cast(storage->getData()) + offset; + + const uint8_t *bufferData = NULL; + gl::Error error = storage->getData(&bufferData); + if (error.isError()) + { + return error; + } + + indices = bufferData + offset; } const int indexType = isLevel9() ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; @@ -1376,9 +1458,23 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * gl::Error Renderer11::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, bool rasterizerDiscard, bool transformFeedbackActive) { - ShaderExecutable *vertexExe = programBinary->getVertexExecutableForInputLayout(inputLayout); - ShaderExecutable *pixelExe = programBinary->getPixelExecutableForFramebuffer(framebuffer); - ShaderExecutable *geometryExe = programBinary->getGeometryExecutable(); + ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary->getImplementation()); + + ShaderExecutable *vertexExe = NULL; + gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe); + if (error.isError()) + { + return error; + } + + ShaderExecutable *pixelExe = NULL; + error = programD3D->getPixelExecutableForFramebuffer(framebuffer, &pixelExe); + if (error.isError()) + { + return error; + } + + ShaderExecutable *geometryExe = programD3D->getGeometryExecutable(); ID3D11VertexShader *vertexShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader() : NULL); @@ -1433,16 +1529,14 @@ gl::Error Renderer11::applyShaders(gl::ProgramBinary *programBinary, const gl::V if (dirtyUniforms) { - programBinary->dirtyAllUniforms(); + programD3D->dirtyAllUniforms(); } return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::applyUniforms(const gl::ProgramBinary &programBinary) +gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vector &uniformArray) { - const std::vector &uniformArray = programBinary.getUniforms(); - unsigned int totalRegisterCountVS = 0; unsigned int totalRegisterCountPS = 0; @@ -1466,7 +1560,7 @@ gl::Error Renderer11::applyUniforms(const gl::ProgramBinary &programBinary) } } - const ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary.getImplementation()); + const ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(&program); const UniformStorage11 *vertexUniformStorage = UniformStorage11::makeUniformStorage11(&programD3D->getVertexUniformStorage()); const UniformStorage11 *fragmentUniformStorage = UniformStorage11::makeUniformStorage11(&programD3D->getFragmentUniformStorage()); ASSERT(vertexUniformStorage); @@ -1598,7 +1692,7 @@ gl::Error Renderer11::applyUniforms(const gl::ProgramBinary &programBinary) return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) +gl::Error Renderer11::clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) { gl::Error error = mClear->clearFramebuffer(clearParams, frameBuffer); if (error.isError()) @@ -1626,14 +1720,12 @@ void Renderer11::markAllStateDirty() for (size_t vsamplerId = 0; vsamplerId < mForceSetVertexSamplerStates.size(); ++vsamplerId) { mForceSetVertexSamplerStates[vsamplerId] = true; - mCurVertexSRVs[vsamplerId] = NULL; } ASSERT(mForceSetPixelSamplerStates.size() == mCurPixelSRVs.size()); for (size_t fsamplerId = 0; fsamplerId < mForceSetPixelSamplerStates.size(); ++fsamplerId) { mForceSetPixelSamplerStates[fsamplerId] = true; - mCurPixelSRVs[fsamplerId] = NULL; } mForceSetBlendState = true; @@ -1746,32 +1838,20 @@ bool Renderer11::testDeviceResettable() return false; } - D3D_FEATURE_LEVEL featureLevels[] = - { - 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; D3D_FEATURE_LEVEL dummyFeatureLevel; ID3D11DeviceContext* dummyContext; HRESULT result = D3D11CreateDevice(NULL, - D3D_DRIVER_TYPE_HARDWARE, + mDriverType, NULL, #if defined(_DEBUG) D3D11_CREATE_DEVICE_DEBUG, #else 0, #endif - featureLevels, - ArraySize(featureLevels), + mAvailableFeatureLevels.data(), + mAvailableFeatureLevels.size(), D3D11_SDK_VERSION, &dummyDevice, &dummyFeatureLevel, @@ -1939,119 +2019,37 @@ int Renderer11::getMaxSwapInterval() const return 4; } -bool Renderer11::copyToRenderTarget2D(TextureStorage *dest, TextureStorage *source) -{ - if (source && dest) - { - TextureStorage11_2D *source11 = TextureStorage11_2D::makeTextureStorage11_2D(source); - TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(dest); - - mDeviceContext->CopyResource(dest11->getResource(), source11->getResource()); - - dest11->invalidateSwizzleCache(); - - return true; - } - - return false; -} - -bool Renderer11::copyToRenderTargetCube(TextureStorage *dest, TextureStorage *source) -{ - if (source && dest) - { - TextureStorage11_Cube *source11 = TextureStorage11_Cube::makeTextureStorage11_Cube(source); - TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(dest); - - mDeviceContext->CopyResource(dest11->getResource(), source11->getResource()); - - dest11->invalidateSwizzleCache(); - - return true; - } - - return false; -} - -bool Renderer11::copyToRenderTarget3D(TextureStorage *dest, TextureStorage *source) -{ - if (source && dest) - { - TextureStorage11_3D *source11 = TextureStorage11_3D::makeTextureStorage11_3D(source); - TextureStorage11_3D *dest11 = TextureStorage11_3D::makeTextureStorage11_3D(dest); - - mDeviceContext->CopyResource(dest11->getResource(), source11->getResource()); - - dest11->invalidateSwizzleCache(); - - return true; - } - - return false; -} - -bool Renderer11::copyToRenderTarget2DArray(TextureStorage *dest, TextureStorage *source) -{ - if (source && dest) - { - TextureStorage11_2DArray *source11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(source); - TextureStorage11_2DArray *dest11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(dest); - - mDeviceContext->CopyResource(dest11->getResource(), source11->getResource()); - - dest11->invalidateSwizzleCache(); - - return true; - } - - return false; -} - -bool Renderer11::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) +gl::Error Renderer11::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) { gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); - if (!colorbuffer) - { - ERR("Failed to retrieve the color buffer from the frame buffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } + ASSERT(colorbuffer); - RenderTarget11 *sourceRenderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer); - if (!sourceRenderTarget) + RenderTarget11 *sourceRenderTarget = NULL; + gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget); + if (error.isError()) { - ERR("Failed to retrieve the render target from the frame buffer."); - return gl::error(GL_OUT_OF_MEMORY, false); + return error; } + ASSERT(sourceRenderTarget); ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); - if (!source) - { - ERR("Failed to retrieve the render target view from the render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } + ASSERT(source); TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage); - if (!storage11) - { - ERR("Failed to retrieve the texture storage from the destination."); - return gl::error(GL_OUT_OF_MEMORY, false); - } + ASSERT(storage11); gl::ImageIndex index = gl::ImageIndex::Make2D(level); - RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(index)); - if (!destRenderTarget) + RenderTarget *destRenderTarget = NULL; + error = storage11->getRenderTarget(index, &destRenderTarget); + if (error.isError()) { - ERR("Failed to retrieve the render target from the destination storage."); - return gl::error(GL_OUT_OF_MEMORY, false); + return error; } + ASSERT(destRenderTarget); - ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); - if (!dest) - { - ERR("Failed to retrieve the render target view from the destination render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } + ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView(); + ASSERT(dest); gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); @@ -2061,59 +2059,48 @@ bool Renderer11::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle & // Use nearest filtering because source and destination are the same size for the direct // copy - bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, - destFormat, GL_NEAREST); + mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST); + if (error.isError()) + { + return error; + } storage11->invalidateSwizzleCacheLevel(level); - return ret; + return gl::Error(GL_NO_ERROR); } -bool Renderer11::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level) +gl::Error Renderer11::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level) { gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); - if (!colorbuffer) - { - ERR("Failed to retrieve the color buffer from the frame buffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } + ASSERT(colorbuffer); - RenderTarget11 *sourceRenderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer); - if (!sourceRenderTarget) + RenderTarget11 *sourceRenderTarget = NULL; + gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget); + if (error.isError()) { - ERR("Failed to retrieve the render target from the frame buffer."); - return gl::error(GL_OUT_OF_MEMORY, false); + return error; } + ASSERT(sourceRenderTarget); ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); - if (!source) - { - ERR("Failed to retrieve the render target view from the render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } + ASSERT(source); TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage); - if (!storage11) - { - ERR("Failed to retrieve the texture storage from the destination."); - return gl::error(GL_OUT_OF_MEMORY, false); - } + ASSERT(storage11); gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); - RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(index)); - if (!destRenderTarget) + RenderTarget *destRenderTarget = NULL; + error = storage11->getRenderTarget(index, &destRenderTarget); + if (error.isError()) { - ERR("Failed to retrieve the render target from the destination storage."); - return gl::error(GL_OUT_OF_MEMORY, false); + return error; } + ASSERT(destRenderTarget); - ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); - if (!dest) - { - ERR("Failed to retrieve the render target view from the destination render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } + ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView(); + ASSERT(dest); gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); @@ -2123,123 +2110,48 @@ bool Renderer11::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle // Use nearest filtering because source and destination are the same size for the direct // copy - bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, - destFormat, GL_NEAREST); + error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST); + if (error.isError()) + { + return error; + } storage11->invalidateSwizzleCacheLevel(level); - return ret; + return gl::Error(GL_NO_ERROR); } -bool Renderer11::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) -{ - gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); - if (!colorbuffer) - { - ERR("Failed to retrieve the color buffer from the frame buffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - RenderTarget11 *sourceRenderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer); - if (!sourceRenderTarget) - { - ERR("Failed to retrieve the render target from the frame buffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); - if (!source) - { - ERR("Failed to retrieve the render target view from the render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage); - if (!storage11) - { - ERR("Failed to retrieve the texture storage from the destination."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - gl::ImageIndex index = gl::ImageIndex::Make3D(level, zOffset); - RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(index)); - if (!destRenderTarget) - { - ERR("Failed to retrieve the render target from the destination storage."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); - if (!dest) - { - ERR("Failed to retrieve the render target view from the destination render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); - gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); - - gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1); - gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); - - // Use nearest filtering because source and destination are the same size for the direct - // copy - bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, - destFormat, GL_NEAREST); - - storage11->invalidateSwizzleCacheLevel(level); - - return ret; -} - -bool Renderer11::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, +gl::Error Renderer11::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) { gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); - if (!colorbuffer) - { - ERR("Failed to retrieve the color buffer from the frame buffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } + ASSERT(colorbuffer); - RenderTarget11 *sourceRenderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer); - if (!sourceRenderTarget) + RenderTarget11 *sourceRenderTarget = NULL; + gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget); + if (error.isError()) { - ERR("Failed to retrieve the render target from the frame buffer."); - return gl::error(GL_OUT_OF_MEMORY, false); + return error; } + ASSERT(sourceRenderTarget); ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); - if (!source) - { - ERR("Failed to retrieve the render target view from the render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } + ASSERT(source); - TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage); - if (!storage11) - { - SafeRelease(source); - ERR("Failed to retrieve the texture storage from the destination."); - return gl::error(GL_OUT_OF_MEMORY, false); - } + TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage); + ASSERT(storage11); - gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, zOffset); - RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(index)); - if (!destRenderTarget) + gl::ImageIndex index = gl::ImageIndex::Make3D(level, zOffset); + RenderTarget *destRenderTarget = NULL; + error = storage11->getRenderTarget(index, &destRenderTarget); + if (error.isError()) { - SafeRelease(source); - ERR("Failed to retrieve the render target from the destination storage."); - return gl::error(GL_OUT_OF_MEMORY, false); + return error; } + ASSERT(destRenderTarget); - ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); - if (!dest) - { - ERR("Failed to retrieve the render target view from the destination render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } + ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView(); + ASSERT(dest); gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); @@ -2249,12 +2161,66 @@ bool Renderer11::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectan // Use nearest filtering because source and destination are the same size for the direct // copy - bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, - destFormat, GL_NEAREST); + error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST); + if (error.isError()) + { + return error; + } storage11->invalidateSwizzleCacheLevel(level); - return ret; + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) +{ + gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); + ASSERT(colorbuffer); + + RenderTarget11 *sourceRenderTarget = NULL; + gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(sourceRenderTarget); + + ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); + ASSERT(source); + + TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage); + ASSERT(storage11); + + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, zOffset); + RenderTarget *destRenderTarget = NULL; + error = storage11->getRenderTarget(index, &destRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(destRenderTarget); + + ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView(); + ASSERT(dest); + + gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); + + gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); + + // Use nearest filtering because source and destination are the same size for the direct + // copy + error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST); + if (error.isError()) + { + return error; + } + + storage11->invalidateSwizzleCacheLevel(level); + + return gl::Error(GL_NO_ERROR); } void Renderer11::unapplyRenderTargets() @@ -2277,39 +2243,150 @@ void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView } } -RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth) +gl::Error Renderer11::createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT) { SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain); - RenderTarget11 *renderTarget = NULL; + *outRT = new SurfaceRenderTarget11(swapChain11, depth); + return gl::Error(GL_NO_ERROR); +} - if (depth) +gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT) +{ + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(format); + + const gl::TextureCaps &textureCaps = getRendererTextureCaps().get(format); + GLuint supportedSamples = textureCaps.getNearestSamples(samples); + + if (width > 0 && height > 0) { - // Note: depth stencil may be NULL for 0 sized surfaces - renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(), - swapChain11->getDepthStencilTexture(), - swapChain11->getDepthStencilShaderResource(), - swapChain11->getWidth(), swapChain11->getHeight(), 1); + // Create texture resource + D3D11_TEXTURE2D_DESC desc; + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = formatInfo.texFormat; + desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + // If a rendertarget or depthstencil format exists for this texture format, + // we'll flag it to allow binding that way. Shader resource views are a little + // more complicated. + bool bindRTV = false, bindDSV = false, bindSRV = false; + bindRTV = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); + bindDSV = (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN); + if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) + { + // Multisample targets flagged for binding as depth stencil cannot also be + // flagged for binding as SRV, so make certain not to add the SRV flag for + // these targets. + bindSRV = !(formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN && desc.SampleDesc.Count > 1); + } + + desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) | + (bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) | + (bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0); + + // The format must be either an RTV or a DSV + ASSERT(bindRTV != bindDSV); + + ID3D11Texture2D *texture = NULL; + HRESULT result = mDevice->CreateTexture2D(&desc, NULL, &texture); + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target texture, result: 0x%X.", result); + } + + ID3D11ShaderResourceView *srv = NULL; + if (bindSRV) + { + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = formatInfo.srvFormat; + srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS; + srvDesc.Texture2D.MostDetailedMip = 0; + srvDesc.Texture2D.MipLevels = 1; + + result = mDevice->CreateShaderResourceView(texture, &srvDesc, &srv); + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + SafeRelease(texture); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target shader resource view, result: 0x%X.", result); + } + } + + if (bindDSV) + { + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = formatInfo.dsvFormat; + dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS; + dsvDesc.Texture2D.MipSlice = 0; + dsvDesc.Flags = 0; + + ID3D11DepthStencilView *dsv = NULL; + result = mDevice->CreateDepthStencilView(texture, &dsvDesc, &dsv); + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + SafeRelease(texture); + SafeRelease(srv); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target depth stencil view, result: 0x%X.", result); + } + + *outRT = new TextureRenderTarget11(dsv, texture, srv, format, width, height, 1, supportedSamples); + + SafeRelease(dsv); + } + else if (bindRTV) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = formatInfo.rtvFormat; + rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS; + rtvDesc.Texture2D.MipSlice = 0; + + ID3D11RenderTargetView *rtv = NULL; + result = mDevice->CreateRenderTargetView(texture, &rtvDesc, &rtv); + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + SafeRelease(texture); + SafeRelease(srv); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target render target view, result: 0x%X.", result); + } + + if (formatInfo.dataInitializerFunction != NULL) + { + const float clearValues[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; + mDeviceContext->ClearRenderTargetView(rtv, clearValues); + } + + *outRT = new TextureRenderTarget11(rtv, texture, srv, format, width, height, 1, supportedSamples); + + SafeRelease(rtv); + } + else + { + UNREACHABLE(); + } + + SafeRelease(texture); + SafeRelease(srv); } else { - // Note: render target may be NULL for 0 sized surfaces - renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(), - swapChain11->getOffscreenTexture(), - swapChain11->getRenderTargetShaderResource(), - swapChain11->getWidth(), swapChain11->getHeight(), 1); + *outRT = new TextureRenderTarget11(reinterpret_cast(NULL), NULL, NULL, format, width, height, 1, supportedSamples); } - return renderTarget; + + return gl::Error(GL_NO_ERROR); } -RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples) +ShaderImpl *Renderer11::createShader(const gl::Data &data, GLenum type) { - RenderTarget11 *renderTarget = new RenderTarget11(this, width, height, format, samples); - return renderTarget; -} - -ShaderImpl *Renderer11::createShader(GLenum type) -{ - return new ShaderD3D(type, this); + return new ShaderD3D(data, type, this); } ProgramImpl *Renderer11::createProgram() @@ -2322,22 +2399,23 @@ void Renderer11::releaseShaderCompiler() ShaderD3D::releaseCompiler(); } -ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers) +gl::Error Renderer11::loadExecutable(const void *function, size_t length, ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, ShaderExecutable **outExecutable) { - ShaderExecutable11 *executable = NULL; - HRESULT result; - switch (type) { - case rx::SHADER_VERTEX: + case SHADER_VERTEX: { ID3D11VertexShader *vertexShader = NULL; ID3D11GeometryShader *streamOutShader = NULL; - result = mDevice->CreateVertexShader(function, length, NULL, &vertexShader); + HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vertexShader); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create vertex shader, result: 0x%X.", result); + } if (transformFeedbackVaryings.size() > 0) { @@ -2363,99 +2441,116 @@ ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length result = mDevice->CreateGeometryShaderWithStreamOutput(function, length, soDeclaration.data(), soDeclaration.size(), NULL, 0, 0, NULL, &streamOutShader); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create steam output shader, result: 0x%X.", result); + } } - if (vertexShader) - { - executable = new ShaderExecutable11(function, length, vertexShader, streamOutShader); - } + *outExecutable = new ShaderExecutable11(function, length, vertexShader, streamOutShader); } break; - case rx::SHADER_PIXEL: + case SHADER_PIXEL: { ID3D11PixelShader *pixelShader = NULL; - result = mDevice->CreatePixelShader(function, length, NULL, &pixelShader); + HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pixelShader); ASSERT(SUCCEEDED(result)); - - if (pixelShader) + if (FAILED(result)) { - executable = new ShaderExecutable11(function, length, pixelShader); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create pixel shader, result: 0x%X.", result); } + + *outExecutable = new ShaderExecutable11(function, length, pixelShader); } break; - case rx::SHADER_GEOMETRY: + case SHADER_GEOMETRY: { ID3D11GeometryShader *geometryShader = NULL; - result = mDevice->CreateGeometryShader(function, length, NULL, &geometryShader); + HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &geometryShader); ASSERT(SUCCEEDED(result)); - - if (geometryShader) + if (FAILED(result)) { - executable = new ShaderExecutable11(function, length, geometryShader); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create geometry shader, result: 0x%X.", result); } + + *outExecutable = new ShaderExecutable11(function, length, geometryShader); } break; default: UNREACHABLE(); - break; + return gl::Error(GL_INVALID_OPERATION); } - return executable; + return gl::Error(GL_NO_ERROR); } -ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, D3DWorkaroundType workaround) +gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, D3DWorkaroundType workaround, + ShaderExecutable **outExectuable) { const char *profileType = NULL; switch (type) { - case rx::SHADER_VERTEX: + case SHADER_VERTEX: profileType = "vs"; break; - case rx::SHADER_PIXEL: + case SHADER_PIXEL: profileType = "ps"; break; - case rx::SHADER_GEOMETRY: + case SHADER_GEOMETRY: profileType = "gs"; break; default: UNREACHABLE(); - return NULL; + return gl::Error(GL_INVALID_OPERATION); } - const char *profileVersion = NULL; + unsigned int profileMajorVersion = 0; + unsigned int profileMinorVersion = 0; + const char *profileSuffix = NULL; switch (mFeatureLevel) { case D3D_FEATURE_LEVEL_11_0: - profileVersion = "5_0"; + profileMajorVersion = 5; + profileMinorVersion = 0; break; case D3D_FEATURE_LEVEL_10_1: - profileVersion = "4_1"; + profileMajorVersion = 4; + profileMinorVersion = 1; break; case D3D_FEATURE_LEVEL_10_0: - profileVersion = "4_0"; + profileMajorVersion = 4; + profileMinorVersion = 0; break; case D3D_FEATURE_LEVEL_9_3: - profileVersion = "4_0_level_9_3"; + profileMajorVersion = 4; + profileMinorVersion = 0; + profileSuffix = "_level_9_3"; break; case D3D_FEATURE_LEVEL_9_2: - profileVersion = "4_0_level_9_2"; + profileMajorVersion = 4; + profileMinorVersion = 0; + profileSuffix = "_level_9_2"; break; case D3D_FEATURE_LEVEL_9_1: - profileVersion = "4_0_level_9_1"; + profileMajorVersion = 4; + profileMinorVersion = 0; + profileSuffix = "_level_9_1"; break; + break; default: UNREACHABLE(); - return NULL; + return gl::Error(GL_INVALID_OPERATION); } - char profile[32]; - snprintf(profile, ArraySize(profile), "%s_%s", profileType, profileVersion); + std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion); + if (profileSuffix) + profile += profileSuffix; - UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL0; + UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2; if (gl::perfActive()) { @@ -2464,44 +2559,51 @@ ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const ch #endif flags |= D3DCOMPILE_DEBUG; - - std::string sourcePath = getTempPath(); - std::string sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(shaderHLSL); - writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size()); } // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options. // Try the default flags first and if compilation fails, try some alternatives. - const UINT extraFlags[] = - { - flags, - flags | D3DCOMPILE_SKIP_VALIDATION, - flags | D3DCOMPILE_SKIP_OPTIMIZATION - }; + std::vector configs; + configs.push_back(CompileConfig(flags, "default" )); + configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION, "skip validation" )); + configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_OPTIMIZATION, "skip optimization")); - const static char *extraFlagNames[] = - { - "default", - "skip validation", - "skip optimization" - }; + D3D_SHADER_MACRO loopMacros[] = { {"ANGLE_ENABLE_LOOP_FLATTEN", "1"}, {0, 0} }; - int attempts = ArraySize(extraFlags); - - ID3DBlob *binary = (ID3DBlob*)mCompiler.compileToBinary(infoLog, shaderHLSL, profile, extraFlags, extraFlagNames, attempts); - if (!binary) + ID3DBlob *binary = NULL; + std::string debugInfo; + gl::Error error = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, loopMacros, &binary, &debugInfo); + if (error.isError()) { - return NULL; + return error; } - ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type, - transformFeedbackVaryings, separatedOutputBuffers); - SafeRelease(binary); + // It's possible that binary is NULL if the compiler failed in all configurations. Set the executable to NULL + // and return GL_NO_ERROR to signify that there was a link error but the internal state is still OK. + if (!binary) + { + *outExectuable = NULL; + return gl::Error(GL_NO_ERROR); + } - return executable; + error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, + transformFeedbackVaryings, separatedOutputBuffers, outExectuable); + + SafeRelease(binary); + if (error.isError()) + { + return error; + } + + if (!debugInfo.empty()) + { + (*outExectuable)->appendDebugInfo(debugInfo); + } + + return gl::Error(GL_NO_ERROR); } -rx::UniformStorage *Renderer11::createUniformStorage(size_t storageSize) +UniformStorage *Renderer11::createUniformStorage(size_t storageSize) { return new UniformStorage11(this, storageSize); } @@ -2531,9 +2633,14 @@ QueryImpl *Renderer11::createQuery(GLenum type) return new Query11(this, type); } -FenceImpl *Renderer11::createFence() +FenceNVImpl *Renderer11::createFenceNV() { - return new Fence11(this); + return new FenceNV11(this); +} + +FenceSyncImpl *Renderer11::createFenceSync() +{ + return new FenceSync11(this); } TransformFeedbackImpl* Renderer11::createTransformFeedback() @@ -2576,82 +2683,77 @@ bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const return true; } -bool Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, - GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) +gl::Error Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) { ASSERT(supportsFastCopyBufferToTexture(destinationFormat)); return mPixelTransfer->copyBufferToTexture(unpack, offset, destRenderTarget, destinationFormat, sourcePixelsType, destArea); } -bool Renderer11::getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource) +gl::Error Renderer11::getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndexOut, ID3D11Texture2D **texture2DOut) + { - ASSERT(colorbuffer != NULL); + ASSERT(colorbuffer); - RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer); - if (renderTarget) + RenderTarget11 *renderTarget = NULL; + gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &renderTarget); + if (error.isError()) { - *subresourceIndex = renderTarget->getSubresourceIndex(); - - ID3D11RenderTargetView *colorBufferRTV = renderTarget->getRenderTargetView(); - if (colorBufferRTV) - { - ID3D11Resource *textureResource = NULL; - colorBufferRTV->GetResource(&textureResource); - - if (textureResource) - { - HRESULT result = textureResource->QueryInterface(__uuidof(ID3D11Texture2D), (void**)resource); - SafeRelease(textureResource); - - if (SUCCEEDED(result)) - { - return true; - } - else - { - ERR("Failed to extract the ID3D11Texture2D from the render target resource, " - "HRESULT: 0x%X.", result); - } - } - } + return error; } - return false; + ID3D11Resource *renderTargetResource = renderTarget->getTexture(); + ASSERT(renderTargetResource); + + *subresourceIndexOut = renderTarget->getSubresourceIndex(); + *texture2DOut = d3d11::DynamicCastComObject(renderTargetResource); + + if (!(*texture2DOut)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the ID3D11Texture2D from a RenderTarget"); + } + + return gl::Error(GL_NO_ERROR); } -bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) +gl::Error Renderer11::blitRect(const gl::Framebuffer *readTarget, const gl::Rectangle &readRect, + const gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, + const gl::Rectangle *scissor, bool blitRenderTarget, + bool blitDepth, bool blitStencil, GLenum filter) { if (blitRenderTarget) { gl::FramebufferAttachment *readBuffer = readTarget->getReadColorbuffer(); + ASSERT(readBuffer); - if (!readBuffer) + RenderTarget *readRenderTarget = NULL; + gl::Error error = GetAttachmentRenderTarget(readBuffer, &readRenderTarget); + if (error.isError()) { - ERR("Failed to retrieve the read buffer from the read framebuffer."); - return gl::error(GL_OUT_OF_MEMORY, false); + return error; } - - RenderTarget *readRenderTarget = GetAttachmentRenderTarget(readBuffer); + ASSERT(readRenderTarget); for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { if (drawTarget->isEnabledColorAttachment(colorAttachment)) { gl::FramebufferAttachment *drawBuffer = drawTarget->getColorbuffer(colorAttachment); + ASSERT(drawBuffer); - if (!drawBuffer) + RenderTarget *drawRenderTarget = NULL; + error = GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget); + if (error.isError()) { - ERR("Failed to retrieve the draw buffer from the draw framebuffer."); - return gl::error(GL_OUT_OF_MEMORY, false); + return error; } + ASSERT(drawRenderTarget); - RenderTarget *drawRenderTarget = GetAttachmentRenderTarget(drawBuffer); - - if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, - blitRenderTarget, false, false)) + error = blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, blitRenderTarget, + false, false); + if (error.isError()) { - return false; + return error; } } } @@ -2660,78 +2762,88 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read if (blitDepth || blitStencil) { gl::FramebufferAttachment *readBuffer = readTarget->getDepthOrStencilbuffer(); + ASSERT(readBuffer); + + RenderTarget *readRenderTarget = NULL; + gl::Error error = GetAttachmentRenderTarget(readBuffer, &readRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(readRenderTarget); + gl::FramebufferAttachment *drawBuffer = drawTarget->getDepthOrStencilbuffer(); + ASSERT(drawBuffer); - if (!readBuffer) + RenderTarget *drawRenderTarget = NULL; + error = GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget); + if (error.isError()) { - ERR("Failed to retrieve the read depth-stencil buffer from the read framebuffer."); - return gl::error(GL_OUT_OF_MEMORY, false); + return error; } + ASSERT(drawRenderTarget); - if (!drawBuffer) + error = blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, false, + blitDepth, blitStencil); + if (error.isError()) { - ERR("Failed to retrieve the draw depth-stencil buffer from the draw framebuffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - RenderTarget *readRenderTarget = GetAttachmentRenderTarget(readBuffer); - RenderTarget *drawRenderTarget = GetAttachmentRenderTarget(drawBuffer); - ASSERT(readRenderTarget && drawRenderTarget); - - if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, - false, blitDepth, blitStencil)) - { - return false; + return error; } } invalidateFramebufferSwizzles(drawTarget); - return true; + return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, +gl::Error Renderer11::readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) { ID3D11Texture2D *colorBufferTexture = NULL; unsigned int subresourceIndex = 0; gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); + ASSERT(colorbuffer); - if (colorbuffer && getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture)) + gl::Error error = getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture); + if (error.isError()) { - gl::Rectangle area; - area.x = x; - area.y = y; - area.width = width; - area.height = height; - - gl::Buffer *packBuffer = pack.pixelBuffer.get(); - if (packBuffer != NULL) - { - rx::Buffer11 *packBufferStorage = Buffer11::makeBuffer11(packBuffer->getImplementation()); - PackPixelsParams packParams(area, format, type, outputPitch, pack, reinterpret_cast(pixels)); - - gl::Error error = packBufferStorage->packPixels(colorBufferTexture, subresourceIndex, packParams); - if (error.isError()) - { - return error; - } - - packBuffer->getIndexRangeCache()->clear(); - } - else - { - gl::Error error = readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, pack, pixels); - if (error.isError()) - { - return error; - } - } - - SafeRelease(colorBufferTexture); + return error; } + gl::Rectangle area; + area.x = x; + area.y = y; + area.width = width; + area.height = height; + + gl::Buffer *packBuffer = pack.pixelBuffer.get(); + if (packBuffer != NULL) + { + Buffer11 *packBufferStorage = Buffer11::makeBuffer11(packBuffer->getImplementation()); + PackPixelsParams packParams(area, format, type, outputPitch, pack, reinterpret_cast(pixels)); + + error = packBufferStorage->packPixels(colorBufferTexture, subresourceIndex, packParams); + if (error.isError()) + { + SafeRelease(colorBufferTexture); + return error; + } + + packBuffer->getIndexRangeCache()->clear(); + } + else + { + error = readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, pack, pixels); + if (error.isError()) + { + SafeRelease(colorBufferTexture); + return error; + } + } + + SafeRelease(colorBufferTexture); + return gl::Error(GL_NO_ERROR); } @@ -2740,11 +2852,11 @@ Image *Renderer11::createImage() return new Image11(); } -void Renderer11::generateMipmap(Image *dest, Image *src) +gl::Error Renderer11::generateMipmap(Image *dest, Image *src) { Image11 *dest11 = Image11::makeImage11(dest); Image11 *src11 = Image11::makeImage11(src); - Image11::generateMipmap(dest11, src11); + return Image11::generateMipmap(dest11, src11); } TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain) @@ -2788,6 +2900,19 @@ TextureImpl *Renderer11::createTexture(GLenum target) return NULL; } +RenderbufferImpl *Renderer11::createRenderbuffer() +{ + RenderbufferD3D *renderbuffer = new RenderbufferD3D(this); + return renderbuffer; +} + +RenderbufferImpl *Renderer11::createRenderbuffer(SwapChain *swapChain, bool depth) +{ + RenderbufferD3D *renderbuffer = new RenderbufferD3D(this); + renderbuffer->setStorage(swapChain, depth); + return renderbuffer; +} + gl::Error Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format, GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) { @@ -2882,22 +3007,25 @@ gl::Error Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int sub SafeRelease(srcTex); PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, 0); - packPixels(stagingTex, packParams, pixels); + gl::Error error = packPixels(stagingTex, packParams, pixels); SafeRelease(stagingTex); - return gl::Error(GL_NO_ERROR); + return error; } -void Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, uint8_t *pixelsOut) +gl::Error Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, uint8_t *pixelsOut) { D3D11_TEXTURE2D_DESC textureDesc; readTexture->GetDesc(&textureDesc); D3D11_MAPPED_SUBRESOURCE mapping; HRESULT hr = mDeviceContext->Map(readTexture, 0, D3D11_MAP_READ, 0, &mapping); - UNUSED_ASSERTION_VARIABLE(hr); - ASSERT(SUCCEEDED(hr)); + if (FAILED(hr)) + { + ASSERT(hr == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal texture for reading, result: 0x%X.", hr); + } uint8_t *source; int inputPitch; @@ -2968,24 +3096,23 @@ void Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams } mDeviceContext->Unmap(readTexture, 0); + + return gl::Error(GL_NO_ERROR); } -bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, - RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor, - bool colorBlit, bool depthBlit, bool stencilBlit) +gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, + RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor, + bool colorBlit, bool depthBlit, bool stencilBlit) { // Since blitRenderbufferRect is called for each render buffer that needs to be blitted, // it should never be the case that both color and depth/stencil need to be blitted at // at the same time. ASSERT(colorBlit != (depthBlit || stencilBlit)); - bool result = true; - RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget); if (!drawRenderTarget) { - ERR("Failed to retrieve the draw render target from the draw framebuffer."); - return gl::error(GL_OUT_OF_MEMORY, false); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal draw render target from the draw framebuffer."); } ID3D11Resource *drawTexture = drawRenderTarget11->getTexture(); @@ -2996,8 +3123,7 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget); if (!readRenderTarget) { - ERR("Failed to retrieve the read render target from the read framebuffer."); - return gl::error(GL_OUT_OF_MEMORY, false); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal read render target from the read framebuffer."); } ID3D11Resource *readTexture = NULL; @@ -3019,7 +3145,7 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R if (FAILED(hresult)) { SafeRelease(readTexture); - return gl::error(GL_OUT_OF_MEMORY, false); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create shader resource view to resolve multisampled framebuffer."); } } } @@ -3036,8 +3162,7 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R { SafeRelease(readTexture); SafeRelease(readSRV); - ERR("Failed to retrieve the read render target view from the read render target."); - return gl::error(GL_OUT_OF_MEMORY, false); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal read render target view from the read render target."); } gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1); @@ -3063,6 +3188,8 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(drawRenderTarget->getActualFormat()); bool partialDSBlit = (actualFormatInfo.depthBits > 0 && depthBlit) != (actualFormatInfo.stencilBits > 0 && stencilBlit); + gl::Error result(GL_NO_ERROR); + if (readRenderTarget11->getActualFormat() == drawRenderTarget->getActualFormat() && !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit && (!(depthBlit || stencilBlit) || wholeBufferCopy)) @@ -3109,7 +3236,7 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, dstX, dstY, 0, readTexture, readSubresource, pSrcBox); - result = true; + result = gl::Error(GL_NO_ERROR); } else { @@ -3190,7 +3317,8 @@ void Renderer11::invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *atta ASSERT(attachment->isTexture()); gl::Texture *texture = attachment->getTexture(); - TextureStorage *texStorage = texture->getNativeTexture(); + TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation()); + TextureStorage *texStorage = textureD3D->getNativeTexture(); if (texStorage) { TextureStorage11 *texStorage11 = TextureStorage11::makeTextureStorage11(texStorage); @@ -3204,7 +3332,7 @@ void Renderer11::invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *atta } } -void Renderer11::invalidateFramebufferSwizzles(gl::Framebuffer *framebuffer) +void Renderer11::invalidateFramebufferSwizzles(const gl::Framebuffer *framebuffer) { for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { @@ -3248,7 +3376,7 @@ bool Renderer11::getLUID(LUID *adapterLuid) const return true; } -rx::VertexConversionType Renderer11::getVertexConversionType(const gl::VertexFormat &vertexFormat) const +VertexConversionType Renderer11::getVertexConversionType(const gl::VertexFormat &vertexFormat) const { return d3d11::GetVertexFormatInfo(vertexFormat).conversionType; } @@ -3263,4 +3391,30 @@ void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureC d3d11_gl::GenerateCaps(mDevice, outCaps, outTextureCaps, outExtensions); } +Workarounds Renderer11::generateWorkarounds() const +{ + return d3d11::GenerateWorkarounds(); +} + +void Renderer11::setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv) +{ + std::vector ¤tSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); + + ASSERT(static_cast(resourceSlot) < currentSRVs.size()); + + if (currentSRVs[resourceSlot] != srv) + { + if (shaderType == gl::SAMPLER_VERTEX) + { + mDeviceContext->VSSetShaderResources(resourceSlot, 1, &srv); + } + else + { + mDeviceContext->PSSetShaderResources(resourceSlot, 1, &srv); + } + + currentSRVs[resourceSlot] = srv; + } +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h index 2a53fa1672b..d44bd2fd301 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h @@ -13,12 +13,14 @@ #include "libGLESv2/angletypes.h" #include "common/mathutil.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/d3d/HLSLCompiler.h" #include "libGLESv2/renderer/d3d/d3d11/RenderStateCache.h" #include "libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h" +#include "libGLESv2/renderer/d3d/HLSLCompiler.h" +#include "libGLESv2/renderer/d3d/RendererD3D.h" #include "libGLESv2/renderer/RenderTarget.h" +#include "libEGL/AttributeMap.h" + namespace gl { class FramebufferAttachment; @@ -33,6 +35,7 @@ class StreamingIndexBufferInterface; class Blit11; class Clear11; class PixelTransfer11; +class RenderTarget11; struct PackPixelsParams; enum @@ -41,10 +44,10 @@ enum MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024 }; -class Renderer11 : public Renderer +class Renderer11 : public RendererD3D { public: - Renderer11(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay); + Renderer11(egl::Display *display, EGLNativeDisplayType hDc, const egl::AttributeMap &attributes); virtual ~Renderer11(); static Renderer11 *makeRenderer11(Renderer *renderer); @@ -55,19 +58,19 @@ class Renderer11 : public Renderer virtual int generateConfigs(ConfigDesc **configDescList); virtual void deleteConfigs(ConfigDesc *configDescList); - virtual void sync(bool block); + virtual gl::Error sync(bool block); - virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); + virtual SwapChain *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); virtual gl::Error generateSwizzle(gl::Texture *texture); - virtual gl::Error setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler); + virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler); virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture); virtual gl::Error setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]); virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState); - virtual gl::Error setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask); + gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, + unsigned int sampleMask) override; virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, int stencilBackRef, bool frontFaceCCW); @@ -76,32 +79,32 @@ class Renderer11 : public Renderer bool ignoreViewport); virtual bool applyPrimitiveType(GLenum mode, GLsizei count); - virtual gl::Error applyRenderTarget(gl::Framebuffer *frameBuffer); + gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override; virtual gl::Error applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, bool rasterizerDiscard, bool transformFeedbackActive); - virtual gl::Error applyUniforms(const gl::ProgramBinary &programBinary); - virtual gl::Error applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], - GLint first, GLsizei count, GLsizei instances); + + virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector &uniformArray); + virtual gl::Error applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances); virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); - virtual void applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]); + virtual void applyTransformFeedbackBuffers(const gl::State &state); virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive); virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); - virtual gl::Error clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); + gl::Error clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) override; virtual void markAllStateDirty(); // lost device - void notifyDeviceLost(); - virtual bool isDeviceLost(); - virtual bool testDeviceLost(bool notify); - virtual bool testDeviceResettable(); + void notifyDeviceLost() override; + bool isDeviceLost() override; + bool testDeviceLost(bool notify) override; + bool testDeviceResettable() override; - virtual DWORD getAdapterVendor() const; - virtual std::string getRendererDescription() const; - virtual GUID getAdapterIdentifier() const; + DWORD getAdapterVendor() const override; + std::string getRendererDescription() const override; + GUID getAdapterIdentifier() const override; virtual unsigned int getReservedVertexUniformVectors() const; virtual unsigned int getReservedFragmentUniformVectors() const; @@ -115,47 +118,43 @@ class Renderer11 : public Renderer virtual int getMaxSwapInterval() const; // Pixel operations - virtual bool copyToRenderTarget2D(TextureStorage *dest, TextureStorage *source); - virtual bool copyToRenderTargetCube(TextureStorage *dest, TextureStorage *source); - virtual bool copyToRenderTarget3D(TextureStorage *dest, TextureStorage *source); - virtual bool copyToRenderTarget2DArray(TextureStorage *dest, TextureStorage *source); - - virtual bool copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level); - virtual bool copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level); - virtual bool copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level); - virtual bool copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + virtual gl::Error copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level); + virtual gl::Error copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level); + virtual gl::Error copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level); + virtual gl::Error copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level); - virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter); + gl::Error blitRect(const gl::Framebuffer *readTarget, const gl::Rectangle &readRect, const gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, + const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) override; - virtual gl::Error readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, + virtual gl::Error readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels); // RenderTarget creation - virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth); - virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples); + virtual gl::Error createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT); + virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT); // Shader creation - virtual ShaderImpl *createShader(GLenum type); + virtual ShaderImpl *createShader(const gl::Data &data, GLenum type); virtual ProgramImpl *createProgram(); // Shader operations - virtual void releaseShaderCompiler(); - virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers); - virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, D3DWorkaroundType workaround); + void releaseShaderCompiler() override; + virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, ShaderExecutable **outExecutable); + virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, D3DWorkaroundType workaround, + ShaderExecutable **outExectuable); virtual UniformStorage *createUniformStorage(size_t storageSize); // Image operations virtual Image *createImage(); - virtual void generateMipmap(Image *dest, Image *source); + gl::Error generateMipmap(Image *dest, Image *source) override; virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain); virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels); @@ -165,6 +164,10 @@ class Renderer11 : public Renderer // Texture creation virtual TextureImpl *createTexture(GLenum target); + // Renderbuffer creation + virtual RenderbufferImpl *createRenderbuffer(); + virtual RenderbufferImpl *createRenderbuffer(SwapChain *swapChain, bool depth); + // Buffer creation virtual BufferImpl *createBuffer(); virtual VertexBuffer *createVertexBuffer(); @@ -175,7 +178,8 @@ class Renderer11 : public Renderer // Query and Fence creation virtual QueryImpl *createQuery(GLenum type); - virtual FenceImpl *createFence(); + virtual FenceNVImpl *createFenceNV(); + virtual FenceSyncImpl *createFenceSync(); // Transform Feedback creation virtual TransformFeedbackImpl* createTransformFeedback(); @@ -183,48 +187,54 @@ class Renderer11 : public Renderer // D3D11-renderer specific methods ID3D11Device *getDevice() { return mDevice; } ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; }; - IDXGIFactory *getDxgiFactory() { return mDxgiFactory; }; + DXGIFactory *getDxgiFactory() { return mDxgiFactory; }; bool isLevel9() { return mFeatureLevel <= D3D_FEATURE_LEVEL_9_3; } Blit11 *getBlitter() { return mBlit; } // Buffer-to-texture and Texture-to-buffer copies virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const; - virtual bool fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, - GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); + virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); + + gl::Error getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndexOut, ID3D11Texture2D **texture2DOut); - bool getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource); void unapplyRenderTargets(); void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView); - void packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, uint8_t *pixelsOut); + gl::Error packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, uint8_t *pixelsOut); virtual bool getLUID(LUID *adapterLuid) const; - virtual rx::VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const; + virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const; virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const; - private: - DISALLOW_COPY_AND_ASSIGN(Renderer11); - - virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const; - - gl::Error drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); - gl::Error drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances); - gl::Error readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format, GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels); - bool blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, - RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor, - bool colorBlit, bool depthBlit, bool stencilBlit); + void setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv); + + private: + DISALLOW_COPY_AND_ASSIGN(Renderer11); + + void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const override; + Workarounds generateWorkarounds() const override; + + gl::Error drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); + gl::Error drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances); + + gl::Error blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, + RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor, + bool colorBlit, bool depthBlit, bool stencilBlit); ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource); + void unsetSRVsWithResource(gl::SamplerType shaderType, const ID3D11Resource *resource); static void invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *attachment, int mipLevel); - static void invalidateFramebufferSwizzles(gl::Framebuffer *framebuffer); + static void invalidateFramebufferSwizzles(const gl::Framebuffer *framebuffer); HMODULE mD3d11Module; HMODULE mDxgiModule; EGLNativeDisplayType mDc; - EGLint mRequestedDisplay; + std::vector mAvailableFeatureLevels; + D3D_DRIVER_TYPE mDriverType; HLSLCompiler mCompiler; @@ -243,7 +253,7 @@ class Renderer11 : public Renderer unsigned int mAppliedStencilbufferSerial; bool mDepthStencilInitialized; bool mRenderTargetDescInitialized; - rx::RenderTarget::Desc mRenderTargetDesc; + RenderTarget::Desc mRenderTargetDesc; // Currently applied sampler states std::vector mForceSetVertexSamplerStates; @@ -292,8 +302,14 @@ class Renderer11 : public Renderer unsigned int mAppliedIBOffset; // Currently applied transform feedback buffers - ID3D11Buffer *mAppliedTFBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; - GLintptr mAppliedTFOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; + ID3D11Buffer *mAppliedTFBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current D3D buffers + // in use for streamout + GLintptr mAppliedTFOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current GL-specified + // buffer offsets to transform feedback + // buffers + UINT mCurrentD3DOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the D3D buffer offsets, + // which may differ from GLs, due + // to different append behavior // Currently applied shaders ID3D11VertexShader *mAppliedVertexShader; @@ -339,7 +355,7 @@ class Renderer11 : public Renderer IDXGIAdapter *mDxgiAdapter; DXGI_ADAPTER_DESC mAdapterDescription; char mDescription[128]; - IDXGIFactory *mDxgiFactory; + DXGIFactory *mDxgiFactory; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp index 4b29be055d3..52c8a816331 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp @@ -6,7 +6,6 @@ // SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain. -#include "common/platform.h" #include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h" #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" @@ -16,12 +15,16 @@ #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2dvs.h" #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dps.h" +#include "common/features.h" +#include "common/NativeWindow.h" + namespace rx { -SwapChain11::SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle, +SwapChain11::SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) - : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat) + : mRenderer(renderer), + SwapChain(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat) { mSwapChain = NULL; mBackBufferTexture = NULL; @@ -39,8 +42,8 @@ SwapChain11::SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDL mPassThroughPS = NULL; mWidth = -1; mHeight = -1; - mViewportWidth = -1; - mViewportHeight = -1; + mRotateL = false; + mRotateR = false; mSwapInterval = 0; mAppCreatedShareHandle = mShareHandle != NULL; mPassThroughResourcesInit = false; @@ -91,11 +94,11 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei ASSERT(device != NULL); // D3D11 does not allow zero size textures - ASSERT(backbufferWidth >= 1); - ASSERT(backbufferHeight >= 1); + ASSERT(backbufferWidth != 0); + ASSERT(backbufferHeight != 0); // Preserve the render target content -#if !defined(ANGLE_PLATFORM_WINRT) +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture; if (previousOffscreenTexture) { @@ -137,8 +140,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; mOffscreenTexture->GetDesc(&offscreenTextureDesc); - if (offscreenTextureDesc.Width != (UINT)backbufferWidth || - offscreenTextureDesc.Height != (UINT)backbufferHeight || + if (offscreenTextureDesc.Width != UINT(abs(backbufferWidth)) || + offscreenTextureDesc.Height != UINT(abs(backbufferHeight)) || offscreenTextureDesc.Format != backbufferFormatInfo.texFormat || offscreenTextureDesc.MipLevels != 1 || offscreenTextureDesc.ArraySize != 1) @@ -150,11 +153,11 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei } else { - const bool useSharedResource = !mWindow && mRenderer->getShareHandleSupport(); + const bool useSharedResource = !mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport(); D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; - offscreenTextureDesc.Width = backbufferWidth; - offscreenTextureDesc.Height = backbufferHeight; + offscreenTextureDesc.Width = abs(backbufferWidth); + offscreenTextureDesc.Height = abs(backbufferHeight); offscreenTextureDesc.Format = backbufferFormatInfo.texFormat; offscreenTextureDesc.MipLevels = 1; offscreenTextureDesc.ArraySize = 1; @@ -234,8 +237,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei if (mDepthBufferFormat != GL_NONE) { D3D11_TEXTURE2D_DESC depthStencilTextureDesc; - depthStencilTextureDesc.Width = backbufferWidth; - depthStencilTextureDesc.Height = backbufferHeight; + depthStencilTextureDesc.Width = abs(backbufferWidth); + depthStencilTextureDesc.Height = abs(backbufferHeight); depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat; depthStencilTextureDesc.MipLevels = 1; depthStencilTextureDesc.ArraySize = 1; @@ -286,12 +289,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei mWidth = backbufferWidth; mHeight = backbufferHeight; -#if !defined(ANGLE_PLATFORM_WINRT) || WINAPI_FAMILY==WINAPI_FAMILY_PC_APP - mViewportWidth = backbufferWidth; - mViewportHeight = backbufferHeight; -#endif -#if !defined(ANGLE_PLATFORM_WINRT) +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) if (previousOffscreenTexture != NULL) { D3D11_BOX sourceBox = {0}; @@ -310,7 +309,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei if (mSwapChain) { - swapRect(0, 0, mWidth, mHeight, SWAP_NORMAL); + swapRect(0, 0, mWidth, mHeight); } } #endif @@ -327,8 +326,16 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) return EGL_BAD_ACCESS; } + // Windows Phone works around the rotation limitation by using negative values for the swap chain size +#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + mRotateL = backbufferWidth < 0; // Landscape/InvertedLandscape + mRotateR = backbufferHeight < 0; // InvertedPortrait/InvertedLandscape + backbufferWidth = abs(backbufferWidth); + backbufferHeight = abs(backbufferHeight); +#endif + // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains - if (backbufferWidth < 1 || backbufferHeight < 1) + if (backbufferWidth == 0 || backbufferHeight == 0) { return EGL_SUCCESS; } @@ -336,19 +343,15 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) // Can only call resize if we have already created our swap buffer and resources ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView); +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) // The swap chain is not directly resized on Windows Phone SafeRelease(mBackBufferTexture); SafeRelease(mBackBufferRTView); // Resize swap chain - HRESULT result; -#if !defined(ANGLE_PLATFORM_WINRT) || WINAPI_FAMILY==WINAPI_FAMILY_PC_APP // Windows phone swap chain is never resized, only the texture is -#if !defined(ANGLE_PLATFORM_WINRT) - const int bufferCount = 1; -#else - const int bufferCount = 2; -#endif + DXGI_SWAP_CHAIN_DESC desc; + mSwapChain->GetDesc(&desc); const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat); - result = mSwapChain->ResizeBuffers(bufferCount, backbufferWidth, backbufferHeight, backbufferFormatInfo.texFormat, 0); + HRESULT result = mSwapChain->ResizeBuffers(desc.BufferCount, backbufferWidth, backbufferHeight, backbufferFormatInfo.texFormat, 0); if (FAILED(result)) { @@ -364,7 +367,6 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) return EGL_BAD_ALLOC; } } -#endif result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); ASSERT(SUCCEEDED(result)); @@ -379,6 +381,7 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) { d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); } +#endif return resetOffscreenTexture(backbufferWidth, backbufferHeight); } @@ -412,62 +415,14 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap return EGL_SUCCESS; } - if (mWindow) + if (mNativeWindow.getNativeWindow()) { const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat); - IDXGIFactory *factory = mRenderer->getDxgiFactory(); + HRESULT result = mNativeWindow.createSwapChain(device, mRenderer->getDxgiFactory(), + backbufferFormatInfo.texFormat, + backbufferWidth, backbufferHeight, &mSwapChain); -#if !defined(ANGLE_PLATFORM_WINRT) - DXGI_SWAP_CHAIN_DESC swapChainDesc = {0}; - swapChainDesc.BufferDesc.Width = backbufferWidth; - swapChainDesc.BufferDesc.Height = backbufferHeight; - swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; - swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; - swapChainDesc.BufferDesc.Format = backbufferFormatInfo.texFormat; - swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; - swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; - swapChainDesc.SampleDesc.Count = 1; - swapChainDesc.SampleDesc.Quality = 0; - swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - swapChainDesc.BufferCount = 1; - swapChainDesc.OutputWindow = mWindow; - swapChainDesc.Windowed = TRUE; - swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - swapChainDesc.Flags = 0; - - HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain); -#else - IDXGIFactory2 *factory2; - HRESULT result = factory->QueryInterface(IID_PPV_ARGS(&factory2)); - ASSERT(SUCCEEDED(result)); - - DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; - swapChainDesc.Width = 0; - swapChainDesc.Height = 0; - swapChainDesc.Format = backbufferFormatInfo.texFormat; - swapChainDesc.SampleDesc.Count = 1; - swapChainDesc.SampleDesc.Quality = 0; - swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - swapChainDesc.Stereo = FALSE; - swapChainDesc.Flags = 0; -#if WINAPI_FAMILY==WINAPI_FAMILY_PC_APP - swapChainDesc.Scaling = DXGI_SCALING_NONE; - swapChainDesc.BufferCount = 2; - swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; -#elif WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP - swapChainDesc.BufferCount = 1; - swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; -#endif - - IDXGISwapChain1 *swapChain; - result = factory2->CreateSwapChainForCoreWindow(device, mWindow, &swapChainDesc, NULL, &swapChain); - mSwapChain = swapChain; - HRESULT hr = swapChain->GetDesc1(&swapChainDesc); - ASSERT(SUCCEEDED(hr)); - mViewportWidth = swapChainDesc.Width; - mViewportHeight = swapChainDesc.Height; -#endif if (FAILED(result)) { ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); @@ -537,7 +492,7 @@ void SwapChain11::initPassThroughResources() samplerDesc.BorderColor[2] = 0.0f; samplerDesc.BorderColor[3] = 0.0f; samplerDesc.MinLOD = 0; - samplerDesc.MaxLOD = FLT_MAX; + samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler); ASSERT(SUCCEEDED(result)); @@ -563,7 +518,7 @@ void SwapChain11::initPassThroughResources() } // parameters should be validated/clamped by caller -EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint flags) +EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) { if (!mSwapChain) { @@ -573,16 +528,6 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EG ID3D11Device *device = mRenderer->getDevice(); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - // Set vertices - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - return EGL_BAD_ACCESS; - } - - d3d11::PositionTexCoordVertex *vertices = static_cast(mappedResource.pData); - // Create a quad in homogeneous coordinates float x1 = (x / float(mWidth)) * 2.0f - 1.0f; float y1 = (y / float(mHeight)) * 2.0f - 1.0f; @@ -594,8 +539,18 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EG float u2 = (x + width) / float(mWidth); float v2 = (y + height) / float(mHeight); - const int rotateL = flags & SWAP_ROTATE_90; - const int rotateR = flags & SWAP_ROTATE_270; + const bool rotateL = mRotateL; + const bool rotateR = mRotateR; + + // Set vertices + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return EGL_BAD_ACCESS; + } + + d3d11::PositionTexCoordVertex *vertices = static_cast(mappedResource.pData); d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, rotateL ? u2 : u1, rotateR ? v2 : v1); d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, rotateR ? u2 : u1, rotateL ? v1 : v2); @@ -628,22 +583,23 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EG // Set the viewport D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - viewport.Width = mViewportWidth; - viewport.Height = mViewportHeight; + viewport.TopLeftX = 0.0f; + viewport.TopLeftY = 0.0f; + const bool invertViewport = (mRotateL || mRotateR) && !(mRotateL && mRotateR); + viewport.Width = FLOAT(invertViewport ? mHeight : mWidth); + viewport.Height = FLOAT(invertViewport ? mWidth : mHeight); viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; deviceContext->RSSetViewports(1, &viewport); // Apply textures - deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView); + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, mOffscreenSRView); deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler); // Draw deviceContext->Draw(4, 0); -#ifdef ANGLE_FORCE_VSYNC_OFF +#if ANGLE_VSYNC == ANGLE_DISABLED result = mSwapChain->Present(0, 0); #else result = mSwapChain->Present(mSwapInterval, 0); @@ -667,8 +623,7 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EG } // Unbind - static ID3D11ShaderResourceView *const nullSRV = NULL; - deviceContext->PSSetShaderResources(0, 1, &nullSRV); + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); mRenderer->unapplyRenderTargets(); mRenderer->markAllStateDirty(); @@ -708,8 +663,8 @@ ID3D11Texture2D *SwapChain11::getDepthStencilTexture() SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain) { - ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain11*, swapChain)); - return static_cast(swapChain); + ASSERT(HAS_DYNAMIC_TYPE(SwapChain11*, swapChain)); + return static_cast(swapChain); } void SwapChain11::recreate() diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h index b30b78568ae..77509edcd3c 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h @@ -19,13 +19,13 @@ class Renderer11; class SwapChain11 : public SwapChain { public: - SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle, + SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); virtual ~SwapChain11(); EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval); - virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint flags); + virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height); virtual void recreate(); virtual ID3D11Texture2D *getOffscreenTexture(); @@ -52,13 +52,13 @@ class SwapChain11 : public SwapChain Renderer11 *mRenderer; EGLint mHeight; EGLint mWidth; - EGLint mViewportWidth; - EGLint mViewportHeight; + bool mRotateL; + bool mRotateR; bool mAppCreatedShareHandle; unsigned int mSwapInterval; bool mPassThroughResourcesInit; - IDXGISwapChain *mSwapChain; + DXGISwapChain *mSwapChain; ID3D11Texture2D *mBackBufferTexture; ID3D11RenderTargetView *mBackBufferRTView; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp index 91e7147da66..74af27e8b32 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp @@ -8,6 +8,9 @@ // classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. #include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h" + +#include + #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" #include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" #include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h" @@ -15,6 +18,7 @@ #include "libGLESv2/renderer/d3d/d3d11/Blit11.h" #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" #include "libGLESv2/renderer/d3d/d3d11/Image11.h" +#include "libGLESv2/renderer/d3d/MemoryBuffer.h" #include "libGLESv2/renderer/d3d/TextureD3D.h" #include "libGLESv2/main.h" #include "libGLESv2/ImageIndex.h" @@ -52,46 +56,16 @@ TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle) { } -bool TextureStorage11::SRVKey::operator==(const SRVKey &rhs) const +bool TextureStorage11::SRVKey::operator<(const SRVKey &rhs) const { - return baseLevel == rhs.baseLevel && - mipLevels == rhs.mipLevels && - swizzle == rhs.swizzle; + return std::tie(baseLevel, mipLevels, swizzle) < std::tie(rhs.baseLevel, rhs.mipLevels, rhs.swizzle); } -TextureStorage11::SRVCache::~SRVCache() -{ - for (size_t i = 0; i < cache.size(); i++) - { - SafeRelease(cache[i].srv); - } -} - -ID3D11ShaderResourceView *TextureStorage11::SRVCache::find(const SRVKey &key) const -{ - for (size_t i = 0; i < cache.size(); i++) - { - if (cache[i].key == key) - { - return cache[i].srv; - } - } - - return NULL; -} - -ID3D11ShaderResourceView *TextureStorage11::SRVCache::add(const SRVKey &key, ID3D11ShaderResourceView *srv) -{ - SRVPair pair = {key, srv}; - cache.push_back(pair); - - return srv; -} - -TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags) +TextureStorage11::TextureStorage11(Renderer11 *renderer, UINT bindFlags) : mBindFlags(bindFlags), mTopLevel(0), mMipLevels(0), + mInternalFormat(GL_NONE), mTextureFormat(DXGI_FORMAT_UNKNOWN), mShaderResourceFormat(DXGI_FORMAT_UNKNOWN), mRenderTargetFormat(DXGI_FORMAT_UNKNOWN), @@ -114,6 +88,12 @@ TextureStorage11::~TextureStorage11() { SafeRelease(mLevelSRVs[level]); } + + for (SRVCache::iterator i = mSrvCache.begin(); i != mSrvCache.end(); i++) + { + SafeRelease(i->second); + } + mSrvCache.clear(); } TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage) @@ -183,17 +163,16 @@ int TextureStorage11::getLevelDepth(int mipLevel) const return std::max(static_cast(mTextureDepth) >> mipLevel, 1); } -UINT TextureStorage11::getSubresourceIndex(int mipLevel, int layerTarget) const +UINT TextureStorage11::getSubresourceIndex(const gl::ImageIndex &index) const { - UINT index = 0; - if (getResource()) - { - index = D3D11CalcSubresource(mipLevel, layerTarget, mMipLevels); - } - return index; + UINT mipSlice = static_cast(index.mipIndex + mTopLevel); + UINT arraySlice = static_cast(index.hasLayer() ? index.layerIndex : 0); + UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels); + ASSERT(subresource != std::numeric_limits::max()); + return subresource; } -ID3D11ShaderResourceView *TextureStorage11::getSRV(const gl::SamplerState &samplerState) +gl::Error TextureStorage11::getSRV(const gl::SamplerState &samplerState, ID3D11ShaderResourceView **outSRV) { bool swizzleRequired = samplerState.swizzleRequired(); bool mipmapping = gl::IsMipmapFiltered(samplerState); @@ -206,38 +185,71 @@ ID3D11ShaderResourceView *TextureStorage11::getSRV(const gl::SamplerState &sampl { verifySwizzleExists(samplerState.swizzleRed, samplerState.swizzleGreen, samplerState.swizzleBlue, samplerState.swizzleAlpha); } - + SRVKey key(samplerState.baseLevel, mipLevels, swizzleRequired); - ID3D11ShaderResourceView *srv = srvCache.find(key); - - if(srv) + SRVCache::const_iterator iter = mSrvCache.find(key); + if (iter != mSrvCache.end()) { - return srv; - } - - DXGI_FORMAT format = (swizzleRequired ? mSwizzleShaderResourceFormat : mShaderResourceFormat); - ID3D11Resource *texture = swizzleRequired ? getSwizzleTexture() : getResource(); - - srv = createSRV(samplerState.baseLevel, mipLevels, format, texture); - - return srvCache.add(key, srv); -} - -ID3D11ShaderResourceView *TextureStorage11::getSRVLevel(int mipLevel) -{ - if (mipLevel >= 0 && mipLevel < getLevelCount()) - { - if (!mLevelSRVs[mipLevel]) - { - mLevelSRVs[mipLevel] = createSRV(mipLevel, 1, mShaderResourceFormat, getResource()); - } - - return mLevelSRVs[mipLevel]; + *outSRV = iter->second; } else { - return NULL; + ID3D11Resource *texture = NULL; + if (swizzleRequired) + { + gl::Error error = getSwizzleTexture(&texture); + if (error.isError()) + { + return error; + } + } + else + { + gl::Error error = getResource(&texture); + if (error.isError()) + { + return error; + } + } + + ID3D11ShaderResourceView *srv = NULL; + DXGI_FORMAT format = (swizzleRequired ? mSwizzleShaderResourceFormat : mShaderResourceFormat); + gl::Error error = createSRV(samplerState.baseLevel, mipLevels, format, texture, &srv); + if (error.isError()) + { + return error; + } + + mSrvCache.insert(std::make_pair(key, srv)); + *outSRV = srv; } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11::getSRVLevel(int mipLevel, ID3D11ShaderResourceView **outSRV) +{ + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); + + if (!mLevelSRVs[mipLevel]) + { + ID3D11Resource *resource = NULL; + gl::Error error = getResource(&resource); + if (error.isError()) + { + return error; + } + + error = createSRV(mipLevel, 1, mShaderResourceFormat, resource, &mLevelSRVs[mipLevel]); + if (error.isError()) + { + return error; + } + } + + *outSRV = mLevelSRVs[mipLevel]; + + return gl::Error(GL_NO_ERROR); } gl::Error TextureStorage11::generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) @@ -249,14 +261,25 @@ gl::Error TextureStorage11::generateSwizzles(GLenum swizzleRed, GLenum swizzleGr if (mSwizzleCache[level] != swizzleTarget) { // Need to re-render the swizzle for this level - ID3D11ShaderResourceView *sourceSRV = getSRVLevel(level); - ID3D11RenderTargetView *destRTV = getSwizzleRenderTarget(level); + ID3D11ShaderResourceView *sourceSRV = NULL; + gl::Error error = getSRVLevel(level, &sourceSRV); + if (error.isError()) + { + return error; + } + + ID3D11RenderTargetView *destRTV = NULL; + error = getSwizzleRenderTarget(level, &destRTV); + if (error.isError()) + { + return error; + } gl::Extents size(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level)); Blit11 *blitter = mRenderer->getBlitter(); - gl::Error error = blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); + error = blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); if (error.isError()) { return error; @@ -287,104 +310,120 @@ void TextureStorage11::invalidateSwizzleCache() } } -bool TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsigned int sourceSubresource, - int level, int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth) +gl::Error TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsigned int sourceSubresource, + const gl::ImageIndex &index, const gl::Box ©Area) { - if (srcTexture) + ASSERT(srcTexture); + + GLint level = index.mipIndex; + + invalidateSwizzleCacheLevel(level); + + gl::Extents texSize(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level)); + + bool fullCopy = copyArea.x == 0 && + copyArea.y == 0 && + copyArea.z == 0 && + copyArea.width == texSize.width && + copyArea.height == texSize.height && + copyArea.depth == texSize.depth; + + ID3D11Resource *dstTexture = NULL; + gl::Error error = getResource(&dstTexture); + if (error.isError()) { - invalidateSwizzleCacheLevel(level); - - gl::Extents texSize(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level)); - gl::Box copyArea(xoffset, yoffset, zoffset, width, height, depth); - - bool fullCopy = copyArea.x == 0 && - copyArea.y == 0 && - copyArea.z == 0 && - copyArea.width == texSize.width && - copyArea.height == texSize.height && - copyArea.depth == texSize.depth; - - ID3D11Resource *dstTexture = getResource(); - unsigned int dstSubresource = getSubresourceIndex(level + mTopLevel, layerTarget); - - ASSERT(dstTexture); - - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); - if (!fullCopy && (dxgiFormatInfo.depthBits > 0 || dxgiFormatInfo.stencilBits > 0)) - { - // CopySubresourceRegion cannot copy partial depth stencils, use the blitter instead - Blit11 *blitter = mRenderer->getBlitter(); - - return blitter->copyDepthStencil(srcTexture, sourceSubresource, copyArea, texSize, - dstTexture, dstSubresource, copyArea, texSize, - NULL); - } - else - { - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); - - D3D11_BOX srcBox; - srcBox.left = copyArea.x; - srcBox.top = copyArea.y; - srcBox.right = copyArea.x + roundUp((unsigned int)width, dxgiFormatInfo.blockWidth); - srcBox.bottom = copyArea.y + roundUp((unsigned int)height, dxgiFormatInfo.blockHeight); - srcBox.front = copyArea.z; - srcBox.back = copyArea.z + copyArea.depth; - - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - - context->CopySubresourceRegion(dstTexture, dstSubresource, copyArea.x, copyArea.y, copyArea.z, - srcTexture, sourceSubresource, fullCopy ? NULL : &srcBox); - return true; - } + return error; } - return false; -} + unsigned int dstSubresource = getSubresourceIndex(index); -bool TextureStorage11::copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource, - int level, int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth) -{ - if (dstTexture) + ASSERT(dstTexture); + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); + if (!fullCopy && (dxgiFormatInfo.depthBits > 0 || dxgiFormatInfo.stencilBits > 0)) { - ID3D11Resource *srcTexture = getResource(); - unsigned int srcSubresource = getSubresourceIndex(level + mTopLevel, layerTarget); + // CopySubresourceRegion cannot copy partial depth stencils, use the blitter instead + Blit11 *blitter = mRenderer->getBlitter(); - ASSERT(srcTexture); + return blitter->copyDepthStencil(srcTexture, sourceSubresource, copyArea, texSize, + dstTexture, dstSubresource, copyArea, texSize, + NULL); + } + else + { + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); + + D3D11_BOX srcBox; + srcBox.left = copyArea.x; + srcBox.top = copyArea.y; + srcBox.right = copyArea.x + roundUp(static_cast(copyArea.width), dxgiFormatInfo.blockWidth); + srcBox.bottom = copyArea.y + roundUp(static_cast(copyArea.height), dxgiFormatInfo.blockHeight); + srcBox.front = copyArea.z; + srcBox.back = copyArea.z + copyArea.depth; ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - context->CopySubresourceRegion(dstTexture, dstSubresource, xoffset, yoffset, zoffset, - srcTexture, srcSubresource, NULL); - return true; + context->CopySubresourceRegion(dstTexture, dstSubresource, copyArea.x, copyArea.y, copyArea.z, + srcTexture, sourceSubresource, fullCopy ? NULL : &srcBox); + return gl::Error(GL_NO_ERROR); } - - return false; } -void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest) +gl::Error TextureStorage11::copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource, + const gl::ImageIndex &index, const gl::Box ®ion) { - if (source && dest) + ASSERT(dstTexture); + + ID3D11Resource *srcTexture = NULL; + gl::Error error = getResource(&srcTexture); + if (error.isError()) { - ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView(); - ID3D11RenderTargetView *destRTV = dest->getRenderTargetView(); - - if (sourceSRV && destRTV) - { - gl::Box sourceArea(0, 0, 0, source->getWidth(), source->getHeight(), source->getDepth()); - gl::Extents sourceSize(source->getWidth(), source->getHeight(), source->getDepth()); - - gl::Box destArea(0, 0, 0, dest->getWidth(), dest->getHeight(), dest->getDepth()); - gl::Extents destSize(dest->getWidth(), dest->getHeight(), dest->getDepth()); - - Blit11 *blitter = mRenderer->getBlitter(); - - blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, NULL, - gl::GetInternalFormatInfo(source->getInternalFormat()).format, GL_LINEAR); - } + return error; } + + ASSERT(srcTexture); + + unsigned int srcSubresource = getSubresourceIndex(index); + + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + context->CopySubresourceRegion(dstTexture, dstSubresource, region.x, region.y, region.z, + srcTexture, srcSubresource, NULL); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) +{ + ASSERT(sourceIndex.layerIndex == destIndex.layerIndex); + + invalidateSwizzleCacheLevel(destIndex.mipIndex); + + RenderTarget *source = NULL; + gl::Error error = getRenderTarget(sourceIndex, &source); + if (error.isError()) + { + return error; + } + + RenderTarget *dest = NULL; + error = getRenderTarget(destIndex, &dest); + if (error.isError()) + { + return error; + } + + ID3D11ShaderResourceView *sourceSRV = RenderTarget11::makeRenderTarget11(source)->getShaderResourceView(); + ID3D11RenderTargetView *destRTV = RenderTarget11::makeRenderTarget11(dest)->getRenderTargetView(); + + gl::Box sourceArea(0, 0, 0, source->getWidth(), source->getHeight(), source->getDepth()); + gl::Extents sourceSize(source->getWidth(), source->getHeight(), source->getDepth()); + + gl::Box destArea(0, 0, 0, dest->getWidth(), dest->getHeight(), dest->getDepth()); + gl::Extents destSize(dest->getWidth(), dest->getHeight(), dest->getDepth()); + + Blit11 *blitter = mRenderer->getBlitter(); + return blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, NULL, + gl::GetInternalFormatInfo(source->getInternalFormat()).format, GL_LINEAR); } void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) @@ -396,7 +435,112 @@ void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGree } } -TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain) +gl::Error TextureStorage11::copyToStorage(TextureStorage *destStorage) +{ + ASSERT(destStorage); + + ID3D11Resource *sourceResouce = NULL; + gl::Error error = getResource(&sourceResouce); + if (error.isError()) + { + return error; + } + + TextureStorage11 *dest11 = TextureStorage11::makeTextureStorage11(destStorage); + ID3D11Resource *destResource = NULL; + error = dest11->getResource(&destResource); + if (error.isError()) + { + return error; + } + + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + immediateContext->CopyResource(destResource, sourceResouce); + + dest11->invalidateSwizzleCache(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11::setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixelData) +{ + ID3D11Resource *resource = NULL; + gl::Error error = getResource(&resource); + if (error.isError()) + { + return error; + } + ASSERT(resource); + + UINT destSubresource = getSubresourceIndex(index); + + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(image->getInternalFormat()); + + bool fullUpdate = (destBox == NULL || *destBox == gl::Box(0, 0, 0, mTextureWidth, mTextureHeight, mTextureDepth)); + ASSERT(internalFormatInfo.depthBits == 0 || fullUpdate); + + // TODO(jmadill): Handle compressed formats + // Compressed formats have different load syntax, so we'll have to handle them with slightly + // different logic. Will implemnent this in a follow-up patch, and ensure we do not use SetData + // with compressed formats in the calling logic. + ASSERT(!internalFormatInfo.compressed); + + int width = destBox ? destBox->width : static_cast(image->getWidth()); + int height = destBox ? destBox->height : static_cast(image->getHeight()); + int depth = destBox ? destBox->depth : static_cast(image->getDepth()); + UINT srcRowPitch = internalFormatInfo.computeRowPitch(type, width, unpack.alignment); + UINT srcDepthPitch = internalFormatInfo.computeDepthPitch(type, width, height, unpack.alignment); + + const d3d11::TextureFormat &d3d11Format = d3d11::GetTextureFormatInfo(image->getInternalFormat()); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11Format.texFormat); + + size_t outputPixelSize = dxgiFormatInfo.pixelBytes; + + UINT bufferRowPitch = outputPixelSize * width; + UINT bufferDepthPitch = bufferRowPitch * height; + + MemoryBuffer conversionBuffer; + if (!conversionBuffer.resize(bufferDepthPitch * depth)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal buffer."); + } + + // TODO: fast path + LoadImageFunction loadFunction = d3d11Format.loadFunctions.at(type); + loadFunction(width, height, depth, + pixelData, srcRowPitch, srcDepthPitch, + conversionBuffer.data(), bufferRowPitch, bufferDepthPitch); + + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + + if (!fullUpdate) + { + ASSERT(destBox); + + D3D11_BOX destD3DBox; + destD3DBox.left = destBox->x; + destD3DBox.right = destBox->x + destBox->width; + destD3DBox.top = destBox->y; + destD3DBox.bottom = destBox->y + destBox->height; + destD3DBox.front = 0; + destD3DBox.back = 1; + + immediateContext->UpdateSubresource(resource, destSubresource, + &destD3DBox, conversionBuffer.data(), + bufferRowPitch, bufferDepthPitch); + } + else + { + immediateContext->UpdateSubresource(resource, destSubresource, + NULL, conversionBuffer.data(), + bufferRowPitch, bufferDepthPitch); + } + + return gl::Error(GL_NO_ERROR); +} + +TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain) : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE), mTexture(swapchain->getOffscreenTexture()), mSwizzleTexture(NULL) @@ -418,6 +562,8 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapch mTextureHeight = texDesc.Height; mTextureDepth = 1; + mInternalFormat = swapchain->GetBackBufferInternalFormat(); + ID3D11ShaderResourceView *srv = swapchain->getRenderTargetShaderResource(); D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; srv->GetDesc(&srvDesc); @@ -439,7 +585,7 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapch initializeSerials(1, 1); } -TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) +TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)), mTexture(NULL), mSwizzleTexture(NULL) @@ -451,6 +597,8 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalform mSwizzleRenderTargets[i] = NULL; } + mInternalFormat = internalformat; + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); mTextureFormat = formatInfo.texFormat; mShaderResourceFormat = formatInfo.srvFormat; @@ -460,51 +608,11 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalform mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; - // if the width or height is not positive this should be treated as an incomplete texture - // we handle that here by skipping the d3d texture creation - if (width > 0 && height > 0) - { - // adjust size if needed for compressed textures - d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); - - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_TEXTURE2D_DESC desc; - desc.Width = width; // Compressed texture size constraints? - desc.Height = height; - desc.MipLevels = desc.MipLevels = mRenderer->isLevel9() ? 1 : ((levels > 0) ? (mTopLevel + levels) : 0); - desc.ArraySize = 1; - desc.Format = mTextureFormat; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = getBindFlags(); - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - - HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); - - // this can happen from windows TDR - if (d3d11::isDeviceLostError(result)) - { - mRenderer->notifyDeviceLost(); - gl::error(GL_OUT_OF_MEMORY); - } - else if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - ERR("Creating image failed."); - gl::error(GL_OUT_OF_MEMORY); - } - else - { - mTexture->GetDesc(&desc); - mMipLevels = desc.MipLevels; - mTextureWidth = desc.Width; - mTextureHeight = desc.Height; - mTextureDepth = 1; - } - } + d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); + mMipLevels = mTopLevel + levels; + mTextureWidth = width; + mTextureHeight = height; + mTextureDepth = 1; initializeSerials(getLevelCount(), 1); } @@ -521,7 +629,11 @@ TextureStorage11_2D::~TextureStorage11_2D() if (imageAssociationCorrect) { // We must let the Images recover their data before we delete it from the TextureStorage. - mAssociatedImages[i]->recoverFromAssociatedStorage(); + gl::Error error = mAssociatedImages[i]->recoverFromAssociatedStorage(); + if (error.isError()) + { + // TODO: Find a way to report this back to the context + } } } } @@ -542,8 +654,10 @@ TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage return static_cast(storage); } -void TextureStorage11_2D::associateImage(Image11* image, int level, int layerTarget) +void TextureStorage11_2D::associateImage(Image11* image, const gl::ImageIndex &index) { + GLint level = index.mipIndex; + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) @@ -552,8 +666,10 @@ void TextureStorage11_2D::associateImage(Image11* image, int level, int layerTar } } -bool TextureStorage11_2D::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage) +bool TextureStorage11_2D::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) { + GLint level = index.mipIndex; + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) { // This validation check should never return false. It means the Image/TextureStorage association is broken. @@ -566,8 +682,10 @@ bool TextureStorage11_2D::isAssociatedImageValid(int level, int layerTarget, Ima } // disassociateImage allows an Image to end its association with a Storage. -void TextureStorage11_2D::disassociateImage(int level, int layerTarget, Image11* expectedImage) +void TextureStorage11_2D::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) { + GLint level = index.mipIndex; + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) @@ -582,8 +700,10 @@ void TextureStorage11_2D::disassociateImage(int level, int layerTarget, Image11* } // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. -void TextureStorage11_2D::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage) +gl::Error TextureStorage11_2D::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) { + GLint level = index.mipIndex; + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) @@ -599,137 +719,168 @@ void TextureStorage11_2D::releaseAssociatedImage(int level, int layerTarget, Ima { // Force the image to recover from storage before its data is overwritten. // This will reset mAssociatedImages[level] to NULL too. - mAssociatedImages[level]->recoverFromAssociatedStorage(); + gl::Error error = mAssociatedImages[level]->recoverFromAssociatedStorage(); + if (error.isError()) + { + return error; + } } } } + + return gl::Error(GL_NO_ERROR); } -ID3D11Resource *TextureStorage11_2D::getResource() const +gl::Error TextureStorage11_2D::getResource(ID3D11Resource **outResource) { - return mTexture; + // if the width or height is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0) + { + ASSERT(mMipLevels > 0); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; // Compressed texture size constraints? + desc.Height = mTextureHeight; + desc.MipLevels = mRenderer->isLevel9() ? 1 : mMipLevels; + desc.ArraySize = 1; + desc.Format = mTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); + + // this can happen from windows TDR + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D texture storage, result: 0x%X.", result); + } + else if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D texture storage, result: 0x%X.", result); + } + } + + *outResource = mTexture; + return gl::Error(GL_NO_ERROR); } -RenderTarget *TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index) +gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) { ASSERT(!index.hasLayer()); int level = index.mipIndex; + ASSERT(level >= 0 && level < getLevelCount()); - if (level >= 0 && level < getLevelCount()) + if (!mRenderTarget[level]) { - if (!mRenderTarget[level]) + ID3D11Resource *texture = NULL; + gl::Error error = getResource(&texture); + if (error.isError()) { - ID3D11ShaderResourceView *srv = getSRVLevel(level); - if (!srv) - { - return NULL; - } - - if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) - { - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - rtvDesc.Texture2D.MipSlice = mTopLevel + level; - - ID3D11RenderTargetView *rtv; - HRESULT result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); - - if (result == E_OUTOFMEMORY) - { - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - - mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1); - - // RenderTarget will take ownership of these resources - SafeRelease(rtv); - } - else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) - { - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = mDepthStencilFormat; - dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; - dsvDesc.Texture2D.MipSlice = mTopLevel + level; - dsvDesc.Flags = 0; - - ID3D11DepthStencilView *dsv; - HRESULT result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv); - - if (result == E_OUTOFMEMORY) - { - SafeRelease(srv); - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - - mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1); - - // RenderTarget will take ownership of these resources - SafeRelease(dsv); - } - else - { - UNREACHABLE(); - } + return error; } - return mRenderTarget[level]; - } - else - { - return NULL; + ID3D11ShaderResourceView *srv = NULL; + error = getSRVLevel(level, &srv); + if (error.isError()) + { + return error; + } + + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = mTopLevel + level; + + ID3D11RenderTargetView *rtv; + HRESULT result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); + } + + mRenderTarget[level] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + } + else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = mDepthStencilFormat; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + dsvDesc.Texture2D.MipSlice = mTopLevel + level; + dsvDesc.Flags = 0; + + ID3D11DepthStencilView *dsv; + HRESULT result = device->CreateDepthStencilView(texture, &dsvDesc, &dsv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY,"Failed to create internal depth stencil view for texture storage, result: 0x%X.", result); + } + + mRenderTarget[level] = new TextureRenderTarget11(dsv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(dsv); + } + else + { + UNREACHABLE(); + } } + + ASSERT(outRT); + *outRT = mRenderTarget[level]; + return gl::Error(GL_NO_ERROR); } -ID3D11ShaderResourceView *TextureStorage11_2D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture) +gl::Error TextureStorage11_2D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const { + ASSERT(outSRV); + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; srvDesc.Format = format; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel; - srvDesc.Texture2D.MipLevels = mipLevels; - - ID3D11ShaderResourceView *SRV = NULL; + srvDesc.Texture2D.MipLevels = mRenderer->isLevel9() ? -1 : mipLevels; ID3D11Device *device = mRenderer->getDevice(); - HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV); + HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV); - if (result == E_OUTOFMEMORY) + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) { - gl::error(GL_OUT_OF_MEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result); } - ASSERT(SUCCEEDED(result)); - return SRV; + return gl::Error(GL_NO_ERROR); } -void TextureStorage11_2D::generateMipmaps() +gl::Error TextureStorage11_2D::getSwizzleTexture(ID3D11Resource **outTexture) { - // Base level must already be defined + ASSERT(outTexture); - for (int level = 1; level < getLevelCount(); level++) - { - invalidateSwizzleCacheLevel(level); - - gl::ImageIndex srcIndex = gl::ImageIndex::Make2D(level - 1); - gl::ImageIndex destIndex = gl::ImageIndex::Make2D(level); - - RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(srcIndex)); - RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex)); - - generateMipmapLayer(source, dest); - } -} - -ID3D11Resource *TextureStorage11_2D::getSwizzleTexture() -{ if (!mSwizzleTexture) { ID3D11Device *device = mRenderer->getDevice(); @@ -749,52 +900,52 @@ ID3D11Resource *TextureStorage11_2D::getSwizzleTexture() HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture); - if (result == E_OUTOFMEMORY) + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) { - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result); } - ASSERT(SUCCEEDED(result)); } - return mSwizzleTexture; + *outTexture = mSwizzleTexture; + return gl::Error(GL_NO_ERROR); } -ID3D11RenderTargetView *TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel) +gl::Error TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) { - if (mipLevel >= 0 && mipLevel < getLevelCount()) + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); + ASSERT(outRTV); + + if (!mSwizzleRenderTargets[mipLevel]) { - if (!mSwizzleRenderTargets[mipLevel]) + ID3D11Resource *swizzleTexture = NULL; + gl::Error error = getSwizzleTexture(&swizzleTexture); + if (error.isError()) { - ID3D11Resource *swizzleTexture = getSwizzleTexture(); - if (!swizzleTexture) - { - return NULL; - } - - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mSwizzleRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel; - - HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); - if (result == E_OUTOFMEMORY) - { - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); + return error; } - return mSwizzleRenderTargets[mipLevel]; - } - else - { - return NULL; + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mSwizzleRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel; + + HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle render target view, result: 0x%X.", result); + } } + + *outRTV = mSwizzleRenderTargets[mipLevel]; + return gl::Error(GL_NO_ERROR); } -TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels) +TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels) : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) { mTexture = NULL; @@ -803,13 +954,15 @@ TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internal for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) { mSwizzleRenderTargets[level] = NULL; - for (unsigned int face = 0; face < 6; face++) + for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) { mAssociatedImages[face][level] = NULL; mRenderTarget[face][level] = NULL; } } + mInternalFormat = internalformat; + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); mTextureFormat = formatInfo.texFormat; mShaderResourceFormat = formatInfo.srvFormat; @@ -819,56 +972,23 @@ TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internal mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; - // if the size is not positive this should be treated as an incomplete texture - // we handle that here by skipping the d3d texture creation - if (size > 0) - { - // adjust size if needed for compressed textures - int height = size; - d3d11::MakeValidSize(false, mTextureFormat, &size, &height, &mTopLevel); + // adjust size if needed for compressed textures + int height = size; + d3d11::MakeValidSize(false, mTextureFormat, &size, &height, &mTopLevel); - ID3D11Device *device = mRenderer->getDevice(); + mMipLevels = mTopLevel + levels; + mTextureWidth = size; + mTextureHeight = size; + mTextureDepth = 1; - D3D11_TEXTURE2D_DESC desc; - desc.Width = size; - desc.Height = size; - desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0); - desc.ArraySize = 6; - desc.Format = mTextureFormat; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = getBindFlags(); - desc.CPUAccessFlags = 0; - desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; - - HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); - - if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - ERR("Creating image failed."); - gl::error(GL_OUT_OF_MEMORY); - } - else - { - mTexture->GetDesc(&desc); - mMipLevels = desc.MipLevels; - mTextureWidth = desc.Width; - mTextureHeight = desc.Height; - mTextureDepth = 1; - } - } - - initializeSerials(getLevelCount() * 6, 6); + initializeSerials(getLevelCount() * CUBE_FACE_COUNT, CUBE_FACE_COUNT); } - TextureStorage11_Cube::~TextureStorage11_Cube() { for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) { - for (unsigned int face = 0; face < 6; face++) + for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) { if (mAssociatedImages[face][level] != NULL) { @@ -890,7 +1010,7 @@ TextureStorage11_Cube::~TextureStorage11_Cube() for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) { SafeRelease(mSwizzleRenderTargets[level]); - for (unsigned int face = 0; face < 6; face++) + for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) { SafeDelete(mRenderTarget[face][level]); } @@ -903,25 +1023,31 @@ TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureS return static_cast(storage); } -void TextureStorage11_Cube::associateImage(Image11* image, int level, int layerTarget) +void TextureStorage11_Cube::associateImage(Image11* image, const gl::ImageIndex &index) { + GLint level = index.mipIndex; + GLint layerTarget = index.layerIndex; + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(0 <= layerTarget && layerTarget < 6); + ASSERT(0 <= layerTarget && layerTarget < CUBE_FACE_COUNT); if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) { - if (0 <= layerTarget && layerTarget < 6) + if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT) { mAssociatedImages[layerTarget][level] = image; } } } -bool TextureStorage11_Cube::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage) +bool TextureStorage11_Cube::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) { + GLint level = index.mipIndex; + GLint layerTarget = index.layerIndex; + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) { - if (0 <= layerTarget && layerTarget < 6) + if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT) { // This validation check should never return false. It means the Image/TextureStorage association is broken. bool retValue = (mAssociatedImages[layerTarget][level] == expectedImage); @@ -934,14 +1060,17 @@ bool TextureStorage11_Cube::isAssociatedImageValid(int level, int layerTarget, I } // disassociateImage allows an Image to end its association with a Storage. -void TextureStorage11_Cube::disassociateImage(int level, int layerTarget, Image11* expectedImage) +void TextureStorage11_Cube::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) { + GLint level = index.mipIndex; + GLint layerTarget = index.layerIndex; + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(0 <= layerTarget && layerTarget < 6); + ASSERT(0 <= layerTarget && layerTarget < CUBE_FACE_COUNT); if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) { - if (0 <= layerTarget && layerTarget < 6) + if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT) { ASSERT(mAssociatedImages[layerTarget][level] == expectedImage); @@ -954,14 +1083,17 @@ void TextureStorage11_Cube::disassociateImage(int level, int layerTarget, Image1 } // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. -void TextureStorage11_Cube::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage) +gl::Error TextureStorage11_Cube::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) { + GLint level = index.mipIndex; + GLint layerTarget = index.layerIndex; + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(0 <= layerTarget && layerTarget < 6); + ASSERT(0 <= layerTarget && layerTarget < CUBE_FACE_COUNT); if ((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)) { - if (0 <= layerTarget && layerTarget < 6) + if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT) { // No need to let the old Image recover its data, if it is also the incoming Image. if (mAssociatedImages[layerTarget][level] != NULL && mAssociatedImages[layerTarget][level] != incomingImage) @@ -974,114 +1106,165 @@ void TextureStorage11_Cube::releaseAssociatedImage(int level, int layerTarget, I { // Force the image to recover from storage before its data is overwritten. // This will reset mAssociatedImages[level] to NULL too. - mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage(); + gl::Error error = mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage(); + if (error.isError()) + { + return error; + } } } } } + + return gl::Error(GL_NO_ERROR); } -ID3D11Resource *TextureStorage11_Cube::getResource() const +gl::Error TextureStorage11_Cube::getResource(ID3D11Resource **outResource) { - return mTexture; + // if the size is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0) + { + ASSERT(mMipLevels > 0); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = CUBE_FACE_COUNT; + desc.Format = mTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); + + // this can happen from windows TDR + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube texture storage, result: 0x%X.", result); + } + else if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube texture storage, result: 0x%X.", result); + } + } + + *outResource = mTexture; + return gl::Error(GL_NO_ERROR); } -RenderTarget *TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index) +gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) { int faceIndex = index.layerIndex; int level = index.mipIndex; - if (level >= 0 && level < getLevelCount()) + ASSERT(level >= 0 && level < getLevelCount()); + ASSERT(faceIndex >= 0 && faceIndex < CUBE_FACE_COUNT); + + if (!mRenderTarget[faceIndex][level]) { - if (!mRenderTarget[faceIndex][level]) + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + ID3D11Resource *texture = NULL; + gl::Error error = getResource(&texture); + if (error.isError()) { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = mShaderResourceFormat; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube - srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level; - srvDesc.Texture2DArray.MipLevels = 1; - srvDesc.Texture2DArray.FirstArraySlice = faceIndex; - srvDesc.Texture2DArray.ArraySize = 1; - - ID3D11ShaderResourceView *srv; - result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); - - if (result == E_OUTOFMEMORY) - { - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - - if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) - { - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.MipSlice = mTopLevel + level; - rtvDesc.Texture2DArray.FirstArraySlice = faceIndex; - rtvDesc.Texture2DArray.ArraySize = 1; - - ID3D11RenderTargetView *rtv; - result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); - - if (result == E_OUTOFMEMORY) - { - SafeRelease(srv); - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - - mRenderTarget[faceIndex][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1); - - // RenderTarget will take ownership of these resources - SafeRelease(rtv); - SafeRelease(srv); - } - else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) - { - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = mDepthStencilFormat; - dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; - dsvDesc.Flags = 0; - dsvDesc.Texture2DArray.MipSlice = mTopLevel + level; - dsvDesc.Texture2DArray.FirstArraySlice = faceIndex; - dsvDesc.Texture2DArray.ArraySize = 1; - - ID3D11DepthStencilView *dsv; - result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv); - - if (result == E_OUTOFMEMORY) - { - SafeRelease(srv); - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - - mRenderTarget[faceIndex][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1); - - // RenderTarget will take ownership of these resources - SafeRelease(dsv); - SafeRelease(srv); - } - else - { - UNREACHABLE(); - } + return error; } - return mRenderTarget[faceIndex][level]; - } - else - { - return NULL; + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = mShaderResourceFormat; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube + srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level; + srvDesc.Texture2DArray.MipLevels = 1; + srvDesc.Texture2DArray.FirstArraySlice = faceIndex; + srvDesc.Texture2DArray.ArraySize = 1; + + ID3D11ShaderResourceView *srv; + result = device->CreateShaderResourceView(texture, &srvDesc, &srv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal shader resource view for texture storage, result: 0x%X.", result); + } + + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + level; + rtvDesc.Texture2DArray.FirstArraySlice = faceIndex; + rtvDesc.Texture2DArray.ArraySize = 1; + + ID3D11RenderTargetView *rtv; + result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + SafeRelease(srv); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); + } + + mRenderTarget[faceIndex][level] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + SafeRelease(srv); + } + else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = mDepthStencilFormat; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; + dsvDesc.Flags = 0; + dsvDesc.Texture2DArray.MipSlice = mTopLevel + level; + dsvDesc.Texture2DArray.FirstArraySlice = faceIndex; + dsvDesc.Texture2DArray.ArraySize = 1; + + ID3D11DepthStencilView *dsv; + result = device->CreateDepthStencilView(texture, &dsvDesc, &dsv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + SafeRelease(srv); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal depth stencil view for texture storage, result: 0x%X.", result); + } + + mRenderTarget[faceIndex][level] = new TextureRenderTarget11(dsv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(dsv); + SafeRelease(srv); + } + else + { + UNREACHABLE(); + } } + + ASSERT(outRT); + *outRT = mRenderTarget[faceIndex][level]; + return gl::Error(GL_NO_ERROR); } -ID3D11ShaderResourceView *TextureStorage11_Cube::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture) +gl::Error TextureStorage11_Cube::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const { + ASSERT(outSRV); + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; srvDesc.Format = format; @@ -1093,7 +1276,7 @@ ID3D11ShaderResourceView *TextureStorage11_Cube::createSRV(int baseLevel, int mi srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel; srvDesc.Texture2DArray.MipLevels = 1; srvDesc.Texture2DArray.FirstArraySlice = 0; - srvDesc.Texture2DArray.ArraySize = 6; + srvDesc.Texture2DArray.ArraySize = CUBE_FACE_COUNT; } else { @@ -1102,43 +1285,22 @@ ID3D11ShaderResourceView *TextureStorage11_Cube::createSRV(int baseLevel, int mi srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel; } - ID3D11ShaderResourceView *SRV = NULL; - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV); + HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV); - if (result == E_OUTOFMEMORY) + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) { - gl::error(GL_OUT_OF_MEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result); } - ASSERT(SUCCEEDED(result)); - return SRV; + return gl::Error(GL_NO_ERROR); } -void TextureStorage11_Cube::generateMipmaps() +gl::Error TextureStorage11_Cube::getSwizzleTexture(ID3D11Resource **outTexture) { - // Base level must already be defined + ASSERT(outTexture); - for (int faceIndex = 0; faceIndex < 6; faceIndex++) - { - for (int level = 1; level < getLevelCount(); level++) - { - invalidateSwizzleCacheLevel(level); - - gl::ImageIndex srcIndex = gl::ImageIndex::MakeCube(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level - 1); - gl::ImageIndex destIndex = gl::ImageIndex::MakeCube(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level); - - RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(srcIndex)); - RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex)); - - generateMipmapLayer(source, dest); - } - } -} - -ID3D11Resource *TextureStorage11_Cube::getSwizzleTexture() -{ if (!mSwizzleTexture) { ID3D11Device *device = mRenderer->getDevice(); @@ -1147,7 +1309,7 @@ ID3D11Resource *TextureStorage11_Cube::getSwizzleTexture() desc.Width = mTextureWidth; desc.Height = mTextureHeight; desc.MipLevels = mMipLevels; - desc.ArraySize = 6; + desc.ArraySize = CUBE_FACE_COUNT; desc.Format = mSwizzleTextureFormat; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; @@ -1158,55 +1320,54 @@ ID3D11Resource *TextureStorage11_Cube::getSwizzleTexture() HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture); - if (result == E_OUTOFMEMORY) + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) { - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result); } - ASSERT(SUCCEEDED(result)); } - return mSwizzleTexture; + *outTexture = mSwizzleTexture; + return gl::Error(GL_NO_ERROR); } -ID3D11RenderTargetView *TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel) +gl::Error TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) { - if (mipLevel >= 0 && mipLevel < getLevelCount()) + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); + ASSERT(outRTV); + + if (!mSwizzleRenderTargets[mipLevel]) { - if (!mSwizzleRenderTargets[mipLevel]) + ID3D11Resource *swizzleTexture = NULL; + gl::Error error = getSwizzleTexture(&swizzleTexture); + if (error.isError()) { - ID3D11Resource *swizzleTexture = getSwizzleTexture(); - if (!swizzleTexture) - { - return NULL; - } - - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mSwizzleRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; - rtvDesc.Texture2DArray.FirstArraySlice = 0; - rtvDesc.Texture2DArray.ArraySize = 6; - - HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); - - if (result == E_OUTOFMEMORY) - { - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); + return error; } - return mSwizzleRenderTargets[mipLevel]; - } - else - { - return NULL; + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mSwizzleRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture2DArray.FirstArraySlice = 0; + rtvDesc.Texture2DArray.ArraySize = CUBE_FACE_COUNT; + + HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle render target view, result: 0x%X.", result); + } } + + *outRTV = mSwizzleRenderTargets[mipLevel]; + return gl::Error(GL_NO_ERROR); } -TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, GLenum internalformat, bool renderTarget, +TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) { @@ -1220,6 +1381,8 @@ TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, GLenum internalform mSwizzleRenderTargets[i] = NULL; } + mInternalFormat = internalformat; + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); mTextureFormat = formatInfo.texFormat; mShaderResourceFormat = formatInfo.srvFormat; @@ -1229,49 +1392,13 @@ TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, GLenum internalform mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; - // If the width, height or depth are not positive this should be treated as an incomplete texture - // we handle that here by skipping the d3d texture creation - if (width > 0 && height > 0 && depth > 0) - { - // adjust size if needed for compressed textures - d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); + // adjust size if needed for compressed textures + d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_TEXTURE3D_DESC desc; - desc.Width = width; - desc.Height = height; - desc.Depth = depth; - desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0); - desc.Format = mTextureFormat; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = getBindFlags(); - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - - HRESULT result = device->CreateTexture3D(&desc, NULL, &mTexture); - - // this can happen from windows TDR - if (d3d11::isDeviceLostError(result)) - { - mRenderer->notifyDeviceLost(); - gl::error(GL_OUT_OF_MEMORY); - } - else if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - ERR("Creating image failed."); - gl::error(GL_OUT_OF_MEMORY); - } - else - { - mTexture->GetDesc(&desc); - mMipLevels = desc.MipLevels; - mTextureWidth = desc.Width; - mTextureHeight = desc.Height; - mTextureDepth = desc.Depth; - } - } + mMipLevels = mTopLevel + levels; + mTextureWidth = width; + mTextureHeight = height; + mTextureDepth = depth; initializeSerials(getLevelCount() * depth, depth); } @@ -1315,8 +1442,10 @@ TextureStorage11_3D *TextureStorage11_3D::makeTextureStorage11_3D(TextureStorage return static_cast(storage); } -void TextureStorage11_3D::associateImage(Image11* image, int level, int layerTarget) +void TextureStorage11_3D::associateImage(Image11* image, const gl::ImageIndex &index) { + GLint level = index.mipIndex; + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) @@ -1325,8 +1454,10 @@ void TextureStorage11_3D::associateImage(Image11* image, int level, int layerTar } } -bool TextureStorage11_3D::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage) +bool TextureStorage11_3D::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) { + GLint level = index.mipIndex; + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) { // This validation check should never return false. It means the Image/TextureStorage association is broken. @@ -1339,8 +1470,10 @@ bool TextureStorage11_3D::isAssociatedImageValid(int level, int layerTarget, Ima } // disassociateImage allows an Image to end its association with a Storage. -void TextureStorage11_3D::disassociateImage(int level, int layerTarget, Image11* expectedImage) +void TextureStorage11_3D::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) { + GLint level = index.mipIndex; + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) @@ -1355,8 +1488,10 @@ void TextureStorage11_3D::disassociateImage(int level, int layerTarget, Image11* } // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. -void TextureStorage11_3D::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage) +gl::Error TextureStorage11_3D::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) { + GLint level = index.mipIndex; + ASSERT((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)); if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) @@ -1372,148 +1507,188 @@ void TextureStorage11_3D::releaseAssociatedImage(int level, int layerTarget, Ima { // Force the image to recover from storage before its data is overwritten. // This will reset mAssociatedImages[level] to NULL too. - mAssociatedImages[level]->recoverFromAssociatedStorage(); + gl::Error error = mAssociatedImages[level]->recoverFromAssociatedStorage(); + if (error.isError()) + { + return error; + } } } } + + return gl::Error(GL_NO_ERROR); } -ID3D11Resource *TextureStorage11_3D::getResource() const +gl::Error TextureStorage11_3D::getResource(ID3D11Resource **outResource) { - return mTexture; + // If the width, height or depth are not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0) + { + ASSERT(mMipLevels > 0); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE3D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.Depth = mTextureDepth; + desc.MipLevels = mMipLevels; + desc.Format = mTextureFormat; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture3D(&desc, NULL, &mTexture); + + // this can happen from windows TDR + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 3D texture storage, result: 0x%X.", result); + } + else if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 3D texture storage, result: 0x%X.", result); + } + } + + *outResource = mTexture; + return gl::Error(GL_NO_ERROR); } -ID3D11ShaderResourceView *TextureStorage11_3D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture) +gl::Error TextureStorage11_3D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const { + ASSERT(outSRV); + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; srvDesc.Format = format; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; srvDesc.Texture3D.MostDetailedMip = baseLevel; srvDesc.Texture3D.MipLevels = mipLevels; - ID3D11ShaderResourceView *SRV = NULL; - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV); + HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV); - if (result == E_OUTOFMEMORY) + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) { - gl::error(GL_OUT_OF_MEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result); } - ASSERT(SUCCEEDED(result)); - return SRV; + return gl::Error(GL_NO_ERROR); } -RenderTarget *TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index) +gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) { int mipLevel = index.mipIndex; + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); - if (mipLevel >= 0 && mipLevel < getLevelCount()) + ASSERT(mRenderTargetFormat != DXGI_FORMAT_UNKNOWN); + + if (!index.hasLayer()) { - ASSERT(mRenderTargetFormat != DXGI_FORMAT_UNKNOWN); - - if (!index.hasLayer()) + if (!mLevelRenderTargets[mipLevel]) { - if (!mLevelRenderTargets[mipLevel]) + ID3D11Resource *texture = NULL; + gl::Error error = getResource(&texture); + if (error.isError()) { - ID3D11ShaderResourceView *srv = getSRVLevel(mipLevel); - if (!srv) - { - return NULL; - } - - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; - rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; - rtvDesc.Texture3D.FirstWSlice = 0; - rtvDesc.Texture3D.WSize = -1; - - ID3D11RenderTargetView *rtv; - HRESULT result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); - - if (result == E_OUTOFMEMORY) - { - SafeRelease(srv); - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - - mLevelRenderTargets[mipLevel] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), getLevelDepth(mipLevel)); - - // RenderTarget will take ownership of these resources - SafeRelease(rtv); + return error; } - return mLevelRenderTargets[mipLevel]; - } - else - { - int layer = index.layerIndex; - - LevelLayerKey key(mipLevel, layer); - if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end()) + ID3D11ShaderResourceView *srv = NULL; + error = getSRVLevel(mipLevel, &srv); + if (error.isError()) { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; + return error; + } - // TODO, what kind of SRV is expected here? - ID3D11ShaderResourceView *srv = NULL; + ID3D11Device *device = mRenderer->getDevice(); - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; - rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; - rtvDesc.Texture3D.FirstWSlice = layer; - rtvDesc.Texture3D.WSize = 1; + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture3D.FirstWSlice = 0; + rtvDesc.Texture3D.WSize = -1; - ID3D11RenderTargetView *rtv; - result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); + ID3D11RenderTargetView *rtv; + HRESULT result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); - if (result == E_OUTOFMEMORY) - { - SafeRelease(srv); - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - - mLevelLayerRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1); - - // RenderTarget will take ownership of these resources - SafeRelease(rtv); + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { SafeRelease(srv); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); } - return mLevelLayerRenderTargets[key]; + mLevelRenderTargets[mipLevel] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), getLevelDepth(mipLevel), 0); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); } + + ASSERT(outRT); + *outRT = mLevelRenderTargets[mipLevel]; + return gl::Error(GL_NO_ERROR); } - - return NULL; -} - -void TextureStorage11_3D::generateMipmaps() -{ - // Base level must already be defined - - for (int level = 1; level < getLevelCount(); level++) + else { - invalidateSwizzleCacheLevel(level); + int layer = index.layerIndex; - gl::ImageIndex srcIndex = gl::ImageIndex::Make3D(level - 1); - gl::ImageIndex destIndex = gl::ImageIndex::Make3D(level); + LevelLayerKey key(mipLevel, layer); + if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end()) + { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; - RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(srcIndex)); - RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex)); + ID3D11Resource *texture = NULL; + gl::Error error = getResource(&texture); + if (error.isError()) + { + return error; + } - generateMipmapLayer(source, dest); + // TODO, what kind of SRV is expected here? + ID3D11ShaderResourceView *srv = NULL; + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture3D.FirstWSlice = layer; + rtvDesc.Texture3D.WSize = 1; + + ID3D11RenderTargetView *rtv; + result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + SafeRelease(srv); return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); + } + ASSERT(SUCCEEDED(result)); + + mLevelLayerRenderTargets[key] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + } + + ASSERT(outRT); + *outRT = mLevelLayerRenderTargets[key]; + return gl::Error(GL_NO_ERROR); } } -ID3D11Resource *TextureStorage11_3D::getSwizzleTexture() +gl::Error TextureStorage11_3D::getSwizzleTexture(ID3D11Resource **outTexture) { + ASSERT(outTexture); + if (!mSwizzleTexture) { ID3D11Device *device = mRenderer->getDevice(); @@ -1531,55 +1706,54 @@ ID3D11Resource *TextureStorage11_3D::getSwizzleTexture() HRESULT result = device->CreateTexture3D(&desc, NULL, &mSwizzleTexture); - if (result == E_OUTOFMEMORY) + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) { - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result); } - ASSERT(SUCCEEDED(result)); } - return mSwizzleTexture; + *outTexture = mSwizzleTexture; + return gl::Error(GL_NO_ERROR); } -ID3D11RenderTargetView *TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel) +gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) { - if (mipLevel >= 0 && mipLevel < getLevelCount()) + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); + ASSERT(outRTV); + + if (!mSwizzleRenderTargets[mipLevel]) { - if (!mSwizzleRenderTargets[mipLevel]) + ID3D11Resource *swizzleTexture = NULL; + gl::Error error = getSwizzleTexture(&swizzleTexture); + if (error.isError()) { - ID3D11Resource *swizzleTexture = getSwizzleTexture(); - if (!swizzleTexture) - { - return NULL; - } - - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mSwizzleRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; - rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; - rtvDesc.Texture3D.FirstWSlice = 0; - rtvDesc.Texture3D.WSize = -1; - - HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); - - if (result == E_OUTOFMEMORY) - { - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); + return error; } - return mSwizzleRenderTargets[mipLevel]; - } - else - { - return NULL; + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mSwizzleRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture3D.FirstWSlice = 0; + rtvDesc.Texture3D.WSize = -1; + + HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle render target view, result: 0x%X.", result); + } } + + *outRTV = mSwizzleRenderTargets[mipLevel]; + return gl::Error(GL_NO_ERROR); } -TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum internalformat, bool renderTarget, +TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) { @@ -1591,6 +1765,8 @@ TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum in mSwizzleRenderTargets[level] = NULL; } + mInternalFormat = internalformat; + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); mTextureFormat = formatInfo.texFormat; mShaderResourceFormat = formatInfo.srvFormat; @@ -1600,51 +1776,13 @@ TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum in mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; - // if the width, height or depth is not positive this should be treated as an incomplete texture - // we handle that here by skipping the d3d texture creation - if (width > 0 && height > 0 && depth > 0) - { - // adjust size if needed for compressed textures - d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); + // adjust size if needed for compressed textures + d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_TEXTURE2D_DESC desc; - desc.Width = width; - desc.Height = height; - desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0); - desc.ArraySize = depth; - desc.Format = mTextureFormat; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = getBindFlags(); - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - - HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); - - // this can happen from windows TDR - if (d3d11::isDeviceLostError(result)) - { - mRenderer->notifyDeviceLost(); - gl::error(GL_OUT_OF_MEMORY); - } - else if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - ERR("Creating image failed."); - gl::error(GL_OUT_OF_MEMORY); - } - else - { - mTexture->GetDesc(&desc); - mMipLevels = desc.MipLevels; - mTextureWidth = desc.Width; - mTextureHeight = desc.Height; - mTextureDepth = desc.ArraySize; - } - } + mMipLevels = mTopLevel + levels; + mTextureWidth = width; + mTextureHeight = height; + mTextureDepth = depth; initializeSerials(getLevelCount() * depth, depth); } @@ -1685,8 +1823,11 @@ TextureStorage11_2DArray *TextureStorage11_2DArray::makeTextureStorage11_2DArray return static_cast(storage); } -void TextureStorage11_2DArray::associateImage(Image11* image, int level, int layerTarget) +void TextureStorage11_2DArray::associateImage(Image11* image, const gl::ImageIndex &index) { + GLint level = index.mipIndex; + GLint layerTarget = index.layerIndex; + ASSERT(0 <= level && level < getLevelCount()); if (0 <= level && level < getLevelCount()) @@ -1696,8 +1837,11 @@ void TextureStorage11_2DArray::associateImage(Image11* image, int level, int lay } } -bool TextureStorage11_2DArray::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage) +bool TextureStorage11_2DArray::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) { + GLint level = index.mipIndex; + GLint layerTarget = index.layerIndex; + LevelLayerKey key(level, layerTarget); // This validation check should never return false. It means the Image/TextureStorage association is broken. @@ -1707,8 +1851,11 @@ bool TextureStorage11_2DArray::isAssociatedImageValid(int level, int layerTarget } // disassociateImage allows an Image to end its association with a Storage. -void TextureStorage11_2DArray::disassociateImage(int level, int layerTarget, Image11* expectedImage) +void TextureStorage11_2DArray::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) { + GLint level = index.mipIndex; + GLint layerTarget = index.layerIndex; + LevelLayerKey key(level, layerTarget); bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() && (mAssociatedImages[key] == expectedImage)); @@ -1721,8 +1868,11 @@ void TextureStorage11_2DArray::disassociateImage(int level, int layerTarget, Ima } // releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. -void TextureStorage11_2DArray::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage) +gl::Error TextureStorage11_2DArray::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) { + GLint level = index.mipIndex; + GLint layerTarget = index.layerIndex; + LevelLayerKey key(level, layerTarget); ASSERT(mAssociatedImages.find(key) != mAssociatedImages.end()); @@ -1739,18 +1889,62 @@ void TextureStorage11_2DArray::releaseAssociatedImage(int level, int layerTarget { // Force the image to recover from storage before its data is overwritten. // This will reset mAssociatedImages[level] to NULL too. - mAssociatedImages[key]->recoverFromAssociatedStorage(); + gl::Error error = mAssociatedImages[key]->recoverFromAssociatedStorage(); + if (error.isError()) + { + return error; + } } } } + + return gl::Error(GL_NO_ERROR); } -ID3D11Resource *TextureStorage11_2DArray::getResource() const +gl::Error TextureStorage11_2DArray::getResource(ID3D11Resource **outResource) { - return mTexture; + // if the width, height or depth is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0) + { + ASSERT(mMipLevels > 0); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = mTextureDepth; + desc.Format = mTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); + + // this can happen from windows TDR + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D array texture storage, result: 0x%X.", result); + } + else if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D array texture storage, result: 0x%X.", result); + } + } + + *outResource = mTexture; + return gl::Error(GL_NO_ERROR); } -ID3D11ShaderResourceView *TextureStorage11_2DArray::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture) +gl::Error TextureStorage11_2DArray::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const { D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; srvDesc.Format = format; @@ -1760,112 +1954,94 @@ ID3D11ShaderResourceView *TextureStorage11_2DArray::createSRV(int baseLevel, int srvDesc.Texture2DArray.FirstArraySlice = 0; srvDesc.Texture2DArray.ArraySize = mTextureDepth; - ID3D11ShaderResourceView *SRV = NULL; - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV); + HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV); - if (result == E_OUTOFMEMORY) + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) { - gl::error(GL_OUT_OF_MEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result); } - ASSERT(SUCCEEDED(result)); - return SRV; + return gl::Error(GL_NO_ERROR); } -RenderTarget *TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index) +gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) { ASSERT(index.hasLayer()); int mipLevel = index.mipIndex; int layer = index.layerIndex; - if (mipLevel >= 0 && mipLevel < getLevelCount()) + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); + + LevelLayerKey key(mipLevel, layer); + if (mRenderTargets.find(key) == mRenderTargets.end()) { - LevelLayerKey key(mipLevel, layer); - if (mRenderTargets.find(key) == mRenderTargets.end()) + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + ID3D11Resource *texture = NULL; + gl::Error error = getResource(&texture); + if (error.isError()) { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; + return error; + } - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = mShaderResourceFormat; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; - srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + mipLevel; - srvDesc.Texture2DArray.MipLevels = 1; - srvDesc.Texture2DArray.FirstArraySlice = layer; - srvDesc.Texture2DArray.ArraySize = 1; + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = mShaderResourceFormat; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + mipLevel; + srvDesc.Texture2DArray.MipLevels = 1; + srvDesc.Texture2DArray.FirstArraySlice = layer; + srvDesc.Texture2DArray.ArraySize = 1; - ID3D11ShaderResourceView *srv; - result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); + ID3D11ShaderResourceView *srv; + result = device->CreateShaderResourceView(texture, &srvDesc, &srv); - if (result == E_OUTOFMEMORY) + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal shader resource view for texture storage, result: 0x%X.", result); + } + + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture2DArray.FirstArraySlice = layer; + rtvDesc.Texture2DArray.ArraySize = 1; + + ID3D11RenderTargetView *rtv; + result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) { - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - - if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) - { - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; - rtvDesc.Texture2DArray.FirstArraySlice = layer; - rtvDesc.Texture2DArray.ArraySize = 1; - - ID3D11RenderTargetView *rtv; - result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); - - if (result == E_OUTOFMEMORY) - { - SafeRelease(srv); - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - - mRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1); - - // RenderTarget will take ownership of these resources - SafeRelease(rtv); SafeRelease(srv); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); } - else - { - UNREACHABLE(); - } + + mRenderTargets[key] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + SafeRelease(srv); } - - return mRenderTargets[key]; - } - else - { - return NULL; - } -} - -void TextureStorage11_2DArray::generateMipmaps() -{ - // Base level must already be defined - - for (int level = 0; level < getLevelCount(); level++) - { - invalidateSwizzleCacheLevel(level); - for (unsigned int layer = 0; layer < mTextureDepth; layer++) + else { - gl::ImageIndex sourceIndex = gl::ImageIndex::Make2DArray(level - 1, layer); - gl::ImageIndex destIndex = gl::ImageIndex::Make2DArray(level, layer); - - RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(sourceIndex)); - RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex)); - - generateMipmapLayer(source, dest); + UNREACHABLE(); } } + + ASSERT(outRT); + *outRT = mRenderTargets[key]; + return gl::Error(GL_NO_ERROR); } -ID3D11Resource *TextureStorage11_2DArray::getSwizzleTexture() +gl::Error TextureStorage11_2DArray::getSwizzleTexture(ID3D11Resource **outTexture) { if (!mSwizzleTexture) { @@ -1886,52 +2062,51 @@ ID3D11Resource *TextureStorage11_2DArray::getSwizzleTexture() HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture); - if (result == E_OUTOFMEMORY) + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) { - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result); } - ASSERT(SUCCEEDED(result)); } - return mSwizzleTexture; + *outTexture = mSwizzleTexture; + return gl::Error(GL_NO_ERROR); } -ID3D11RenderTargetView *TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel) +gl::Error TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) { - if (mipLevel >= 0 && mipLevel < getLevelCount()) + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); + ASSERT(outRTV); + + if (!mSwizzleRenderTargets[mipLevel]) { - if (!mSwizzleRenderTargets[mipLevel]) + ID3D11Resource *swizzleTexture = NULL; + gl::Error error = getSwizzleTexture(&swizzleTexture); + if (error.isError()) { - ID3D11Resource *swizzleTexture = getSwizzleTexture(); - if (!swizzleTexture) - { - return NULL; - } - - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mSwizzleRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; - rtvDesc.Texture2DArray.FirstArraySlice = 0; - rtvDesc.Texture2DArray.ArraySize = mTextureDepth; - - HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); - - if (result == E_OUTOFMEMORY) - { - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); + return error; } - return mSwizzleRenderTargets[mipLevel]; - } - else - { - return NULL; + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mSwizzleRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture2DArray.FirstArraySlice = 0; + rtvDesc.Texture2DArray.ArraySize = mTextureDepth; + + HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle render target view, result: 0x%X.", result); + } } + + *outRTV = mSwizzleRenderTargets[mipLevel]; + return gl::Error(GL_NO_ERROR); } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h index 9d63b2699de..930300a63de 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h @@ -25,7 +25,6 @@ namespace rx { class RenderTarget; class RenderTarget11; -class Renderer; class Renderer11; class SwapChain11; class Image11; @@ -41,47 +40,49 @@ class TextureStorage11 : public TextureStorage UINT getBindFlags() const; - virtual ID3D11Resource *getResource() const = 0; - virtual ID3D11ShaderResourceView *getSRV(const gl::SamplerState &samplerState); - virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index) = 0; + virtual gl::Error getResource(ID3D11Resource **outResource) = 0; + virtual gl::Error getSRV(const gl::SamplerState &samplerState, ID3D11ShaderResourceView **outSRV); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) = 0; - virtual void generateMipmaps() = 0; + virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex); virtual int getTopLevel() const; virtual bool isRenderTarget() const; virtual bool isManaged() const; virtual int getLevelCount() const; - UINT getSubresourceIndex(int mipLevel, int layerTarget) const; + UINT getSubresourceIndex(const gl::ImageIndex &index) const; gl::Error generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); void invalidateSwizzleCacheLevel(int mipLevel); void invalidateSwizzleCache(); - bool updateSubresourceLevel(ID3D11Resource *texture, unsigned int sourceSubresource, int level, - int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth); + gl::Error updateSubresourceLevel(ID3D11Resource *texture, unsigned int sourceSubresource, + const gl::ImageIndex &index, const gl::Box ©Area); - bool copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource, int level, - int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth); + gl::Error copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource, + const gl::ImageIndex &index, const gl::Box ®ion); - virtual void associateImage(Image11* image, int level, int layerTarget) = 0; - virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage) = 0; - virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage) = 0; - virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage) = 0; + virtual void associateImage(Image11* image, const gl::ImageIndex &index) = 0; + virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) = 0; + virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) = 0; + virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) = 0; + + virtual gl::Error copyToStorage(TextureStorage *destStorage); + virtual gl::Error setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixelData); protected: - TextureStorage11(Renderer *renderer, UINT bindFlags); - void generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest); + TextureStorage11(Renderer11 *renderer, UINT bindFlags); int getLevelWidth(int mipLevel) const; int getLevelHeight(int mipLevel) const; int getLevelDepth(int mipLevel) const; - virtual ID3D11Resource *getSwizzleTexture() = 0; - virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel) = 0; - ID3D11ShaderResourceView *getSRVLevel(int mipLevel); + virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture) = 0; + virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) = 0; + gl::Error getSRVLevel(int mipLevel, ID3D11ShaderResourceView **outSRV); - virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture) = 0; + virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const = 0; void verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); @@ -89,6 +90,7 @@ class TextureStorage11 : public TextureStorage int mTopLevel; unsigned int mMipLevels; + GLenum mInternalFormat; DXGI_FORMAT mTextureFormat; DXGI_FORMAT mShaderResourceFormat; DXGI_FORMAT mRenderTargetFormat; @@ -115,69 +117,53 @@ class TextureStorage11 : public TextureStorage }; SwizzleCacheValue mSwizzleCache[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - struct SRVKey - { - SRVKey(int baseLevel = 0, int mipLevels = 0, bool swizzle = false); - - bool operator==(const SRVKey &rhs) const; - - int baseLevel; - int mipLevels; - bool swizzle; - }; - - struct SRVPair - { - SRVKey key; - ID3D11ShaderResourceView *srv; - }; - - struct SRVCache - { - ~SRVCache(); - - ID3D11ShaderResourceView *find(const SRVKey &key) const; - ID3D11ShaderResourceView *add(const SRVKey &key, ID3D11ShaderResourceView *srv); - - std::vector cache; - }; - private: DISALLOW_COPY_AND_ASSIGN(TextureStorage11); const UINT mBindFlags; - SRVCache srvCache; + struct SRVKey + { + SRVKey(int baseLevel = 0, int mipLevels = 0, bool swizzle = false); + + bool operator<(const SRVKey &rhs) const; + + int baseLevel; + int mipLevels; + bool swizzle; + }; + typedef std::map SRVCache; + + SRVCache mSrvCache; ID3D11ShaderResourceView *mLevelSRVs[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; }; class TextureStorage11_2D : public TextureStorage11 { public: - TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain); - TextureStorage11_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); + TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain); + TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); virtual ~TextureStorage11_2D(); static TextureStorage11_2D *makeTextureStorage11_2D(TextureStorage *storage); - virtual ID3D11Resource *getResource() const; - virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index); + virtual gl::Error getResource(ID3D11Resource **outResource); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); - virtual void generateMipmaps(); - - virtual void associateImage(Image11* image, int level, int layerTarget); - virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage); - virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage); - virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage); + virtual void associateImage(Image11* image, const gl::ImageIndex &index); + virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); + virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage); + virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage); protected: - virtual ID3D11Resource *getSwizzleTexture(); - virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel); + virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); + virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); private: DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2D); - virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture); + virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const; ID3D11Texture2D *mTexture; RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; @@ -191,68 +177,68 @@ class TextureStorage11_2D : public TextureStorage11 class TextureStorage11_Cube : public TextureStorage11 { public: - TextureStorage11_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels); + TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels); virtual ~TextureStorage11_Cube(); static TextureStorage11_Cube *makeTextureStorage11_Cube(TextureStorage *storage); - virtual ID3D11Resource *getResource() const; - virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index); + virtual gl::Error getResource(ID3D11Resource **outResource); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); - virtual void generateMipmaps(); - - virtual void associateImage(Image11* image, int level, int layerTarget); - virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage); - virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage); - virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage); + virtual void associateImage(Image11* image, const gl::ImageIndex &index); + virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); + virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage); + virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage); protected: - virtual ID3D11Resource *getSwizzleTexture(); - virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel); + virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); + virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); private: DISALLOW_COPY_AND_ASSIGN(TextureStorage11_Cube); - virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture); + virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const; + + static const size_t CUBE_FACE_COUNT = 6; ID3D11Texture2D *mTexture; - RenderTarget11 *mRenderTarget[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + RenderTarget11 *mRenderTarget[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; ID3D11Texture2D *mSwizzleTexture; ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - Image11 *mAssociatedImages[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + Image11 *mAssociatedImages[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; }; class TextureStorage11_3D : public TextureStorage11 { public: - TextureStorage11_3D(Renderer *renderer, GLenum internalformat, bool renderTarget, + TextureStorage11_3D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); virtual ~TextureStorage11_3D(); static TextureStorage11_3D *makeTextureStorage11_3D(TextureStorage *storage); - virtual ID3D11Resource *getResource() const; + virtual gl::Error getResource(ID3D11Resource **outResource); // Handles both layer and non-layer RTs - virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); - virtual void generateMipmaps(); - - virtual void associateImage(Image11* image, int level, int layerTarget); - virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage); - virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage); - virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage); + virtual void associateImage(Image11* image, const gl::ImageIndex &index); + virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); + virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage); + virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage); protected: - virtual ID3D11Resource *getSwizzleTexture(); - virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel); + virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); + virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); private: DISALLOW_COPY_AND_ASSIGN(TextureStorage11_3D); - virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture); + virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const; typedef std::pair LevelLayerKey; typedef std::map RenderTargetMap; @@ -270,30 +256,29 @@ class TextureStorage11_3D : public TextureStorage11 class TextureStorage11_2DArray : public TextureStorage11 { public: - TextureStorage11_2DArray(Renderer *renderer, GLenum internalformat, bool renderTarget, + TextureStorage11_2DArray(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); virtual ~TextureStorage11_2DArray(); static TextureStorage11_2DArray *makeTextureStorage11_2DArray(TextureStorage *storage); - virtual ID3D11Resource *getResource() const; - virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index); + virtual gl::Error getResource(ID3D11Resource **outResource); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); - virtual void generateMipmaps(); - - virtual void associateImage(Image11* image, int level, int layerTarget); - virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage); - virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage); - virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage); + virtual void associateImage(Image11* image, const gl::ImageIndex &index); + virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); + virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage); + virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage); protected: - virtual ID3D11Resource *getSwizzleTexture(); - virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel); + virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); + virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); private: DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2DArray); - virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture); + virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const; typedef std::pair LevelLayerKey; typedef std::map RenderTargetMap; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h index 590cb9f05a4..70bc3bb26f3 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h @@ -19,7 +19,7 @@ class Renderer11; class VertexArray11 : public VertexArrayImpl { public: - VertexArray11(rx::Renderer11 *renderer) + VertexArray11(Renderer11 *renderer) : VertexArrayImpl(), mRenderer(renderer) { @@ -34,7 +34,7 @@ class VertexArray11 : public VertexArrayImpl private: DISALLOW_COPY_AND_ASSIGN(VertexArray11); - rx::Renderer11 *mRenderer; + Renderer11 *mRenderer; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp index 9bc5b1d2d16..a9d6fa2ca43 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp @@ -16,7 +16,7 @@ namespace rx { -VertexBuffer11::VertexBuffer11(rx::Renderer11 *const renderer) : mRenderer(renderer) +VertexBuffer11::VertexBuffer11(Renderer11 *const renderer) : mRenderer(renderer) { mBuffer = NULL; mBufferSize = 0; @@ -91,8 +91,13 @@ gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attri { if (buffer) { - Buffer11 *storage = Buffer11::makeBuffer11(buffer->getImplementation()); - input = static_cast(storage->getData()) + static_cast(attrib.offset); + BufferD3D *storage = BufferD3D::makeFromBuffer(buffer); + gl::Error error = storage->getData(&input); + if (error.isError()) + { + return error; + } + input += static_cast(attrib.offset); } else { @@ -132,7 +137,7 @@ gl::Error VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GL else { // Round up to divisor, if possible - elementCount = rx::UnsignedCeilDivide(static_cast(instances), attrib.divisor); + elementCount = UnsignedCeilDivide(static_cast(instances), attrib.divisor); } gl::VertexFormat vertexFormat(attrib); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h index 0e10da1df88..a9bbac98fad 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h @@ -18,7 +18,7 @@ class Renderer11; class VertexBuffer11 : public VertexBuffer { public: - explicit VertexBuffer11(rx::Renderer11 *const renderer); + explicit VertexBuffer11(Renderer11 *const renderer); virtual ~VertexBuffer11(); virtual gl::Error initialize(unsigned int size, bool dynamicUsage); @@ -40,7 +40,7 @@ class VertexBuffer11 : public VertexBuffer private: DISALLOW_COPY_AND_ASSIGN(VertexBuffer11); - rx::Renderer11 *const mRenderer; + Renderer11 *const mRenderer; ID3D11Buffer *mBuffer; unsigned int mBufferSize; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp index c07828757d8..90a879e170b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp @@ -795,7 +795,7 @@ static D3D11ES3FormatMap BuildD3D11FormatMap() // From GL_EXT_texture_storage // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | - InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ); InsertD3D11FormatInfo(&map, GL_LUMINANCE8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ); InsertD3D11FormatInfo(&map, GL_ALPHA32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ); InsertD3D11FormatInfo(&map, GL_LUMINANCE32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp index 2af97e73f04..121aa3bbadf 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp @@ -10,6 +10,7 @@ #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" #include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" +#include "libGLESv2/renderer/Workarounds.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/Framebuffer.h" @@ -95,9 +96,6 @@ #ifndef D3D10_1_VS_OUTPUT_REGISTER_COUNT # define D3D10_1_VS_OUTPUT_REGISTER_COUNT 32 #endif -#ifndef D3D11_VS_OUTPUT_REGISTER_COUNT -# define D3D11_VS_OUTPUT_REGISTER_COUNT 32 -#endif namespace rx { @@ -357,7 +355,7 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: @@ -377,7 +375,7 @@ static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_MAX_MAXANISOTROPY; @@ -399,7 +397,7 @@ static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: @@ -421,7 +419,7 @@ static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: @@ -441,7 +439,7 @@ static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: @@ -466,7 +464,7 @@ static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: @@ -486,7 +484,7 @@ static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; @@ -506,7 +504,7 @@ static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; @@ -526,7 +524,7 @@ static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION; @@ -546,7 +544,7 @@ static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; @@ -566,7 +564,7 @@ static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; @@ -586,7 +584,7 @@ static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX; @@ -612,7 +610,7 @@ static size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: @@ -636,7 +634,7 @@ static size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: @@ -655,7 +653,7 @@ static size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_STANDARD_VERTEX_ELEMENT_COUNT; @@ -677,7 +675,7 @@ static size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel) // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; @@ -704,7 +702,7 @@ static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers(); @@ -733,7 +731,7 @@ static size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); @@ -754,7 +752,7 @@ static size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; @@ -778,7 +776,7 @@ static size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel) // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; @@ -805,7 +803,7 @@ static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers(); @@ -826,7 +824,7 @@ static size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); @@ -847,7 +845,7 @@ static size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; @@ -868,7 +866,7 @@ static int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE; @@ -889,7 +887,7 @@ static int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE; @@ -914,7 +912,7 @@ static size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; @@ -935,7 +933,7 @@ static size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_SO_BUFFER_SLOT_COUNT; @@ -951,11 +949,11 @@ static size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel) } } -static size_t GetMaximumStreamOutputInterleavedComponenets(D3D_FEATURE_LEVEL featureLevel) +static size_t GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif case D3D_FEATURE_LEVEL_11_0: @@ -971,14 +969,14 @@ static size_t GetMaximumStreamOutputInterleavedComponenets(D3D_FEATURE_LEVEL fea } } -static size_t GetMaximumStreamOutputSeparateCompeonents(D3D_FEATURE_LEVEL featureLevel) +static size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if _MSC_VER >= 1700 +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: #endif - case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponenets(featureLevel) / + case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponents(featureLevel) / GetMaximumStreamOutputBuffers(featureLevel); @@ -1087,9 +1085,9 @@ void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *text caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits; // Transform feedback limits - caps->maxTransformFeedbackInterleavedComponents = GetMaximumStreamOutputInterleavedComponenets(featureLevel); + caps->maxTransformFeedbackInterleavedComponents = GetMaximumStreamOutputInterleavedComponents(featureLevel); caps->maxTransformFeedbackSeparateAttributes = GetMaximumStreamOutputBuffers(featureLevel); - caps->maxTransformFeedbackSeparateComponents = GetMaximumStreamOutputSeparateCompeonents(featureLevel); + caps->maxTransformFeedbackSeparateComponents = GetMaximumStreamOutputSeparateComponents(featureLevel); // GL extension support extensions->setTextureExtensionSupport(*textureCapsMap); @@ -1198,17 +1196,31 @@ void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, flo HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) { -#if !defined(__MINGW32__) && defined(_DEBUG) +#if defined(_DEBUG) && !defined(__MINGW32__) return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name); #else return S_OK; #endif } -RenderTarget11 *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment) +gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget11 **outRT) { - RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment); - return RenderTarget11::makeRenderTarget11(renderTarget); + RenderTarget *renderTarget = NULL; + gl::Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget); + if (error.isError()) + { + return error; + } + *outRT = RenderTarget11::makeRenderTarget11(renderTarget); + return gl::Error(GL_NO_ERROR); +} + +Workarounds GenerateWorkarounds() +{ + Workarounds workarounds; + workarounds.mrtPerfWorkaround = true; + workarounds.setDataFasterThanImageUpload = true; + return workarounds; } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h index 4c05eb92562..9df9c95763e 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h @@ -12,6 +12,7 @@ #include "libGLESv2/angletypes.h" #include "libGLESv2/Caps.h" +#include "libGLESv2/Error.h" #include @@ -23,6 +24,7 @@ class FramebufferAttachment; namespace rx { class RenderTarget11; +struct Workarounds; namespace gl_d3d11 { @@ -176,7 +178,9 @@ inline void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBu context->Unmap(constantBuffer, 0); } -RenderTarget11 *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment); +gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget11 **outRT); + +Workarounds GenerateWorkarounds(); } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp index f061a32c52b..2ca7a9cf8a6 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp @@ -46,10 +46,16 @@ const size_t g_shaderSize[] = namespace rx { -Blit9::Blit9(rx::Renderer9 *renderer) - : mRenderer(renderer), mQuadVertexBuffer(NULL), mQuadVertexDeclaration(NULL), mSavedStateBlock(NULL), mSavedRenderTarget(NULL), mSavedDepthStencil(NULL) + +Blit9::Blit9(Renderer9 *renderer) + : mRenderer(renderer), + mGeometryLoaded(false), + mQuadVertexBuffer(NULL), + mQuadVertexDeclaration(NULL), + mSavedStateBlock(NULL), + mSavedRenderTarget(NULL), + mSavedDepthStencil(NULL) { - initGeometry(); memset(mCompiledShaders, 0, sizeof(mCompiledShaders)); } @@ -65,8 +71,13 @@ Blit9::~Blit9() } } -void Blit9::initGeometry() +gl::Error Blit9::initialize() { + if (mGeometryLoaded) + { + return gl::Error(GL_NO_ERROR); + } + static const float quad[] = { -1, -1, @@ -82,7 +93,7 @@ void Blit9::initGeometry() if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return gl::error(GL_OUT_OF_MEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal blit vertex shader, result: 0x%X.", result); } void *lockPtr = NULL; @@ -91,7 +102,8 @@ void Blit9::initGeometry() if (FAILED(result) || lockPtr == NULL) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return gl::error(GL_OUT_OF_MEMORY); + SafeRelease(mQuadVertexBuffer); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal blit vertex shader, result: 0x%X.", result); } memcpy(lockPtr, quad, sizeof(quad)); @@ -108,14 +120,18 @@ void Blit9::initGeometry() if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return gl::error(GL_OUT_OF_MEMORY); + SafeRelease(mQuadVertexBuffer); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal blit vertex declaration, result: 0x%X.", result); } + + mGeometryLoaded = true; + return gl::Error(GL_NO_ERROR); } template -bool Blit9::setShader(ShaderId source, const char *profile, - D3DShaderType *(rx::Renderer9::*createShader)(const DWORD *, size_t length), - HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)) +gl::Error Blit9::setShader(ShaderId source, const char *profile, + gl::Error (Renderer9::*createShader)(const DWORD *, size_t length, D3DShaderType **outShader), + HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)) { IDirect3DDevice9 *device = mRenderer->getDevice(); @@ -130,35 +146,32 @@ bool Blit9::setShader(ShaderId source, const char *profile, const BYTE* shaderCode = g_shaderCode[source]; size_t shaderSize = g_shaderSize[source]; - shader = (mRenderer->*createShader)(reinterpret_cast(shaderCode), shaderSize); - if (!shader) + gl::Error error = (mRenderer->*createShader)(reinterpret_cast(shaderCode), shaderSize, &shader); + if (error.isError()) { - ERR("Failed to create shader for blit operation"); - return false; + return error; } mCompiledShaders[source] = shader; } HRESULT hr = (device->*setShader)(shader); - if (FAILED(hr)) { - ERR("Failed to set shader for blit operation"); - return false; + return gl::Error(GL_OUT_OF_MEMORY, "Failed to set shader for blit operation, result: 0x%X.", hr); } - return true; + return gl::Error(GL_NO_ERROR); } -bool Blit9::setVertexShader(ShaderId shader) +gl::Error Blit9::setVertexShader(ShaderId shader) { - return setShader(shader, "vs_2_0", &rx::Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader); + return setShader(shader, "vs_2_0", &Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader); } -bool Blit9::setPixelShader(ShaderId shader) +gl::Error Blit9::setPixelShader(ShaderId shader) { - return setShader(shader, "ps_2_0", &rx::Renderer9::createPixelShader, &IDirect3DDevice9::SetPixelShader); + return setShader(shader, "ps_2_0", &Renderer9::createPixelShader, &IDirect3DDevice9::SetPixelShader); } RECT Blit9::getSurfaceRect(IDirect3DSurface9 *surface) const @@ -175,12 +188,19 @@ RECT Blit9::getSurfaceRect(IDirect3DSurface9 *surface) const return rect; } -bool Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) +gl::Error Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) { - IDirect3DTexture9 *texture = copySurfaceToTexture(source, getSurfaceRect(source)); - if (!texture) + gl::Error error = initialize(); + if (error.isError()) { - return false; + return error; + } + + IDirect3DTexture9 *texture = NULL; + error = copySurfaceToTexture(source, getSurfaceRect(source), &texture); + if (error.isError()) + { + return error; } IDirect3DDevice9 *device = mRenderer->getDevice(); @@ -205,87 +225,90 @@ bool Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) restoreState(); - return true; + return gl::Error(GL_NO_ERROR); } -bool Blit9::copy2D(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) +gl::Error Blit9::copy2D(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) { - RenderTarget9 *renderTarget = NULL; - IDirect3DSurface9 *source = NULL; + gl::Error error = initialize(); + if (error.isError()) + { + return error; + } + gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); + ASSERT(colorbuffer); - if (colorbuffer) + RenderTarget9 *renderTarget9 = NULL; + error = d3d9::GetAttachmentRenderTarget(colorbuffer, &renderTarget9); + if (error.isError()) { - renderTarget = d3d9::GetAttachmentRenderTarget(colorbuffer); + return error; } + ASSERT(renderTarget9); - if (renderTarget) - { - source = renderTarget->getSurface(); - } - - if (!source) - { - ERR("Failed to retrieve the render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } + IDirect3DSurface9 *source = renderTarget9->getSurface(); + ASSERT(source); + IDirect3DSurface9 *destSurface = NULL; TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage); - IDirect3DSurface9 *destSurface = storage9->getSurfaceLevel(level, true); - bool result = false; - - if (destSurface) + error = storage9->getSurfaceLevel(level, true, &destSurface); + if (error.isError()) { - result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface); - SafeRelease(destSurface); + return error; } + ASSERT(destSurface); + gl::Error result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface); + + SafeRelease(destSurface); SafeRelease(source); + return result; } -bool Blit9::copyCube(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level) +gl::Error Blit9::copyCube(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level) { - RenderTarget9 *renderTarget = NULL; - IDirect3DSurface9 *source = NULL; + gl::Error error = initialize(); + if (error.isError()) + { + return error; + } + gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); + ASSERT(colorbuffer); - if (colorbuffer) + RenderTarget9 *renderTarget9 = NULL; + error = d3d9::GetAttachmentRenderTarget(colorbuffer, &renderTarget9); + if (error.isError()) { - renderTarget = d3d9::GetAttachmentRenderTarget(colorbuffer); + return error; } + ASSERT(renderTarget9); - if (renderTarget) - { - source = renderTarget->getSurface(); - } - - if (!source) - { - ERR("Failed to retrieve the render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } + IDirect3DSurface9 *source = renderTarget9->getSurface(); + ASSERT(source); + IDirect3DSurface9 *destSurface = NULL; TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage); - IDirect3DSurface9 *destSurface = storage9->getCubeMapSurface(target, level, true); - bool result = false; - - if (destSurface) + error = storage9->getCubeMapSurface(target, level, true, &destSurface); + if (error.isError()) { - result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface); - SafeRelease(destSurface); + return error; } + ASSERT(destSurface); + gl::Error result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface); + + SafeRelease(destSurface); SafeRelease(source); + return result; } -bool Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) +gl::Error Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) { - if (!dest) - { - return false; - } + ASSERT(source != NULL && dest != NULL); IDirect3DDevice9 *device = mRenderer->getDevice(); @@ -303,22 +326,30 @@ bool Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destF if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return gl::error(GL_OUT_OF_MEMORY, false); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to blit between textures, StretchRect result: 0x%X.", result); } + + return gl::Error(GL_NO_ERROR); } else { return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest); } - return true; } -bool Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) +gl::Error Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) { - IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect); - if (!texture) + gl::Error error = initialize(); + if (error.isError()) { - return false; + return error; + } + + IDirect3DTexture9 *texture = NULL; + error = copySurfaceToTexture(source, sourceRect, &texture); + if (error.isError()) + { + return error; } IDirect3DDevice9 *device = mRenderer->getDevice(); @@ -331,7 +362,9 @@ bool Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLe setViewport(sourceRect, xoffset, yoffset); setCommonBlitState(); - if (setFormatConvertShaders(destFormat)) + + error = setFormatConvertShaders(destFormat); + if (!error.isError()) { render(); } @@ -340,12 +373,16 @@ bool Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLe restoreState(); - return true; + return error; } -bool Blit9::setFormatConvertShaders(GLenum destFormat) +gl::Error Blit9::setFormatConvertShaders(GLenum destFormat) { - bool okay = setVertexShader(SHADER_VS_STANDARD); + gl::Error error = setVertexShader(SHADER_VS_STANDARD); + if (error.isError()) + { + return error; + } switch (destFormat) { @@ -356,18 +393,18 @@ bool Blit9::setFormatConvertShaders(GLenum destFormat) case GL_RG_EXT: case GL_RED_EXT: case GL_ALPHA: - okay = okay && setPixelShader(SHADER_PS_COMPONENTMASK); + error = setPixelShader(SHADER_PS_COMPONENTMASK); break; case GL_LUMINANCE: case GL_LUMINANCE_ALPHA: - okay = okay && setPixelShader(SHADER_PS_LUMINANCE); + error = setPixelShader(SHADER_PS_LUMINANCE); break; } - if (!okay) + if (error.isError()) { - return false; + return error; } enum { X = 0, Y = 1, Z = 2, W = 3 }; @@ -463,15 +500,12 @@ bool Blit9::setFormatConvertShaders(GLenum destFormat) mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst, 2); - return true; + return gl::Error(GL_NO_ERROR); } -IDirect3DTexture9 *Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect) +gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect, IDirect3DTexture9 **outTexture) { - if (!surface) - { - return NULL; - } + ASSERT(surface); IDirect3DDevice9 *device = mRenderer->getDevice(); @@ -485,7 +519,7 @@ IDirect3DTexture9 *Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal texture for blit, result: 0x%X.", result); } IDirect3DSurface9 *textureSurface; @@ -495,7 +529,7 @@ IDirect3DTexture9 *Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); SafeRelease(texture); - return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to query surface of internal blit texture, result: 0x%X.", result); } mRenderer->endScene(); @@ -507,10 +541,11 @@ IDirect3DTexture9 *Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); SafeRelease(texture); - return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to copy between internal blit textures, result: 0x%X.", result); } - return texture; + *outTexture = texture; + return gl::Error(GL_NO_ERROR); } void Blit9::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h index 46a3ee1cf36..5c7a76ce055 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h @@ -10,6 +10,7 @@ #define LIBGLESV2_BLIT9_H_ #include "common/angleutils.h" +#include "libGLESv2/Error.h" #include @@ -29,32 +30,33 @@ class Blit9 explicit Blit9(Renderer9 *renderer); ~Blit9(); + gl::Error initialize(); + // Copy from source surface to dest surface. // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left) - bool copy2D(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level); - bool copyCube(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level); + gl::Error copy2D(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level); + gl::Error copyCube(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level); // Copy from source surface to dest surface. // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left) // source is interpreted as RGBA and destFormat specifies the desired result format. For example, if destFormat = GL_RGB, the alpha channel will be forced to 0. - bool formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest); + gl::Error formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest); // 2x2 box filter sample from source to dest. // Requires that source is RGB(A) and dest has the same format as source. - bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); + gl::Error boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); private: - rx::Renderer9 *mRenderer; + Renderer9 *mRenderer; + bool mGeometryLoaded; IDirect3DVertexBuffer9 *mQuadVertexBuffer; IDirect3DVertexDeclaration9 *mQuadVertexDeclaration; - void initGeometry(); + gl::Error setFormatConvertShaders(GLenum destFormat); - bool setFormatConvertShaders(GLenum destFormat); - - bool copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest); - IDirect3DTexture9 *copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect); + gl::Error copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest); + gl::Error copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect, IDirect3DTexture9 **outTexture); void setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset); void setCommonBlitState(); RECT getSurfaceRect(IDirect3DSurface9 *surface) const; @@ -74,12 +76,12 @@ class Blit9 IUnknown *mCompiledShaders[SHADER_COUNT]; template - bool setShader(ShaderId source, const char *profile, - D3DShaderType *(Renderer9::*createShader)(const DWORD *, size_t length), - HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)); + gl::Error setShader(ShaderId source, const char *profile, + gl::Error (Renderer9::*createShader)(const DWORD *, size_t length, D3DShaderType **outShader), + HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)); - bool setVertexShader(ShaderId shader); - bool setPixelShader(ShaderId shader); + gl::Error setVertexShader(ShaderId shader); + gl::Error setPixelShader(ShaderId shader); void render(); void saveState(); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp index c02db515a28..430fe81e502 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp @@ -13,7 +13,7 @@ namespace rx { -Buffer9::Buffer9(rx::Renderer9 *renderer) +Buffer9::Buffer9(Renderer9 *renderer) : BufferD3D(), mRenderer(renderer), mSize(0) @@ -41,7 +41,7 @@ gl::Error Buffer9::setData(const void* data, size_t size, GLenum usage) } mSize = size; - if (data) + if (data && size > 0) { memcpy(mMemory.data(), data, size); } @@ -56,9 +56,10 @@ gl::Error Buffer9::setData(const void* data, size_t size, GLenum usage) return gl::Error(GL_NO_ERROR); } -void *Buffer9::getData() +gl::Error Buffer9::getData(const uint8_t **outData) { - return mMemory.data(); + *outData = mMemory.data(); + return gl::Error(GL_NO_ERROR); } gl::Error Buffer9::setSubData(const void* data, size_t size, size_t offset) @@ -72,7 +73,7 @@ gl::Error Buffer9::setSubData(const void* data, size_t size, size_t offset) } mSize = std::max(mSize, offset + size); - if (data) + if (data && size > 0) { memcpy(mMemory.data() + offset, data, size); } @@ -113,7 +114,7 @@ void Buffer9::markTransformFeedbackUsage() UNREACHABLE(); } -Renderer* Buffer9::getRenderer() +RendererD3D *Buffer9::getRenderer() { return mRenderer; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h index e78182f9050..c80b0097384 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h @@ -20,7 +20,7 @@ class Renderer9; class Buffer9 : public BufferD3D { public: - Buffer9(rx::Renderer9 *renderer); + Buffer9(Renderer9 *renderer); virtual ~Buffer9(); static Buffer9 *makeBuffer9(BufferImpl *buffer); @@ -28,11 +28,11 @@ class Buffer9 : public BufferD3D // BufferD3D implementation virtual size_t getSize() const { return mSize; } virtual bool supportsDirectBinding() const { return false; } - virtual Renderer* getRenderer(); + RendererD3D *getRenderer() override; // BufferImpl implementation virtual gl::Error setData(const void* data, size_t size, GLenum usage); - virtual void *getData(); + gl::Error getData(const uint8_t **outData) override; virtual gl::Error setSubData(const void* data, size_t size, size_t offset); virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); virtual gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr); @@ -42,7 +42,7 @@ class Buffer9 : public BufferD3D private: DISALLOW_COPY_AND_ASSIGN(Buffer9); - rx::Renderer9 *mRenderer; + Renderer9 *mRenderer; MemoryBuffer mMemory; size_t mSize; }; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp index e352a5f50af..66263fe110d 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -// Fence9.cpp: Defines the rx::Fence9 class. +// Fence9.cpp: Defines the rx::FenceNV9 class. #include "libGLESv2/renderer/d3d/d3d9/Fence9.h" #include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" @@ -14,39 +14,41 @@ namespace rx { -Fence9::Fence9(rx::Renderer9 *renderer) +FenceNV9::FenceNV9(Renderer9 *renderer) + : FenceNVImpl(), + mRenderer(renderer), + mQuery(NULL) { - mRenderer = renderer; - mQuery = NULL; } -Fence9::~Fence9() +FenceNV9::~FenceNV9() { SafeRelease(mQuery); } -bool Fence9::isSet() const -{ - return mQuery != NULL; -} - -void Fence9::set() +gl::Error FenceNV9::set() { if (!mQuery) { - mQuery = mRenderer->allocateEventQuery(); - if (!mQuery) + gl::Error error = mRenderer->allocateEventQuery(&mQuery); + if (error.isError()) { - return gl::error(GL_OUT_OF_MEMORY); + return error; } } HRESULT result = mQuery->Issue(D3DISSUE_END); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + SafeRelease(mQuery); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to end event query, result: 0x%X.", result); + } + + return gl::Error(GL_NO_ERROR); } -bool Fence9::test(bool flushCommandBuffer) +gl::Error FenceNV9::test(bool flushCommandBuffer, GLboolean *outFinished) { ASSERT(mQuery); @@ -56,17 +58,34 @@ bool Fence9::test(bool flushCommandBuffer) if (d3d9::isDeviceLostError(result)) { mRenderer->notifyDeviceLost(); - return gl::error(GL_OUT_OF_MEMORY, true); + return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while querying result of an event query."); + } + else if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get query data, result: 0x%X.", result); } ASSERT(result == S_OK || result == S_FALSE); - - return (result == S_OK); + *outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE); + return gl::Error(GL_NO_ERROR); } -bool Fence9::hasError() const +gl::Error FenceNV9::finishFence(GLboolean *outFinished) { - return mRenderer->isDeviceLost(); + ASSERT(outFinished); + + while (*outFinished != GL_TRUE) + { + gl::Error error = test(true, outFinished); + if (error.isError()) + { + return error; + } + + Sleep(0); + } + + return gl::Error(GL_NO_ERROR); } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h index e923a2178cf..d7873d52648 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h @@ -4,7 +4,7 @@ // found in the LICENSE file. // -// Fence9.h: Defines the rx::Fence9 class which implements rx::FenceImpl. +// Fence9.h: Defines the rx::FenceNV9 class which implements rx::FenceNVImpl. #ifndef LIBGLESV2_RENDERER_FENCE9_H_ #define LIBGLESV2_RENDERER_FENCE9_H_ @@ -15,21 +15,20 @@ namespace rx { class Renderer9; -class Fence9 : public FenceImpl +class FenceNV9 : public FenceNVImpl { public: - explicit Fence9(rx::Renderer9 *renderer); - virtual ~Fence9(); + explicit FenceNV9(Renderer9 *renderer); + virtual ~FenceNV9(); - bool isSet() const; - void set(); - bool test(bool flushCommandBuffer); - bool hasError() const; + gl::Error set(); + gl::Error test(bool flushCommandBuffer, GLboolean *outFinished); + gl::Error finishFence(GLboolean *outFinished); private: - DISALLOW_COPY_AND_ASSIGN(Fence9); + DISALLOW_COPY_AND_ASSIGN(FenceNV9); - rx::Renderer9 *mRenderer; + Renderer9 *mRenderer; IDirect3DQuery9 *mQuery; }; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp index 18383fba78f..2a06d12942a 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp @@ -17,7 +17,7 @@ #include "libGLESv2/Framebuffer.h" #include "libGLESv2/FramebufferAttachment.h" #include "libGLESv2/Renderbuffer.h" - +#include "common/utilities.h" namespace rx { @@ -36,15 +36,23 @@ Image9::~Image9() SafeRelease(mSurface); } -void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface) +gl::Error Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface) { D3DSURFACE_DESC destDesc; HRESULT result = destSurface->GetDesc(&destDesc); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the source surface description for mipmap generation, result: 0x%X.", result); + } D3DSURFACE_DESC sourceDesc; result = sourceSurface->GetDesc(&sourceDesc); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the destination surface description for mipmap generation, result: 0x%X.", result); + } ASSERT(sourceDesc.Format == destDesc.Format); ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width); @@ -56,74 +64,111 @@ void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sour D3DLOCKED_RECT sourceLocked = {0}; result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the source surface for mipmap generation, result: 0x%X.", result); + } D3DLOCKED_RECT destLocked = {0}; result = destSurface->LockRect(&destLocked, NULL, 0); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + sourceSurface->UnlockRect(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the destination surface for mipmap generation, result: 0x%X.", result); + } const uint8_t *sourceData = reinterpret_cast(sourceLocked.pBits); uint8_t *destData = reinterpret_cast(destLocked.pBits); - if (sourceData && destData) - { - d3dFormatInfo.mipGenerationFunction(sourceDesc.Width, sourceDesc.Height, 1, sourceData, sourceLocked.Pitch, 0, - destData, destLocked.Pitch, 0); - } + ASSERT(sourceData && destData); + + d3dFormatInfo.mipGenerationFunction(sourceDesc.Width, sourceDesc.Height, 1, sourceData, sourceLocked.Pitch, 0, + destData, destLocked.Pitch, 0); destSurface->UnlockRect(); sourceSurface->UnlockRect(); + + return gl::Error(GL_NO_ERROR); } Image9 *Image9::makeImage9(Image *img) { - ASSERT(HAS_DYNAMIC_TYPE(rx::Image9*, img)); - return static_cast(img); + ASSERT(HAS_DYNAMIC_TYPE(Image9*, img)); + return static_cast(img); } -void Image9::generateMipmap(Image9 *dest, Image9 *source) +gl::Error Image9::generateMipmap(Image9 *dest, Image9 *source) { - IDirect3DSurface9 *sourceSurface = source->getSurface(); - if (sourceSurface == NULL) - return gl::error(GL_OUT_OF_MEMORY); + IDirect3DSurface9 *sourceSurface = NULL; + gl::Error error = source->getSurface(&sourceSurface); + if (error.isError()) + { + return error; + } - IDirect3DSurface9 *destSurface = dest->getSurface(); - generateMip(destSurface, sourceSurface); + IDirect3DSurface9 *destSurface = NULL; + error = dest->getSurface(&destSurface); + if (error.isError()) + { + return error; + } + + error = generateMip(destSurface, sourceSurface); + if (error.isError()) + { + return error; + } dest->markDirty(); + + return gl::Error(GL_NO_ERROR); } -void Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source) +gl::Error Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source) { D3DLOCKED_RECT sourceLock = {0}; D3DLOCKED_RECT destLock = {0}; - source->LockRect(&sourceLock, NULL, 0); - dest->LockRect(&destLock, NULL, 0); + HRESULT result; - if (sourceLock.pBits && destLock.pBits) + result = source->LockRect(&sourceLock, NULL, 0); + if (FAILED(result)) { - D3DSURFACE_DESC desc; - source->GetDesc(&desc); - - const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); - unsigned int rows = desc.Height / d3dFormatInfo.blockHeight; - - unsigned int bytes = d3d9::ComputeBlockSize(desc.Format, desc.Width, d3dFormatInfo.blockHeight); - ASSERT(bytes <= static_cast(sourceLock.Pitch) && - bytes <= static_cast(destLock.Pitch)); - - for(unsigned int i = 0; i < rows; i++) - { - memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes); - } - - source->UnlockRect(); - dest->UnlockRect(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock source surface for copy, result: 0x%X.", result); } - else UNREACHABLE(); + + result = dest->LockRect(&destLock, NULL, 0); + if (FAILED(result)) + { + source->UnlockRect(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock source surface for copy, result: 0x%X.", result); + } + + ASSERT(sourceLock.pBits && destLock.pBits); + + D3DSURFACE_DESC desc; + source->GetDesc(&desc); + + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); + unsigned int rows = desc.Height / d3dFormatInfo.blockHeight; + + unsigned int bytes = d3d9::ComputeBlockSize(desc.Format, desc.Width, d3dFormatInfo.blockHeight); + ASSERT(bytes <= static_cast(sourceLock.Pitch) && + bytes <= static_cast(destLock.Pitch)); + + for(unsigned int i = 0; i < rows; i++) + { + memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes); + } + + source->UnlockRect(); + dest->UnlockRect(); + + return gl::Error(GL_NO_ERROR); } -bool Image9::redefine(rx::Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) +bool Image9::redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) { // 3D textures are not supported by the D3D9 backend. ASSERT(depth <= 1); @@ -160,11 +205,11 @@ bool Image9::redefine(rx::Renderer *renderer, GLenum target, GLenum internalform return false; } -void Image9::createSurface() +gl::Error Image9::createSurface() { - if(mSurface) + if (mSurface) { - return; + return gl::Error(GL_NO_ERROR); } IDirect3DTexture9 *newTexture = NULL; @@ -187,8 +232,7 @@ void Image9::createSurface() if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - ERR("Creating image surface failed."); - return gl::error(GL_OUT_OF_MEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create image surface, result: 0x%X.", result); } newTexture->GetSurfaceLevel(levelToFetch, &newSurface); @@ -206,35 +250,51 @@ void Image9::createSurface() D3DLOCKED_RECT lockedRect; result = newSurface->LockRect(&lockedRect, &entireRect, 0); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock image surface, result: 0x%X.", result); + } d3dFormatInfo.dataInitializerFunction(mWidth, mHeight, 1, reinterpret_cast(lockedRect.pBits), lockedRect.Pitch, 0); result = newSurface->UnlockRect(); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock image surface, result: 0x%X.", result); + } } } mSurface = newSurface; mDirty = false; mD3DPool = poolToUse; + + return gl::Error(GL_NO_ERROR); } -HRESULT Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT *rect) +gl::Error Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT &rect) { - createSurface(); - - HRESULT result = D3DERR_INVALIDCALL; + gl::Error error = createSurface(); + if (error.isError()) + { + return error; + } if (mSurface) { - result = mSurface->LockRect(lockedRect, rect, 0); + HRESULT result = mSurface->LockRect(lockedRect, &rect, 0); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock image surface, result: 0x%X.", result); + } mDirty = true; } - return result; + return gl::Error(GL_NO_ERROR); } void Image9::unlock() @@ -263,26 +323,43 @@ bool Image9::isDirty() const return (mSurface || d3d9::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL) && mDirty; } -IDirect3DSurface9 *Image9::getSurface() +gl::Error Image9::getSurface(IDirect3DSurface9 **outSurface) { - createSurface(); + gl::Error error = createSurface(); + if (error.isError()) + { + return error; + } - return mSurface; + *outSurface = mSurface; + return gl::Error(GL_NO_ERROR); } -void Image9::setManagedSurface2D(TextureStorage *storage, int level) +gl::Error Image9::setManagedSurface2D(TextureStorage *storage, int level) { + IDirect3DSurface9 *surface = NULL; TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage); - setManagedSurface(storage9->getSurfaceLevel(level, false)); + gl::Error error = storage9->getSurfaceLevel(level, false, &surface); + if (error.isError()) + { + return error; + } + return setManagedSurface(surface); } -void Image9::setManagedSurfaceCube(TextureStorage *storage, int face, int level) +gl::Error Image9::setManagedSurfaceCube(TextureStorage *storage, int face, int level) { + IDirect3DSurface9 *surface = NULL; TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage); - setManagedSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false)); + gl::Error error = storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false, &surface); + if (error.isError()) + { + return error; + } + return setManagedSurface(surface); } -void Image9::setManagedSurface(IDirect3DSurface9 *surface) +gl::Error Image9::setManagedSurface(IDirect3DSurface9 *surface) { D3DSURFACE_DESC desc; surface->GetDesc(&desc); @@ -292,97 +369,119 @@ void Image9::setManagedSurface(IDirect3DSurface9 *surface) { if (mSurface) { - copyLockableSurfaces(surface, mSurface); + gl::Error error = copyLockableSurfaces(surface, mSurface); SafeRelease(mSurface); + if (error.isError()) + { + return error; + } } mSurface = surface; mD3DPool = desc.Pool; } + + return gl::Error(GL_NO_ERROR); } -bool Image9::copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +gl::Error Image9::copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion) { - ASSERT(getSurface() != NULL); - TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage); - return copyToSurface(storage9->getSurfaceLevel(level, true), xoffset, yoffset, width, height); -} - -bool Image9::copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) -{ - ASSERT(getSurface() != NULL); - TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage); - return copyToSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true), xoffset, yoffset, width, height); -} - -bool Image9::copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) -{ - // 3D textures are not supported by the D3D9 backend. - UNREACHABLE(); - return false; -} - -bool Image9::copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height) -{ - // 2D array textures are not supported by the D3D9 backend. - UNREACHABLE(); - return false; -} - -bool Image9::copyToSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) -{ - ASSERT(width > 0 && height > 0); - - if (!destSurface) - return false; - - IDirect3DSurface9 *sourceSurface = getSurface(); - - if (sourceSurface && sourceSurface != destSurface) + gl::Error error = createSurface(); + if (error.isError()) { - RECT rect; - rect.left = xoffset; - rect.top = yoffset; - rect.right = xoffset + width; - rect.bottom = yoffset + height; + return error; + } - POINT point = {rect.left, rect.top}; + IDirect3DSurface9 *destSurface = NULL; - IDirect3DDevice9 *device = mRenderer->getDevice(); - - if (mD3DPool == D3DPOOL_MANAGED) + if (index.type == GL_TEXTURE_2D) + { + TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage); + gl::Error error = storage9->getSurfaceLevel(index.mipIndex, true, &destSurface); + if (error.isError()) { - D3DSURFACE_DESC desc; - sourceSurface->GetDesc(&desc); - - IDirect3DSurface9 *surf = 0; - HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); - - if (SUCCEEDED(result)) - { - copyLockableSurfaces(surf, sourceSurface); - result = device->UpdateSurface(surf, &rect, destSurface, &point); - ASSERT(SUCCEEDED(result)); - SafeRelease(surf); - } + return error; } - else + } + else + { + ASSERT(gl::IsCubemapTextureTarget(index.type)); + TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage); + gl::Error error = storage9->getCubeMapSurface(index.type, index.mipIndex, true, &destSurface); + if (error.isError()) { - // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools - HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(SUCCEEDED(result)); + return error; } } + error = copyToSurface(destSurface, region.x, region.y, region.width, region.height); SafeRelease(destSurface); - return true; + return error; +} + +gl::Error Image9::copyToSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + ASSERT(width > 0 && height > 0); + ASSERT(destSurface); + + IDirect3DSurface9 *sourceSurface = NULL; + gl::Error error = getSurface(&sourceSurface); + if (error.isError()) + { + return error; + } + + ASSERT(sourceSurface && sourceSurface != destSurface); + + RECT rect; + rect.left = xoffset; + rect.top = yoffset; + rect.right = xoffset + width; + rect.bottom = yoffset + height; + + POINT point = {rect.left, rect.top}; + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + if (mD3DPool == D3DPOOL_MANAGED) + { + D3DSURFACE_DESC desc; + sourceSurface->GetDesc(&desc); + + IDirect3DSurface9 *surf = 0; + HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal CreateOffscreenPlainSurface call failed, result: 0x%X.", result); + } + + copyLockableSurfaces(surf, sourceSurface); + result = device->UpdateSurface(surf, &rect, destSurface, &point); + SafeRelease(surf); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal UpdateSurface call failed, result: 0x%X.", result); + } + } + else + { + // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools + HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal UpdateSurface call failed, result: 0x%X.", result); + } + } + + return gl::Error(GL_NO_ERROR); } // Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input // into the target pixel rectangle. -void Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLint unpackAlignment, GLenum type, const void *input) +gl::Error Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLint unpackAlignment, GLenum type, const void *input) { // 3D textures are not supported by the D3D9 backend. ASSERT(zoffset == 0 && depth == 1); @@ -400,10 +499,10 @@ void Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width }; D3DLOCKED_RECT locked; - HRESULT result = lock(&locked, &lockRect); - if (FAILED(result)) + gl::Error error = lock(&locked, lockRect); + if (error.isError()) { - return; + return error; } d3dFormatInfo.loadFunction(width, height, depth, @@ -411,10 +510,12 @@ void Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width reinterpret_cast(locked.pBits), locked.Pitch, 0); unlock(); + + return gl::Error(GL_NO_ERROR); } -void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - const void *input) +gl::Error Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + const void *input) { // 3D textures are not supported by the D3D9 backend. ASSERT(zoffset == 0 && depth == 1); @@ -437,10 +538,10 @@ void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLs }; D3DLOCKED_RECT locked; - HRESULT result = lock(&locked, &lockRect); - if (FAILED(result)) + gl::Error error = lock(&locked, lockRect); + if (error.isError()) { - return; + return error; } d3d9FormatInfo.loadFunction(width, height, depth, @@ -448,33 +549,22 @@ void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLs reinterpret_cast(locked.pBits), locked.Pitch, 0); unlock(); + + return gl::Error(GL_NO_ERROR); } // This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures -void Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +gl::Error Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source) { + ASSERT(source); + // ES3.0 only behaviour to copy into a 3d texture ASSERT(zoffset == 0); - RenderTarget9 *renderTarget = NULL; - IDirect3DSurface9 *surface = NULL; - gl::FramebufferAttachment *colorbuffer = source->getColorbuffer(0); + RenderTarget9 *renderTarget = RenderTarget9::makeRenderTarget9(source); - if (colorbuffer) - { - renderTarget = d3d9::GetAttachmentRenderTarget(colorbuffer); - } - - if (renderTarget) - { - surface = renderTarget->getSurface(); - } - - if (!surface) - { - ERR("Failed to retrieve the render target."); - return gl::error(GL_OUT_OF_MEMORY); - } + IDirect3DSurface9 *surface = renderTarget->getSurface(); + ASSERT(surface); IDirect3DDevice9 *device = mRenderer->getDevice(); @@ -486,212 +576,200 @@ void Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, if (FAILED(result)) { - ERR("Could not create matching destination surface."); SafeRelease(surface); - return gl::error(GL_OUT_OF_MEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Could not create matching destination surface, result: 0x%X.", result); } result = device->GetRenderTargetData(surface, renderTargetData); if (FAILED(result)) { - ERR("GetRenderTargetData unexpectedly failed."); SafeRelease(renderTargetData); SafeRelease(surface); - return gl::error(GL_OUT_OF_MEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "GetRenderTargetData unexpectedly failed, result: 0x%X.", result); } - RECT sourceRect = {x, y, x + width, y + height}; - RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + height}; + int width = sourceArea.width; + int height = sourceArea.height; + + RECT sourceRect = { sourceArea.x, sourceArea.y, sourceArea.x + width, sourceArea.y + height }; + RECT destRect = { xoffset, yoffset, xoffset + width, yoffset + height }; D3DLOCKED_RECT sourceLock = {0}; result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0); if (FAILED(result)) { - ERR("Failed to lock the source surface (rectangle might be invalid)."); SafeRelease(renderTargetData); SafeRelease(surface); - return gl::error(GL_OUT_OF_MEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the source surface (rectangle might be invalid), result: 0x%X.", result); } D3DLOCKED_RECT destLock = {0}; - result = lock(&destLock, &destRect); - - if (FAILED(result)) + gl::Error error = lock(&destLock, destRect); + if (error.isError()) { - ERR("Failed to lock the destination surface (rectangle might be invalid)."); renderTargetData->UnlockRect(); SafeRelease(renderTargetData); SafeRelease(surface); - return gl::error(GL_OUT_OF_MEMORY); + return error; } - if (destLock.pBits && sourceLock.pBits) - { - unsigned char *source = (unsigned char*)sourceLock.pBits; - unsigned char *dest = (unsigned char*)destLock.pBits; + ASSERT(destLock.pBits && sourceLock.pBits); - switch (description.Format) + unsigned char *sourcePixels = (unsigned char*)sourceLock.pBits; + unsigned char *destPixels = (unsigned char*)destLock.pBits; + + switch (description.Format) + { + case D3DFMT_X8R8G8B8: + case D3DFMT_A8R8G8B8: + switch (getD3DFormat()) { case D3DFMT_X8R8G8B8: case D3DFMT_A8R8G8B8: - switch(getD3DFormat()) + for (int y = 0; y < height; y++) { - case D3DFMT_X8R8G8B8: - case D3DFMT_A8R8G8B8: - for(int y = 0; y < height; y++) - { - memcpy(dest, source, 4 * width); - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - dest[x] = source[x * 4 + 2]; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_A8L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - dest[x * 2 + 0] = source[x * 4 + 2]; - dest[x * 2 + 1] = source[x * 4 + 3]; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - default: - UNREACHABLE(); + memcpy(destPixels, sourcePixels, 4 * width); + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; } break; - case D3DFMT_R5G6B5: - switch(getD3DFormat()) + case D3DFMT_L8: + for (int y = 0; y < height; y++) { - case D3DFMT_X8R8G8B8: - for(int y = 0; y < height; y++) + for (int x = 0; x < width; x++) { - for(int x = 0; x < width; x++) - { - unsigned short rgb = ((unsigned short*)source)[x]; - unsigned char red = (rgb & 0xF800) >> 8; - unsigned char green = (rgb & 0x07E0) >> 3; - unsigned char blue = (rgb & 0x001F) << 3; - dest[x + 0] = blue | (blue >> 5); - dest[x + 1] = green | (green >> 6); - dest[x + 2] = red | (red >> 5); - dest[x + 3] = 0xFF; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; + destPixels[x] = sourcePixels[x * 4 + 2]; } - break; - case D3DFMT_L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned char red = source[x * 2 + 1] & 0xF8; - dest[x] = red | (red >> 5); - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - default: - UNREACHABLE(); + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; } break; - case D3DFMT_A1R5G5B5: - switch(getD3DFormat()) + case D3DFMT_A8L8: + for (int y = 0; y < height; y++) { - case D3DFMT_X8R8G8B8: - for(int y = 0; y < height; y++) + for (int x = 0; x < width; x++) { - for(int x = 0; x < width; x++) - { - unsigned short argb = ((unsigned short*)source)[x]; - unsigned char red = (argb & 0x7C00) >> 7; - unsigned char green = (argb & 0x03E0) >> 2; - unsigned char blue = (argb & 0x001F) << 3; - dest[x + 0] = blue | (blue >> 5); - dest[x + 1] = green | (green >> 5); - dest[x + 2] = red | (red >> 5); - dest[x + 3] = 0xFF; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; + destPixels[x * 2 + 0] = sourcePixels[x * 4 + 2]; + destPixels[x * 2 + 1] = sourcePixels[x * 4 + 3]; } - break; - case D3DFMT_A8R8G8B8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned short argb = ((unsigned short*)source)[x]; - unsigned char red = (argb & 0x7C00) >> 7; - unsigned char green = (argb & 0x03E0) >> 2; - unsigned char blue = (argb & 0x001F) << 3; - unsigned char alpha = (signed short)argb >> 15; - dest[x + 0] = blue | (blue >> 5); - dest[x + 1] = green | (green >> 5); - dest[x + 2] = red | (red >> 5); - dest[x + 3] = alpha; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned char red = source[x * 2 + 1] & 0x7C; - dest[x] = (red << 1) | (red >> 4); - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_A8L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned char red = source[x * 2 + 1] & 0x7C; - dest[x * 2 + 0] = (red << 1) | (red >> 4); - dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - default: - UNREACHABLE(); + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; } break; default: UNREACHABLE(); } + break; + case D3DFMT_R5G6B5: + switch (getD3DFormat()) + { + case D3DFMT_X8R8G8B8: + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + unsigned short rgb = ((unsigned short*)sourcePixels)[x]; + unsigned char red = (rgb & 0xF800) >> 8; + unsigned char green = (rgb & 0x07E0) >> 3; + unsigned char blue = (rgb & 0x001F) << 3; + destPixels[x + 0] = blue | (blue >> 5); + destPixels[x + 1] = green | (green >> 6); + destPixels[x + 2] = red | (red >> 5); + destPixels[x + 3] = 0xFF; + } + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; + } + break; + case D3DFMT_L8: + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + unsigned char red = sourcePixels[x * 2 + 1] & 0xF8; + destPixels[x] = red | (red >> 5); + } + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; + } + break; + default: + UNREACHABLE(); + } + break; + case D3DFMT_A1R5G5B5: + switch (getD3DFormat()) + { + case D3DFMT_X8R8G8B8: + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + unsigned short argb = ((unsigned short*)sourcePixels)[x]; + unsigned char red = (argb & 0x7C00) >> 7; + unsigned char green = (argb & 0x03E0) >> 2; + unsigned char blue = (argb & 0x001F) << 3; + destPixels[x + 0] = blue | (blue >> 5); + destPixels[x + 1] = green | (green >> 5); + destPixels[x + 2] = red | (red >> 5); + destPixels[x + 3] = 0xFF; + } + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; + } + break; + case D3DFMT_A8R8G8B8: + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + unsigned short argb = ((unsigned short*)sourcePixels)[x]; + unsigned char red = (argb & 0x7C00) >> 7; + unsigned char green = (argb & 0x03E0) >> 2; + unsigned char blue = (argb & 0x001F) << 3; + unsigned char alpha = (signed short)argb >> 15; + destPixels[x + 0] = blue | (blue >> 5); + destPixels[x + 1] = green | (green >> 5); + destPixels[x + 2] = red | (red >> 5); + destPixels[x + 3] = alpha; + } + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; + } + break; + case D3DFMT_L8: + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + unsigned char red = sourcePixels[x * 2 + 1] & 0x7C; + destPixels[x] = (red << 1) | (red >> 4); + } + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; + } + break; + case D3DFMT_A8L8: + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + unsigned char red = sourcePixels[x * 2 + 1] & 0x7C; + destPixels[x * 2 + 0] = (red << 1) | (red >> 4); + destPixels[x * 2 + 1] = (signed char)sourcePixels[x * 2 + 1] >> 7; + } + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; + } + break; + default: + UNREACHABLE(); + } + break; + default: + UNREACHABLE(); } unlock(); @@ -701,6 +779,14 @@ void Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, SafeRelease(surface); mDirty = true; + return gl::Error(GL_NO_ERROR); +} + +gl::Error Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &area, const gl::ImageIndex &srcIndex, TextureStorage *srcStorage) +{ + // Currently unreachable, due to only being used in a D3D11-only workaround + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION); } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h index 08d8ee35450..8cc22588599 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h @@ -20,7 +20,6 @@ class Framebuffer; namespace rx { -class Renderer; class Renderer9; class Image9 : public ImageD3D @@ -31,41 +30,41 @@ class Image9 : public ImageD3D static Image9 *makeImage9(Image *img); - static void generateMipmap(Image9 *dest, Image9 *source); - static void generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface); - static void copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source); + static gl::Error generateMipmap(Image9 *dest, Image9 *source); + static gl::Error generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface); + static gl::Error copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source); - virtual bool redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease); + bool redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) override; D3DFORMAT getD3DFormat() const; virtual bool isDirty() const; - IDirect3DSurface9 *getSurface(); - virtual void setManagedSurface2D(TextureStorage *storage, int level); - virtual void setManagedSurfaceCube(TextureStorage *storage, int face, int level); - virtual bool copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - virtual bool copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - virtual bool copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); - virtual bool copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height); + virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level); + virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level); + virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion); - virtual void loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLint unpackAlignment, GLenum type, const void *input); - virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - const void *input); + virtual gl::Error loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLint unpackAlignment, GLenum type, const void *input); + virtual gl::Error loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + const void *input); - virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset,GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source); + virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, + const gl::ImageIndex &sourceIndex, TextureStorage *source); private: DISALLOW_COPY_AND_ASSIGN(Image9); - void createSurface(); - void setManagedSurface(IDirect3DSurface9 *surface); - bool copyToSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + gl::Error getSurface(IDirect3DSurface9 **outSurface); - HRESULT lock(D3DLOCKED_RECT *lockedRect, const RECT *rect); + gl::Error createSurface(); + gl::Error setManagedSurface(IDirect3DSurface9 *surface); + gl::Error copyToSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + + gl::Error lock(D3DLOCKED_RECT *lockedRect, const RECT &rect); void unlock(); - + Renderer9 *mRenderer; D3DPOOL mD3DPool; // can only be D3DPOOL_SYSTEMMEM or D3DPOOL_MANAGED since it needs to be lockable. diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h index d0970d6ac57..2375fcf4b0d 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h @@ -40,7 +40,7 @@ class IndexBuffer9 : public IndexBuffer private: DISALLOW_COPY_AND_ASSIGN(IndexBuffer9); - rx::Renderer9 *const mRenderer; + Renderer9 *const mRenderer; IDirect3DIndexBuffer9 *mIndexBuffer; unsigned int mBufferSize; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp index 815fc01a9b7..a3cab578be1 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp @@ -15,7 +15,7 @@ namespace rx { -Query9::Query9(rx::Renderer9 *renderer, GLenum type) +Query9::Query9(Renderer9 *renderer, GLenum type) : QueryImpl(type), mResult(GL_FALSE), mQueryFinished(false), diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h index 513e0ba6fd5..36851c6c6ca 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h @@ -18,7 +18,7 @@ class Renderer9; class Query9 : public QueryImpl { public: - Query9(rx::Renderer9 *renderer, GLenum type); + Query9(Renderer9 *renderer, GLenum type); virtual ~Query9(); virtual gl::Error begin(); @@ -34,7 +34,7 @@ class Query9 : public QueryImpl GLuint mResult; bool mQueryFinished; - rx::Renderer9 *mRenderer; + Renderer9 *mRenderer; IDirect3DQuery9 *mQuery; }; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp index 13321ac8cd2..53d1f752fa6 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp @@ -10,115 +10,83 @@ #include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" #include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" #include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h" #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" #include "libGLESv2/main.h" namespace rx { -// TODO: AddRef the incoming surface to take ownership instead of expecting that its ref is being given. -RenderTarget9::RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface) +RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTarget *target) { - mRenderer = Renderer9::makeRenderer9(renderer); - mRenderTarget = surface; + ASSERT(HAS_DYNAMIC_TYPE(RenderTarget9*, target)); + return static_cast(target); +} + +void RenderTarget9::invalidate(GLint x, GLint y, GLsizei width, GLsizei height) +{ + // Currently a no-op +} + +// TODO: AddRef the incoming surface to take ownership instead of expecting that its ref is being given. +TextureRenderTarget9::TextureRenderTarget9(IDirect3DSurface9 *surface, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, + GLsizei samples) + : mWidth(width), + mHeight(height), + mDepth(depth), + mInternalFormat(internalFormat), + mActualFormat(internalFormat), + mSamples(samples), + mRenderTarget(surface) +{ + ASSERT(mDepth == 1); if (mRenderTarget) { D3DSURFACE_DESC description; mRenderTarget->GetDesc(&description); - mWidth = description.Width; - mHeight = description.Height; - mDepth = 1; - const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(description.Format); - mInternalFormat = d3dFormatInfo.internalFormat; mActualFormat = d3dFormatInfo.internalFormat; - mSamples = d3d9_gl::GetSamplesCount(description.MultiSampleType); } } -RenderTarget9::RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples) -{ - mRenderer = Renderer9::makeRenderer9(renderer); - mRenderTarget = NULL; - - const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(internalFormat); - const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(d3d9FormatInfo.renderFormat); - - const gl::TextureCaps &textureCaps = mRenderer->getRendererTextureCaps().get(internalFormat); - GLuint supportedSamples = textureCaps.getNearestSamples(samples); - - HRESULT result = D3DERR_INVALIDCALL; - - if (width > 0 && height > 0) - { - IDirect3DDevice9 *device = mRenderer->getDevice(); - - bool requiresInitialization = false; - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); - if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) - { - result = device->CreateDepthStencilSurface(width, height, d3d9FormatInfo.renderFormat, - gl_d3d9::GetMultisampleType(supportedSamples), - 0, FALSE, &mRenderTarget, NULL); - } - else - { - requiresInitialization = (d3d9FormatInfo.dataInitializerFunction != NULL); - result = device->CreateRenderTarget(width, height, d3d9FormatInfo.renderFormat, - gl_d3d9::GetMultisampleType(supportedSamples), - 0, FALSE, &mRenderTarget, NULL); - } - - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) - { - gl::error(GL_OUT_OF_MEMORY); - - return; - } - - ASSERT(SUCCEEDED(result)); - - if (requiresInitialization) - { - // This format requires that the data be initialized before the render target can be used - // Unfortunately this requires a Get call on the d3d device but it is far better than having - // to mark the render target as lockable and copy data to the gpu. - IDirect3DSurface9 *prevRenderTarget = NULL; - device->GetRenderTarget(0, &prevRenderTarget); - device->SetRenderTarget(0, mRenderTarget); - device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.0f, 0); - device->SetRenderTarget(0, prevRenderTarget); - } - } - - mWidth = width; - mHeight = height; - mDepth = 1; - mInternalFormat = internalFormat; - mSamples = supportedSamples; - mActualFormat = d3dFormatInfo.internalFormat; -} - -RenderTarget9::~RenderTarget9() +TextureRenderTarget9::~TextureRenderTarget9() { SafeRelease(mRenderTarget); } -RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTarget *target) +GLsizei TextureRenderTarget9::getWidth() const { - ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget9*, target)); - return static_cast(target); + return mWidth; } -void RenderTarget9::invalidate(GLint x, GLint y, GLsizei width, GLsizei height) +GLsizei TextureRenderTarget9::getHeight() const { - // Currently a no-op + return mHeight; } -IDirect3DSurface9 *RenderTarget9::getSurface() +GLsizei TextureRenderTarget9::getDepth() const +{ + return mDepth; +} + +GLenum TextureRenderTarget9::getInternalFormat() const +{ + return mInternalFormat; +} + +GLenum TextureRenderTarget9::getActualFormat() const +{ + return mActualFormat; +} + +GLsizei TextureRenderTarget9::getSamples() const +{ + return mSamples; +} + +IDirect3DSurface9 *TextureRenderTarget9::getSurface() { // Caller is responsible for releasing the returned surface reference. // TODO: remove the AddRef to match RenderTarget11 @@ -130,4 +98,51 @@ IDirect3DSurface9 *RenderTarget9::getSurface() return mRenderTarget; } + +SurfaceRenderTarget9::SurfaceRenderTarget9(SwapChain9 *swapChain, bool depth) + : mSwapChain(swapChain), + mDepth(depth) +{ +} + +SurfaceRenderTarget9::~SurfaceRenderTarget9() +{ +} + +GLsizei SurfaceRenderTarget9::getWidth() const +{ + return mSwapChain->getWidth(); +} + +GLsizei SurfaceRenderTarget9::getHeight() const +{ + return mSwapChain->getHeight(); +} + +GLsizei SurfaceRenderTarget9::getDepth() const +{ + return 1; +} + +GLenum SurfaceRenderTarget9::getInternalFormat() const +{ + return (mDepth ? mSwapChain->GetDepthBufferInternalFormat() : mSwapChain->GetBackBufferInternalFormat()); +} + +GLenum SurfaceRenderTarget9::getActualFormat() const +{ + return d3d9::GetD3DFormatInfo(d3d9::GetTextureFormatInfo(getInternalFormat()).texFormat).internalFormat; +} + +GLsizei SurfaceRenderTarget9::getSamples() const +{ + // Our EGL surfaces do not support multisampling. + return 0; +} + +IDirect3DSurface9 *SurfaceRenderTarget9::getSurface() +{ + return (mDepth ? mSwapChain->getDepthStencil() : mSwapChain->getRenderTarget()); +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h index 68d7adb49ef..4585697f4c1 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h @@ -14,28 +14,74 @@ namespace rx { -class Renderer; class Renderer9; +class SwapChain9; class RenderTarget9 : public RenderTarget { public: - RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface); - RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples); - virtual ~RenderTarget9(); + RenderTarget9() { } + virtual ~RenderTarget9() { } static RenderTarget9 *makeRenderTarget9(RenderTarget *renderTarget); - virtual void invalidate(GLint x, GLint y, GLsizei width, GLsizei height); + void invalidate(GLint x, GLint y, GLsizei width, GLsizei height) override; - IDirect3DSurface9 *getSurface(); + virtual IDirect3DSurface9 *getSurface() = 0; private: DISALLOW_COPY_AND_ASSIGN(RenderTarget9); +}; + +class TextureRenderTarget9 : public RenderTarget9 +{ + public: + TextureRenderTarget9(IDirect3DSurface9 *surface, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, + GLsizei samples); + virtual ~TextureRenderTarget9(); + + GLsizei getWidth() const override; + GLsizei getHeight() const override; + GLsizei getDepth() const override; + GLenum getInternalFormat() const override; + GLenum getActualFormat() const override; + GLsizei getSamples() const override; + + IDirect3DSurface9 *getSurface() override; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureRenderTarget9); + + GLsizei mWidth; + GLsizei mHeight; + GLsizei mDepth; + GLenum mInternalFormat; + GLenum mActualFormat; + GLsizei mSamples; IDirect3DSurface9 *mRenderTarget; +}; - Renderer9 *mRenderer; +class SurfaceRenderTarget9 : public RenderTarget9 +{ + public: + SurfaceRenderTarget9(SwapChain9 *swapChain, bool depth); + virtual ~SurfaceRenderTarget9(); + + GLsizei getWidth() const override; + GLsizei getHeight() const override; + GLsizei getDepth() const override; + GLenum getInternalFormat() const override; + GLenum getActualFormat() const override; + GLsizei getSamples() const override; + + IDirect3DSurface9 *getSurface() override; + + private: + DISALLOW_COPY_AND_ASSIGN(SurfaceRenderTarget9); + + SwapChain9 *mSwapChain; + bool mDepth; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp index d63f9b8582a..601cd24b105 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp @@ -26,6 +26,7 @@ #include "libGLESv2/renderer/d3d/ShaderD3D.h" #include "libGLESv2/renderer/d3d/TextureD3D.h" #include "libGLESv2/renderer/d3d/TransformFeedbackD3D.h" +#include "libGLESv2/renderer/d3d/RenderbufferD3D.h" #include "libGLESv2/main.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/Texture.h" @@ -33,10 +34,12 @@ #include "libGLESv2/FramebufferAttachment.h" #include "libGLESv2/Renderbuffer.h" #include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/State.h" #include "libGLESv2/angletypes.h" #include "libEGL/Display.h" +#include "common/features.h" #include "common/utilities.h" #include @@ -44,14 +47,6 @@ // Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros #define REF_RAST 0 -// The "Debug This Pixel..." feature in PIX often fails when using the -// D3D9Ex interfaces. In order to get debug pixel to work on a Vista/Win 7 -// machine, define "ANGLE_ENABLE_D3D9EX=0" in your project file. -#if !defined(ANGLE_ENABLE_D3D9EX) -// Enables use of the IDirect3D9Ex interface, when available -#define ANGLE_ENABLE_D3D9EX 1 -#endif // !defined(ANGLE_ENABLE_D3D9EX) - #if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) #define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 #endif @@ -96,8 +91,8 @@ enum MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4 }; -Renderer9::Renderer9(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay) - : Renderer(display), +Renderer9::Renderer9(egl::Display *display, EGLNativeDisplayType hDc, const egl::AttributeMap &attributes) + : RendererD3D(display), mDc(hDc) { mD3d9Module = NULL; @@ -177,8 +172,8 @@ void Renderer9::release() Renderer9 *Renderer9::makeRenderer9(Renderer *renderer) { - ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer9*, renderer)); - return static_cast(renderer); + ASSERT(HAS_DYNAMIC_TYPE(Renderer9*, renderer)); + return static_cast(renderer); } EGLint Renderer9::initialize() @@ -202,7 +197,7 @@ EGLint Renderer9::initialize() // Use Direct3D9Ex if available. Among other things, this version is less // inclined to report a lost context, for example when the user switches // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available. - if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) + if (ANGLE_D3D9EX == ANGLE_ENABLED && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) { ASSERT(mD3d9Ex); mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast(&mD3d9)); @@ -386,10 +381,13 @@ void Renderer9::initializeDevice() mSceneStarted = false; - ASSERT(!mBlit && !mVertexDataManager && !mIndexDataManager); + ASSERT(!mBlit); mBlit = new Blit9(this); - mVertexDataManager = new rx::VertexDataManager(this); - mIndexDataManager = new rx::IndexDataManager(this); + mBlit->initialize(); + + ASSERT(!mVertexDataManager && !mIndexDataManager); + mVertexDataManager = new VertexDataManager(this); + mIndexDataManager = new IndexDataManager(this); } D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters() @@ -481,68 +479,92 @@ void Renderer9::endScene() } } -void Renderer9::sync(bool block) +gl::Error Renderer9::sync(bool block) { - HRESULT result; - - IDirect3DQuery9* query = allocateEventQuery(); - if (!query) + IDirect3DQuery9* query = NULL; + gl::Error error = allocateEventQuery(&query); + if (error.isError()) { - return; + return error; } - result = query->Issue(D3DISSUE_END); - ASSERT(SUCCEEDED(result)); - - do + HRESULT result = query->Issue(D3DISSUE_END); + if (FAILED(result)) { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to issue event query, result: 0x%X.", result); + } + + // Grab the query data once in blocking and non-blocking case + result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); + if (FAILED(result)) + { + if (d3d9::isDeviceLostError(result)) + { + notifyDeviceLost(); + } + + freeEventQuery(query); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result); + } + + // If blocking, loop until the query completes + while (block && result == S_FALSE) + { + // Keep polling, but allow other threads to do something useful first + Sleep(0); + result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); - if(block && result == S_FALSE) + // explicitly check for device loss + // some drivers seem to return S_FALSE even if the device is lost + // instead of D3DERR_DEVICELOST like they should + if (result == S_FALSE && testDeviceLost(false)) { - // Keep polling, but allow other threads to do something useful first - Sleep(0); - // explicitly check for device loss - // some drivers seem to return S_FALSE even if the device is lost - // instead of D3DERR_DEVICELOST like they should - if (testDeviceLost(false)) - { - result = D3DERR_DEVICELOST; - } + result = D3DERR_DEVICELOST; } + + if (FAILED(result)) + { + if (d3d9::isDeviceLostError(result)) + { + notifyDeviceLost(); + } + + freeEventQuery(query); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result); + } + } - while(block && result == S_FALSE); freeEventQuery(query); - if (d3d9::isDeviceLostError(result)) - { - notifyDeviceLost(); - } + return gl::Error(GL_NO_ERROR); } -SwapChain *Renderer9::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) +SwapChain *Renderer9::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) { - return new rx::SwapChain9(this, window, shareHandle, backBufferFormat, depthBufferFormat); + return new SwapChain9(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat); } -IDirect3DQuery9* Renderer9::allocateEventQuery() +gl::Error Renderer9::allocateEventQuery(IDirect3DQuery9 **outQuery) { - IDirect3DQuery9 *query = NULL; - if (mEventQueryPool.empty()) { - HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(SUCCEEDED(result)); + HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, outQuery); + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate event query, result: 0x%X.", result); + } } else { - query = mEventQueryPool.back(); + *outQuery = mEventQueryPool.back(); mEventQueryPool.pop_back(); } - return query; + return gl::Error(GL_NO_ERROR); } void Renderer9::freeEventQuery(IDirect3DQuery9* query) @@ -557,14 +579,14 @@ void Renderer9::freeEventQuery(IDirect3DQuery9* query) } } -IDirect3DVertexShader9 *Renderer9::createVertexShader(const DWORD *function, size_t length) +gl::Error Renderer9::createVertexShader(const DWORD *function, size_t length, IDirect3DVertexShader9 **outShader) { - return mVertexShaderCache.create(function, length); + return mVertexShaderCache.create(function, length, outShader); } -IDirect3DPixelShader9 *Renderer9::createPixelShader(const DWORD *function, size_t length) +gl::Error Renderer9::createPixelShader(const DWORD *function, size_t length, IDirect3DPixelShader9 **outShader) { - return mPixelShaderCache.create(function, length); + return mPixelShaderCache.create(function, length, outShader); } HRESULT Renderer9::createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer) @@ -604,9 +626,16 @@ QueryImpl *Renderer9::createQuery(GLenum type) return new Query9(this, type); } -FenceImpl *Renderer9::createFence() +FenceNVImpl *Renderer9::createFenceNV() { - return new Fence9(this); + return new FenceNV9(this); +} + +FenceSyncImpl *Renderer9::createFenceSync() +{ + // Renderer9 doesn't support ES 3.0 and its sync objects. + UNREACHABLE(); + return NULL; } TransformFeedbackImpl* Renderer9::createTransformFeedback() @@ -620,12 +649,12 @@ bool Renderer9::supportsFastCopyBufferToTexture(GLenum internalFormat) const return false; } -bool Renderer9::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, - GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) +gl::Error Renderer9::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) { // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3. UNREACHABLE(); - return false; + return gl::Error(GL_INVALID_OPERATION); } gl::Error Renderer9::generateSwizzle(gl::Texture *texture) @@ -635,7 +664,7 @@ gl::Error Renderer9::generateSwizzle(gl::Texture *texture) return gl::Error(GL_INVALID_OPERATION); } -gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState) +gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &samplerState) { std::vector &forceSetSamplers = (type == gl::SAMPLER_PIXEL) ? mForceSetPixelSamplerStates : mForceSetVertexSamplerStates; std::vector &appliedSamplers = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates: mCurVertexSamplerStates; @@ -645,6 +674,10 @@ gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, const gl:: int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; int d3dSampler = index + d3dSamplerOffset; + // Make sure to add the level offset for our tiny compressed texture workaround + TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation()); + DWORD baseLevel = samplerState.baseLevel + textureD3D->getNativeTexture()->getTopLevel(); + mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, gl_d3d9::ConvertTextureWrap(samplerState.wrapS)); mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, gl_d3d9::ConvertTextureWrap(samplerState.wrapT)); @@ -653,7 +686,7 @@ gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, const gl:: gl_d3d9::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, samplerState.maxAnisotropy); mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter); mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter); - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, samplerState.baseLevel); + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, baseLevel); if (getRendererExtensions().textureFilterAnisotropic) { mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy); @@ -684,7 +717,12 @@ gl::Error Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *te if (texStorage) { TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage); - d3dTexture = storage9->getBaseTexture(); + + gl::Error error = storage9->getBaseTexture(&d3dTexture); + if (error.isError()) + { + return error; + } } // If we get NULL back from getBaseTexture here, something went wrong // in the texture class and we're unexpectedly missing the d3d texture @@ -751,7 +789,7 @@ gl::Error Renderer9::setRasterizerState(const gl::RasterizerState &rasterState) return gl::Error(GL_NO_ERROR); } -gl::Error Renderer9::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, +gl::Error Renderer9::setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, unsigned int sampleMask) { bool blendStateChanged = mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0; @@ -1097,13 +1135,9 @@ bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count) } -gl::FramebufferAttachment *Renderer9::getNullColorbuffer(gl::FramebufferAttachment *depthbuffer) +gl::Error Renderer9::getNullColorbuffer(gl::FramebufferAttachment *depthbuffer, gl::FramebufferAttachment **outColorBuffer) { - if (!depthbuffer) - { - ERR("Unexpected null depthbuffer for depth-only FBO."); - return NULL; - } + ASSERT(depthbuffer); GLsizei width = depthbuffer->getWidth(); GLsizei height = depthbuffer->getHeight(); @@ -1116,11 +1150,19 @@ gl::FramebufferAttachment *Renderer9::getNullColorbuffer(gl::FramebufferAttachme mNullColorbufferCache[i].height == height) { mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU; - return mNullColorbufferCache[i].buffer; + *outColorBuffer = mNullColorbufferCache[i].buffer; + return gl::Error(GL_NO_ERROR); } } - gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(0, new gl::Colorbuffer(this, width, height, GL_NONE, 0)); + gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(createRenderbuffer(), 0); + gl::Error error = nullRenderbuffer->setStorage(width, height, GL_NONE, 0); + if (error.isError()) + { + SafeDelete(nullRenderbuffer); + return error; + } + gl::RenderbufferAttachment *nullbuffer = new gl::RenderbufferAttachment(GL_NONE, nullRenderbuffer); // add nullbuffer to the cache @@ -1139,40 +1181,40 @@ gl::FramebufferAttachment *Renderer9::getNullColorbuffer(gl::FramebufferAttachme oldest->width = width; oldest->height = height; - return nullbuffer; + *outColorBuffer = nullbuffer; + return gl::Error(GL_NO_ERROR); } -gl::Error Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) +gl::Error Renderer9::applyRenderTarget(const gl::Framebuffer *framebuffer) { // if there is no color attachment we must synthesize a NULL colorattachment // to keep the D3D runtime happy. This should only be possible if depth texturing. gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(0); if (!attachment) { - attachment = getNullColorbuffer(framebuffer->getDepthbuffer()); - } - if (!attachment) - { - return gl::Error(GL_OUT_OF_MEMORY, "Unable to locate renderbuffer for FBO."); + gl::Error error = getNullColorbuffer(framebuffer->getDepthbuffer(), &attachment); + if (error.isError()) + { + return error; + } } + ASSERT(attachment); bool renderTargetChanged = false; unsigned int renderTargetSerial = GetAttachmentSerial(attachment); if (renderTargetSerial != mAppliedRenderTargetSerial) { // Apply the render target on the device - IDirect3DSurface9 *renderTargetSurface = NULL; - - RenderTarget9 *renderTarget = d3d9::GetAttachmentRenderTarget(attachment); - if (renderTarget) + RenderTarget9 *renderTarget = NULL; + gl::Error error = d3d9::GetAttachmentRenderTarget(attachment, &renderTarget); + if (error.isError()) { - renderTargetSurface = renderTarget->getSurface(); + return error; } + ASSERT(renderTarget); - if (!renderTargetSurface) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal render target pointer unexpectedly null."); - } + IDirect3DSurface9 *renderTargetSurface = renderTarget->getSurface(); + ASSERT(renderTargetSurface); mDevice->SetRenderTarget(0, renderTargetSurface); SafeRelease(renderTargetSurface); @@ -1204,18 +1246,16 @@ gl::Error Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) // Apply the depth stencil on the device if (depthStencil) { - IDirect3DSurface9 *depthStencilSurface = NULL; - rx::RenderTarget9 *depthStencilRenderTarget = d3d9::GetAttachmentRenderTarget(depthStencil); - - if (depthStencilRenderTarget) + RenderTarget9 *depthStencilRenderTarget = NULL; + gl::Error error = d3d9::GetAttachmentRenderTarget(depthStencil, &depthStencilRenderTarget); + if (error.isError()) { - depthStencilSurface = depthStencilRenderTarget->getSurface(); + return error; } + ASSERT(depthStencilRenderTarget); - if (!depthStencilSurface) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil pointer unexpectedly null."); - } + IDirect3DSurface9 *depthStencilSurface = depthStencilRenderTarget->getSurface(); + ASSERT(depthStencilSurface); mDevice->SetDepthStencilSurface(depthStencilSurface); SafeRelease(depthStencilSurface); @@ -1260,17 +1300,16 @@ gl::Error Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) return gl::Error(GL_NO_ERROR); } -gl::Error Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], - GLint first, GLsizei count, GLsizei instances) +gl::Error Renderer9::applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances) { TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; - gl::Error error = mVertexDataManager->prepareVertexData(vertexAttributes, currentValues, programBinary, first, count, attributes, instances); + gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, attributes, instances); if (error.isError()) { return error; } - return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, &mRepeatDraw); + return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, state.getCurrentProgramBinary(), instances, &mRepeatDraw); } // Applies the indices and element array bindings to the Direct3D 9 device @@ -1296,7 +1335,7 @@ gl::Error Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *element return gl::Error(GL_NO_ERROR); } -void Renderer9::applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]) +void Renderer9::applyTransformFeedbackBuffers(const gl::State& state) { UNREACHABLE(); } @@ -1373,10 +1412,15 @@ gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indi // Get the raw indices for an indexed draw if (type != GL_NONE && elementArrayBuffer) { - gl::Buffer *indexBuffer = elementArrayBuffer; - BufferImpl *storage = indexBuffer->getImplementation(); + BufferD3D *storage = BufferD3D::makeFromBuffer(elementArrayBuffer); intptr_t offset = reinterpret_cast(indices); - indices = static_cast(storage->getData()) + offset; + const uint8_t *bufferData = NULL; + gl::Error error = storage->getData(&bufferData); + if (error.isError()) + { + return error; + } + indices = bufferData + offset; } unsigned int startIndex = 0; @@ -1570,9 +1614,17 @@ gl::Error Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid if (elementArrayBuffer) { - BufferImpl *storage = elementArrayBuffer->getImplementation(); + BufferD3D *storage = BufferD3D::makeFromBuffer(elementArrayBuffer); intptr_t offset = reinterpret_cast(indices); - indices = static_cast(storage->getData()) + offset; + + const uint8_t *bufferData = NULL; + gl::Error error = storage->getData(&bufferData); + if (error.isError()) + { + return error; + } + + indices = bufferData + offset; } switch (type) @@ -1662,8 +1714,21 @@ gl::Error Renderer9::applyShaders(gl::ProgramBinary *programBinary, const gl::Ve ASSERT(!transformFeedbackActive); ASSERT(!rasterizerDiscard); - ShaderExecutable *vertexExe = programBinary->getVertexExecutableForInputLayout(inputLayout); - ShaderExecutable *pixelExe = programBinary->getPixelExecutableForFramebuffer(framebuffer); + ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary->getImplementation()); + + ShaderExecutable *vertexExe = NULL; + gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe); + if (error.isError()) + { + return error; + } + + ShaderExecutable *pixelExe = NULL; + error = programD3D->getPixelExecutableForFramebuffer(framebuffer, &pixelExe); + if (error.isError()) + { + return error; + } IDirect3DVertexShader9 *vertexShader = (vertexExe ? ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader() : NULL); IDirect3DPixelShader9 *pixelShader = (pixelExe ? ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader() : NULL); @@ -1688,7 +1753,7 @@ gl::Error Renderer9::applyShaders(gl::ProgramBinary *programBinary, const gl::Ve unsigned int programSerial = programBinary->getSerial(); if (programSerial != mAppliedProgramSerial) { - programBinary->dirtyAllUniforms(); + programD3D->dirtyAllUniforms(); mDxUniformsDirty = true; mAppliedProgramSerial = programSerial; } @@ -1696,10 +1761,8 @@ gl::Error Renderer9::applyShaders(gl::ProgramBinary *programBinary, const gl::Ve return gl::Error(GL_NO_ERROR); } -gl::Error Renderer9::applyUniforms(const gl::ProgramBinary &programBinary) +gl::Error Renderer9::applyUniforms(const ProgramImpl &program, const std::vector &uniformArray) { - const std::vector &uniformArray = programBinary.getUniforms(); - for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++) { gl::LinkedUniform *targetUniform = uniformArray[uniformIndex]; @@ -1797,7 +1860,7 @@ void Renderer9::applyUniformnbv(gl::LinkedUniform *targetUniform, const GLint *v applyUniformnfv(targetUniform, (GLfloat*)vector); } -gl::Error Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) +gl::Error Renderer9::clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) { if (clearParams.colorClearType != GL_FLOAT) { @@ -2219,7 +2282,7 @@ bool Renderer9::isRemovedDeviceResettable() const { bool success = false; -#ifdef ANGLE_ENABLE_D3D9EX +#if ANGLE_D3D9EX == ANGLE_ENABLED IDirect3D9Ex *d3d9Ex = NULL; typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**); Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex")); @@ -2330,82 +2393,6 @@ int Renderer9::getMaxSwapInterval() const return mMaxSwapInterval; } -bool Renderer9::copyToRenderTarget2D(TextureStorage *dest, TextureStorage *source) -{ - bool result = false; - - if (source && dest) - { - TextureStorage9_2D *source9 = TextureStorage9_2D::makeTextureStorage9_2D(source); - TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(dest); - - int levels = source9->getLevelCount(); - for (int i = 0; i < levels; ++i) - { - IDirect3DSurface9 *srcSurf = source9->getSurfaceLevel(i, false); - IDirect3DSurface9 *dstSurf = dest9->getSurfaceLevel(i, false); - - result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged()); - - SafeRelease(srcSurf); - SafeRelease(dstSurf); - - if (!result) - { - return false; - } - } - } - - return result; -} - -bool Renderer9::copyToRenderTargetCube(TextureStorage *dest, TextureStorage *source) -{ - bool result = false; - - if (source && dest) - { - TextureStorage9_Cube *source9 = TextureStorage9_Cube::makeTextureStorage9_Cube(source); - TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(dest); - int levels = source9->getLevelCount(); - for (int f = 0; f < 6; f++) - { - for (int i = 0; i < levels; i++) - { - IDirect3DSurface9 *srcSurf = source9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false); - IDirect3DSurface9 *dstSurf = dest9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true); - - result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged()); - - SafeRelease(srcSurf); - SafeRelease(dstSurf); - - if (!result) - { - return false; - } - } - } - } - - return result; -} - -bool Renderer9::copyToRenderTarget3D(TextureStorage *dest, TextureStorage *source) -{ - // 3D textures are not available in the D3D9 backend. - UNREACHABLE(); - return false; -} - -bool Renderer9::copyToRenderTarget2DArray(TextureStorage *dest, TextureStorage *source) -{ - // 2D array textures are not supported by the D3D9 backend. - UNREACHABLE(); - return false; -} - D3DPOOL Renderer9::getBufferPool(DWORD usage) const { if (mD3d9Ex != NULL) @@ -2423,8 +2410,8 @@ D3DPOOL Renderer9::getBufferPool(DWORD usage) const return D3DPOOL_DEFAULT; } -bool Renderer9::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) +gl::Error Renderer9::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) { RECT rect; rect.left = sourceRect.x; @@ -2435,8 +2422,8 @@ bool Renderer9::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &s return mBlit->copy2D(framebuffer, rect, destFormat, xoffset, yoffset, storage, level); } -bool Renderer9::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level) +gl::Error Renderer9::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level) { RECT rect; rect.left = sourceRect.x; @@ -2447,24 +2434,26 @@ bool Renderer9::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle return mBlit->copyCube(framebuffer, rect, destFormat, xoffset, yoffset, storage, target, level); } -bool Renderer9::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) +gl::Error Renderer9::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) { // 3D textures are not available in the D3D9 backend. UNREACHABLE(); - return false; + return gl::Error(GL_INVALID_OPERATION); } -bool Renderer9::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) +gl::Error Renderer9::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) { // 2D array textures are not available in the D3D9 backend. UNREACHABLE(); - return false; + return gl::Error(GL_INVALID_OPERATION); } -bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect, gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect, - const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) +gl::Error Renderer9::blitRect(const gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect, + const gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect, + const gl::Rectangle *scissor, bool blitRenderTarget, + bool blitDepth, bool blitStencil, GLenum filter) { ASSERT(filter == GL_NEAREST); @@ -2473,35 +2462,33 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle & if (blitRenderTarget) { gl::FramebufferAttachment *readBuffer = readFramebuffer->getColorbuffer(0); - gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getColorbuffer(0); + ASSERT(readBuffer); + RenderTarget9 *readRenderTarget = NULL; + gl::Error error = d3d9::GetAttachmentRenderTarget(readBuffer, &readRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(readRenderTarget); + + gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getColorbuffer(0); + ASSERT(drawBuffer); + RenderTarget9 *drawRenderTarget = NULL; - IDirect3DSurface9* readSurface = NULL; - IDirect3DSurface9* drawSurface = NULL; + error = d3d9::GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(drawRenderTarget); - if (readBuffer) - { - readRenderTarget = d3d9::GetAttachmentRenderTarget(readBuffer); - } - if (drawBuffer) - { - drawRenderTarget = d3d9::GetAttachmentRenderTarget(drawBuffer); - } + // The getSurface calls do an AddRef so save them until after no errors are possible + IDirect3DSurface9* readSurface = readRenderTarget->getSurface(); + ASSERT(readSurface); - if (readRenderTarget) - { - readSurface = readRenderTarget->getSurface(); - } - if (drawRenderTarget) - { - drawSurface = drawRenderTarget->getSurface(); - } - - if (!readSurface || !drawSurface) - { - ERR("Failed to retrieve the render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } + IDirect3DSurface9* drawSurface = drawRenderTarget->getSurface(); + ASSERT(drawSurface); gl::Extents srcSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1); gl::Extents dstSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1); @@ -2594,43 +2581,40 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle & if (FAILED(result)) { - ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result); - return false; + return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result); } } if (blitDepth || blitStencil) { gl::FramebufferAttachment *readBuffer = readFramebuffer->getDepthOrStencilbuffer(); - gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer(); + ASSERT(readBuffer); + RenderTarget9 *readDepthStencil = NULL; + gl::Error error = d3d9::GetAttachmentRenderTarget(readBuffer, &readDepthStencil); + if (error.isError()) + { + return error; + } + ASSERT(readDepthStencil); + + gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer(); + ASSERT(drawBuffer); + RenderTarget9 *drawDepthStencil = NULL; - IDirect3DSurface9* readSurface = NULL; - IDirect3DSurface9* drawSurface = NULL; + error = d3d9::GetAttachmentRenderTarget(drawBuffer, &drawDepthStencil); + if (error.isError()) + { + return error; + } + ASSERT(drawDepthStencil); - if (readBuffer) - { - readDepthStencil = d3d9::GetAttachmentRenderTarget(readBuffer); - } - if (drawBuffer) - { - drawDepthStencil = d3d9::GetAttachmentRenderTarget(drawBuffer); - } + // The getSurface calls do an AddRef so save them until after no errors are possible + IDirect3DSurface9* readSurface = readDepthStencil->getSurface(); + ASSERT(readDepthStencil); - if (readDepthStencil) - { - readSurface = readDepthStencil->getSurface(); - } - if (drawDepthStencil) - { - drawSurface = drawDepthStencil->getSurface(); - } - - if (!readSurface || !drawSurface) - { - ERR("Failed to retrieve the render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } + IDirect3DSurface9* drawSurface = drawDepthStencil->getSurface(); + ASSERT(drawDepthStencil); HRESULT result = mDevice->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE); @@ -2639,38 +2623,31 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle & if (FAILED(result)) { - ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result); - return false; + return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result); } } - return true; + return gl::Error(GL_NO_ERROR); } -gl::Error Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, +gl::Error Renderer9::readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) { ASSERT(pack.pixelBuffer.get() == NULL); - RenderTarget9 *renderTarget = NULL; - IDirect3DSurface9 *surface = NULL; gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); + ASSERT(colorbuffer); - if (colorbuffer) + RenderTarget9 *renderTarget = NULL; + gl::Error error = d3d9::GetAttachmentRenderTarget(colorbuffer, &renderTarget); + if (error.isError()) { - renderTarget = d3d9::GetAttachmentRenderTarget(colorbuffer); + return error; } + ASSERT(renderTarget); - if (renderTarget) - { - surface = renderTarget->getSurface(); - } - - if (!surface) - { - // context must be lost - return gl::Error(GL_NO_ERROR); - } + IDirect3DSurface9 *surface = renderTarget->getSurface(); + ASSERT(surface); D3DSURFACE_DESC desc; surface->GetDesc(&desc); @@ -2825,33 +2802,67 @@ gl::Error Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, return gl::Error(GL_NO_ERROR); } -RenderTarget *Renderer9::createRenderTarget(SwapChain *swapChain, bool depth) +gl::Error Renderer9::createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT) { SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain); - IDirect3DSurface9 *surface = NULL; - if (depth) - { - surface = swapChain9->getDepthStencil(); - } - else - { - surface = swapChain9->getRenderTarget(); - } - - RenderTarget9 *renderTarget = new RenderTarget9(this, surface); - - return renderTarget; + *outRT = new SurfaceRenderTarget9(swapChain9, depth); + return gl::Error(GL_NO_ERROR); } -RenderTarget *Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples) +gl::Error Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT) { - RenderTarget9 *renderTarget = new RenderTarget9(this, width, height, format, samples); - return renderTarget; + const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(format); + + const gl::TextureCaps &textureCaps = getRendererTextureCaps().get(format); + GLuint supportedSamples = textureCaps.getNearestSamples(samples); + + IDirect3DSurface9 *renderTarget = NULL; + if (width > 0 && height > 0) + { + bool requiresInitialization = false; + HRESULT result = D3DERR_INVALIDCALL; + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) + { + result = mDevice->CreateDepthStencilSurface(width, height, d3d9FormatInfo.renderFormat, + gl_d3d9::GetMultisampleType(supportedSamples), + 0, FALSE, &renderTarget, NULL); + } + else + { + requiresInitialization = (d3d9FormatInfo.dataInitializerFunction != NULL); + result = mDevice->CreateRenderTarget(width, height, d3d9FormatInfo.renderFormat, + gl_d3d9::GetMultisampleType(supportedSamples), + 0, FALSE, &renderTarget, NULL); + } + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target, result: 0x%X.", result); + } + + if (requiresInitialization) + { + // This format requires that the data be initialized before the render target can be used + // Unfortunately this requires a Get call on the d3d device but it is far better than having + // to mark the render target as lockable and copy data to the gpu. + IDirect3DSurface9 *prevRenderTarget = NULL; + mDevice->GetRenderTarget(0, &prevRenderTarget); + mDevice->SetRenderTarget(0, renderTarget); + mDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.0f, 0); + mDevice->SetRenderTarget(0, prevRenderTarget); + } + } + + *outRT = new TextureRenderTarget9(renderTarget, format, width, height, 1, supportedSamples); + return gl::Error(GL_NO_ERROR); } -ShaderImpl *Renderer9::createShader(GLenum type) +ShaderImpl *Renderer9::createShader(const gl::Data &data, GLenum type) { - return new ShaderD3D(type, this); + return new ShaderD3D(data, type, this); } ProgramImpl *Renderer9::createProgram() @@ -2864,64 +2875,69 @@ void Renderer9::releaseShaderCompiler() ShaderD3D::releaseCompiler(); } -ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers) +gl::Error Renderer9::loadExecutable(const void *function, size_t length, ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, ShaderExecutable **outExecutable) { // Transform feedback is not supported in ES2 or D3D9 ASSERT(transformFeedbackVaryings.size() == 0); - ShaderExecutable9 *executable = NULL; - switch (type) { - case rx::SHADER_VERTEX: + case SHADER_VERTEX: { - IDirect3DVertexShader9 *vshader = createVertexShader((DWORD*)function, length); - if (vshader) + IDirect3DVertexShader9 *vshader = NULL; + gl::Error error = createVertexShader((DWORD*)function, length, &vshader); + if (error.isError()) { - executable = new ShaderExecutable9(function, length, vshader); + return error; } + *outExecutable = new ShaderExecutable9(function, length, vshader); } break; - case rx::SHADER_PIXEL: + case SHADER_PIXEL: { - IDirect3DPixelShader9 *pshader = createPixelShader((DWORD*)function, length); - if (pshader) + IDirect3DPixelShader9 *pshader = NULL; + gl::Error error = createPixelShader((DWORD*)function, length, &pshader); + if (error.isError()) { - executable = new ShaderExecutable9(function, length, pshader); + return error; } + *outExecutable = new ShaderExecutable9(function, length, pshader); } break; default: UNREACHABLE(); - break; + return gl::Error(GL_INVALID_OPERATION); } - return executable; + return gl::Error(GL_NO_ERROR); } -ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, D3DWorkaroundType workaround) +gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, D3DWorkaroundType workaround, + ShaderExecutable **outExectuable) { // Transform feedback is not supported in ES2 or D3D9 ASSERT(transformFeedbackVaryings.size() == 0); - const char *profile = NULL; - + const char *profileType = NULL; switch (type) { - case rx::SHADER_VERTEX: - profile = getMajorShaderModel() >= 3 ? "vs_3_0" : "vs_2_0"; + case SHADER_VERTEX: + profileType = "vs"; break; - case rx::SHADER_PIXEL: - profile = getMajorShaderModel() >= 3 ? "ps_3_0" : "ps_2_0"; + case SHADER_PIXEL: + profileType = "ps"; break; default: UNREACHABLE(); - return NULL; + return gl::Error(GL_INVALID_OPERATION); } + unsigned int profileMajorVersion = (getMajorShaderModel() >= 3) ? 3 : 2; + unsigned int profileMinorVersion = 0; + std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion); UINT flags = ANGLE_COMPILE_OPTIMIZATION_LEVEL; @@ -2942,49 +2958,54 @@ ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const cha #endif flags |= D3DCOMPILE_DEBUG; - - std::string sourcePath = getTempPath(); - std::string sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(shaderHLSL); - writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size()); } // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options. // Try the default flags first and if compilation fails, try some alternatives. - const UINT extraFlags[] = - { - flags, - flags | D3DCOMPILE_AVOID_FLOW_CONTROL, - flags | D3DCOMPILE_PREFER_FLOW_CONTROL - }; + std::vector configs; + configs.push_back(CompileConfig(flags, "default" )); + configs.push_back(CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control" )); + configs.push_back(CompileConfig(flags | D3DCOMPILE_PREFER_FLOW_CONTROL, "prefer flow control")); - const static char *extraFlagNames[] = + ID3DBlob *binary = NULL; + std::string debugInfo; + gl::Error error = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, NULL, &binary, &debugInfo); + if (error.isError()) { - "default", - "avoid flow control", - "prefer flow control" - }; - - int attempts = ArraySize(extraFlags); - - ID3DBlob *binary = (ID3DBlob*)mCompiler.compileToBinary(infoLog, shaderHLSL, profile, extraFlags, extraFlagNames, attempts); - if (!binary) - { - return NULL; + return error; } - ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, - transformFeedbackVaryings, separatedOutputBuffers); - SafeRelease(binary); + // It's possible that binary is NULL if the compiler failed in all configurations. Set the executable to NULL + // and return GL_NO_ERROR to signify that there was a link error but the internal state is still OK. + if (!binary) + { + *outExectuable = NULL; + return gl::Error(GL_NO_ERROR); + } - return executable; + error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, + transformFeedbackVaryings, separatedOutputBuffers, outExectuable); + + SafeRelease(binary); + if (error.isError()) + { + return error; + } + + if (!debugInfo.empty()) + { + (*outExectuable)->appendDebugInfo(debugInfo); + } + + return gl::Error(GL_NO_ERROR); } -rx::UniformStorage *Renderer9::createUniformStorage(size_t storageSize) +UniformStorage *Renderer9::createUniformStorage(size_t storageSize) { return new UniformStorage(storageSize); } -bool Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) +gl::Error Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) { return mBlit->boxFilter(source, dest); } @@ -3006,41 +3027,40 @@ D3DPOOL Renderer9::getTexturePool(DWORD usage) const return D3DPOOL_DEFAULT; } -bool Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged) +gl::Error Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged) { - if (source && dest) + ASSERT(source && dest); + + HRESULT result = D3DERR_OUTOFVIDEOMEMORY; + + if (fromManaged) { - HRESULT result = D3DERR_OUTOFVIDEOMEMORY; + D3DSURFACE_DESC desc; + source->GetDesc(&desc); - if (fromManaged) + IDirect3DSurface9 *surf = 0; + result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); + + if (SUCCEEDED(result)) { - D3DSURFACE_DESC desc; - source->GetDesc(&desc); - - IDirect3DSurface9 *surf = 0; - result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); - - if (SUCCEEDED(result)) - { - Image9::copyLockableSurfaces(surf, source); - result = mDevice->UpdateSurface(surf, NULL, dest, NULL); - SafeRelease(surf); - } - } - else - { - endScene(); - result = mDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE); - } - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return false; + Image9::copyLockableSurfaces(surf, source); + result = mDevice->UpdateSurface(surf, NULL, dest, NULL); + SafeRelease(surf); } } + else + { + endScene(); + result = mDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE); + } - return true; + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to blit internal texture, result: 0x%X.", result); + } + + return gl::Error(GL_NO_ERROR); } Image *Renderer9::createImage() @@ -3048,11 +3068,11 @@ Image *Renderer9::createImage() return new Image9(); } -void Renderer9::generateMipmap(Image *dest, Image *src) +gl::Error Renderer9::generateMipmap(Image *dest, Image *src) { Image9 *src9 = Image9::makeImage9(src); Image9 *dst9 = Image9::makeImage9(dest); - Image9::generateMipmap(dst9, src9); + return Image9::generateMipmap(dst9, src9); } TextureStorage *Renderer9::createTextureStorage2D(SwapChain *swapChain) @@ -3099,6 +3119,19 @@ TextureImpl *Renderer9::createTexture(GLenum target) return NULL; } +RenderbufferImpl *Renderer9::createRenderbuffer() +{ + RenderbufferD3D *renderbuffer = new RenderbufferD3D(this); + return renderbuffer; +} + +RenderbufferImpl *Renderer9::createRenderbuffer(SwapChain *swapChain, bool depth) +{ + RenderbufferD3D *renderbuffer = new RenderbufferD3D(this); + renderbuffer->setStorage(swapChain, depth); + return renderbuffer; +} + bool Renderer9::getLUID(LUID *adapterLuid) const { adapterLuid->HighPart = 0; @@ -3113,7 +3146,7 @@ bool Renderer9::getLUID(LUID *adapterLuid) const return false; } -rx::VertexConversionType Renderer9::getVertexConversionType(const gl::VertexFormat &vertexFormat) const +VertexConversionType Renderer9::getVertexConversionType(const gl::VertexFormat &vertexFormat) const { return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormat).conversionType; } @@ -3128,4 +3161,9 @@ void Renderer9::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCa d3d9_gl::GenerateCaps(mD3d9, mDevice, mDeviceType, mAdapter, outCaps, outTextureCaps, outExtensions); } +Workarounds Renderer9::generateWorkarounds() const +{ + return d3d9::GenerateWorkarounds(); +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h index dd5f30268a7..10d2fb11e8d 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h @@ -11,10 +11,10 @@ #include "common/angleutils.h" #include "common/mathutil.h" -#include "libGLESv2/renderer/d3d/HLSLCompiler.h" #include "libGLESv2/renderer/d3d/d3d9/ShaderCache.h" #include "libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h" -#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/d3d/HLSLCompiler.h" +#include "libGLESv2/renderer/d3d/RendererD3D.h" #include "libGLESv2/renderer/RenderTarget.h" namespace gl @@ -22,6 +22,11 @@ namespace gl class FramebufferAttachment; } +namespace egl +{ +class AttributeMap; +} + namespace rx { class VertexDataManager; @@ -31,10 +36,10 @@ class StaticIndexBufferInterface; struct TranslatedAttribute; class Blit9; -class Renderer9 : public Renderer +class Renderer9 : public RendererD3D { public: - Renderer9(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay); + Renderer9(egl::Display *display, EGLNativeDisplayType hDc, const egl::AttributeMap &attributes); virtual ~Renderer9(); static Renderer9 *makeRenderer9(Renderer *renderer); @@ -48,27 +53,27 @@ class Renderer9 : public Renderer void startScene(); void endScene(); - virtual void sync(bool block); + virtual gl::Error sync(bool block); - virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); + virtual SwapChain *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); - IDirect3DQuery9* allocateEventQuery(); + gl::Error allocateEventQuery(IDirect3DQuery9 **outQuery); void freeEventQuery(IDirect3DQuery9* query); // resource creation - IDirect3DVertexShader9 *createVertexShader(const DWORD *function, size_t length); - IDirect3DPixelShader9 *createPixelShader(const DWORD *function, size_t length); + gl::Error createVertexShader(const DWORD *function, size_t length, IDirect3DVertexShader9 **outShader); + gl::Error createPixelShader(const DWORD *function, size_t length, IDirect3DPixelShader9 **outShader); HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer); HRESULT createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer); virtual gl::Error generateSwizzle(gl::Texture *texture); - virtual gl::Error setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler); + virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler); virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture); virtual gl::Error setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]); virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState); - virtual gl::Error setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask); + gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, + unsigned int sampleMask) override; virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, int stencilBackRef, bool frontFaceCCW); @@ -76,35 +81,35 @@ class Renderer9 : public Renderer virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, bool ignoreViewport); - virtual gl::Error applyRenderTarget(gl::Framebuffer *frameBuffer); + gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override; virtual gl::Error applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, bool rasterizerDiscard, bool transformFeedbackActive); - virtual gl::Error applyUniforms(const gl::ProgramBinary &programBinary); + virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector &uniformArray); virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount); - virtual gl::Error applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], - GLint first, GLsizei count, GLsizei instances); + virtual gl::Error applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances); virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); - virtual void applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]); + virtual void applyTransformFeedbackBuffers(const gl::State& state); virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive); virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); - virtual gl::Error clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); + gl::Error clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) override; virtual void markAllStateDirty(); // lost device - void notifyDeviceLost(); - virtual bool isDeviceLost(); - virtual bool testDeviceLost(bool notify); - virtual bool testDeviceResettable(); + void notifyDeviceLost() override; + bool isDeviceLost() override; + bool testDeviceLost(bool notify) override; + bool testDeviceResettable() override; + + DWORD getAdapterVendor() const override; + std::string getRendererDescription() const override; + GUID getAdapterIdentifier() const override; IDirect3DDevice9 *getDevice() { return mDevice; } - virtual DWORD getAdapterVendor() const; - virtual std::string getRendererDescription() const; - virtual GUID getAdapterIdentifier() const; virtual unsigned int getReservedVertexUniformVectors() const; virtual unsigned int getReservedFragmentUniformVectors() const; @@ -119,47 +124,45 @@ class Renderer9 : public Renderer virtual int getMaxSwapInterval() const; // Pixel operations - virtual bool copyToRenderTarget2D(TextureStorage *dest, TextureStorage *source); - virtual bool copyToRenderTargetCube(TextureStorage *dest, TextureStorage *source); - virtual bool copyToRenderTarget3D(TextureStorage *dest, TextureStorage *source); - virtual bool copyToRenderTarget2DArray(TextureStorage *dest, TextureStorage *source); - - virtual bool copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level); - virtual bool copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level); - virtual bool copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level); - virtual bool copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + virtual gl::Error copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level); + virtual gl::Error copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level); + virtual gl::Error copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level); + virtual gl::Error copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level); - virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter); + gl::Error blitRect(const gl::Framebuffer *readTarget, const gl::Rectangle &readRect, + const gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, + const gl::Rectangle *scissor, bool blitRenderTarget, + bool blitDepth, bool blitStencil, GLenum filter) override; - virtual gl::Error readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, + virtual gl::Error readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels); // RenderTarget creation - virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth); - virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples); + virtual gl::Error createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT); + virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT); // Shader creation - virtual ShaderImpl *createShader(GLenum type); + virtual ShaderImpl *createShader(const gl::Data &data, GLenum type); virtual ProgramImpl *createProgram(); // Shader operations - virtual void releaseShaderCompiler(); - virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers); - virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, D3DWorkaroundType workaround); + void releaseShaderCompiler() override; + virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, ShaderExecutable **outExecutable); + virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, D3DWorkaroundType workaround, + ShaderExecutable **outExectuable); virtual UniformStorage *createUniformStorage(size_t storageSize); // Image operations virtual Image *createImage(); - virtual void generateMipmap(Image *dest, Image *source); + gl::Error generateMipmap(Image *dest, Image *source) override; virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain); virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels); @@ -169,6 +172,10 @@ class Renderer9 : public Renderer // Texture creation virtual TextureImpl *createTexture(GLenum target); + // Renderbuffer creation + virtual RenderbufferImpl *createRenderbuffer(); + virtual RenderbufferImpl *createRenderbuffer(SwapChain *swapChain, bool depth); + // Buffer creation virtual BufferImpl *createBuffer(); virtual VertexBuffer *createVertexBuffer(); @@ -179,29 +186,33 @@ class Renderer9 : public Renderer // Query and Fence creation virtual QueryImpl *createQuery(GLenum type); - virtual FenceImpl *createFence(); + virtual FenceNVImpl *createFenceNV(); + virtual FenceSyncImpl *createFenceSync(); // Transform Feedback creation virtual TransformFeedbackImpl* createTransformFeedback(); // Buffer-to-texture and Texture-to-buffer copies virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const; - virtual bool fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, - GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); + virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); // D3D9-renderer specific methods - bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); + gl::Error boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); D3DPOOL getTexturePool(DWORD usage) const; virtual bool getLUID(LUID *adapterLuid) const; - virtual rx::VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const; + virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const; virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const; + gl::Error copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged); + private: DISALLOW_COPY_AND_ASSIGN(Renderer9); - virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const; + void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const override; + Workarounds generateWorkarounds() const override; void release(); @@ -214,8 +225,7 @@ class Renderer9 : public Renderer gl::Error getCountingIB(size_t count, StaticIndexBufferInterface **outIB); - bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged); - gl::FramebufferAttachment *getNullColorbuffer(gl::FramebufferAttachment *depthbuffer); + gl::Error getNullColorbuffer(gl::FramebufferAttachment *depthbuffer, gl::FramebufferAttachment **outColorBuffer); D3DPOOL getBufferPool(DWORD usage) const; @@ -263,7 +273,7 @@ class Renderer9 : public Renderer unsigned int mAppliedStencilbufferSerial; bool mDepthStencilInitialized; bool mRenderTargetDescInitialized; - rx::RenderTarget::Desc mRenderTargetDesc; + RenderTarget::Desc mRenderTargetDesc; unsigned int mCurStencilSize; unsigned int mCurDepthSize; @@ -310,8 +320,8 @@ class Renderer9 : public Renderer IDirect3DPixelShader9 *mAppliedPixelShader; unsigned int mAppliedProgramSerial; - rx::dx_VertexConstants mVertexConstants; - rx::dx_PixelConstants mPixelConstants; + dx_VertexConstants mVertexConstants; + dx_PixelConstants mPixelConstants; bool mDxUniformsDirty; // A pool of event queries that are currently unused. diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h index 2ad30228398..6d7d2d648f0 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h @@ -10,6 +10,8 @@ #ifndef LIBGLESV2_RENDERER_SHADER_CACHE_H_ #define LIBGLESV2_RENDERER_SHADER_CACHE_H_ +#include "libGLESv2/Error.h" + #include "common/debug.h" #include @@ -37,21 +39,22 @@ class ShaderCache mDevice = device; } - ShaderObject *create(const DWORD *function, size_t length) + gl::Error create(const DWORD *function, size_t length, ShaderObject **outShaderObject) { std::string key(reinterpret_cast(function), length); typename Map::iterator it = mMap.find(key); if (it != mMap.end()) { it->second->AddRef(); - return it->second; + *outShaderObject = it->second; + return gl::Error(GL_NO_ERROR); } ShaderObject *shader; HRESULT result = createShader(function, &shader); if (FAILED(result)) { - return NULL; + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create shader, result: 0x%X.", result); } // Random eviction policy. @@ -64,7 +67,8 @@ class ShaderCache shader->AddRef(); mMap[key] = shader; - return shader; + *outShaderObject = shader; + return gl::Error(GL_NO_ERROR); } void clear() diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp index 0aeaabb1caf..95eb1a4371f 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp @@ -11,12 +11,15 @@ #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" #include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#include "common/features.h" + namespace rx { -SwapChain9::SwapChain9(Renderer9 *renderer, HWND window, HANDLE shareHandle, +SwapChain9::SwapChain9(Renderer9 *renderer, NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) - : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat) + : mRenderer(renderer), + SwapChain(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat) { mSwapChain = NULL; mBackBuffer = NULL; @@ -41,7 +44,7 @@ void SwapChain9::release() SafeRelease(mRenderTarget); SafeRelease(mOffscreenTexture); - if (mWindow) + if (mNativeWindow.getNativeWindow()) { mShareHandle = NULL; } @@ -49,7 +52,7 @@ void SwapChain9::release() static DWORD convertInterval(EGLint interval) { -#ifdef ANGLE_FORCE_VSYNC_OFF +#if ANGLE_VSYNC == ANGLE_DISABLED return D3DPRESENT_INTERVAL_IMMEDIATE; #else switch(interval) @@ -95,7 +98,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI SafeRelease(mDepthStencil); HANDLE *pShareHandle = NULL; - if (!mWindow && mRenderer->getShareHandleSupport()) + if (!mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport()) { pShareHandle = &mShareHandle; } @@ -152,7 +155,8 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI const d3d9::TextureFormat &depthBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mDepthBufferFormat); - if (mWindow) + EGLNativeWindowType window = mNativeWindow.getNativeWindow(); + if (window) { D3DPRESENT_PARAMETERS presentParameters = {0}; presentParameters.AutoDepthStencilFormat = depthBufferd3dFormatInfo.renderFormat; @@ -160,7 +164,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI presentParameters.BackBufferFormat = backBufferd3dFormatInfo.renderFormat; presentParameters.EnableAutoDepthStencil = FALSE; presentParameters.Flags = 0; - presentParameters.hDeviceWindow = mWindow; + presentParameters.hDeviceWindow = window; presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented presentParameters.PresentationInterval = convertInterval(swapInterval); @@ -203,7 +207,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); ASSERT(SUCCEEDED(result)); - InvalidateRect(mWindow, NULL, FALSE); + InvalidateRect(window, NULL, FALSE); } if (mDepthBufferFormat != GL_NONE) @@ -238,7 +242,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI } // parameters should be validated/clamped by caller -EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint) +EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) { if (!mSwapChain) { @@ -379,8 +383,8 @@ IDirect3DTexture9 *SwapChain9::getOffscreenTexture() SwapChain9 *SwapChain9::makeSwapChain9(SwapChain *swapChain) { - ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain9*, swapChain)); - return static_cast(swapChain); + ASSERT(HAS_DYNAMIC_TYPE(SwapChain9*, swapChain)); + return static_cast(swapChain); } void SwapChain9::recreate() diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h index 4d756f80d12..cb33bfbc0c5 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h @@ -19,19 +19,22 @@ class Renderer9; class SwapChain9 : public SwapChain { public: - SwapChain9(Renderer9 *renderer, HWND window, HANDLE shareHandle, + SwapChain9(Renderer9 *renderer, NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); virtual ~SwapChain9(); EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval); - virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint); + virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height); virtual void recreate(); virtual IDirect3DSurface9 *getRenderTarget(); virtual IDirect3DSurface9 *getDepthStencil(); virtual IDirect3DTexture9 *getOffscreenTexture(); + EGLint getWidth() const { return mWidth; } + EGLint getHeight() const { return mHeight; } + static SwapChain9 *makeSwapChain9(SwapChain *swapChain); private: diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp index f44e33db184..0ff4fd3b0f2 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp @@ -20,8 +20,13 @@ namespace rx { -TextureStorage9::TextureStorage9(Renderer *renderer, DWORD usage) +TextureStorage9::TextureStorage9(Renderer9 *renderer, DWORD usage) : mTopLevel(0), + mMipLevels(0), + mTextureWidth(0), + mTextureHeight(0), + mInternalFormat(GL_NONE), + mTextureFormat(D3DFMT_UNKNOWN), mRenderer(Renderer9::makeRenderer9(renderer)), mD3DUsage(usage), mD3DPool(mRenderer->getTexturePool(usage)) @@ -84,44 +89,52 @@ int TextureStorage9::getTopLevel() const int TextureStorage9::getLevelCount() const { - return getBaseTexture() ? (getBaseTexture()->GetLevelCount() - getTopLevel()) : 0; + return mMipLevels - mTopLevel; } -TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain) +gl::Error TextureStorage9::setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixelData) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchain) : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET) { IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture(); mTexture = surfaceTexture; + mMipLevels = surfaceTexture->GetLevelCount(); + + mInternalFormat = swapchain->GetBackBufferInternalFormat(); + + D3DSURFACE_DESC surfaceDesc; + surfaceTexture->GetLevelDesc(0, &surfaceDesc); + mTextureWidth = surfaceDesc.Width; + mTextureHeight = surfaceDesc.Height; + mTextureFormat = surfaceDesc.Format; + mRenderTarget = NULL; - initializeRenderTarget(); initializeSerials(1, 1); } -TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) +TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget)) { mTexture = NULL; mRenderTarget = NULL; - // if the width or height is not positive this should be treated as an incomplete texture - // we handle that here by skipping the d3d texture creation - if (width > 0 && height > 0) - { - IDirect3DDevice9 *device = mRenderer->getDevice(); - const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat); - d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &width, &height, &mTopLevel); - UINT creationLevels = (levels == 0) ? 0 : mTopLevel + levels; - HRESULT result = device->CreateTexture(width, height, creationLevels, getUsage(), d3dFormatInfo.texFormat, getPool(), &mTexture, NULL); + mInternalFormat = internalformat; - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - gl::error(GL_OUT_OF_MEMORY); - } - } + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat); + mTextureFormat = d3dFormatInfo.texFormat; + + d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &width, &height, &mTopLevel); + mTextureWidth = width; + mTextureHeight = height; + mMipLevels = mTopLevel + levels; - initializeRenderTarget(); initializeSerials(getLevelCount(), 1); } @@ -139,104 +152,168 @@ TextureStorage9_2D *TextureStorage9_2D::makeTextureStorage9_2D(TextureStorage *s // Increments refcount on surface. // caller must Release() the returned surface -IDirect3DSurface9 *TextureStorage9_2D::getSurfaceLevel(int level, bool dirty) +gl::Error TextureStorage9_2D::getSurfaceLevel(int level, bool dirty, IDirect3DSurface9 **outSurface) { - IDirect3DSurface9 *surface = NULL; - - if (mTexture) + IDirect3DBaseTexture9 *baseTexture = NULL; + gl::Error error = getBaseTexture(&baseTexture); + if (error.isError()) { - HRESULT result = mTexture->GetSurfaceLevel(level + mTopLevel, &surface); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(SUCCEEDED(result)); - - // With managed textures the driver needs to be informed of updates to the lower mipmap levels - if (level + mTopLevel != 0 && isManaged() && dirty) - { - mTexture->AddDirtyRect(NULL); - } + return error; } - return surface; -} + IDirect3DTexture9 *texture = static_cast(baseTexture); -RenderTarget *TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &/*index*/) -{ - return mRenderTarget; -} + HRESULT result = texture->GetSurfaceLevel(level + mTopLevel, outSurface); -void TextureStorage9_2D::generateMipmaps() -{ - // Base level must already be defined - - for (int level = 1; level < getLevelCount(); level++) + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) { - IDirect3DSurface9 *upper = getSurfaceLevel(level - 1, false); - IDirect3DSurface9 *lower = getSurfaceLevel(level, true); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the surface from a texture, result: 0x%X.", result); + } - if (upper != NULL && lower != NULL) + // With managed textures the driver needs to be informed of updates to the lower mipmap levels + if (level + mTopLevel != 0 && isManaged() && dirty) + { + texture->AddDirtyRect(NULL); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &/*index*/, RenderTarget **outRT) +{ + if (!mRenderTarget && isRenderTarget()) + { + IDirect3DSurface9 *surface = NULL; + gl::Error error = getSurfaceLevel(0, false, &surface); + if (error.isError()) { - mRenderer->boxFilter(upper, lower); + return error; } + mRenderTarget = new TextureRenderTarget9(surface, mInternalFormat, mTextureWidth, mTextureHeight, 1, 0); + } + + ASSERT(outRT); + *outRT = mRenderTarget; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage9_2D::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) +{ + IDirect3DSurface9 *upper = NULL; + gl::Error error = getSurfaceLevel(sourceIndex.mipIndex, false, &upper); + if (error.isError()) + { + return error; + } + + IDirect3DSurface9 *lower = NULL; + error = getSurfaceLevel(destIndex.mipIndex, true, &lower); + if (error.isError()) + { SafeRelease(upper); - SafeRelease(lower); - } -} - -IDirect3DBaseTexture9 *TextureStorage9_2D::getBaseTexture() const -{ - return mTexture; -} - -void TextureStorage9_2D::initializeRenderTarget() -{ - ASSERT(mRenderTarget == NULL); - - if (mTexture != NULL && isRenderTarget()) - { - IDirect3DSurface9 *surface = getSurfaceLevel(0, false); - - mRenderTarget = new RenderTarget9(mRenderer, surface); - } -} - -TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels) - : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget)) -{ - mTexture = NULL; - for (int i = 0; i < 6; ++i) - { - mRenderTarget[i] = NULL; + return error; } - // if the size is not positive this should be treated as an incomplete texture + ASSERT(upper && lower); + error = mRenderer->boxFilter(upper, lower); + + SafeRelease(upper); + SafeRelease(lower); + + return error; +} + +gl::Error TextureStorage9_2D::getBaseTexture(IDirect3DBaseTexture9 **outTexture) +{ + // if the width or height is not positive this should be treated as an incomplete texture // we handle that here by skipping the d3d texture creation - if (size > 0) + if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0) { - IDirect3DDevice9 *device = mRenderer->getDevice(); - int height = size; - const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat); - d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &size, &height, &mTopLevel); - UINT creationLevels = (levels == 0) ? 0 : mTopLevel + levels; + ASSERT(mMipLevels > 0); - HRESULT result = device->CreateCubeTexture(size, creationLevels, getUsage(), d3dFormatInfo.texFormat, getPool(), &mTexture, NULL); + IDirect3DDevice9 *device = mRenderer->getDevice(); + HRESULT result = device->CreateTexture(mTextureWidth, mTextureHeight, mMipLevels, getUsage(), mTextureFormat, + getPool(), &mTexture, NULL); if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - gl::error(GL_OUT_OF_MEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D storage texture, result: 0x%X.", result); } } - initializeRenderTarget(); - initializeSerials(getLevelCount() * 6, 6); + *outTexture = mTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage9_2D::copyToStorage(TextureStorage *destStorage) +{ + ASSERT(destStorage); + + TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(destStorage); + + int levels = getLevelCount(); + for (int i = 0; i < levels; ++i) + { + IDirect3DSurface9 *srcSurf = NULL; + gl::Error error = getSurfaceLevel(i, false, &srcSurf); + if (error.isError()) + { + return error; + } + + IDirect3DSurface9 *dstSurf = NULL; + error = dest9->getSurfaceLevel(i, true, &dstSurf); + if (error.isError()) + { + SafeRelease(srcSurf); + return error; + } + + error = mRenderer->copyToRenderTarget(dstSurf, srcSurf, isManaged()); + + SafeRelease(srcSurf); + SafeRelease(dstSurf); + + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +TextureStorage9_Cube::TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels) + : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget)) +{ + mTexture = NULL; + for (int i = 0; i < CUBE_FACE_COUNT; ++i) + { + mRenderTarget[i] = NULL; + } + + mInternalFormat = internalformat; + + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat); + mTextureFormat = d3dFormatInfo.texFormat; + + int height = size; + d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &size, &height, &mTopLevel); + mTextureWidth = size; + mTextureHeight = size; + mMipLevels = mTopLevel + levels; + + initializeSerials(getLevelCount() * CUBE_FACE_COUNT, CUBE_FACE_COUNT); } TextureStorage9_Cube::~TextureStorage9_Cube() { SafeRelease(mTexture); - for (int i = 0; i < 6; ++i) + for (int i = 0; i < CUBE_FACE_COUNT; ++i) { SafeDelete(mRenderTarget[i]); } @@ -250,74 +327,146 @@ TextureStorage9_Cube *TextureStorage9_Cube::makeTextureStorage9_Cube(TextureStor // Increments refcount on surface. // caller must Release() the returned surface -IDirect3DSurface9 *TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, bool dirty) +gl::Error TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, bool dirty, IDirect3DSurface9 **outSurface) { - IDirect3DSurface9 *surface = NULL; - - if (mTexture) + IDirect3DBaseTexture9 *baseTexture = NULL; + gl::Error error = getBaseTexture(&baseTexture); + if (error.isError()) { - D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget); - HRESULT result = mTexture->GetCubeMapSurface(face, level + mTopLevel, &surface); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(SUCCEEDED(result)); - - // With managed textures the driver needs to be informed of updates to the lower mipmap levels - if (level != 0 && isManaged() && dirty) - { - mTexture->AddDirtyRect(face, NULL); - } + return error; } - return surface; -} + IDirect3DCubeTexture9 *texture = static_cast(baseTexture); -RenderTarget *TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index) -{ - return mRenderTarget[index.layerIndex]; -} + D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget); + HRESULT result = texture->GetCubeMapSurface(face, level + mTopLevel, outSurface); -void TextureStorage9_Cube::generateMipmaps() -{ - // Base level must already be defined - - for (int faceIndex = 0; faceIndex < 6; faceIndex++) + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) { - for (int level = 1; level < getLevelCount(); level++) - { - IDirect3DSurface9 *upper = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level - 1, false); - IDirect3DSurface9 *lower = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level, true); - - if (upper != NULL && lower != NULL) - { - mRenderer->boxFilter(upper, lower); - } - - SafeRelease(upper); - SafeRelease(lower); - } + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the surface from a texture, result: 0x%X.", result); } + + // With managed textures the driver needs to be informed of updates to the lower mipmap levels + if (level != 0 && isManaged() && dirty) + { + texture->AddDirtyRect(face, NULL); + } + + return gl::Error(GL_NO_ERROR); } -IDirect3DBaseTexture9 *TextureStorage9_Cube::getBaseTexture() const +gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) { - return mTexture; -} + ASSERT(outRT); + ASSERT(index.mipIndex == 0); + ASSERT(index.layerIndex >= 0 && index.layerIndex < CUBE_FACE_COUNT); -void TextureStorage9_Cube::initializeRenderTarget() -{ - if (mTexture != NULL && isRenderTarget()) + if (mRenderTarget[index.layerIndex] == NULL && isRenderTarget()) { IDirect3DSurface9 *surface = NULL; - - for (int i = 0; i < 6; ++i) + gl::Error error = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + index.layerIndex, 0, false, &surface); + if (error.isError()) { - ASSERT(mRenderTarget[i] == NULL); - - surface = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, false); - - mRenderTarget[i] = new RenderTarget9(mRenderer, surface); + return error; } + + mRenderTarget[index.layerIndex] = new TextureRenderTarget9(surface, mInternalFormat, mTextureWidth, mTextureHeight, 1, 0); } + + *outRT = mRenderTarget[index.layerIndex]; + return gl::Error(GL_NO_ERROR); } -} \ No newline at end of file +gl::Error TextureStorage9_Cube::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) +{ + IDirect3DSurface9 *upper = NULL; + gl::Error error = getCubeMapSurface(sourceIndex.type, sourceIndex.mipIndex, false, &upper); + if (error.isError()) + { + return error; + } + + IDirect3DSurface9 *lower = NULL; + error = getCubeMapSurface(destIndex.type, destIndex.mipIndex, true, &lower); + if (error.isError()) + { + SafeRelease(upper); + return error; + } + + ASSERT(upper && lower); + error = mRenderer->boxFilter(upper, lower); + + SafeRelease(upper); + SafeRelease(lower); + + return error; +} + +gl::Error TextureStorage9_Cube::getBaseTexture(IDirect3DBaseTexture9 **outTexture) +{ + // if the size is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0) + { + ASSERT(mMipLevels > 0); + ASSERT(mTextureWidth == mTextureHeight); + + IDirect3DDevice9 *device = mRenderer->getDevice(); + HRESULT result = device->CreateCubeTexture(mTextureWidth, mMipLevels, getUsage(), mTextureFormat, getPool(), + &mTexture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube storage texture, result: 0x%X.", result); + } + } + + *outTexture = mTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage9_Cube::copyToStorage(TextureStorage *destStorage) +{ + ASSERT(destStorage); + + TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(destStorage); + + int levels = getLevelCount(); + for (int f = 0; f < CUBE_FACE_COUNT; f++) + { + for (int i = 0; i < levels; i++) + { + IDirect3DSurface9 *srcSurf = NULL; + gl::Error error = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false, &srcSurf); + if (error.isError()) + { + return error; + } + + IDirect3DSurface9 *dstSurf = NULL; + error = dest9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true, &dstSurf); + if (error.isError()) + { + SafeRelease(srcSurf); + return error; + } + + error = mRenderer->copyToRenderTarget(dstSurf, srcSurf, isManaged()); + + SafeRelease(srcSurf); + SafeRelease(dstSurf); + + if (error.isError()) + { + return error; + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h index e698c7dd564..da0e1f2f18b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h @@ -33,20 +33,28 @@ class TextureStorage9 : public TextureStorage D3DPOOL getPool() const; DWORD getUsage() const; - virtual IDirect3DBaseTexture9 *getBaseTexture() const = 0; - virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index) = 0; - virtual void generateMipmaps() = 0; + virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture) = 0; + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) = 0; virtual int getTopLevel() const; virtual bool isRenderTarget() const; virtual bool isManaged() const; virtual int getLevelCount() const; + virtual gl::Error setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixelData); + protected: int mTopLevel; + size_t mMipLevels; + size_t mTextureWidth; + size_t mTextureHeight; + GLenum mInternalFormat; + D3DFORMAT mTextureFormat; + Renderer9 *mRenderer; - TextureStorage9(Renderer *renderer, DWORD usage); + TextureStorage9(Renderer9 *renderer, DWORD usage); private: DISALLOW_COPY_AND_ASSIGN(TextureStorage9); @@ -58,22 +66,21 @@ class TextureStorage9 : public TextureStorage class TextureStorage9_2D : public TextureStorage9 { public: - TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain); - TextureStorage9_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); + TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchain); + TextureStorage9_2D(Renderer9 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); virtual ~TextureStorage9_2D(); static TextureStorage9_2D *makeTextureStorage9_2D(TextureStorage *storage); - IDirect3DSurface9 *getSurfaceLevel(int level, bool dirty); - virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index); - virtual IDirect3DBaseTexture9 *getBaseTexture() const; - virtual void generateMipmaps(); + gl::Error getSurfaceLevel(int level, bool dirty, IDirect3DSurface9 **outSurface); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); + virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture); + virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex); + virtual gl::Error copyToStorage(TextureStorage *destStorage); private: DISALLOW_COPY_AND_ASSIGN(TextureStorage9_2D); - void initializeRenderTarget(); - IDirect3DTexture9 *mTexture; RenderTarget9 *mRenderTarget; }; @@ -81,23 +88,24 @@ class TextureStorage9_2D : public TextureStorage9 class TextureStorage9_Cube : public TextureStorage9 { public: - TextureStorage9_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels); + TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels); virtual ~TextureStorage9_Cube(); static TextureStorage9_Cube *makeTextureStorage9_Cube(TextureStorage *storage); - IDirect3DSurface9 *getCubeMapSurface(GLenum faceTarget, int level, bool dirty); - virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index); - virtual IDirect3DBaseTexture9 *getBaseTexture() const; - virtual void generateMipmaps(); + gl::Error getCubeMapSurface(GLenum faceTarget, int level, bool dirty, IDirect3DSurface9 **outSurface); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); + virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture); + virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex); + virtual gl::Error copyToStorage(TextureStorage *destStorage); private: DISALLOW_COPY_AND_ASSIGN(TextureStorage9_Cube); - void initializeRenderTarget(); + static const size_t CUBE_FACE_COUNT = 6; IDirect3DCubeTexture9 *mTexture; - RenderTarget9 *mRenderTarget[6]; + RenderTarget9 *mRenderTarget[CUBE_FACE_COUNT]; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h index 66a6c64d81c..791c108462b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h @@ -19,7 +19,7 @@ class Renderer9; class VertexArray9 : public VertexArrayImpl { public: - VertexArray9(rx::Renderer9 *renderer) + VertexArray9(Renderer9 *renderer) : VertexArrayImpl(), mRenderer(renderer) { @@ -35,7 +35,7 @@ class VertexArray9 : public VertexArrayImpl private: DISALLOW_COPY_AND_ASSIGN(VertexArray9); - rx::Renderer9 *mRenderer; + Renderer9 *mRenderer; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp index 4cf77791185..b90133097c9 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp @@ -10,14 +10,14 @@ #include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" #include "libGLESv2/renderer/vertexconversion.h" -#include "libGLESv2/renderer/BufferImpl.h" +#include "libGLESv2/renderer/d3d/BufferD3D.h" #include "libGLESv2/VertexAttribute.h" #include "libGLESv2/Buffer.h" namespace rx { -VertexBuffer9::VertexBuffer9(rx::Renderer9 *renderer) : mRenderer(renderer) +VertexBuffer9::VertexBuffer9(Renderer9 *renderer) : mRenderer(renderer) { mVertexBuffer = NULL; mBufferSize = 0; @@ -97,8 +97,14 @@ gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib { if (buffer) { - BufferImpl *storage = buffer->getImplementation(); - input = static_cast(storage->getData()) + static_cast(attrib.offset); + BufferD3D *storage = BufferD3D::makeFromBuffer(buffer); + ASSERT(storage); + gl::Error error = storage->getData(&input); + if (error.isError()) + { + return error; + } + input += static_cast(attrib.offset); } else { @@ -203,7 +209,7 @@ gl::Error VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::s else { // Round up to divisor, if possible - elementCount = rx::UnsignedCeilDivide(static_cast(instances), attrib.divisor); + elementCount = UnsignedCeilDivide(static_cast(instances), attrib.divisor); } if (d3d9VertexInfo.outputElementSize <= std::numeric_limits::max() / elementCount) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h index bdcf4bb64a3..9af2b98a6ed 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h @@ -18,7 +18,7 @@ class Renderer9; class VertexBuffer9 : public VertexBuffer { public: - explicit VertexBuffer9(rx::Renderer9 *renderer); + explicit VertexBuffer9(Renderer9 *renderer); virtual ~VertexBuffer9(); virtual gl::Error initialize(unsigned int size, bool dynamicUsage); @@ -39,7 +39,7 @@ class VertexBuffer9 : public VertexBuffer private: DISALLOW_COPY_AND_ASSIGN(VertexBuffer9); - rx::Renderer9 *mRenderer; + Renderer9 *mRenderer; IDirect3DVertexBuffer9 *mVertexBuffer; unsigned int mBufferSize; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp index e7a91e62d69..a98b2081f3b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp @@ -9,6 +9,7 @@ #include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" +#include "libGLESv2/renderer/Workarounds.h" #include "libGLESv2/formatutils.h" #include "libGLESv2/Framebuffer.h" #include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" @@ -390,8 +391,9 @@ void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceT caps->maxVertexUniformBlocks = 0; - const size_t MAX_VERTEX_OUTPUT_VECTORS_SM3 = 10; - const size_t MAX_VERTEX_OUTPUT_VECTORS_SM2 = 8; + // SM3 only supports 11 output variables, with a special 12th register for PSIZE. + const size_t MAX_VERTEX_OUTPUT_VECTORS_SM3 = 9; + const size_t MAX_VERTEX_OUTPUT_VECTORS_SM2 = 7; caps->maxVertexOutputComponents = ((deviceCaps.VertexShaderVersion >= D3DVS_VERSION(3, 0)) ? MAX_VERTEX_OUTPUT_VECTORS_SM3 : MAX_VERTEX_OUTPUT_VECTORS_SM2) * 4; @@ -459,7 +461,7 @@ void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceT extensions->textureNPOT = !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) && !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) && - !(isWindowsVistaOrGreater() && adapterId.VendorId == VENDOR_ID_AMD); + !(!isWindowsVistaOrGreater() && adapterId.VendorId == VENDOR_ID_AMD); } else { @@ -531,10 +533,24 @@ void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsize *levelOffset = upsampleCount; } -RenderTarget9 *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment) +gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget9 **outRT) { - RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment); - return RenderTarget9::makeRenderTarget9(renderTarget); + RenderTarget *renderTarget = NULL; + gl::Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget); + if (error.isError()) + { + return error; + } + *outRT = RenderTarget9::makeRenderTarget9(renderTarget); + return gl::Error(GL_NO_ERROR); +} + +Workarounds GenerateWorkarounds() +{ + Workarounds workarounds; + workarounds.mrtPerfWorkaround = true; + workarounds.setDataFasterThanImageUpload = false; + return workarounds; } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h index b0a940e60ae..9760b9735a4 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h @@ -12,6 +12,7 @@ #include "libGLESv2/angletypes.h" #include "libGLESv2/Caps.h" +#include "libGLESv2/Error.h" namespace gl { @@ -21,6 +22,7 @@ class FramebufferAttachment; namespace rx { class RenderTarget9; +struct Workarounds; namespace gl_d3d9 { @@ -74,7 +76,8 @@ inline bool isDeviceLostError(HRESULT errorCode) } } -RenderTarget9 *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment); +gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget9 **outRT); +Workarounds GenerateWorkarounds(); } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp index f777b30be6f..159b4c7e9f5 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp @@ -10,10 +10,6 @@ #include "libGLESv2/renderer/loadimage.h" -#if !defined(__SSE2__) && (defined(_M_X64) || _M_IX86_FP == 2) -#define __SSE2__ -#endif - namespace rx { @@ -21,7 +17,12 @@ void LoadA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { -#ifdef __SSE2__ +#if defined(_M_ARM) + // Ensure that this function is reported as not implemented for ARM builds because + // the instructions below are not present for that architecture. + UNIMPLEMENTED(); + return; +#else __m128i zeroWide = _mm_setzero_si128(); for (size_t z = 0; z < depth; z++) @@ -66,7 +67,12 @@ void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) { -#ifdef __SSE2__ +#if defined(_M_ARM) + // Ensure that this function is reported as not implemented for ARM builds because + // the instructions below are not present for that architecture. + UNIMPLEMENTED(); + return; +#else __m128i brMask = _mm_set1_epi32(0x00ff00ff); for (size_t z = 0; z < depth; z++) diff --git a/src/3rdparty/angle/src/libGLESv2/validationES.cpp b/src/3rdparty/angle/src/libGLESv2/validationES.cpp index f79bc97e4f6..265f4b4fba1 100644 --- a/src/3rdparty/angle/src/libGLESv2/validationES.cpp +++ b/src/3rdparty/angle/src/libGLESv2/validationES.cpp @@ -24,6 +24,9 @@ #include "common/mathutil.h" #include "common/utilities.h" +// FIXME(jmadill): remove this when we support buffer data caching +#include "libGLESv2/renderer/d3d/BufferD3D.h" + namespace gl { @@ -497,14 +500,26 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint gl::Framebuffer *readFramebuffer = context->getState().getReadFramebuffer(); gl::Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer(); - if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE || - !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) + + if (!readFramebuffer || !drawFramebuffer) { context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); return false; } - if (drawFramebuffer->getSamples() != 0) + if (!readFramebuffer->completeness(context->getData())) + { + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return false; + } + + if (!drawFramebuffer->completeness(context->getData())) + { + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return false; + } + + if (drawFramebuffer->getSamples(context->getData()) != 0) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -588,16 +603,20 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint return false; } - if (attachment->getActualFormat() != readColorBuffer->getActualFormat()) + // Return an error if the destination formats do not match + if (attachment->getInternalFormat() != readColorBuffer->getInternalFormat()) { context->recordError(Error(GL_INVALID_OPERATION)); return false; } } } - if (readFramebuffer->getSamples() != 0 && IsPartialBlit(context, readColorBuffer, drawColorBuffer, - srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1)) + + int readSamples = readFramebuffer->getSamples(context->getData()); + + if (readSamples != 0 && IsPartialBlit(context, readColorBuffer, drawColorBuffer, + srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1)) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -912,13 +931,14 @@ bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsize gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); ASSERT(framebuffer); - if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) + if (framebuffer->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE) { context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); return false; } - if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0) + if (context->getState().getReadFramebuffer()->id() != 0 && + framebuffer->getSamples(context->getData()) != 0) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -1172,7 +1192,7 @@ bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, { Framebuffer *framebuffer = context->getState().getReadFramebuffer(); ASSERT(framebuffer); - if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) + if (framebuffer->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -1236,13 +1256,13 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi } gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); - if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) + if (framebuffer->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE) { context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); return false; } - if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0) + if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples(context->getData()) != 0) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -1441,7 +1461,7 @@ static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsiz } const gl::Framebuffer *fbo = state.getDrawFramebuffer(); - if (!fbo || fbo->completeness() != GL_FRAMEBUFFER_COMPLETE) + if (!fbo || fbo->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE) { context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); return false; @@ -1667,11 +1687,20 @@ bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum t // TODO: also disable index checking on back-ends that are robust to out-of-range accesses. if (elementArrayBuffer) { - GLint64 offset = reinterpret_cast(indices); + uintptr_t offset = reinterpret_cast(indices); if (!elementArrayBuffer->getIndexRangeCache()->findRange(type, offset, count, indexRangeOut, NULL)) { - const void *dataPointer = elementArrayBuffer->getImplementation()->getData(); - const uint8_t *offsetPointer = static_cast(dataPointer) + offset; + // FIXME(jmadill): Use buffer data caching instead of the D3D back-end + rx::BufferD3D *bufferD3D = rx::BufferD3D::makeBufferD3D(elementArrayBuffer->getImplementation()); + const uint8_t *dataPointer = NULL; + Error error = bufferD3D->getData(&dataPointer); + if (error.isError()) + { + context->recordError(error); + return false; + } + + const uint8_t *offsetPointer = dataPointer + offset; *indexRangeOut = rx::IndexRangeCache::ComputeRange(type, offsetPointer, count); } } @@ -1850,6 +1879,11 @@ bool ValidateGetUniformBase(Context *context, GLuint program, GLint location) return false; } + if (!ValidProgram(context, program)) + { + return false; + } + gl::Program *programObject = context->getProgram(program); if (!programObject || !programObject->isLinked()) diff --git a/src/3rdparty/angle/src/libGLESv2/validationES3.cpp b/src/3rdparty/angle/src/libGLESv2/validationES3.cpp index 251c6ad2c4b..2d3a039e139 100644 --- a/src/3rdparty/angle/src/libGLESv2/validationES3.cpp +++ b/src/3rdparty/angle/src/libGLESv2/validationES3.cpp @@ -542,7 +542,8 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, return false; } - size_t copyBytes = widthSize * heightSize * depthSize * pixelBytes; + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat); + size_t copyBytes = formatInfo.computeBlockSize(type, width, height); size_t offset = reinterpret_cast(pixels); if (!rx::IsUnsignedAdditionSafe(offset, copyBytes) || @@ -555,12 +556,15 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, // ...data is not evenly divisible into the number of bytes needed to store in memory a datum // indicated by type. - size_t dataBytesPerPixel = static_cast(gl::GetTypeInfo(type).bytes); - - if ((offset % dataBytesPerPixel) != 0) + if (!isCompressed) { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; + size_t dataBytesPerPixel = static_cast(gl::GetTypeInfo(type).bytes); + + if ((offset % dataBytesPerPixel) != 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } } // ...the buffer object's data store is currently mapped. @@ -872,13 +876,14 @@ bool ValidateES3CopyTexImageParameters(Context *context, GLenum target, GLint le gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); - if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) + if (framebuffer->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE) { context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); return false; } - if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0) + if (context->getState().getReadFramebuffer()->id() != 0 && + framebuffer->getSamples(context->getData()) != 0) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -1258,7 +1263,7 @@ bool ValidateClearBuffer(Context *context) } const gl::Framebuffer *fbo = context->getState().getDrawFramebuffer(); - if (!fbo || fbo->completeness() != GL_FRAMEBUFFER_COMPLETE) + if (!fbo || fbo->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE) { context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); return false; diff --git a/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.cpp b/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.cpp index 19a9644d709..97dfcaac513 100644 --- a/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.cpp +++ b/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.cpp @@ -24,6 +24,7 @@ */ #include +#include "common/platform.h" #if _WIN32_WINNT_WINBLUE #include @@ -52,7 +53,11 @@ bool isWindowsVistaOrGreater() if (!initialized) { initialized = true; +#if defined(ANGLE_ENABLE_WINDOWS_STORE) + cachedIsWindowsVistaOrGreater = true; +#else cachedIsWindowsVistaOrGreater = IsWindowsVistaOrGreater(); +#endif } return cachedIsWindowsVistaOrGreater; } diff --git a/src/3rdparty/freebsd/0001-Patch-the-FreeBSD-strto-u-ll-functions-to-work-insid.patch b/src/3rdparty/freebsd/0001-Patch-the-FreeBSD-strto-u-ll-functions-to-work-insid.patch new file mode 100644 index 00000000000..ac7580d5c45 --- /dev/null +++ b/src/3rdparty/freebsd/0001-Patch-the-FreeBSD-strto-u-ll-functions-to-work-insid.patch @@ -0,0 +1,149 @@ +From 81a2d1a38becdeed2cd8b963e190aedf197e39c6 Mon Sep 17 00:00:00 2001 +From: Thiago Macieira +Date: Thu, 2 Oct 2014 22:03:19 -0700 +Subject: [PATCH 1/1] Patch the FreeBSD strto(u)ll functions to work inside + QtCore + +Changes: + - remove the #includes and the SCCSID + - rename from strtoxx_l to qt_strtoxx (merging the two functions) + - remove __restrict + - remove the locale_t parameter and use ascii_isspace instead of isspace_l + +Change-Id: I1e522e12da90eb35eefcf4025102dc11b22c60a5 +--- + src/3rdparty/freebsd/strtoll.c | 27 +++++---------------------- + src/3rdparty/freebsd/strtoull.c | 27 +++++---------------------- + 2 files changed, 10 insertions(+), 44 deletions(-) + +diff --git a/src/3rdparty/freebsd/strtoll.c b/src/3rdparty/freebsd/strtoll.c +index 16a8196..0ded267 100644 +--- a/src/3rdparty/freebsd/strtoll.c ++++ b/src/3rdparty/freebsd/strtoll.c +@@ -32,18 +32,6 @@ + * SUCH DAMAGE. + */ + +-#if defined(LIBC_SCCS) && !defined(lint) +-static char sccsid[] = "@(#)strtoq.c 8.1 (Berkeley) 6/4/93"; +-#endif /* LIBC_SCCS and not lint */ +-#include +-__FBSDID("$FreeBSD$"); +- +-#include +-#include +-#include +-#include +-#include "xlocale_private.h" +- + /* + * Convert a string to a long long integer. + * +@@ -51,15 +39,15 @@ __FBSDID("$FreeBSD$"); + * alphabets and digits are each contiguous. + */ + long long +-strtoll_l(const char * __restrict nptr, char ** __restrict endptr, int base, +- locale_t locale) ++qt_strtoll(const char * nptr, char **endptr, int base) + { + const char *s; + unsigned long long acc; + char c; + unsigned long long cutoff; + int neg, any, cutlim; +- FIX_LOCALE(locale); + + /* + * Skip white space and pick up leading +/- sign if any. +@@ -69,7 +55,7 @@ strtoll_l(const char * __restrict nptr, char ** __restrict endptr, int base, + s = nptr; + do { + c = *s++; +- } while (isspace_l((unsigned char)c, locale)); ++ } while (ascii_isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; +@@ -141,13 +127,8 @@ strtoll_l(const char * __restrict nptr, char ** __restrict endptr, int base, + noconv: + errno = EINVAL; + } else if (neg) +- acc = -acc; ++ acc = (unsigned long long) -(long long)acc; + if (endptr != NULL) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); + } +-long long +-strtoll(const char * __restrict nptr, char ** __restrict endptr, int base) +-{ +- return strtoll_l(nptr, endptr, base, __get_locale()); +-} +diff --git a/src/3rdparty/freebsd/strtoull.c b/src/3rdparty/freebsd/strtoull.c +index dc40e0e..cb04adb 100644 +--- a/src/3rdparty/freebsd/strtoull.c ++++ b/src/3rdparty/freebsd/strtoull.c +@@ -32,18 +32,6 @@ + * SUCH DAMAGE. + */ + +-#if defined(LIBC_SCCS) && !defined(lint) +-static char sccsid[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93"; +-#endif /* LIBC_SCCS and not lint */ +-#include +-__FBSDID("$FreeBSD$"); +- +-#include +-#include +-#include +-#include +-#include "xlocale_private.h" +- + /* + * Convert a string to an unsigned long long integer. + * +@@ -51,15 +39,15 @@ __FBSDID("$FreeBSD$"); + * alphabets and digits are each contiguous. + */ + unsigned long long +-strtoull_l(const char * __restrict nptr, char ** __restrict endptr, int base, +- locale_t locale) ++qt_strtoull(const char * nptr, char **endptr, int base) + { + const char *s; + unsigned long long acc; + char c; + unsigned long long cutoff; + int neg, any, cutlim; +- FIX_LOCALE(locale); + + /* + * See strtoq for comments as to the logic used. +@@ -67,7 +53,7 @@ strtoull_l(const char * __restrict nptr, char ** __restrict endptr, int base, + s = nptr; + do { + c = *s++; +- } while (isspace_l((unsigned char)c, locale)); ++ } while (ascii_isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; +@@ -119,13 +105,8 @@ strtoull_l(const char * __restrict nptr, char ** __restrict endptr, int base, + noconv: + errno = EINVAL; + } else if (neg) +- acc = -acc; ++ acc = (unsigned long long) -(long long)acc; + if (endptr != NULL) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); + } +-unsigned long long +-strtoull(const char * __restrict nptr, char ** __restrict endptr, int base) +-{ +- return strtoull_l(nptr, endptr, base, __get_locale()); +-} +-- +1.8.4.5 + diff --git a/src/3rdparty/freebsd/strtoll.c b/src/3rdparty/freebsd/strtoll.c new file mode 100644 index 00000000000..6f06e03dc8b --- /dev/null +++ b/src/3rdparty/freebsd/strtoll.c @@ -0,0 +1,134 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Convert a string to a long long integer. + * + * Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +long long +qt_strtoll(const char * nptr, char **endptr, int base) +{ + const char *s; + unsigned long long acc; + char c; + unsigned long long cutoff; + int neg, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + s = nptr; + do { + c = *s++; + } while (ascii_isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X') && + ((s[1] >= '0' && s[1] <= '9') || + (s[1] >= 'A' && s[1] <= 'F') || + (s[1] >= 'a' && s[1] <= 'f'))) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + acc = any = 0; + if (base < 2 || base > 36) + goto noconv; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for quads is + * [-9223372036854775808..9223372036854775807] and the input base + * is 10, cutoff will be set to 922337203685477580 and cutlim to + * either 7 (neg==0) or 8 (neg==1), meaning that if we have + * accumulated a value > 922337203685477580, or equal but the + * next digit is > 7 (or 8), the number is too big, and we will + * return a range error. + * + * Set 'any' if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? (unsigned long long)-(LLONG_MIN + LLONG_MAX) + LLONG_MAX + : LLONG_MAX; + cutlim = cutoff % base; + cutoff /= base; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = neg ? LLONG_MIN : LLONG_MAX; + errno = ERANGE; + } else if (!any) { +noconv: + errno = EINVAL; + } else if (neg) + acc = (unsigned long long) -(long long)acc; + if (endptr != NULL) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} diff --git a/src/3rdparty/freebsd/strtoull.c b/src/3rdparty/freebsd/strtoull.c new file mode 100644 index 00000000000..7cb97f02f4a --- /dev/null +++ b/src/3rdparty/freebsd/strtoull.c @@ -0,0 +1,112 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Convert a string to an unsigned long long integer. + * + * Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +unsigned long long +qt_strtoull(const char * nptr, char **endptr, int base) +{ + const char *s; + unsigned long long acc; + char c; + unsigned long long cutoff; + int neg, any, cutlim; + + /* + * See strtoq for comments as to the logic used. + */ + s = nptr; + do { + c = *s++; + } while (ascii_isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X') && + ((s[1] >= '0' && s[1] <= '9') || + (s[1] >= 'A' && s[1] <= 'F') || + (s[1] >= 'a' && s[1] <= 'f'))) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + acc = any = 0; + if (base < 2 || base > 36) + goto noconv; + + cutoff = ULLONG_MAX / base; + cutlim = ULLONG_MAX % base; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULLONG_MAX; + errno = ERANGE; + } else if (!any) { +noconv: + errno = EINVAL; + } else if (neg) + acc = (unsigned long long) -(long long)acc; + if (endptr != NULL) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c index 653705f6ca6..9a2726c9355 100644 --- a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c +++ b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c @@ -276,7 +276,9 @@ static sljit_si cpu_has_sse2 = -1; #endif static sljit_si cpu_has_cmov = -1; -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#ifdef _WIN32_WCE +#include +#elif defined(_MSC_VER) && _MSC_VER >= 1400 #include #endif diff --git a/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java b/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java index 0eda08c9d9a..a8583cde17e 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java +++ b/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java @@ -49,6 +49,7 @@ import java.io.OutputStreamWriter; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; +import java.util.Map; import org.json.JSONArray; import org.json.JSONException; @@ -67,6 +68,7 @@ import android.graphics.NinePatch; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; +import android.graphics.PorterDuff; import android.graphics.drawable.AnimationDrawable; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ClipDrawable; @@ -94,8 +96,11 @@ public class ExtractStyle { native static int[] extractChunkInfo20(byte[] chunkData); native static int[] extractNativeChunkInfo20(long nativeChunk); + Class styleableClass = getClass("android.R$styleable"); + Class rippleDrawableClass = getClass("android.graphics.drawable.RippleDrawable"); + Class animatedStateListDrawableClass = getClass("android.graphics.drawable.AnimatedStateListDrawable"); + Class vectorDrawableClass = getClass("android.graphics.drawable.VectorDrawable"); - Class styleableClass = getStylableClass(); final int[] EMPTY_STATE_SET = {}; final int[] ENABLED_STATE_SET = {android.R.attr.state_enabled}; final int[] FOCUSED_STATE_SET = {android.R.attr.state_focused}; @@ -386,15 +391,44 @@ public class ExtractStyle { return null; } - private Class getStylableClass() { + private Class getClass(String className) { try { - return Class.forName("android.R$styleable"); + return Class.forName(className); } catch (ClassNotFoundException e) { e.printStackTrace(); } return null; } + Field getAccessibleField(Class clazz, String fieldName) { + try { + Field f = clazz.getDeclaredField(fieldName); + f.setAccessible(true); + return f; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + Field tryGetAccessibleField(Class clazz, String fieldName) { + if (clazz == null) + return null; + + try { + Field f = clazz.getDeclaredField(fieldName); + f.setAccessible(true); + return f; + } catch (Exception e) { + for (Class c : clazz.getInterfaces()) { + Field f = tryGetAccessibleField(c, fieldName); + if (f != null) + return f; + } + } + return tryGetAccessibleField(clazz.getSuperclass(), fieldName); + } + int getField(Class clazz, String fieldName) { try { @@ -619,10 +653,9 @@ public class ExtractStyle { JSONObject stateJson = new JSONObject(); final Drawable d = (Drawable) StateListDrawable.class.getMethod("getStateDrawable", Integer.TYPE).invoke(stateList, i); final int [] states = (int[]) StateListDrawable.class.getMethod("getStateSet", Integer.TYPE).invoke(stateList, i); - if (states == null) - continue; - stateJson.put("states", getStatesList(states)); - stateJson.put("drawable", getDrawable(d, filename+"__"+getStatesName(states), null)); + if (states != null) + stateJson.put("states", getStatesList(states)); + stateJson.put("drawable", getDrawable(d, filename+"__" + (states != null ? getStatesName(states) : ("state_pos_" + i)), null)); array.put(stateJson); } json.put("type", "stateslist"); @@ -647,7 +680,8 @@ public class ExtractStyle { GradientDrawable.Orientation orientation=(Orientation) gradientStateClass.getField("mOrientation").get(obj); json.put("orientation",orientation.name()); int [] intArray=(int[]) gradientStateClass.getField("mColors").get(obj); - json.put("colors",getJsonArray(intArray, 0, intArray.length)); + if (intArray != null) + json.put("colors",getJsonArray(intArray, 0, intArray.length)); json.put("positions",getJsonArray((float[]) gradientStateClass.getField("mPositions").get(obj))); json.put("strokeWidth",gradientStateClass.getField("mStrokeWidth").getInt(obj)); json.put("strokeDashWidth",gradientStateClass.getField("mStrokeDashWidth").getFloat(obj)); @@ -681,27 +715,13 @@ public class ExtractStyle { json.put("type", "rotate"); Object obj = drawable.getConstantState(); Class rotateStateClass = obj.getClass(); - Field f = rotateStateClass.getDeclaredField("mDrawable"); - f.setAccessible(true); - json.put("drawable", getDrawable(f.get(obj), filename, null)); - f = rotateStateClass.getDeclaredField("mPivotX"); - f.setAccessible(true); - json.put("pivotX", f.getFloat(obj)); - f = rotateStateClass.getDeclaredField("mPivotXRel"); - f.setAccessible(true); - json.put("pivotXRel", f.getBoolean(obj)); - f = rotateStateClass.getDeclaredField("mPivotY"); - f.setAccessible(true); - json.put("pivotY", f.getFloat(obj)); - f = rotateStateClass.getDeclaredField("mPivotYRel"); - f.setAccessible(true); - json.put("pivotYRel", f.getBoolean(obj)); - f = rotateStateClass.getDeclaredField("mFromDegrees"); - f.setAccessible(true); - json.put("fromDegrees", f.getFloat(obj)); - f = rotateStateClass.getDeclaredField("mToDegrees"); - f.setAccessible(true); - json.put("toDegrees", f.getFloat(obj)); + json.put("drawable", getDrawable(getAccessibleField(rotateStateClass, "mDrawable").get(obj), filename, null)); + json.put("pivotX", getAccessibleField(rotateStateClass, "mPivotX").getFloat(obj)); + json.put("pivotXRel", getAccessibleField(rotateStateClass, "mPivotXRel").getBoolean(obj)); + json.put("pivotY", getAccessibleField(rotateStateClass, "mPivotY").getFloat(obj)); + json.put("pivotYRel", getAccessibleField(rotateStateClass, "mPivotYRel").getBoolean(obj)); + json.put("fromDegrees", getAccessibleField(rotateStateClass, "mFromDegrees").getFloat(obj)); + json.put("toDegrees", getAccessibleField(rotateStateClass, "mToDegrees").getFloat(obj)); } catch (Exception e) { e.printStackTrace(); } @@ -772,22 +792,14 @@ public class ExtractStyle { private JSONObject findPatchesMarings(Drawable d) throws JSONException, NoSuchFieldException, IllegalAccessException { - Field mNinePatch = ((NinePatchDrawable)d).getClass().getDeclaredField("mNinePatch"); - mNinePatch.setAccessible(true); - NinePatch np = (NinePatch) mNinePatch.get(d); + NinePatch np = (NinePatch) getAccessibleField(NinePatchDrawable.class, "mNinePatch").get(d); if (Build.VERSION.SDK_INT < 19) - { - Field mChunk = np.getClass().getDeclaredField("mChunk"); - mChunk.setAccessible(true); - return getJsonChunkInfo(extractChunkInfo((byte[]) mChunk.get(np))); - } + return getJsonChunkInfo(extractChunkInfo((byte[]) getAccessibleField(np.getClass(), "mChunk").get(np))); else { - Field mNativeChunk = np.getClass().getDeclaredField("mNativeChunk"); - mNativeChunk.setAccessible(true); if (Build.VERSION.SDK_INT > 19) - return getJsonChunkInfo(extractNativeChunkInfo20(mNativeChunk.getLong(np))); - return getJsonChunkInfo(extractNativeChunkInfo(mNativeChunk.getInt(np))); + return getJsonChunkInfo(extractNativeChunkInfo20(getAccessibleField(np.getClass(), "mNativeChunk").getLong(np))); + return getJsonChunkInfo(extractNativeChunkInfo(getAccessibleField(np.getClass(), "mNativeChunk").getInt(np))); } } @@ -803,8 +815,177 @@ public class ExtractStyle { } private HashMap m_drawableCache = new HashMap(); + private JSONObject getRippleDrawable(Object drawable, String filename, Rect padding) + { + JSONObject json = getLayerDrawable(drawable, filename); + JSONObject ripple = new JSONObject(); + try { + final Object mState = getAccessibleField(rippleDrawableClass, "mState").get(drawable); + ripple.put("mask", getDrawable((Drawable)getAccessibleField(rippleDrawableClass, "mMask").get(drawable), filename, padding)); + ripple.put("maxRadius", getAccessibleField(mState.getClass(), "mMaxRadius").getInt(mState)); + ripple.put("color", getColorStateList((ColorStateList)getAccessibleField(mState.getClass(), "mColor").get(mState))); + json.put("ripple", ripple); + } catch (Exception e) { + e.printStackTrace(); + } + return json; + } + + private HashMap getStateTransitions(Object sa) throws Exception + { + HashMap transitions = new HashMap(); + final int sz = getAccessibleField(sa.getClass(), "mSize").getInt(sa); + long[] keys = (long[]) getAccessibleField(sa.getClass(), "mKeys").get(sa); + long[] values = (long[]) getAccessibleField(sa.getClass(), "mValues").get(sa); + for (int i = 0; i < sz; i++) { + transitions.put(keys[i], values[i]); + } + return transitions; + } + + private HashMap getStateIds(Object sa) throws Exception + { + HashMap states = new HashMap(); + final int sz = getAccessibleField(sa.getClass(), "mSize").getInt(sa); + int[] keys = (int[]) getAccessibleField(sa.getClass(), "mKeys").get(sa); + int[] values = (int[]) getAccessibleField(sa.getClass(), "mValues").get(sa); + for (int i = 0; i < sz; i++) { + states.put(keys[i], values[i]); + } + return states; + } + + private int findStateIndex(int id, HashMap stateIds) + { + for (Map.Entry s : stateIds.entrySet()) { + if (id == s.getValue()) + return s.getKey(); + } + return -1; + } + + private JSONObject getAnimatedStateListDrawable(Object drawable, String filename) + { + JSONObject json = getStateListDrawable(drawable, filename); + try { + Object state = getAccessibleField(animatedStateListDrawableClass, "mState").get(drawable); + + HashMap stateIds = getStateIds(getAccessibleField(state.getClass(), "mStateIds").get(state)); + HashMap transitions = getStateTransitions(getAccessibleField(state.getClass(), "mTransitions").get(state)); + + for (Map.Entry t : transitions.entrySet()) { + final int toState = findStateIndex(t.getKey().intValue(), stateIds); + final int fromState = findStateIndex((int) (t.getKey() >> 32), stateIds); + + JSONObject transition = new JSONObject(); + transition.put("from", fromState); + transition.put("to", toState); + transition.put("reverse", (t.getValue() >> 32) != 0); + + JSONArray stateslist = json.getJSONArray("stateslist"); + JSONObject stateobj = stateslist.getJSONObject(t.getValue().intValue()); + stateobj.put("transition", transition); + } + } catch (Exception e) { + e.printStackTrace(); + } + return json; + } + + private JSONObject getVPath(Object path) throws Exception + { + JSONObject json = new JSONObject(); + final Class pathClass = path.getClass(); + json.put("type", "path"); + json.put("name", tryGetAccessibleField(pathClass, "mPathName").get(path)); + Object[] mNodes = (Object[]) tryGetAccessibleField(pathClass, "mNodes").get(path); + JSONArray nodes = new JSONArray(); + for (Object n: mNodes) { + JSONObject node = new JSONObject(); + node.put("type", String.valueOf(getAccessibleField(n.getClass(), "mType").getChar(n))); + node.put("params", getJsonArray((float[])getAccessibleField(n.getClass(), "mParams").get(n))); + nodes.put(node); + } + json.put("nodes", nodes); + json.put("isClip", (Boolean) pathClass.getMethod("isClipPath").invoke(path)); + + if (tryGetAccessibleField(pathClass, "mStrokeColor") == null) + return json; // not VFullPath + + json.put("strokeColor", getAccessibleField(pathClass, "mStrokeColor").getInt(path)); + json.put("strokeWidth", getAccessibleField(pathClass, "mStrokeWidth").getFloat(path)); + json.put("fillColor", getAccessibleField(pathClass, "mFillColor").getInt(path)); + json.put("strokeAlpha", getAccessibleField(pathClass, "mStrokeAlpha").getFloat(path)); + json.put("fillRule", getAccessibleField(pathClass, "mFillRule").getInt(path)); + json.put("fillAlpha", getAccessibleField(pathClass, "mFillAlpha").getFloat(path)); + json.put("trimPathStart", getAccessibleField(pathClass, "mTrimPathStart").getFloat(path)); + json.put("trimPathEnd", getAccessibleField(pathClass, "mTrimPathEnd").getFloat(path)); + json.put("trimPathOffset", getAccessibleField(pathClass, "mTrimPathOffset").getFloat(path)); + json.put("strokeLineCap", (Paint.Cap) getAccessibleField(pathClass, "mStrokeLineCap").get(path)); + json.put("strokeLineJoin", (Paint.Join) getAccessibleField(pathClass, "mStrokeLineJoin").get(path)); + json.put("strokeMiterlimit", getAccessibleField(pathClass, "mStrokeMiterlimit").getFloat(path)); + return json; + } + + @SuppressWarnings("unchecked") + private JSONObject getVGroup(Object group) throws Exception + { + JSONObject json = new JSONObject(); + json.put("type", "group"); + final Class groupClass = group.getClass(); + json.put("name", getAccessibleField(groupClass, "mGroupName").get(group)); + json.put("rotate", getAccessibleField(groupClass, "mRotate").getFloat(group)); + json.put("pivotX", getAccessibleField(groupClass, "mPivotX").getFloat(group)); + json.put("pivotY", getAccessibleField(groupClass, "mPivotY").getFloat(group)); + json.put("scaleX", getAccessibleField(groupClass, "mScaleX").getFloat(group)); + json.put("scaleY", getAccessibleField(groupClass, "mScaleY").getFloat(group)); + json.put("translateX", getAccessibleField(groupClass, "mTranslateX").getFloat(group)); + json.put("translateY", getAccessibleField(groupClass, "mTranslateY").getFloat(group)); + + ArrayList mChildren = (ArrayList) getAccessibleField(groupClass, "mChildren").get(group); + JSONArray children = new JSONArray(); + for (Object c: mChildren) { + if (groupClass.isInstance(c)) + children.put(getVGroup(c)); + else + children.put(getVPath(c)); + } + json.put("children", children); + return json; + } + + private JSONObject getVectorDrawable(Object drawable, String filename, Rect padding) + { + JSONObject json = new JSONObject(); + try { + json.put("type", "vector"); + final Object state = getAccessibleField(vectorDrawableClass, "mVectorState").get(drawable); + final Class stateClass = state.getClass(); + final ColorStateList mTint = (ColorStateList) getAccessibleField(stateClass, "mTint").get(state); + if (mTint != null) { + json.put("tintList", getColorStateList(mTint)); + json.put("tintMode", (PorterDuff.Mode) getAccessibleField(stateClass, "mTintMode").get(state)); + } + final Object mVPathRenderer = getAccessibleField(stateClass, "mVPathRenderer").get(state); + final Class VPathRendererClass = mVPathRenderer.getClass(); + json.put("baseWidth", getAccessibleField(VPathRendererClass, "mBaseWidth").getFloat(mVPathRenderer)); + json.put("baseHeight", getAccessibleField(VPathRendererClass, "mBaseHeight").getFloat(mVPathRenderer)); + json.put("viewportWidth", getAccessibleField(VPathRendererClass, "mViewportWidth").getFloat(mVPathRenderer)); + json.put("viewportHeight", getAccessibleField(VPathRendererClass, "mViewportHeight").getFloat(mVPathRenderer)); + json.put("rootAlpha", getAccessibleField(VPathRendererClass, "mRootAlpha").getInt(mVPathRenderer)); + json.put("rootName", getAccessibleField(VPathRendererClass, "mRootName").get(mVPathRenderer)); + json.put("rootGroup", getVGroup(getAccessibleField(mVPathRenderer.getClass(), "mRootGroup").get(mVPathRenderer))); + } catch(Exception e) { + e.printStackTrace(); + } + return json; + } + public JSONObject getDrawable(Object drawable, String filename, Rect padding) { + if (drawable == null) + return null; + DrawableCache dc = m_drawableCache.get(filename); if (dc != null) { @@ -819,10 +1000,39 @@ public class ExtractStyle { bmp = (Bitmap) drawable; else { - if (drawable instanceof BitmapDrawable) - bmp = ((BitmapDrawable)drawable).getBitmap(); + if (drawable instanceof BitmapDrawable) { + BitmapDrawable bitmapDrawable = (BitmapDrawable)drawable; + bmp = bitmapDrawable.getBitmap(); + try { + json.put("gravity", bitmapDrawable.getGravity()); + json.put("tileModeX", bitmapDrawable.getTileModeX()); + json.put("tileModeY", bitmapDrawable.getTileModeY()); + if (Build.VERSION.SDK_INT >= 18) { + json.put("antialias", (Boolean) BitmapDrawable.class.getMethod("hasAntiAlias").invoke(bitmapDrawable)); + json.put("mipMap", (Boolean) BitmapDrawable.class.getMethod("hasMipMap").invoke(bitmapDrawable)); + } + if (Build.VERSION.SDK_INT >= 21) { + json.put("tintMode", (PorterDuff.Mode) BitmapDrawable.class.getMethod("getTintMode").invoke(bitmapDrawable)); + ColorStateList tintList = (ColorStateList) BitmapDrawable.class.getMethod("getTint").invoke(bitmapDrawable); + if (tintList != null) + json.put("tintList", getColorStateList(tintList)); + } + } catch (Exception e) { + e.printStackTrace(); + } + } else { + + if (rippleDrawableClass != null && rippleDrawableClass.isInstance(drawable)) + return getRippleDrawable(drawable, filename, padding); + + if (animatedStateListDrawableClass != null && animatedStateListDrawableClass.isInstance(drawable)) + return getAnimatedStateListDrawable(drawable, filename); + + if (vectorDrawableClass != null && vectorDrawableClass.isInstance(drawable)) + return getVectorDrawable(drawable, filename, padding); + if (drawable instanceof ScaleDrawable) { return getDrawable(((ScaleDrawable)drawable).getDrawable(), filename, null); @@ -852,9 +1062,7 @@ public class ExtractStyle { try { json.put("type", "clipDrawable"); Drawable.ConstantState dcs = ((ClipDrawable)drawable).getConstantState(); - Field f = dcs.getClass().getDeclaredField("mDrawable"); - f.setAccessible(true); - json.put("drawable", getDrawable(f.get(dcs), filename, null)); + json.put("drawable", getDrawable(getAccessibleField(dcs.getClass(), "mDrawable").get(dcs), filename, null)); if (null != padding) json.put("padding", getJsonRect(padding)); else { @@ -892,14 +1100,10 @@ public class ExtractStyle { { try { InsetDrawable d = (InsetDrawable)drawable; - Field mInsetState = d.getClass().getDeclaredField("mInsetState"); - mInsetState.setAccessible(true); - Object mInsetStateObject = mInsetState.get(drawable); - Field mDrawable = mInsetStateObject.getClass().getDeclaredField("mDrawable"); - mDrawable.setAccessible(true); + Object mInsetStateObject = getAccessibleField(InsetDrawable.class, "mInsetState").get(d); Rect _padding = new Rect(); boolean hasPadding = d.getPadding(_padding); - return getDrawable(mDrawable.get(mInsetStateObject), filename, hasPadding ? _padding : null); + return getDrawable(getAccessibleField(mInsetStateObject.getClass(), "mDrawable").get(mInsetStateObject), filename, hasPadding ? _padding : null); } catch (Exception e) { e.printStackTrace(); } @@ -1210,9 +1414,17 @@ public class ExtractStyle { json.put("TextView_drawableEnd", getDrawable(a.getDrawable(attr), styleName + "_TextView_drawableEnd", null)); else if (attr == TextView_drawablePadding) json.put("TextView_drawablePadding", a.getDimensionPixelSize(attr, 0)); - else if (attr == TextView_textCursorDrawable) - json.put("TextView_textCursorDrawable", getDrawable(m_context.getResources().getDrawable(a.getResourceId(attr, 0)), styleName + "_TextView_textCursorDrawable", null)); - else if (attr == TextView_maxLines) + else if (attr == TextView_textCursorDrawable) { + try { + json.put("TextView_textCursorDrawable", getDrawable(a.getDrawable(attr), styleName + "_TextView_textCursorDrawable", null)); + } catch (Exception e_) { + try { + json.put("TextView_textCursorDrawable", getDrawable(m_context.getResources().getDrawable(a.getResourceId(attr, 0)), styleName + "_TextView_textCursorDrawable", null)); + } catch (Exception e) { + e.printStackTrace(); + } + } + }else if (attr == TextView_maxLines) json.put("TextView_maxLines", a.getInt(attr, -1)); else if (attr == TextView_maxHeight) json.put("TextView_maxHeight", a.getDimensionPixelSize(attr, -1)); @@ -1300,13 +1512,37 @@ public class ExtractStyle { json.put("TextView_imeActionId", a.getInt(attr,0)); else if (attr == TextView_privateImeOptions) json.put("TextView_privateImeOptions", a.getString(attr)); - else if (attr == TextView_textSelectHandleLeft && styleName.equals("textViewStyle")) - json.put("TextView_textSelectHandleLeft", getDrawable(m_context.getResources().getDrawable(a.getResourceId(attr, 0)), styleName + "_TextView_textSelectHandleLeft", null)); - else if (attr == TextView_textSelectHandleRight && styleName.equals("textViewStyle")) - json.put("TextView_textSelectHandleRight", getDrawable(m_context.getResources().getDrawable(a.getResourceId(attr, 0)), styleName + "_TextView_textSelectHandleRight", null)); - else if (attr == TextView_textSelectHandle && styleName.equals("textViewStyle")) - json.put("TextView_textSelectHandle", getDrawable(m_context.getResources().getDrawable(a.getResourceId(attr, 0)), styleName + "_TextView_textSelectHandle", null)); - else if (attr == TextView_textIsSelectable) + else if (attr == TextView_textSelectHandleLeft && styleName.equals("textViewStyle")) { + try { + json.put("TextView_textSelectHandleLeft", getDrawable(a.getDrawable(attr), styleName + "_TextView_textSelectHandleLeft", null)); + } catch (Exception _e) { + try { + json.put("TextView_textSelectHandleLeft", getDrawable(m_context.getResources().getDrawable(a.getResourceId(attr, 0)), styleName + "_TextView_textSelectHandleLeft", null)); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else if (attr == TextView_textSelectHandleRight && styleName.equals("textViewStyle")) { + try { + json.put("TextView_textSelectHandleRight", getDrawable(a.getDrawable(attr), styleName + "_TextView_textSelectHandleRight", null)); + } catch (Exception _e) { + try { + json.put("TextView_textSelectHandleRight", getDrawable(m_context.getResources().getDrawable(a.getResourceId(attr, 0)), styleName + "_TextView_textSelectHandleRight", null)); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else if (attr == TextView_textSelectHandle && styleName.equals("textViewStyle")) { + try { + json.put("TextView_textSelectHandle", getDrawable(a.getDrawable(attr), styleName + "_TextView_textSelectHandle", null)); + } catch (Exception _e) { + try { + json.put("TextView_textSelectHandle", getDrawable(m_context.getResources().getDrawable(a.getResourceId(attr, 0)), styleName + "_TextView_textSelectHandle", null)); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else if (attr == TextView_textIsSelectable) json.put("TextView_textIsSelectable", a.getBoolean(attr, false)); else if (attr == TextView_textAllCaps) allCaps = a.getBoolean(attr, false); @@ -1511,6 +1747,11 @@ public class ExtractStyle { json.put("Switch_switchPadding", a.getDimensionPixelSize(getField(styleableClass, "Switch_switchPadding"), 0)); json.put("Switch_thumbTextPadding", a.getDimensionPixelSize(getField(styleableClass, "Switch_thumbTextPadding"), 0)); + if (Build.VERSION.SDK_INT >= 21) { + json.put("Switch_showText", a.getBoolean(getField(styleableClass, "Switch_showText"), true)); + json.put("Switch_splitTrack", a.getBoolean(getField(styleableClass, "Switch_splitTrack"), false)); + } + a.recycle(); jsonWriter.name(styleName).value(json); } catch (Exception e) { @@ -1729,6 +1970,23 @@ public class ExtractStyle { } } + private JSONObject extractDefaultPalette() + { + TypedArray array = m_theme.obtainStyledAttributes(new int[]{ + android.R.attr.textAppearance + }); + int pos = 0; + JSONObject json = extractTextAppearance(array.getResourceId(pos++, -1)); + try { + json.put("defaultBackgroundColor", defaultBackgroundColor); + json.put("defaultTextColorPrimary", defaultTextColor); + } catch (Exception e) { + e.printStackTrace(); + } + array.recycle(); + return json; + } + public ExtractStyle(Context context, String extractPath) { // Log.i(MinistroService.TAG, "Extract " + extractPath); @@ -1740,9 +1998,13 @@ public class ExtractStyle { TypedArray array = m_theme.obtainStyledAttributes(new int[]{ android.R.attr.colorBackground, android.R.attr.textColorPrimary, + android.R.attr.textColor }); defaultBackgroundColor = array.getColor(0, 0); - defaultTextColor = array.getColor(1, 0xFFFFFF); + int textColor = array.getColor(1, 0xFFFFFF); + if (textColor == 0xFFFFFF) + textColor = array.getColor(2, 0xFFFFFF); + defaultTextColor = textColor; array.recycle(); try @@ -1750,6 +2012,7 @@ public class ExtractStyle { SimpleJsonWriter jsonWriter = new SimpleJsonWriter(m_extractPath+"style.json"); jsonWriter.beginObject(); try { + jsonWriter.name("defaultStyle").value(extractDefaultPalette()); extractWindow(jsonWriter, "windowStyle"); jsonWriter.name("buttonStyle").value(extractTextAppearanceInformations("buttonStyle", "QPushButton", null, -1)); jsonWriter.name("spinnerStyle").value(extractTextAppearanceInformations("spinnerStyle", "QComboBox", null, -1)); 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 7642bc38b58..f44465b4c51 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -50,6 +50,8 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Configuration; import android.graphics.drawable.ColorDrawable; +import android.net.LocalServerSocket; +import android.net.LocalSocket; import android.os.Build; import android.os.Bundle; import android.os.Handler; @@ -72,8 +74,11 @@ import android.view.ViewGroup; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; +import java.io.BufferedReader; +import java.io.DataOutputStream; import java.io.File; import java.io.FileWriter; +import java.io.InputStreamReader; import java.io.IOException; import java.lang.reflect.Method; import java.util.ArrayList; @@ -265,30 +270,31 @@ public class QtActivityDelegate } if (Build.VERSION.SDK_INT > 10 && (inputHints & ImhHiddenText) != 0) - inputType |= 0x10; + inputType |= 0x10 /* TYPE_NUMBER_VARIATION_PASSWORD */; } else if ((inputHints & ImhDialableCharactersOnly) != 0) { inputType = android.text.InputType.TYPE_CLASS_PHONE; } else if ((inputHints & (ImhDate | ImhTime)) != 0) { inputType = android.text.InputType.TYPE_CLASS_DATETIME; - if ((inputHints & ImhDate) != 0) - inputType |= android.text.InputType.TYPE_DATETIME_VARIATION_DATE; - if ((inputHints & ImhTime) != 0) - inputType |= android.text.InputType.TYPE_DATETIME_VARIATION_TIME; + if ((inputHints & (ImhDate | ImhTime)) != (ImhDate | ImhTime)) { + if ((inputHints & ImhDate) != 0) + inputType |= android.text.InputType.TYPE_DATETIME_VARIATION_DATE; + if ((inputHints & ImhTime) != 0) + inputType |= android.text.InputType.TYPE_DATETIME_VARIATION_TIME; + } // else { TYPE_DATETIME_VARIATION_NORMAL(0) } } else { // CLASS_TEXT - if ((inputHints & ImhHiddenText) != 0) { + if ((inputHints & (ImhEmailCharactersOnly | ImhUrlCharactersOnly)) != 0) { + if ((inputHints & ImhUrlCharactersOnly) != 0) { + inputType |= android.text.InputType.TYPE_TEXT_VARIATION_URI; + imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_GO; + } else if ((inputHints & ImhEmailCharactersOnly) != 0) { + inputType |= android.text.InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS; + } + } else if ((inputHints & ImhHiddenText) != 0) { inputType |= android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD; - } else if ((inputHints & (ImhNoAutoUppercase | ImhNoPredictiveText | ImhSensitiveData)) != 0) { + } else if ((inputHints & ImhSensitiveData) != 0) { inputType |= android.text.InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD; } - if ((inputHints & ImhEmailCharactersOnly) != 0) - inputType |= android.text.InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS; - - if ((inputHints & ImhUrlCharactersOnly) != 0) { - inputType |= android.text.InputType.TYPE_TEXT_VARIATION_URI; - imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_GO; - } - if ((inputHints & ImhMultiLine) != 0) inputType |= android.text.InputType.TYPE_TEXT_FLAG_MULTI_LINE; @@ -300,8 +306,10 @@ public class QtActivityDelegate inputType |= android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES; } - if ((inputHints & ImhNoPredictiveText) != 0 || (inputHints & ImhSensitiveData) != 0) + if ((inputHints & ImhNoPredictiveText) != 0 || (inputHints & ImhSensitiveData) != 0 + || (inputHints & ImhHiddenText) != 0) { inputType |= android.text.InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS; + } } if ((inputHints & ImhMultiLine) != 0) @@ -485,6 +493,59 @@ public class QtActivityDelegate Log.i(QtNative.QtTAG, "DEBUGGER: " + msg); } + private class DebugWaitRunnable implements Runnable { + + public DebugWaitRunnable(String pingPongSocket) throws IOException { + socket = new LocalServerSocket(pingPongSocket); + } + + public boolean wasFailure; + private LocalServerSocket socket; + + public void run() { + final int napTime = 200; // milliseconds between file accesses + final int timeOut = 30000; // ms until we give up on ping and pong + final int maxAttempts = timeOut / napTime; + + try { + LocalSocket connectionFromClient = socket.accept(); + debugLog("Debug socket accepted"); + BufferedReader inFromClient = + new BufferedReader(new InputStreamReader(connectionFromClient.getInputStream())); + DataOutputStream outToClient = new DataOutputStream(connectionFromClient.getOutputStream()); + outToClient.writeBytes("" + android.os.Process.myPid()); + + for (int i = 0; i < maxAttempts; i++) { + String clientData = inFromClient.readLine(); + debugLog("Incoming socket " + clientData); + if (!clientData.isEmpty()) + break; + + if (connectionFromClient.isClosed()) { + wasFailure = true; + break; + } + Thread.sleep(napTime); + } + } catch (IOException ioEx) { + ioEx.printStackTrace(); + wasFailure = true; + Log.e(QtNative.QtTAG,"Can't start debugger" + ioEx.getMessage()); + } catch (InterruptedException interruptEx) { + wasFailure = true; + Log.e(QtNative.QtTAG,"Can't start debugger" + interruptEx.getMessage()); + } + } + + public void shutdown() throws IOException + { + wasFailure = true; + try { + socket.close(); + } catch (IOException ignored) { } + } + }; + public boolean startApplication() { // start application @@ -492,190 +553,218 @@ public class QtActivityDelegate // FIXME turn on debuggable check // if the applications is debuggable and it has a native debug request Bundle extras = m_activity.getIntent().getExtras(); - if ( /*(ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0 - &&*/ extras != null - && extras.containsKey("native_debug") - && extras.getString("native_debug").equals("true")) { - try { - String packagePath = - m_activity.getPackageManager().getApplicationInfo(m_activity.getPackageName(), - PackageManager.GET_CONFIGURATIONS).dataDir + "/"; - String gdbserverPath = - extras.containsKey("gdbserver_path") - ? extras.getString("gdbserver_path") - : packagePath+"lib/gdbserver "; + if (extras != null) { - String socket = - extras.containsKey("gdbserver_socket") - ? extras.getString("gdbserver_socket") - : "+debug-socket"; + if ( /*(ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0 + &&*/ extras.containsKey("native_debug") + && extras.getString("native_debug").equals("true")) { + try { + String packagePath = + m_activity.getPackageManager().getApplicationInfo(m_activity.getPackageName(), + PackageManager.GET_CONFIGURATIONS).dataDir + "/"; + String gdbserverPath = + extras.containsKey("gdbserver_path") + ? extras.getString("gdbserver_path") + : packagePath+"lib/gdbserver "; - if (!(new File(gdbserverPath)).exists()) - gdbserverPath += ".so"; + String socket = + extras.containsKey("gdbserver_socket") + ? extras.getString("gdbserver_socket") + : "+debug-socket"; - // start debugger - m_debuggerProcess = Runtime.getRuntime().exec(gdbserverPath - + socket - + " --attach " - + android.os.Process.myPid(), - null, - new File(packagePath)); - } catch (IOException ioe) { - Log.e(QtNative.QtTAG,"Can't start debugger" + ioe.getMessage()); - } catch (SecurityException se) { - Log.e(QtNative.QtTAG,"Can't start debugger" + se.getMessage()); - } catch (NameNotFoundException e) { - Log.e(QtNative.QtTAG,"Can't start debugger" + e.getMessage()); + if (!(new File(gdbserverPath)).exists()) + gdbserverPath += ".so"; + + // start debugger + m_debuggerProcess = Runtime.getRuntime().exec(gdbserverPath + + socket + + " --attach " + + android.os.Process.myPid(), + null, + new File(packagePath)); + } catch (IOException ioe) { + Log.e(QtNative.QtTAG,"Can't start debugger" + ioe.getMessage()); + } catch (SecurityException se) { + Log.e(QtNative.QtTAG,"Can't start debugger" + se.getMessage()); + } catch (NameNotFoundException e) { + Log.e(QtNative.QtTAG,"Can't start debugger" + e.getMessage()); + } } - } - if ( /*(ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0 - &&*/ extras != null - && extras.containsKey("debug_ping") - && extras.getString("debug_ping").equals("true")) { - try { - debugLog("extra parameters: " + extras); - String packageName = m_activity.getPackageName(); - String pingFile = extras.getString("ping_file"); - String pongFile = extras.getString("pong_file"); - String gdbserverSocket = extras.getString("gdbserver_socket"); - String gdbserverCommand = extras.getString("gdbserver_command"); - boolean usePing = pingFile != null; - boolean usePong = pongFile != null; - boolean useSocket = gdbserverSocket != null; - int napTime = 200; // milliseconds between file accesses - int timeOut = 30000; // ms until we give up on ping and pong - int maxAttempts = timeOut / napTime; + if ( /*(ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0 + &&*/ extras.containsKey("debug_ping") + && extras.getString("debug_ping").equals("true")) { + try { + debugLog("extra parameters: " + extras); + String packageName = m_activity.getPackageName(); + String pingFile = extras.getString("ping_file"); + String pongFile = extras.getString("pong_file"); + String gdbserverSocket = extras.getString("gdbserver_socket"); + String gdbserverCommand = extras.getString("gdbserver_command"); + String pingSocket = extras.getString("ping_socket"); + boolean usePing = pingFile != null; + boolean usePong = pongFile != null; + boolean useSocket = gdbserverSocket != null; + boolean usePingSocket = pingSocket != null; + int napTime = 200; // milliseconds between file accesses + int timeOut = 30000; // ms until we give up on ping and pong + int maxAttempts = timeOut / napTime; - if (gdbserverSocket != null) { - debugLog("removing gdb socket " + gdbserverSocket); - new File(gdbserverSocket).delete(); - } - - if (usePing) { - debugLog("removing ping file " + pingFile); - File ping = new File(pingFile); - if (ping.exists()) { - if (!ping.delete()) - debugLog("ping file cannot be deleted"); + if (gdbserverSocket != null) { + debugLog("removing gdb socket " + gdbserverSocket); + new File(gdbserverSocket).delete(); } - } - if (usePong) { - debugLog("removing pong file " + pongFile); - File pong = new File(pongFile); - if (pong.exists()) { - if (!pong.delete()) - debugLog("pong file cannot be deleted"); - } - } - - debugLog("starting " + gdbserverCommand); - m_debuggerProcess = Runtime.getRuntime().exec(gdbserverCommand); - debugLog("gdbserver started"); - - if (useSocket) { - int i; - for (i = 0; i < maxAttempts; ++i) { - debugLog("waiting for socket at " + gdbserverSocket + ", attempt " + i); - File file = new File(gdbserverSocket); - if (file.exists()) { - file.setReadable(true, false); - file.setWritable(true, false); - file.setExecutable(true, false); - break; + if (usePing) { + debugLog("removing ping file " + pingFile); + File ping = new File(pingFile); + if (ping.exists()) { + if (!ping.delete()) + debugLog("ping file cannot be deleted"); } - Thread.sleep(napTime); } - if (i == maxAttempts) { - debugLog("time out when waiting for socket"); - return false; - } - - debugLog("socket ok"); - } else { - debugLog("socket not used"); - } - - if (usePing) { - // Tell we are ready. - debugLog("writing ping at " + pingFile); - FileWriter writer = new FileWriter(pingFile); - writer.write("" + android.os.Process.myPid()); - writer.close(); - File file = new File(pingFile); - file.setReadable(true, false); - file.setWritable(true, false); - file.setExecutable(true, false); - debugLog("wrote ping"); - } else { - debugLog("ping not requested"); - } - - // Wait until other side is ready. - if (usePong) { - int i; - for (i = 0; i < maxAttempts; ++i) { - debugLog("waiting for pong at " + pongFile + ", attempt " + i); - File file = new File(pongFile); - if (file.exists()) { - file.delete(); - break; + if (usePong) { + debugLog("removing pong file " + pongFile); + File pong = new File(pongFile); + if (pong.exists()) { + if (!pong.delete()) + debugLog("pong file cannot be deleted"); } - debugLog("go to sleep"); - Thread.sleep(napTime); - } - debugLog("Removing pingFile " + pingFile); - new File(pingFile).delete(); - - if (i == maxAttempts) { - debugLog("time out when waiting for pong file"); - return false; } - debugLog("got pong " + pongFile); - } else { - debugLog("pong not requested"); + debugLog("starting " + gdbserverCommand); + m_debuggerProcess = Runtime.getRuntime().exec(gdbserverCommand); + debugLog("gdbserver started"); + + if (useSocket) { + int i; + for (i = 0; i < maxAttempts; ++i) { + debugLog("waiting for socket at " + gdbserverSocket + ", attempt " + i); + File file = new File(gdbserverSocket); + if (file.exists()) { + file.setReadable(true, false); + file.setWritable(true, false); + file.setExecutable(true, false); + break; + } + Thread.sleep(napTime); + } + + if (i == maxAttempts) { + debugLog("time out when waiting for debug socket"); + return false; + } + + debugLog("socket ok"); + } else { + debugLog("socket not used"); + } + + if (usePingSocket) { + DebugWaitRunnable runnable = new DebugWaitRunnable(pingSocket); + Thread waitThread = new Thread(runnable); + waitThread.start(); + + int i; + for (i = 0; i < maxAttempts && waitThread.isAlive(); ++i) { + debugLog("Waiting for debug socket connect"); + debugLog("go to sleep"); + Thread.sleep(napTime); + } + + if (i == maxAttempts) { + debugLog("time out when waiting for ping socket"); + runnable.shutdown(); + return false; + } + + if (runnable.wasFailure) { + debugLog("Could not connect to debug client"); + return false; + } else { + debugLog("Got pid acknowledgment"); + } + } + + if (usePing) { + // Tell we are ready. + debugLog("writing ping at " + pingFile); + FileWriter writer = new FileWriter(pingFile); + writer.write("" + android.os.Process.myPid()); + writer.close(); + File file = new File(pingFile); + file.setReadable(true, false); + file.setWritable(true, false); + file.setExecutable(true, false); + debugLog("wrote ping"); + } else { + debugLog("ping not requested"); + } + + // Wait until other side is ready. + if (usePong) { + int i; + for (i = 0; i < maxAttempts; ++i) { + debugLog("waiting for pong at " + pongFile + ", attempt " + i); + File file = new File(pongFile); + if (file.exists()) { + file.delete(); + break; + } + debugLog("go to sleep"); + Thread.sleep(napTime); + } + debugLog("Removing pingFile " + pingFile); + new File(pingFile).delete(); + + if (i == maxAttempts) { + debugLog("time out when waiting for pong file"); + return false; + } + + debugLog("got pong " + pongFile); + } else { + debugLog("pong not requested"); + } + + } catch (IOException ioe) { + Log.e(QtNative.QtTAG,"Can't start debugger" + ioe.getMessage()); + } catch (SecurityException se) { + Log.e(QtNative.QtTAG,"Can't start debugger" + se.getMessage()); } - - } catch (IOException ioe) { - Log.e(QtNative.QtTAG,"Can't start debugger" + ioe.getMessage()); - } catch (SecurityException se) { - Log.e(QtNative.QtTAG,"Can't start debugger" + se.getMessage()); } - } - if (/*(ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0 - &&*/ extras != null - && extras.containsKey("qml_debug") - && extras.getString("qml_debug").equals("true")) { - String qmljsdebugger; - if (extras.containsKey("qmljsdebugger")) { - qmljsdebugger = extras.getString("qmljsdebugger"); - qmljsdebugger.replaceAll("\\s", ""); // remove whitespace for security - } else { - qmljsdebugger = "port:3768"; + if (/*(ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0 + &&*/ extras.containsKey("qml_debug") + && extras.getString("qml_debug").equals("true")) { + String qmljsdebugger; + if (extras.containsKey("qmljsdebugger")) { + qmljsdebugger = extras.getString("qmljsdebugger"); + qmljsdebugger.replaceAll("\\s", ""); // remove whitespace for security + } else { + qmljsdebugger = "port:3768"; + } + m_applicationParameters += "\t-qmljsdebugger=" + qmljsdebugger; } - m_applicationParameters += "\t-qmljsdebugger=" + qmljsdebugger; - } - if (extras.containsKey("extraenvvars")) { - try { - m_environmentVariables += "\t" + new String(Base64.decode(extras.getString("extraenvvars"), Base64.DEFAULT), "UTF-8"); - } catch (Exception e) { - e.printStackTrace(); + if (extras.containsKey("extraenvvars")) { + try { + m_environmentVariables += "\t" + new String(Base64.decode(extras.getString("extraenvvars"), Base64.DEFAULT), "UTF-8"); + } catch (Exception e) { + e.printStackTrace(); + } } - } - if (extras.containsKey("extraappparams")) { - try { - m_applicationParameters += "\t" + new String(Base64.decode(extras.getString("extraappparams"), Base64.DEFAULT), "UTF-8"); - } catch (Exception e) { - e.printStackTrace(); + if (extras.containsKey("extraappparams")) { + try { + m_applicationParameters += "\t" + new String(Base64.decode(extras.getString("extraappparams"), Base64.DEFAULT), "UTF-8"); + } catch (Exception e) { + e.printStackTrace(); + } } - } + } // extras != null if (null == m_surfaces) onCreate(null); 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 51688441e01..0e0072d2343 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java @@ -191,6 +191,16 @@ public class QtNative } } + private static void runQtOnUiThread(final long id) + { + runAction(new Runnable() { + @Override + public void run() { + QtNative.onAndroidUiThread(id); + } + }); + } + public static boolean startApplication(String params, String environment, String mainLibrary, @@ -618,4 +628,6 @@ public class QtNative // activity methods public static native void onActivityResult(int requestCode, int resultCode, Intent data); + + public static native void onAndroidUiThread(long id); } diff --git a/src/android/templates/templates.pro b/src/android/templates/templates.pro index 684a556c5be..55387f3af7c 100644 --- a/src/android/templates/templates.pro +++ b/src/android/templates/templates.pro @@ -2,6 +2,7 @@ CONFIG -= qt android_install templates.files = \ $$PWD/AndroidManifest.xml \ + $$PWD/build.gradle \ $$PWD/res templates.path = $$[QT_INSTALL_PREFIX]/src/android/templates @@ -17,5 +18,6 @@ INSTALLS += templates QMAKE_POST_LINK += \ $${QMAKE_COPY} $$shell_path($$PWD/AndroidManifest.xml) $$OUT_PATH $$RETURN \ + $${QMAKE_COPY} $$shell_path($$PWD/build.gradle) $$OUT_PATH $$RETURN \ $${QMAKE_COPY_DIR} $$shell_path($$PWD/res) $$OUT_PATH } diff --git a/src/angle/patches/0000-General-fixes-for-ANGLE-2.1.patch b/src/angle/patches/0000-General-fixes-for-ANGLE-2.1.patch index d5e3697c4f7..ad3187ec7c0 100644 --- a/src/angle/patches/0000-General-fixes-for-ANGLE-2.1.patch +++ b/src/angle/patches/0000-General-fixes-for-ANGLE-2.1.patch @@ -1,178 +1,49 @@ -From f409f6837ce80d722eb6d2ff178b61b713d3e8c7 Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Thu, 25 Sep 2014 13:23:19 +0300 +From bd27c33a4a7c48bd14b9b6c18c8cdce1c3aae155 Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Fri, 14 Nov 2014 10:53:40 +0200 Subject: [PATCH] General fixes for ANGLE 2.1 - Fix commit.h include (use hard-coded version) -- Fix undefined intptr_t in egl.h and eglext.h - Fix export mismatch in libEGL.cpp and libGLESv2.cpp -- Remove D3D9 d3dcompiler.h include requirement in the translator - Normalize all precompiled shader names and includes - Remove third-party event tracing; it was hardly used in ANGLE and not enabled in Qt builds anyway. Change-Id: I22254aed62e89a26756ca0784bae95909189c0f9 --- - src/3rdparty/angle/include/EGL/egl.h | 2 +- - src/3rdparty/angle/include/EGL/eglext.h | 2 +- - src/3rdparty/angle/src/common/event_tracer.cpp | 49 -- - src/3rdparty/angle/src/common/event_tracer.h | 43 -- - src/3rdparty/angle/src/common/version.h | 2 +- - src/3rdparty/angle/src/libEGL/libEGL.cpp | 3 + - src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp | 5 + - src/3rdparty/angle/src/libGLESv2/libGLESv2.def | 3 - - .../angle/src/libGLESv2/libGLESv2_mingw32.def | 3 - - src/3rdparty/angle/src/libGLESv2/libGLESv2d.def | 3 - - .../angle/src/libGLESv2/libGLESv2d_mingw32.def | 3 - - .../angle/src/libGLESv2/renderer/Renderer.cpp | 1 - - .../angle/src/libGLESv2/renderer/SwapChain.h | 4 - - .../src/libGLESv2/renderer/d3d/HLSLCompiler.cpp | 6 +- - .../src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp | 66 +- - .../src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp | 12 +- - .../renderer/d3d/d3d11/PixelTransfer11.cpp | 10 +- - .../libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp | 4 +- - .../renderer/d3d/d3d11/shaders/Clear11.hlsl | 4 + - .../src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp | 20 +- - .../src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp | 12 - - .../libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps | 6 +- - .../libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs | 4 +- - .../src/third_party/trace_event/trace_event.h | 826 --------------------- - src/angle/src/common/common.pri | 2 - - 25 files changed, 80 insertions(+), 1015 deletions(-) - delete mode 100644 src/3rdparty/angle/src/common/event_tracer.cpp - delete mode 100644 src/3rdparty/angle/src/common/event_tracer.h - delete mode 100644 src/3rdparty/angle/src/third_party/trace_event/trace_event.h + src/3rdparty/angle/src/commit.h | 6 +- + src/3rdparty/angle/src/common/version.h | 2 +- + .../src/common/winrt/CoreWindowNativeWindow.cpp | 2 +- + src/3rdparty/angle/src/libEGL/libEGL.cpp | 3 + + src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp | 4 ++ + src/3rdparty/angle/src/libGLESv2/libGLESv2.def | 3 - + .../src/libGLESv2/renderer/d3d/HLSLCompiler.cpp | 3 - + .../src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp | 66 +++++++++++----------- + .../src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp | 12 ++-- + .../renderer/d3d/d3d11/PixelTransfer11.cpp | 10 ++-- + .../libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp | 4 +- + .../renderer/d3d/d3d11/shaders/Clear11.hlsl | 4 ++ + .../src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp | 20 +++---- + .../src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp | 12 ---- + .../libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps | 6 +- + .../libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs | 4 +- + 16 files changed, 76 insertions(+), 85 deletions(-) -diff --git a/src/3rdparty/angle/include/EGL/egl.h b/src/3rdparty/angle/include/EGL/egl.h -index 12590a0..ab2f0cd 100644 ---- a/src/3rdparty/angle/include/EGL/egl.h -+++ b/src/3rdparty/angle/include/EGL/egl.h -@@ -238,7 +238,7 @@ EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void); - #ifndef EGL_VERSION_1_5 - #define EGL_VERSION_1_5 1 - typedef void *EGLSync; --typedef intptr_t EGLAttrib; -+typedef khronos_intptr_t EGLAttrib; - typedef khronos_utime_nanoseconds_t EGLTime; - #define EGL_CONTEXT_MAJOR_VERSION 0x3098 - #define EGL_CONTEXT_MINOR_VERSION 0x30FB -diff --git a/src/3rdparty/angle/include/EGL/eglext.h b/src/3rdparty/angle/include/EGL/eglext.h -index 9e29605..989359b 100644 ---- a/src/3rdparty/angle/include/EGL/eglext.h -+++ b/src/3rdparty/angle/include/EGL/eglext.h -@@ -59,7 +59,7 @@ extern "C" { - #ifndef EGL_KHR_cl_event2 - #define EGL_KHR_cl_event2 1 - typedef void *EGLSyncKHR; --typedef intptr_t EGLAttribKHR; -+typedef khronos_intptr_t EGLAttribKHR; - typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNC64KHRPROC) (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list); - #ifdef EGL_EGLEXT_PROTOTYPES - EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list); -diff --git a/src/3rdparty/angle/src/common/event_tracer.cpp b/src/3rdparty/angle/src/common/event_tracer.cpp -deleted file mode 100644 -index 353c69d..0000000 ---- a/src/3rdparty/angle/src/common/event_tracer.cpp -+++ /dev/null -@@ -1,49 +0,0 @@ --// 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 --// found in the LICENSE file. +diff --git a/src/3rdparty/angle/src/commit.h b/src/3rdparty/angle/src/commit.h +index 4c89a65..08fc893 100644 +--- a/src/3rdparty/angle/src/commit.h ++++ b/src/3rdparty/angle/src/commit.h +@@ -7,8 +7,6 @@ + // This is a default commit hash header, when git is not available. + // + +-#define ANGLE_COMMIT_HASH "unknown hash" ++#define ANGLE_COMMIT_HASH "30d6c255d238" + #define ANGLE_COMMIT_HASH_SIZE 12 +-#define ANGLE_COMMIT_DATE "unknown date" - --#include "common/event_tracer.h" -- --namespace gl --{ -- --GetCategoryEnabledFlagFunc g_getCategoryEnabledFlag; --AddTraceEventFunc g_addTraceEvent; -- --} // namespace gl -- --extern "C" { -- --void TRACE_ENTRY SetTraceFunctionPointers(GetCategoryEnabledFlagFunc getCategoryEnabledFlag, -- AddTraceEventFunc addTraceEvent) --{ -- gl::g_getCategoryEnabledFlag = getCategoryEnabledFlag; -- gl::g_addTraceEvent = addTraceEvent; --} -- --} // extern "C" -- --namespace gl --{ -- --const unsigned char* TraceGetTraceCategoryEnabledFlag(const char* name) --{ -- if (g_getCategoryEnabledFlag) -- { -- return g_getCategoryEnabledFlag(name); -- } -- static unsigned char disabled = 0; -- return &disabled; --} -- --void TraceAddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id, -- int numArgs, const char** argNames, const unsigned char* argTypes, -- const unsigned long long* argValues, unsigned char flags) --{ -- if (g_addTraceEvent) -- { -- g_addTraceEvent(phase, categoryGroupEnabled, name, id, numArgs, argNames, argTypes, argValues, flags); -- } --} -- --} // namespace gl -diff --git a/src/3rdparty/angle/src/common/event_tracer.h b/src/3rdparty/angle/src/common/event_tracer.h -deleted file mode 100644 -index fa97435..0000000 ---- a/src/3rdparty/angle/src/common/event_tracer.h -+++ /dev/null -@@ -1,43 +0,0 @@ --// 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 --// found in the LICENSE file. -- --#ifndef COMMON_EVENT_TRACER_H_ --#define COMMON_EVENT_TRACER_H_ -- --#include "common/platform.h" -- --#if !defined(TRACE_ENTRY) --# ifdef ANGLE_PLATFORM_WINDOWS --# define TRACE_ENTRY __stdcall --# else --# define TRACE_ENTRY --# endif // ANGLE_PLATFORM_WINDOWS --#endif //TRACE_ENTRY -- --extern "C" { -- --typedef const unsigned char* (*GetCategoryEnabledFlagFunc)(const char* name); --typedef void (*AddTraceEventFunc)(char phase, const unsigned char* categoryGroupEnabled, const char* name, -- unsigned long long id, int numArgs, const char** argNames, -- const unsigned char* argTypes, const unsigned long long* argValues, -- unsigned char flags); -- --// extern "C" so that it has a reasonable name for GetProcAddress. --void TRACE_ENTRY SetTraceFunctionPointers(GetCategoryEnabledFlagFunc get_category_enabled_flag, -- AddTraceEventFunc add_trace_event_func); -- --} -- --namespace gl --{ -- --const unsigned char* TraceGetTraceCategoryEnabledFlag(const char* name); -- --void TraceAddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id, -- int numArgs, const char** argNames, const unsigned char* argTypes, -- const unsigned long long* argValues, unsigned char flags); -- --} -- --#endif // COMMON_EVENT_TRACER_H_ +-#define ANGLE_DISABLE_PROGRAM_BINARY_LOAD ++#define ANGLE_COMMIT_DATE "2014-11-13 17:37:03 +0000" diff --git a/src/3rdparty/angle/src/common/version.h b/src/3rdparty/angle/src/common/version.h index d9148d1..f01e024 100644 --- a/src/3rdparty/angle/src/common/version.h @@ -183,8 +54,19 @@ index d9148d1..f01e024 100644 #define ANGLE_MAJOR_VERSION 2 #define ANGLE_MINOR_VERSION 1 +diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp +index 0de16f4..0e63fa5 100644 +--- a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp ++++ b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp +@@ -184,4 +184,4 @@ long ConvertDipsToPixels(float dips) + static const float dipsPerInch = 96.0f; + return lround((dips * GetLogicalDpi() / dipsPerInch)); + } +-} +\ No newline at end of file ++} diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp -index f9a4780..7ce2b93 100644 +index 851b723..6110698 100644 --- a/src/3rdparty/angle/src/libEGL/libEGL.cpp +++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp @@ -6,6 +6,9 @@ @@ -198,7 +80,7 @@ index f9a4780..7ce2b93 100644 #include "common/debug.h" diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp -index 198c0ee..07f5d47 100644 +index 2306168..587950a 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp @@ -6,6 +6,10 @@ @@ -212,14 +94,6 @@ index 198c0ee..07f5d47 100644 #include "common/version.h" #include "common/utilities.h" -@@ -30,6 +34,7 @@ - #include "libGLESv2/validationES3.h" - #include "libGLESv2/queryconversions.h" - -+ - extern "C" - { - diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def index 88dceb3..33557eb 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def @@ -231,93 +105,29 @@ index 88dceb3..33557eb 100644 - - ; Setting up TRACE macro callbacks - SetTraceFunctionPointers @284 -diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def -index d6272c4d..18ffcf6 100644 ---- a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def -+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def -@@ -294,6 +294,3 @@ EXPORTS - glBindTexImage@4 @158 NONAME - glCreateRenderer @177 NONAME - glDestroyRenderer @178 NONAME -- -- ; Setting up TRACE macro callbacks -- SetTraceFunctionPointers@8 @284 -diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def -index d301aa0..120371e 100644 ---- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def -+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def -@@ -294,6 +294,3 @@ EXPORTS - glBindTexImage @158 NONAME - glCreateRenderer @177 NONAME - glDestroyRenderer @178 NONAME -- -- ; Setting up TRACE macro callbacks -- SetTraceFunctionPointers @284 -diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def -index a82d629..8c1306a 100644 ---- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def -+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def -@@ -294,6 +294,3 @@ EXPORTS - glBindTexImage@4 @158 NONAME - glCreateRenderer @177 NONAME - glDestroyRenderer @178 NONAME -- -- ; Setting up TRACE macro callbacks -- SetTraceFunctionPointers@8 @284 -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp -index df43012..910d028 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp -@@ -10,7 +10,6 @@ - #include "libGLESv2/Program.h" - #include "libGLESv2/renderer/Renderer.h" - #include "common/utilities.h" --#include "third_party/trace_event/trace_event.h" - #include "libGLESv2/Shader.h" - - #if defined (ANGLE_ENABLE_D3D9) -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h -index c53b2af..12be9b3 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h -@@ -16,10 +16,6 @@ - #include - #include - --#if !defined(ANGLE_FORCE_VSYNC_OFF) --#define ANGLE_FORCE_VSYNC_OFF 0 --#endif -- - namespace rx - { - diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp -index df2e46c..acbd852 100644 +index 5c44fe0..bfeaf51 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp -@@ -10,8 +10,6 @@ - +@@ -11,8 +11,6 @@ + #include "common/features.h" #include "common/utilities.h" -#include "third_party/trace_event/trace_event.h" - - namespace rx + // Definitions local to the translation unit + namespace { - -@@ -28,7 +26,11 @@ HLSLCompiler::~HLSLCompiler() +@@ -120,7 +118,6 @@ HLSLCompiler::~HLSLCompiler() bool HLSLCompiler::initialize() { -+<<<<<<< HEAD - TRACE_EVENT0("gpu", "initializeCompiler"); -+======= -+#if !defined(ANGLE_PLATFORM_WINRT) -+>>>>>>> 429814a... ANGLE: remove event tracing +- TRACE_EVENT0("gpu", "initializeCompiler"); + #if !defined(ANGLE_ENABLE_WINDOWS_STORE) #if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES) // Find a D3DCompiler module that had already been loaded based on a predefined list of versions. - static const char *d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp -index 3bdb9e7..72820a4 100644 +index 8ed1650..91e7552 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp @@ -13,39 +13,39 @@ @@ -394,7 +204,7 @@ index 3bdb9e7..72820a4 100644 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h" #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h" diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp -index c60b7a6..5caa427 100644 +index 12905d0..4630762 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp @@ -15,14 +15,14 @@ @@ -419,7 +229,7 @@ index c60b7a6..5caa427 100644 namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp -index f54bacc..edaafec 100644 +index 1bc2bd8..a4072d8 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp @@ -22,11 +22,11 @@ @@ -440,7 +250,7 @@ index f54bacc..edaafec 100644 namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp -index 5ec132e..50dae4e 100644 +index 3fcacf6..834b7bd 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp @@ -12,8 +12,8 @@ @@ -452,8 +262,8 @@ index 5ec132e..50dae4e 100644 +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2dvs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dps.h" - namespace rx - { + #include "common/features.h" + #include "common/NativeWindow.h" diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl index 6deef2b..b4cf380 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl @@ -485,7 +295,7 @@ index 6deef2b..b4cf380 100644 } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp -index 80503d5..f061a32 100644 +index d4fcd17..2ca7a9c 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp @@ -27,20 +27,20 @@ namespace @@ -520,11 +330,11 @@ index 80503d5..f061a32 100644 } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp -index 73c1abc..e8564bd 100644 +index 3bac4ba..82963ec 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp -@@ -39,8 +39,6 @@ - +@@ -42,8 +42,6 @@ + #include "common/features.h" #include "common/utilities.h" -#include "third_party/trace_event/trace_event.h" @@ -532,7 +342,7 @@ index 73c1abc..e8564bd 100644 #include // Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros -@@ -190,7 +188,6 @@ EGLint Renderer9::initialize() +@@ -185,7 +183,6 @@ EGLint Renderer9::initialize() return EGL_NOT_INITIALIZED; } @@ -540,9 +350,9 @@ index 73c1abc..e8564bd 100644 mD3d9Module = GetModuleHandle(TEXT("d3d9.dll")); if (mD3d9Module == NULL) -@@ -207,14 +204,12 @@ EGLint Renderer9::initialize() +@@ -202,14 +199,12 @@ EGLint Renderer9::initialize() // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available. - if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) + if (ANGLE_D3D9EX == ANGLE_ENABLED && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) { - TRACE_EVENT0("gpu", "D3d9Ex_QueryInterface"); ASSERT(mD3d9Ex); @@ -555,7 +365,7 @@ index 73c1abc..e8564bd 100644 mD3d9 = Direct3DCreate9(D3D_SDK_VERSION); } -@@ -233,7 +228,6 @@ EGLint Renderer9::initialize() +@@ -228,7 +223,6 @@ EGLint Renderer9::initialize() // Give up on getting device caps after about one second. { @@ -563,7 +373,7 @@ index 73c1abc..e8564bd 100644 for (int i = 0; i < 10; ++i) { result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps); -@@ -268,7 +262,6 @@ EGLint Renderer9::initialize() +@@ -263,7 +257,6 @@ EGLint Renderer9::initialize() } { @@ -571,7 +381,7 @@ index 73c1abc..e8564bd 100644 mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier); } -@@ -305,7 +298,6 @@ EGLint Renderer9::initialize() +@@ -300,7 +293,6 @@ EGLint Renderer9::initialize() static const TCHAR className[] = TEXT("STATIC"); { @@ -579,7 +389,7 @@ index 73c1abc..e8564bd 100644 mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL); } -@@ -313,7 +305,6 @@ EGLint Renderer9::initialize() +@@ -308,7 +300,6 @@ EGLint Renderer9::initialize() DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES; { @@ -587,7 +397,7 @@ index 73c1abc..e8564bd 100644 result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice); } if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST) -@@ -323,7 +314,6 @@ EGLint Renderer9::initialize() +@@ -318,7 +309,6 @@ EGLint Renderer9::initialize() if (FAILED(result)) { @@ -595,7 +405,7 @@ index 73c1abc..e8564bd 100644 result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice); if (FAILED(result)) -@@ -335,13 +325,11 @@ EGLint Renderer9::initialize() +@@ -330,13 +320,11 @@ EGLint Renderer9::initialize() if (mD3d9Ex) { @@ -662,858 +472,6 @@ index 3a36980..3bd611b 100644 { VS_OUTPUT Out; -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 -deleted file mode 100644 -index 1880056..0000000 ---- a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h -+++ /dev/null -@@ -1,826 +0,0 @@ --// Copyright (c) 2013 The Chromium Authors. All rights reserved. --// Use of this source code is governed by a BSD-style license that can be --// found in the LICENSE file. -- --// Trace events are for tracking application performance and resource usage. --// Macros are provided to track: --// Begin and end of function calls --// Counters --// --// Events are issued against categories. Whereas LOG's --// categories are statically defined, TRACE categories are created --// implicitly with a string. For example: --// TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent") --// --// Events can be INSTANT, or can be pairs of BEGIN and END in the same scope: --// TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly") --// doSomethingCostly() --// TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly") --// Note: our tools can't always determine the correct BEGIN/END pairs unless --// these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you need them --// to be in separate scopes. --// --// A common use case is to trace entire function scopes. This --// issues a trace BEGIN and END automatically: --// void doSomethingCostly() { --// TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly"); --// ... --// } --// --// Additional parameters can be associated with an event: --// void doSomethingCostly2(int howMuch) { --// TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly", --// "howMuch", howMuch); --// ... --// } --// --// The trace system will automatically add to this information the --// current process id, thread id, and a timestamp in microseconds. --// --// To trace an asynchronous procedure such as an IPC send/receive, use ASYNC_BEGIN and --// ASYNC_END: --// [single threaded sender code] --// static int send_count = 0; --// ++send_count; --// TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count); --// Send(new MyMessage(send_count)); --// [receive code] --// void OnMyMessage(send_count) { --// TRACE_EVENT_ASYNC_END0("ipc", "message", send_count); --// } --// The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs. --// ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process. Pointers can --// be used for the ID parameter, and they will be mangled internally so that --// the same pointer on two different processes will not match. For example: --// class MyTracedClass { --// public: --// MyTracedClass() { --// TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this); --// } --// ~MyTracedClass() { --// TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this); --// } --// } --// --// Trace event also supports counters, which is a way to track a quantity --// as it varies over time. Counters are created with the following macro: --// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue); --// --// Counters are process-specific. The macro itself can be issued from any --// thread, however. --// --// Sometimes, you want to track two counters at once. You can do this with two --// counter macros: --// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]); --// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]); --// Or you can do it with a combined macro: --// TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter", --// "bytesPinned", g_myCounterValue[0], --// "bytesAllocated", g_myCounterValue[1]); --// This indicates to the tracing UI that these counters should be displayed --// in a single graph, as a summed area chart. --// --// Since counters are in a global namespace, you may want to disembiguate with a --// unique ID, by using the TRACE_COUNTER_ID* variations. --// --// By default, trace collection is compiled in, but turned off at runtime. --// Collecting trace data is the responsibility of the embedding --// application. In Chrome's case, navigating to about:tracing will turn on --// tracing and display data collected across all active processes. --// --// --// Memory scoping note: --// Tracing copies the pointers, not the string content, of the strings passed --// in for category, name, and arg_names. Thus, the following code will --// cause problems: --// char* str = strdup("impprtantName"); --// TRACE_EVENT_INSTANT0("SUBSYSTEM", str); // BAD! --// free(str); // Trace system now has dangling pointer --// --// To avoid this issue with the |name| and |arg_name| parameters, use the --// TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime overhead. --// Notes: The category must always be in a long-lived char* (i.e. static const). --// The |arg_values|, when used, are always deep copied with the _COPY --// macros. --// --// When are string argument values copied: --// const char* arg_values are only referenced by default: --// TRACE_EVENT1("category", "name", --// "arg1", "literal string is only referenced"); --// Use TRACE_STR_COPY to force copying of a const char*: --// TRACE_EVENT1("category", "name", --// "arg1", TRACE_STR_COPY("string will be copied")); --// std::string arg_values are always copied: --// TRACE_EVENT1("category", "name", --// "arg1", std::string("string will be copied")); --// --// --// Thread Safety: --// A thread safe singleton and mutex are used for thread safety. Category --// enabled flags are used to limit the performance impact when the system --// is not enabled. --// --// TRACE_EVENT macros first cache a pointer to a category. The categories are --// statically allocated and safe at all times, even after exit. Fetching a --// category is protected by the TraceLog::lock_. Multiple threads initializing --// the static variable is safe, as they will be serialized by the lock and --// multiple calls will return the same pointer to the category. --// --// Then the category_enabled flag is checked. This is a unsigned char, and --// not intended to be multithread safe. It optimizes access to addTraceEvent --// which is threadsafe internally via TraceLog::lock_. The enabled flag may --// cause some threads to incorrectly call or skip calling addTraceEvent near --// the time of the system being enabled or disabled. This is acceptable as --// we tolerate some data loss while the system is being enabled/disabled and --// because addTraceEvent is threadsafe internally and checks the enabled state --// again under lock. --// --// Without the use of these static category pointers and enabled flags all --// trace points would carry a significant performance cost of aquiring a lock --// and resolving the category. -- --#ifndef COMMON_TRACE_EVENT_H_ --#define COMMON_TRACE_EVENT_H_ -- --#include -- --#include "common/event_tracer.h" -- --// By default, const char* argument values are assumed to have long-lived scope --// and will not be copied. Use this macro to force a const char* to be copied. --#define TRACE_STR_COPY(str) \ -- WebCore::TraceEvent::TraceStringWithCopy(str) -- --// Records a pair of begin and end events called "name" for the current --// scope, with 0, 1 or 2 associated arguments. If the category is not --// enabled, then this does nothing. --// - category and name strings must have application lifetime (statics or --// literals). They may not include " chars. --#define TRACE_EVENT0(category, name) \ -- INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name) --#define TRACE_EVENT1(category, name, arg1_name, arg1_val) \ -- INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, arg1_name, arg1_val) --#define TRACE_EVENT2(category, name, arg1_name, arg1_val, arg2_name, arg2_val) \ -- INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, arg1_name, arg1_val, \ -- arg2_name, arg2_val) -- --// Records a single event called "name" immediately, with 0, 1 or 2 --// associated arguments. If the category is not enabled, then this --// does nothing. --// - category and name strings must have application lifetime (statics or --// literals). They may not include " chars. --#define TRACE_EVENT_INSTANT0(category, name) \ -- INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ -- category, name, TRACE_EVENT_FLAG_NONE) --#define TRACE_EVENT_INSTANT1(category, name, arg1_name, arg1_val) \ -- INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ -- category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) --#define TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, \ -- arg2_name, arg2_val) \ -- INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ -- category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ -- arg2_name, arg2_val) --#define TRACE_EVENT_COPY_INSTANT0(category, name) \ -- INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ -- category, name, TRACE_EVENT_FLAG_COPY) --#define TRACE_EVENT_COPY_INSTANT1(category, name, arg1_name, arg1_val) \ -- INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ -- category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) --#define TRACE_EVENT_COPY_INSTANT2(category, name, arg1_name, arg1_val, \ -- arg2_name, arg2_val) \ -- INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ -- category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \ -- arg2_name, arg2_val) -- --// Records a single BEGIN event called "name" immediately, with 0, 1 or 2 --// associated arguments. If the category is not enabled, then this --// does nothing. --// - category and name strings must have application lifetime (statics or --// literals). They may not include " chars. --#define TRACE_EVENT_BEGIN0(category, name) \ -- INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ -- category, name, TRACE_EVENT_FLAG_NONE) --#define TRACE_EVENT_BEGIN1(category, name, arg1_name, arg1_val) \ -- INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ -- category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) --#define TRACE_EVENT_BEGIN2(category, name, arg1_name, arg1_val, \ -- arg2_name, arg2_val) \ -- INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ -- category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ -- arg2_name, arg2_val) --#define TRACE_EVENT_COPY_BEGIN0(category, name) \ -- INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ -- category, name, TRACE_EVENT_FLAG_COPY) --#define TRACE_EVENT_COPY_BEGIN1(category, name, arg1_name, arg1_val) \ -- INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ -- category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) --#define TRACE_EVENT_COPY_BEGIN2(category, name, arg1_name, arg1_val, \ -- arg2_name, arg2_val) \ -- INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ -- category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \ -- arg2_name, arg2_val) -- --// Records a single END event for "name" immediately. If the category --// is not enabled, then this does nothing. --// - category and name strings must have application lifetime (statics or --// literals). They may not include " chars. --#define TRACE_EVENT_END0(category, name) \ -- INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ -- category, name, TRACE_EVENT_FLAG_NONE) --#define TRACE_EVENT_END1(category, name, arg1_name, arg1_val) \ -- INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ -- category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) --#define TRACE_EVENT_END2(category, name, arg1_name, arg1_val, \ -- arg2_name, arg2_val) \ -- INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ -- category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ -- arg2_name, arg2_val) --#define TRACE_EVENT_COPY_END0(category, name) \ -- INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ -- category, name, TRACE_EVENT_FLAG_COPY) --#define TRACE_EVENT_COPY_END1(category, name, arg1_name, arg1_val) \ -- INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ -- category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) --#define TRACE_EVENT_COPY_END2(category, name, arg1_name, arg1_val, \ -- arg2_name, arg2_val) \ -- INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ -- category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \ -- arg2_name, arg2_val) -- --// Records the value of a counter called "name" immediately. Value --// must be representable as a 32 bit integer. --// - category and name strings must have application lifetime (statics or --// literals). They may not include " chars. --#define TRACE_COUNTER1(category, name, value) \ -- INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ -- category, name, TRACE_EVENT_FLAG_NONE, \ -- "value", static_cast(value)) --#define TRACE_COPY_COUNTER1(category, name, value) \ -- INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ -- category, name, TRACE_EVENT_FLAG_COPY, \ -- "value", static_cast(value)) -- --// Records the values of a multi-parted counter called "name" immediately. --// The UI will treat value1 and value2 as parts of a whole, displaying their --// values as a stacked-bar chart. --// - category and name strings must have application lifetime (statics or --// literals). They may not include " chars. --#define TRACE_COUNTER2(category, name, value1_name, value1_val, \ -- value2_name, value2_val) \ -- INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ -- category, name, TRACE_EVENT_FLAG_NONE, \ -- value1_name, static_cast(value1_val), \ -- value2_name, static_cast(value2_val)) --#define TRACE_COPY_COUNTER2(category, name, value1_name, value1_val, \ -- value2_name, value2_val) \ -- INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ -- category, name, TRACE_EVENT_FLAG_COPY, \ -- value1_name, static_cast(value1_val), \ -- value2_name, static_cast(value2_val)) -- --// Records the value of a counter called "name" immediately. Value --// must be representable as a 32 bit integer. --// - category and name strings must have application lifetime (statics or --// literals). They may not include " chars. --// - |id| is used to disambiguate counters with the same name. It must either --// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits --// will be xored with a hash of the process ID so that the same pointer on --// two different processes will not collide. --#define TRACE_COUNTER_ID1(category, name, id, value) \ -- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ -- category, name, id, TRACE_EVENT_FLAG_NONE, \ -- "value", static_cast(value)) --#define TRACE_COPY_COUNTER_ID1(category, name, id, value) \ -- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ -- category, name, id, TRACE_EVENT_FLAG_COPY, \ -- "value", static_cast(value)) -- --// Records the values of a multi-parted counter called "name" immediately. --// The UI will treat value1 and value2 as parts of a whole, displaying their --// values as a stacked-bar chart. --// - category and name strings must have application lifetime (statics or --// literals). They may not include " chars. --// - |id| is used to disambiguate counters with the same name. It must either --// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits --// will be xored with a hash of the process ID so that the same pointer on --// two different processes will not collide. --#define TRACE_COUNTER_ID2(category, name, id, value1_name, value1_val, \ -- value2_name, value2_val) \ -- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ -- category, name, id, TRACE_EVENT_FLAG_NONE, \ -- value1_name, static_cast(value1_val), \ -- value2_name, static_cast(value2_val)) --#define TRACE_COPY_COUNTER_ID2(category, name, id, value1_name, value1_val, \ -- value2_name, value2_val) \ -- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ -- category, name, id, TRACE_EVENT_FLAG_COPY, \ -- value1_name, static_cast(value1_val), \ -- value2_name, static_cast(value2_val)) -- --// Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2 --// associated arguments. If the category is not enabled, then this --// does nothing. --// - category and name strings must have application lifetime (statics or --// literals). They may not include " chars. --// - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event. ASYNC --// events are considered to match if their category, name and id values all --// match. |id| must either be a pointer or an integer value up to 64 bits. If --// it's a pointer, the bits will be xored with a hash of the process ID so --// that the same pointer on two different processes will not collide. --// An asynchronous operation can consist of multiple phases. The first phase is --// defined by the ASYNC_BEGIN calls. Additional phases can be defined using the --// ASYNC_STEP_BEGIN macros. When the operation completes, call ASYNC_END. --// An async operation can span threads and processes, but all events in that --// operation must use the same |name| and |id|. Each event can have its own --// args. --#define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \ -- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ -- category, name, id, TRACE_EVENT_FLAG_NONE) --#define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \ -- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ -- category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) --#define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \ -- arg2_name, arg2_val) \ -- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ -- category, name, id, TRACE_EVENT_FLAG_NONE, \ -- arg1_name, arg1_val, arg2_name, arg2_val) --#define TRACE_EVENT_COPY_ASYNC_BEGIN0(category, name, id) \ -- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ -- category, name, id, TRACE_EVENT_FLAG_COPY) --#define TRACE_EVENT_COPY_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \ -- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ -- category, name, id, TRACE_EVENT_FLAG_COPY, \ -- arg1_name, arg1_val) --#define TRACE_EVENT_COPY_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \ -- arg2_name, arg2_val) \ -- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ -- category, name, id, TRACE_EVENT_FLAG_COPY, \ -- arg1_name, arg1_val, arg2_name, arg2_val) -- --// Records a single ASYNC_STEP event for |step| immediately. If the category --// is not enabled, then this does nothing. The |name| and |id| must match the --// ASYNC_BEGIN event above. The |step| param identifies this step within the --// async event. This should be called at the beginning of the next phase of an --// asynchronous operation. --#define TRACE_EVENT_ASYNC_STEP0(category, name, id, step) \ -- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \ -- category, name, id, TRACE_EVENT_FLAG_NONE, "step", step) --#define TRACE_EVENT_ASYNC_STEP1(category, name, id, step, \ -- arg1_name, arg1_val) \ -- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \ -- category, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \ -- arg1_name, arg1_val) --#define TRACE_EVENT_COPY_ASYNC_STEP0(category, name, id, step) \ -- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \ -- category, name, id, TRACE_EVENT_FLAG_COPY, "step", step) --#define TRACE_EVENT_COPY_ASYNC_STEP1(category, name, id, step, \ -- arg1_name, arg1_val) \ -- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \ -- category, name, id, TRACE_EVENT_FLAG_COPY, "step", step, \ -- arg1_name, arg1_val) -- --// Records a single ASYNC_END event for "name" immediately. If the category --// is not enabled, then this does nothing. --#define TRACE_EVENT_ASYNC_END0(category, name, id) \ -- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ -- category, name, id, TRACE_EVENT_FLAG_NONE) --#define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \ -- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ -- category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) --#define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, \ -- arg2_name, arg2_val) \ -- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ -- category, name, id, TRACE_EVENT_FLAG_NONE, \ -- arg1_name, arg1_val, arg2_name, arg2_val) --#define TRACE_EVENT_COPY_ASYNC_END0(category, name, id) \ -- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ -- category, name, id, TRACE_EVENT_FLAG_COPY) --#define TRACE_EVENT_COPY_ASYNC_END1(category, name, id, arg1_name, arg1_val) \ -- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ -- category, name, id, TRACE_EVENT_FLAG_COPY, \ -- arg1_name, arg1_val) --#define TRACE_EVENT_COPY_ASYNC_END2(category, name, id, arg1_name, arg1_val, \ -- arg2_name, arg2_val) \ -- INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ -- category, name, id, TRACE_EVENT_FLAG_COPY, \ -- arg1_name, arg1_val, arg2_name, arg2_val) -- --// Creates a scope of a sampling state with the given category and name (both must --// be constant strings). These states are intended for a sampling profiler. --// Implementation note: we store category and name together because we don't --// want the inconsistency/expense of storing two pointers. --// |thread_bucket| is [0..2] and is used to statically isolate samples in one --// thread from others. --// --// { // The sampling state is set within this scope. --// TRACE_EVENT_SAMPLING_STATE_SCOPE_FOR_BUCKET(0, "category", "name"); --// ...; --// } --#define TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \ -- TraceEvent::SamplingStateScope traceEventSamplingScope(category "\0" name); -- --// Returns a current sampling state of the given bucket. --// The format of the returned string is "category\0name". --#define TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(bucket_number) \ -- TraceEvent::SamplingStateScope::current() -- --// Sets a current sampling state of the given bucket. --// |category| and |name| have to be constant strings. --#define TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \ -- TraceEvent::SamplingStateScope::set(category "\0" name) -- --// Sets a current sampling state of the given bucket. --// |categoryAndName| doesn't need to be a constant string. --// The format of the string is "category\0name". --#define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(bucket_number, categoryAndName) \ -- TraceEvent::SamplingStateScope::set(categoryAndName) -- --// Syntactic sugars for the sampling tracing in the main thread. --#define TRACE_EVENT_SCOPED_SAMPLING_STATE(category, name) \ -- TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(0, category, name) --#define TRACE_EVENT_GET_SAMPLING_STATE() \ -- TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(0) --#define TRACE_EVENT_SET_SAMPLING_STATE(category, name) \ -- TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(0, category, name) --#define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(categoryAndName) \ -- TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(0, categoryAndName) -- --//////////////////////////////////////////////////////////////////////////////// --// Implementation specific tracing API definitions. -- --// Get a pointer to the enabled state of the given trace category. Only --// long-lived literal strings should be given as the category name. The returned --// pointer can be held permanently in a local static for example. If the --// unsigned char is non-zero, tracing is enabled. If tracing is enabled, --// TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled --// between the load of the tracing state and the call to --// TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out --// for best performance when tracing is disabled. --// const unsigned char* --// TRACE_EVENT_API_GET_CATEGORY_ENABLED(const char* category_name) --#define TRACE_EVENT_API_GET_CATEGORY_ENABLED \ -- gl::TraceGetTraceCategoryEnabledFlag -- --// Add a trace event to the platform tracing system. --// void TRACE_EVENT_API_ADD_TRACE_EVENT( --// char phase, --// const unsigned char* category_enabled, --// const char* name, --// unsigned long long id, --// int num_args, --// const char** arg_names, --// const unsigned char* arg_types, --// const unsigned long long* arg_values, --// unsigned char flags) --#define TRACE_EVENT_API_ADD_TRACE_EVENT \ -- gl::TraceAddTraceEvent -- --//////////////////////////////////////////////////////////////////////////////// -- --// Implementation detail: trace event macros create temporary variables --// to keep instrumentation overhead low. These macros give each temporary --// variable a unique name based on the line number to prevent name collissions. --#define INTERNAL_TRACE_EVENT_UID3(a, b) \ -- trace_event_unique_##a##b --#define INTERNAL_TRACE_EVENT_UID2(a, b) \ -- INTERNAL_TRACE_EVENT_UID3(a, b) --#define INTERNALTRACEEVENTUID(name_prefix) \ -- INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__) -- --// Implementation detail: internal macro to create static category. --#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category) \ -- static const unsigned char* INTERNALTRACEEVENTUID(catstatic) = 0; \ -- if (!INTERNALTRACEEVENTUID(catstatic)) \ -- INTERNALTRACEEVENTUID(catstatic) = \ -- TRACE_EVENT_API_GET_CATEGORY_ENABLED(category); -- --// Implementation detail: internal macro to create static category and add --// event if the category is enabled. --#define INTERNAL_TRACE_EVENT_ADD(phase, category, name, flags, ...) \ -- do { \ -- INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \ -- if (*INTERNALTRACEEVENTUID(catstatic)) { \ -- gl::TraceEvent::addTraceEvent( \ -- phase, INTERNALTRACEEVENTUID(catstatic), name, \ -- gl::TraceEvent::noEventId, flags, ##__VA_ARGS__); \ -- } \ -- } while (0) -- --// Implementation detail: internal macro to create static category and add begin --// event if the category is enabled. Also adds the end event when the scope --// ends. --#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, ...) \ -- INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \ -- gl::TraceEvent::TraceEndOnScopeClose \ -- INTERNALTRACEEVENTUID(profileScope); \ -- if (*INTERNALTRACEEVENTUID(catstatic)) { \ -- gl::TraceEvent::addTraceEvent( \ -- TRACE_EVENT_PHASE_BEGIN, \ -- INTERNALTRACEEVENTUID(catstatic), \ -- name, gl::TraceEvent::noEventId, \ -- TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \ -- INTERNALTRACEEVENTUID(profileScope).initialize( \ -- INTERNALTRACEEVENTUID(catstatic), name); \ -- } -- --// Implementation detail: internal macro to create static category and add --// event if the category is enabled. --#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category, name, id, flags, \ -- ...) \ -- do { \ -- INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \ -- if (*INTERNALTRACEEVENTUID(catstatic)) { \ -- unsigned char traceEventFlags = flags | TRACE_EVENT_FLAG_HAS_ID; \ -- gl::TraceEvent::TraceID traceEventTraceID( \ -- id, &traceEventFlags); \ -- gl::TraceEvent::addTraceEvent( \ -- phase, INTERNALTRACEEVENTUID(catstatic), \ -- name, traceEventTraceID.data(), traceEventFlags, \ -- ##__VA_ARGS__); \ -- } \ -- } while (0) -- --// Notes regarding the following definitions: --// New values can be added and propagated to third party libraries, but existing --// definitions must never be changed, because third party libraries may use old --// definitions. -- --// Phase indicates the nature of an event entry. E.g. part of a begin/end pair. --#define TRACE_EVENT_PHASE_BEGIN ('B') --#define TRACE_EVENT_PHASE_END ('E') --#define TRACE_EVENT_PHASE_INSTANT ('I') --#define TRACE_EVENT_PHASE_ASYNC_BEGIN ('S') --#define TRACE_EVENT_PHASE_ASYNC_STEP ('T') --#define TRACE_EVENT_PHASE_ASYNC_END ('F') --#define TRACE_EVENT_PHASE_METADATA ('M') --#define TRACE_EVENT_PHASE_COUNTER ('C') --#define TRACE_EVENT_PHASE_SAMPLE ('P') -- --// Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT. --#define TRACE_EVENT_FLAG_NONE (static_cast(0)) --#define TRACE_EVENT_FLAG_COPY (static_cast(1 << 0)) --#define TRACE_EVENT_FLAG_HAS_ID (static_cast(1 << 1)) --#define TRACE_EVENT_FLAG_MANGLE_ID (static_cast(1 << 2)) -- --// Type values for identifying types in the TraceValue union. --#define TRACE_VALUE_TYPE_BOOL (static_cast(1)) --#define TRACE_VALUE_TYPE_UINT (static_cast(2)) --#define TRACE_VALUE_TYPE_INT (static_cast(3)) --#define TRACE_VALUE_TYPE_DOUBLE (static_cast(4)) --#define TRACE_VALUE_TYPE_POINTER (static_cast(5)) --#define TRACE_VALUE_TYPE_STRING (static_cast(6)) --#define TRACE_VALUE_TYPE_COPY_STRING (static_cast(7)) -- -- --namespace gl { -- --namespace TraceEvent { -- --// Specify these values when the corresponding argument of addTraceEvent is not --// used. --const int zeroNumArgs = 0; --const unsigned long long noEventId = 0; -- --// TraceID encapsulates an ID that can either be an integer or pointer. Pointers --// are mangled with the Process ID so that they are unlikely to collide when the --// same pointer is used on different processes. --class TraceID { --public: -- explicit TraceID(const void* id, unsigned char* flags) : -- m_data(static_cast(reinterpret_cast(id))) -- { -- *flags |= TRACE_EVENT_FLAG_MANGLE_ID; -- } -- explicit TraceID(unsigned long long id, unsigned char* flags) : m_data(id) { (void)flags; } -- explicit TraceID(unsigned long id, unsigned char* flags) : m_data(id) { (void)flags; } -- explicit TraceID(unsigned int id, unsigned char* flags) : m_data(id) { (void)flags; } -- explicit TraceID(unsigned short id, unsigned char* flags) : m_data(id) { (void)flags; } -- explicit TraceID(unsigned char id, unsigned char* flags) : m_data(id) { (void)flags; } -- explicit TraceID(long long id, unsigned char* flags) : -- m_data(static_cast(id)) { (void)flags; } -- explicit TraceID(long id, unsigned char* flags) : -- m_data(static_cast(id)) { (void)flags; } -- explicit TraceID(int id, unsigned char* flags) : -- m_data(static_cast(id)) { (void)flags; } -- explicit TraceID(short id, unsigned char* flags) : -- m_data(static_cast(id)) { (void)flags; } -- explicit TraceID(signed char id, unsigned char* flags) : -- m_data(static_cast(id)) { (void)flags; } -- -- unsigned long long data() const { return m_data; } -- --private: -- unsigned long long m_data; --}; -- --// Simple union to store various types as unsigned long long. --union TraceValueUnion { -- bool m_bool; -- unsigned long long m_uint; -- long long m_int; -- double m_double; -- const void* m_pointer; -- const char* m_string; --}; -- --// Simple container for const char* that should be copied instead of retained. --class TraceStringWithCopy { --public: -- explicit TraceStringWithCopy(const char* str) : m_str(str) { } -- operator const char* () const { return m_str; } --private: -- const char* m_str; --}; -- --// Define setTraceValue for each allowed type. It stores the type and --// value in the return arguments. This allows this API to avoid declaring any --// structures so that it is portable to third_party libraries. --#define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, \ -- union_member, \ -- value_type_id) \ -- static inline void setTraceValue(actual_type arg, \ -- unsigned char* type, \ -- unsigned long long* value) { \ -- TraceValueUnion typeValue; \ -- typeValue.union_member = arg; \ -- *type = value_type_id; \ -- *value = typeValue.m_uint; \ -- } --// Simpler form for int types that can be safely casted. --#define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, \ -- value_type_id) \ -- static inline void setTraceValue(actual_type arg, \ -- unsigned char* type, \ -- unsigned long long* value) { \ -- *type = value_type_id; \ -- *value = static_cast(arg); \ -- } -- --INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT) --INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT) --INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT) --INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT) --INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT) --INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT) --INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT) --INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT) --INTERNAL_DECLARE_SET_TRACE_VALUE(bool, m_bool, TRACE_VALUE_TYPE_BOOL) --INTERNAL_DECLARE_SET_TRACE_VALUE(double, m_double, TRACE_VALUE_TYPE_DOUBLE) --INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, m_pointer, -- TRACE_VALUE_TYPE_POINTER) --INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, m_string, -- TRACE_VALUE_TYPE_STRING) --INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, m_string, -- TRACE_VALUE_TYPE_COPY_STRING) -- --#undef INTERNAL_DECLARE_SET_TRACE_VALUE --#undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT -- --static inline void setTraceValue(const std::string& arg, -- unsigned char* type, -- unsigned long long* value) { -- TraceValueUnion typeValue; -- typeValue.m_string = arg.data(); -- *type = TRACE_VALUE_TYPE_COPY_STRING; -- *value = typeValue.m_uint; --} -- --// These addTraceEvent template functions are defined here instead of in the --// macro, because the arg values could be temporary string objects. In order to --// store pointers to the internal c_str and pass through to the tracing API, the --// arg values must live throughout these procedures. -- --static inline void addTraceEvent(char phase, -- const unsigned char* categoryEnabled, -- const char* name, -- unsigned long long id, -- unsigned char flags) { -- TRACE_EVENT_API_ADD_TRACE_EVENT( -- phase, categoryEnabled, name, id, -- zeroNumArgs, 0, 0, 0, -- flags); --} -- --template --static inline void addTraceEvent(char phase, -- const unsigned char* categoryEnabled, -- const char* name, -- unsigned long long id, -- unsigned char flags, -- const char* arg1Name, -- const ARG1_TYPE& arg1Val) { -- const int numArgs = 1; -- unsigned char argTypes[1]; -- unsigned long long argValues[1]; -- setTraceValue(arg1Val, &argTypes[0], &argValues[0]); -- TRACE_EVENT_API_ADD_TRACE_EVENT( -- phase, categoryEnabled, name, id, -- numArgs, &arg1Name, argTypes, argValues, -- flags); --} -- --template --static inline void addTraceEvent(char phase, -- const unsigned char* categoryEnabled, -- const char* name, -- unsigned long long id, -- unsigned char flags, -- const char* arg1Name, -- const ARG1_TYPE& arg1Val, -- const char* arg2Name, -- const ARG2_TYPE& arg2Val) { -- const int numArgs = 2; -- const char* argNames[2] = { arg1Name, arg2Name }; -- unsigned char argTypes[2]; -- unsigned long long argValues[2]; -- setTraceValue(arg1Val, &argTypes[0], &argValues[0]); -- setTraceValue(arg2Val, &argTypes[1], &argValues[1]); -- return TRACE_EVENT_API_ADD_TRACE_EVENT( -- phase, categoryEnabled, name, id, -- numArgs, argNames, argTypes, argValues, -- flags); --} -- --// Used by TRACE_EVENTx macro. Do not use directly. --class TraceEndOnScopeClose { --public: -- // Note: members of m_data intentionally left uninitialized. See initialize. -- TraceEndOnScopeClose() : m_pdata(0) { } -- ~TraceEndOnScopeClose() -- { -- if (m_pdata) -- addEventIfEnabled(); -- } -- -- void initialize(const unsigned char* categoryEnabled, -- const char* name) -- { -- m_data.categoryEnabled = categoryEnabled; -- m_data.name = name; -- m_pdata = &m_data; -- } -- --private: -- // Add the end event if the category is still enabled. -- void addEventIfEnabled() -- { -- // Only called when m_pdata is non-null. -- if (*m_pdata->categoryEnabled) { -- TRACE_EVENT_API_ADD_TRACE_EVENT( -- TRACE_EVENT_PHASE_END, -- m_pdata->categoryEnabled, -- m_pdata->name, noEventId, -- zeroNumArgs, 0, 0, 0, -- TRACE_EVENT_FLAG_NONE); -- } -- } -- -- // This Data struct workaround is to avoid initializing all the members -- // in Data during construction of this object, since this object is always -- // constructed, even when tracing is disabled. If the members of Data were -- // members of this class instead, compiler warnings occur about potential -- // uninitialized accesses. -- struct Data { -- const unsigned char* categoryEnabled; -- const char* name; -- }; -- Data* m_pdata; -- Data m_data; --}; -- --// TraceEventSamplingStateScope records the current sampling state --// and sets a new sampling state. When the scope exists, it restores --// the sampling state having recorded. --template --class SamplingStateScope { --public: -- SamplingStateScope(const char* categoryAndName) -- { -- m_previousState = SamplingStateScope::current(); -- SamplingStateScope::set(categoryAndName); -- } -- -- ~SamplingStateScope() -- { -- SamplingStateScope::set(m_previousState); -- } -- -- // FIXME: Make load/store to traceSamplingState[] thread-safe and atomic. -- static inline const char* current() -- { -- return reinterpret_cast(*gl::traceSamplingState[BucketNumber]); -- } -- static inline void set(const char* categoryAndName) -- { -- *gl::traceSamplingState[BucketNumber] = reinterpret_cast(const_cast(categoryAndName)); -- } -- --private: -- const char* m_previousState; --}; -- --} // namespace TraceEvent -- --} // namespace gl -- --#endif -diff --git a/src/angle/src/common/common.pri b/src/angle/src/common/common.pri -index fd1c31c..8baedc5 100644 ---- a/src/angle/src/common/common.pri -+++ b/src/angle/src/common/common.pri -@@ -51,7 +51,6 @@ static: DEFINES *= QT_OPENGL_ES_2_ANGLE_STATIC - HEADERS += \ - $$ANGLE_DIR/src/common/angleutils.h \ - $$ANGLE_DIR/src/common/debug.h \ -- $$ANGLE_DIR/src/common/event_tracer.h \ - $$ANGLE_DIR/src/common/mathutil.h \ - $$ANGLE_DIR/src/common/platform.h \ - $$ANGLE_DIR/src/common/RefCountObject.h \ -@@ -61,7 +60,6 @@ HEADERS += \ - SOURCES += \ - $$ANGLE_DIR/src/common/angleutils.cpp \ - $$ANGLE_DIR/src/common/debug.cpp \ -- $$ANGLE_DIR/src/common/event_tracer.cpp \ - $$ANGLE_DIR/src/common/RefCountObject.cpp \ - $$ANGLE_DIR/src/common/tls.cpp - -- -1.9.0.msysgit.0 +1.9.4.msysgit.1 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 deleted file mode 100644 index f2252540eb0..00000000000 --- a/src/angle/patches/0001-Fix-compilation-for-MSVC-2008-and-std-tuple.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 3ea314039783d2e6e558cb10aa86dbf278631eef Mon Sep 17 00:00:00 2001 -From: Thomas Hartmann -Date: Tue, 16 Sep 2014 23:24:24 +0300 -Subject: [PATCH 01/16] Fix compilation for MSVC 2008 and std::tuple - -For MSVC 2008 make_tuple is in the tr1 namespace. - -Change-Id: I4a51f6cabdf068993869b404b12ed1484a21a9d4 ---- - 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 d472e14..f68ac38 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp -@@ -111,7 +111,11 @@ IndexRangeCache::IndexRange::IndexRange(GLenum typ, intptr_t off, GLsizei c) - - bool IndexRangeCache::IndexRange::operator<(const IndexRange& rhs) const - { -+#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); -+#endif - } - - IndexRangeCache::IndexBounds::IndexBounds() --- -1.9.0.msysgit.0 - diff --git a/src/angle/patches/0002-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 deleted file mode 100644 index 322d1211491..00000000000 --- a/src/angle/patches/0002-Fix-compilation-of-ANGLE-with-mingw-tdm64-gcc-4.8.1.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 9f1217589c029d2f91e863c54f7f9d52ef496f71 Mon Sep 17 00:00:00 2001 -From: Kai Koehne -Date: Tue, 16 Sep 2014 23:33:42 +0300 -Subject: [PATCH 02/16] Fix compilation of ANGLE with mingw-tdm64 gcc 4.8.1 - -Do not rely on sprintf_s being declared/defined. This also fixes -deployment to Windows XP. - -See https://chromium-review.googlesource.com/#/c/182975/ for a similar -commit proposed upstream. - -Task-number: QTBUG-36242 -Change-Id: I520e2f61aeab34963e7a57baafd413c7db93f110 ---- - src/3rdparty/angle/src/libEGL/Display.cpp | 2 +- - 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 ecf3395..aaebdb3 100644 ---- a/src/3rdparty/angle/src/libEGL/Display.cpp -+++ b/src/3rdparty/angle/src/libEGL/Display.cpp -@@ -597,7 +597,7 @@ void Display::initVendorString() - if (mRenderer && mRenderer->getLUID(&adapterLuid)) - { - char adapterLuidString[64]; -- sprintf_s(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart); -+ snprintf(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart); - - mVendorString += adapterLuidString; - } --- -1.9.0.msysgit.0 - 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 index 1dfe6154e7f..45a3f17ccab 100644 --- 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 @@ -1,6 +1,6 @@ -From cb00356bad800ca2397301cb8b79ad0b097bddd8 Mon Sep 17 00:00:00 2001 +From 3a39939b5eba9f788789961c4800ba62618f758c Mon Sep 17 00:00:00 2001 From: Friedemann Kleint -Date: Tue, 16 Sep 2014 23:43:00 +0300 +Date: Tue, 11 Nov 2014 10:26:32 +0200 Subject: [PATCH 04/16] Make it possible to link ANGLE statically for single-thread use. @@ -11,8 +11,8 @@ Change-Id: Ifab25a820adf5953bb3b09036de53dbf7f1a7fd5 --- src/3rdparty/angle/include/KHR/khrplatform.h | 2 +- src/3rdparty/angle/src/libEGL/main.cpp | 10 ++++++++++ - src/3rdparty/angle/src/libGLESv2/main.cpp | 10 ++++++++++ - 3 files changed, 21 insertions(+), 1 deletion(-) + src/3rdparty/angle/src/libGLESv2/main.cpp | 10 ++++++++-- + 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/3rdparty/angle/include/KHR/khrplatform.h b/src/3rdparty/angle/include/KHR/khrplatform.h index c9e6f17..1ac2d3f 100644 @@ -28,7 +28,7 @@ index c9e6f17..1ac2d3f 100644 #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 0f8439c..8a1baef 100644 +index d1489f2..e88cad7 100644 --- a/src/3rdparty/angle/src/libEGL/main.cpp +++ b/src/3rdparty/angle/src/libEGL/main.cpp @@ -49,6 +49,8 @@ void DeallocateCurrent() @@ -40,7 +40,7 @@ index 0f8439c..8a1baef 100644 extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) { switch (reason) -@@ -100,16 +102,24 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved +@@ -108,16 +110,24 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved return TRUE; } @@ -64,26 +64,27 @@ index 0f8439c..8a1baef 100644 +#endif } - void setCurrentError(EGLint error) + void recordError(const Error &error) diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp -index 4444d1a..1c577bc 100644 +index 3ac00d5..00f63ae 100644 --- a/src/3rdparty/angle/src/libGLESv2/main.cpp +++ b/src/3rdparty/angle/src/libGLESv2/main.cpp -@@ -46,6 +46,8 @@ void DeallocateCurrent() +@@ -74,7 +74,7 @@ void DeallocateCurrent() } -+#ifndef QT_OPENGL_ES_2_ANGLE_STATIC -+ +-#ifdef ANGLE_PLATFORM_WINDOWS ++#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(QT_OPENGL_ES_2_ANGLE_STATIC) extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) { switch (reason) -@@ -82,16 +84,24 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved +@@ -117,18 +117,24 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved + return TRUE; } +-#endif ++#endif // ANGLE_PLATFORM_WINDOWS && !QT_OPENGL_ES_2_ANGLE_STATIC -+#endif // !QT_OPENGL_ES_2_ANGLE_STATIC -+ namespace gl { @@ -104,5 +105,5 @@ index 4444d1a..1c577bc 100644 void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface) -- -1.9.0.msysgit.0 +1.9.4.msysgit.1 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 deleted file mode 100644 index 78c3e0fbe8d..00000000000 --- a/src/angle/patches/0005-Fix-build-when-SSE2-is-not-available.patch +++ /dev/null @@ -1,84 +0,0 @@ -From df225c023963f37737b7e2d020c8f89a5d5f878e Mon Sep 17 00:00:00 2001 -From: Andy Shaw -Date: Tue, 16 Sep 2014 23:49:50 +0300 -Subject: [PATCH 05/16] Fix build when SSE2 is not available. - -Although SSE2 support is detected at runtime it still may not be -available at build time, so we have to ensure it only uses SSE2 -when it is available at build time too. - -Change-Id: I86c45a6466ab4cec79aa0f62b0d5230a78ad825a ---- - src/3rdparty/angle/src/common/mathutil.h | 2 ++ - src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp | 8 ++++++++ - 2 files changed, 10 insertions(+) - -diff --git a/src/3rdparty/angle/src/common/mathutil.h b/src/3rdparty/angle/src/common/mathutil.h -index ffcb908..52f2bc1 100644 ---- a/src/3rdparty/angle/src/common/mathutil.h -+++ b/src/3rdparty/angle/src/common/mathutil.h -@@ -118,6 +118,7 @@ inline bool supportsSSE2() - return supports; - } - -+#if defined(_M_IX86) || defined(_M_AMD64) // ARM doesn't provide __cpuid() - int info[4]; - __cpuid(info, 0); - -@@ -127,6 +128,7 @@ inline bool supportsSSE2() - - supports = (info[3] >> 26) & 1; - } -+#endif - - checked = true; - -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp -index cc20d94..f777b30 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp -@@ -10,6 +10,10 @@ - - #include "libGLESv2/renderer/loadimage.h" - -+#if !defined(__SSE2__) && (defined(_M_X64) || _M_IX86_FP == 2) -+#define __SSE2__ -+#endif -+ - namespace rx - { - -@@ -17,6 +21,7 @@ void LoadA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) - { -+#ifdef __SSE2__ - __m128i zeroWide = _mm_setzero_si128(); - - for (size_t z = 0; z < depth; z++) -@@ -54,12 +59,14 @@ void LoadA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, - } - } - } -+#endif - } - - void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) - { -+#ifdef __SSE2__ - __m128i brMask = _mm_set1_epi32(0x00ff00ff); - - for (size_t z = 0; z < depth; z++) -@@ -99,6 +106,7 @@ void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, - } - } - } -+#endif - } - - } --- -1.9.0.msysgit.0 - diff --git a/src/angle/patches/0006-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 deleted file mode 100644 index e60bebd2335..00000000000 --- a/src/angle/patches/0006-Fix-compilation-of-libGLESv2-with-older-MinGW-w64-he.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 2a8568e6f44731df96f6567ffcc59a65ad2b3f29 Mon Sep 17 00:00:00 2001 -From: Kai Koehne -Date: Tue, 16 Sep 2014 23:55:25 +0300 -Subject: [PATCH 06/16] 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 -we officially support). - -Commit 5567 added the D3DCOMPILER_DLL define to d3dcompiler.h, but with -a trailing semicolon that has then fixed in commit 5783. Any toolchain -that ships MinGW-w64 headers from a version in between (like -MinGW-builds gcc 4.7.2-rev11) will unfortunately remain broken. - -Change-Id: I31272a1a991c4fc0f1611f8fb7510be51d6bb925 ---- - .../angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp -index acbd852..eb0dfa5 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp -@@ -10,6 +10,21 @@ - - #include "common/utilities.h" - -+#if defined(__MINGW32__) && !defined(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, -+ const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages); -+typedef HRESULT (WINAPI *pD3DCompile)(const void *data, SIZE_T data_size, const char *filename, -+ const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, -+ const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages); -+ -+#endif // __MINGW32__ && !D3DCOMPILER_DLL -+ - namespace rx - { - --- -1.9.0.msysgit.0 - diff --git a/src/angle/patches/0007-Fix-ANGLE-build-with-Microsoft-Visual-Studio-14-CTP.patch b/src/angle/patches/0007-Fix-ANGLE-build-with-Microsoft-Visual-Studio-14-CTP.patch deleted file mode 100644 index c796ebc95e3..00000000000 --- a/src/angle/patches/0007-Fix-ANGLE-build-with-Microsoft-Visual-Studio-14-CTP.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 76152feea8265f40fec8c6e53f976dbd82fb6c80 Mon Sep 17 00:00:00 2001 -From: Thiago Macieira -Date: Tue, 16 Sep 2014 23:56:43 +0300 -Subject: [PATCH 07/16] Fix ANGLE build with Microsoft Visual Studio "14" CTP - -This version has a few new C99 support added, including snprintf. - -Change-Id: I5776456fd94254a64f08791f59bc775cb24c9b7f ---- - src/3rdparty/angle/src/common/angleutils.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h -index 50a4132..ddbbd5f 100644 ---- a/src/3rdparty/angle/src/common/angleutils.h -+++ b/src/3rdparty/angle/src/common/angleutils.h -@@ -135,7 +135,7 @@ inline std::string Str(int i) - std::string FormatString(const char *fmt, va_list vararg); - std::string FormatString(const char *fmt, ...); - --#if defined(_MSC_VER) -+#if defined(_MSC_VER) && _MSC_VER < 1900 - #define snprintf _snprintf - #endif - --- -1.9.0.msysgit.0 - diff --git a/src/angle/patches/0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-or-t.patch b/src/angle/patches/0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-or-t.patch index 7c821580d04..801db67682a 100644 --- a/src/angle/patches/0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-or-t.patch +++ b/src/angle/patches/0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-or-t.patch @@ -1,6 +1,6 @@ -From 4f6dd1f7cdce3340723cc23e0aea27b156fa3497 Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Tue, 16 Sep 2014 23:59:40 +0300 +From 4a5960465d1632ab089320fcbba4af294d58fd9a Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Fri, 7 Nov 2014 14:05:36 +0200 Subject: [PATCH 08/16] ANGLE: Dynamically load D3D compiler from a list or the environment @@ -11,29 +11,28 @@ QT_D3DCOMPILER_DLL. Change-Id: I0d7a8a8a36cc571836f8fa59ea14513b9b19c19b --- - .../src/libGLESv2/renderer/d3d/HLSLCompiler.cpp | 27 +++++++++++++++++++--- - 1 file changed, 24 insertions(+), 3 deletions(-) + .../src/libGLESv2/renderer/d3d/HLSLCompiler.cpp | 27 ++++++++++++++++++++++ + 1 file changed, 27 insertions(+) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp -index eb0dfa5..5715d5f 100644 +index bfeaf51..9d003b4 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp -@@ -25,6 +25,10 @@ typedef HRESULT (WINAPI *pD3DCompile)(const void *data, SIZE_T data_size, const - - #endif // __MINGW32__ && !D3DCOMPILER_DLL +@@ -11,6 +11,10 @@ + #include "common/features.h" + #include "common/utilities.h" +#ifndef QT_D3DCOMPILER_DLL +#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL +#endif + - namespace rx + // Definitions local to the translation unit + namespace { - -@@ -59,10 +63,27 @@ bool HLSLCompiler::initialize() +@@ -132,6 +136,29 @@ bool HLSLCompiler::initialize() } #endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES -- if (!mD3DCompilerModule) + // Load the compiler DLL specified by the environment, or default to QT_D3DCOMPILER_DLL + const wchar_t *defaultCompiler = _wgetenv(L"QT_D3DCOMPILER_DLL"); + if (!defaultCompiler) @@ -51,15 +50,15 @@ index eb0dfa5..5715d5f 100644 + + // Load the first available known compiler DLL + for (int i = 0; compilerDlls[i]; ++i) - { -- // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. -- mD3DCompilerModule = LoadLibrary(D3DCOMPILER_DLL); ++ { + mD3DCompilerModule = LoadLibrary(compilerDlls[i]); + if (mD3DCompilerModule) + break; - } - ++ } ++ if (!mD3DCompilerModule) + { + // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. -- -1.9.0.msysgit.0 +1.9.4.msysgit.1 diff --git a/src/angle/patches/0009-ANGLE-Support-WinRT.patch b/src/angle/patches/0009-ANGLE-Support-WinRT.patch index f4bae46b630..a38fb4ea13c 100644 --- a/src/angle/patches/0009-ANGLE-Support-WinRT.patch +++ b/src/angle/patches/0009-ANGLE-Support-WinRT.patch @@ -1,1126 +1,673 @@ -From 7ff7dd46f54e23ae309887366bf477de9c33005b Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Wed, 17 Sep 2014 00:58:29 +0300 +From 4d150ba3814f824f1cadaedbdb83d0ac79d0e1a2 Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Fri, 14 Nov 2014 09:28:11 +0200 Subject: [PATCH 09/16] ANGLE: Support WinRT -This enables EGL for WinRT's native types, and adjusts some codepaths -to accommodate differences between desktop Windows and WinRT. +Tweak ANGLE's existing support for WinRT to allow for changing the +window size on Windows Phone. -- WinRT native handles added to eglplatform.h -- References to native handles in libEGL/libGLESv2 follow eglplatform.h -- D3D 11.1 structures and methods used when necessary -- TLS replaced with thread attribute -- LocalAlloc/Free replaced with Heap API - -Change-Id: Ia90377e700d335a1c569c2145008dd4b0dfd84d3 -Reviewed-by: Friedemann Kleint +Change-Id: Ia312b5318b977838a2953f1f530487cbf24974bc --- - src/3rdparty/angle/include/EGL/eglplatform.h | 10 +- - src/3rdparty/angle/src/common/platform.h | 3 + - src/3rdparty/angle/src/common/tls.cpp | 37 ++++- - src/3rdparty/angle/src/common/tls.h | 6 +- - src/3rdparty/angle/src/common/utilities.cpp | 51 +++++- - src/3rdparty/angle/src/libEGL/Display.cpp | 13 +- - src/3rdparty/angle/src/libEGL/Display.h | 6 +- - src/3rdparty/angle/src/libEGL/Surface.cpp | 185 ++++++++++++++++++++- - src/3rdparty/angle/src/libEGL/Surface.h | 37 ++++- - src/3rdparty/angle/src/libEGL/libEGL.cpp | 8 +- - src/3rdparty/angle/src/libEGL/main.cpp | 21 +++ - src/3rdparty/angle/src/libGLESv2/main.cpp | 20 +++ - src/3rdparty/angle/src/libGLESv2/main.h | 4 + - .../angle/src/libGLESv2/renderer/Renderer.h | 2 +- - .../angle/src/libGLESv2/renderer/SwapChain.h | 15 +- - .../src/libGLESv2/renderer/d3d/HLSLCompiler.cpp | 11 +- - .../libGLESv2/renderer/d3d/d3d11/Renderer11.cpp | 13 +- - .../src/libGLESv2/renderer/d3d/d3d11/Renderer11.h | 4 +- - .../libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp | 73 ++++++-- - .../src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h | 6 +- - .../src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp | 2 +- - .../src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h | 2 +- - 22 files changed, 481 insertions(+), 48 deletions(-) + src/3rdparty/angle/include/EGL/eglplatform.h | 5 +- + src/3rdparty/angle/src/common/NativeWindow.h | 7 +- + src/3rdparty/angle/src/common/platform.h | 4 +- + .../angle/src/common/win32/NativeWindow.cpp | 2 +- + .../src/common/winrt/CoreWindowNativeWindow.cpp | 87 +++++++++++++--------- + .../src/common/winrt/CoreWindowNativeWindow.h | 48 ++---------- + .../src/common/winrt/InspectableNativeWindow.cpp | 8 +- + .../src/common/winrt/InspectableNativeWindow.h | 7 +- + .../common/winrt/SwapChainPanelNativeWindow.cpp | 2 +- + .../src/common/winrt/SwapChainPanelNativeWindow.h | 2 +- + src/3rdparty/angle/src/libEGL/Display.h | 1 + + src/3rdparty/angle/src/libEGL/Surface.cpp | 45 ++++++++--- + src/3rdparty/angle/src/libEGL/Surface.h | 4 + + src/3rdparty/angle/src/libEGL/libEGL.cpp | 20 +++++ + .../src/libGLESv2/renderer/d3d/d3d11/Renderer11.h | 2 +- + .../libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp | 74 +++++++++++------- + .../src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h | 2 + + 17 files changed, 189 insertions(+), 131 deletions(-) diff --git a/src/3rdparty/angle/include/EGL/eglplatform.h b/src/3rdparty/angle/include/EGL/eglplatform.h -index 3ab8844..ea9f577 100644 +index 3793e57..2eb3674 100644 --- a/src/3rdparty/angle/include/EGL/eglplatform.h +++ b/src/3rdparty/angle/include/EGL/eglplatform.h -@@ -67,7 +67,15 @@ - * implementations. - */ - --#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */ -+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) /* Windows Runtime */ -+ -+struct IUnknown; -+ -+typedef IUnknown *EGLNativeDisplayType; -+typedef void *EGLNativePixmapType; -+typedef IUnknown *EGLNativeWindowType; -+ -+#elif defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */ - #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN 1 +@@ -73,13 +73,14 @@ #endif -diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h -index d07297d..387ba41 100644 ---- a/src/3rdparty/angle/src/common/platform.h -+++ b/src/3rdparty/angle/src/common/platform.h -@@ -11,6 +11,9 @@ + #include - #if defined(_WIN32) || defined(_WIN64) - # define ANGLE_PLATFORM_WINDOWS 1 -+# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) -+# define ANGLE_PLATFORM_WINRT 1 -+# endif - #elif defined(__APPLE__) - # define ANGLE_PLATFORM_APPLE 1 - # define ANGLE_PLATFORM_POSIX 1 -diff --git a/src/3rdparty/angle/src/common/tls.cpp b/src/3rdparty/angle/src/common/tls.cpp -index 6b78219..c46fab5 100644 ---- a/src/3rdparty/angle/src/common/tls.cpp -+++ b/src/3rdparty/angle/src/common/tls.cpp -@@ -10,11 +10,28 @@ +-typedef HDC EGLNativeDisplayType; + typedef HBITMAP EGLNativePixmapType; - #include - -+#if defined(ANGLE_PLATFORM_WINRT) -+#include -+std::vector *tls = nullptr; -+std::vector *freeIndices = nullptr; -+#endif -+ - TLSIndex CreateTLSIndex() - { - TLSIndex index; - --#ifdef ANGLE_PLATFORM_WINDOWS -+#if defined(ANGLE_PLATFORM_WINRT) -+ if (!tls) -+ tls = new std::vector; -+ if (freeIndices && !freeIndices->empty()) { -+ index = freeIndices->back(); -+ freeIndices->pop_back(); -+ return index; -+ } else { -+ tls->push_back(nullptr); -+ return tls->size() - 1; -+ } -+#elif defined(ANGLE_PLATFORM_WINDOWS) - index = TlsAlloc(); - #elif defined(ANGLE_PLATFORM_POSIX) - // Create global pool key -@@ -36,7 +53,12 @@ bool DestroyTLSIndex(TLSIndex index) - return false; - } - --#ifdef ANGLE_PLATFORM_WINDOWS -+#if defined(ANGLE_PLATFORM_WINRT) -+ if (!freeIndices) -+ freeIndices = new std::vector; -+ freeIndices->push_back(index); -+ return true; -+#elif ANGLE_PLATFORM_WINDOWS - return (TlsFree(index) == TRUE); - #elif defined(ANGLE_PLATFORM_POSIX) - return (pthread_key_delete(index) == 0); -@@ -51,7 +73,10 @@ bool SetTLSValue(TLSIndex index, void *value) - return false; - } - --#ifdef ANGLE_PLATFORM_WINDOWS -+#if defined(ANGLE_PLATFORM_WINRT) -+ tls->at(index) = value; -+ return true; -+#elif defined(ANGLE_PLATFORM_WINDOWS) - return (TlsSetValue(index, value) == TRUE); - #elif defined(ANGLE_PLATFORM_POSIX) - return (pthread_setspecific(index, value) == 0); -@@ -60,13 +85,17 @@ bool SetTLSValue(TLSIndex index, void *value) - - void *GetTLSValue(TLSIndex index) - { -+#if !defined(ANGLE_PLATFORM_WINRT) // Valid on WinRT, as Alloc handles the index creation - assert(index != TLS_INVALID_INDEX && "GetTLSValue(): Invalid TLS Index"); -+#endif - if (index == TLS_INVALID_INDEX) - { - return NULL; - } - --#ifdef ANGLE_PLATFORM_WINDOWS -+#if defined(ANGLE_PLATFORM_WINRT) -+ return tls->at(index); -+#elif defined(ANGLE_PLATFORM_WINDOWS) - return TlsGetValue(index); - #elif defined(ANGLE_PLATFORM_POSIX) - return pthread_getspecific(index); -diff --git a/src/3rdparty/angle/src/common/tls.h b/src/3rdparty/angle/src/common/tls.h -index 4b25fbc..c40ae1a 100644 ---- a/src/3rdparty/angle/src/common/tls.h -+++ b/src/3rdparty/angle/src/common/tls.h -@@ -11,7 +11,11 @@ - - #include "common/platform.h" - --#ifdef ANGLE_PLATFORM_WINDOWS -+#if defined(ANGLE_PLATFORM_WINRT) -+ typedef size_t TLSIndex; -+# define TLS_OUT_OF_INDEXES (static_cast(-1)) -+# define TLS_INVALID_INDEX TLS_OUT_OF_INDEXES -+#elif defined(ANGLE_PLATFORM_WINDOWS) - typedef DWORD TLSIndex; - # define TLS_INVALID_INDEX (TLS_OUT_OF_INDEXES) - #elif defined(ANGLE_PLATFORM_POSIX) -diff --git a/src/3rdparty/angle/src/common/utilities.cpp b/src/3rdparty/angle/src/common/utilities.cpp -index 405f119..4b8e325 100644 ---- a/src/3rdparty/angle/src/common/utilities.cpp -+++ b/src/3rdparty/angle/src/common/utilities.cpp -@@ -9,6 +9,14 @@ - #include "common/utilities.h" - #include "common/mathutil.h" - #include "common/platform.h" -+#if defined(ANGLE_PLATFORM_WINRT) -+# include -+# include -+# include -+# include -+ using namespace Microsoft::WRL; -+ using namespace ABI::Windows::Storage; -+#endif - - #include - -@@ -441,7 +449,48 @@ int VariableSortOrder(GLenum type) - - std::string getTempPath() - { --#ifdef ANGLE_PLATFORM_WINDOWS -+#if defined(ANGLE_PLATFORM_WINRT) -+ static std::string path; -+ -+ while (path.empty()) -+ { -+ ComPtr factory; -+ Wrappers::HStringReference classId(RuntimeClass_Windows_Storage_ApplicationData); -+ HRESULT result = RoGetActivationFactory(classId.Get(), IID_PPV_ARGS(&factory)); -+ if (FAILED(result)) -+ break; -+ -+ ComPtr applicationData; -+ result = factory->get_Current(&applicationData); -+ if (FAILED(result)) -+ break; -+ -+ ComPtr storageFolder; -+ result = applicationData->get_LocalFolder(&storageFolder); -+ if (FAILED(result)) -+ break; -+ -+ ComPtr localFolder; -+ result = storageFolder.As(&localFolder); -+ if (FAILED(result)) -+ break; -+ -+ HSTRING localFolderPath; -+ result = localFolder->get_Path(&localFolderPath); -+ if (FAILED(result)) -+ break; -+ -+ std::wstring_convert< std::codecvt_utf8 > converter; -+ path = converter.to_bytes(WindowsGetStringRawBuffer(localFolderPath, NULL)); -+ if (path.empty()) -+ { -+ UNREACHABLE(); -+ break; -+ } -+ } -+ -+ return path; -+#elif defined(ANGLE_PLATFORM_WINDOWS) - char path[MAX_PATH]; - DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path); - if (pathLen == 0) -diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp -index aaebdb3..ba09631 100644 ---- a/src/3rdparty/angle/src/libEGL/Display.cpp -+++ b/src/3rdparty/angle/src/libEGL/Display.cpp -@@ -56,6 +56,10 @@ Display::Display(EGLNativeDisplayType displayId, EGLint displayType) - mRequestedDisplayType(displayType), - mRenderer(NULL) - { -+#if defined(ANGLE_PLATFORM_WINRT) -+ if (mDisplayId) -+ mDisplayId->AddRef(); -+#endif - } - - Display::~Display() -@@ -68,6 +72,11 @@ Display::~Display() - { - displays->erase(iter); - } -+ -+#if defined(ANGLE_PLATFORM_WINRT) -+ if (mDisplayId) -+ mDisplayId->Release(); -+#endif - } - - bool Display::initialize() -@@ -192,7 +201,7 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) - - - --EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList) -+EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList) - { - const Config *configuration = mConfigSet.get(config); - EGLint postSubBufferSupported = EGL_FALSE; -@@ -493,7 +502,7 @@ bool Display::isValidSurface(egl::Surface *surface) - return mSurfaceSet.find(surface) != mSurfaceSet.end(); - } - --bool Display::hasExistingWindowSurface(HWND window) -+bool Display::hasExistingWindowSurface(EGLNativeWindowType window) - { - for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) - { -diff --git a/src/3rdparty/angle/src/libEGL/Display.h b/src/3rdparty/angle/src/libEGL/Display.h -index 250878f..73ba767 100644 ---- a/src/3rdparty/angle/src/libEGL/Display.h -+++ b/src/3rdparty/angle/src/libEGL/Display.h -@@ -43,7 +43,7 @@ class Display - bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig); - bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value); - -- EGLSurface createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList); -+ EGLSurface createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList); - EGLSurface createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList); - EGLContext createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets, bool robustAccess); - -@@ -54,7 +54,7 @@ class Display - bool isValidConfig(EGLConfig config); - bool isValidContext(gl::Context *context); - bool isValidSurface(egl::Surface *surface); -- bool hasExistingWindowSurface(HWND window); -+ bool hasExistingWindowSurface(EGLNativeWindowType window); - - rx::Renderer *getRenderer() { return mRenderer; }; - -@@ -65,6 +65,8 @@ class Display - const char *getExtensionString() const; - const char *getVendorString() const; - -+ EGLNativeDisplayType getDisplayId() const { return mDisplayId; } -+ - private: - DISALLOW_COPY_AND_ASSIGN(Display); - -diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp -index 13b0f20..fa79961 100644 ---- a/src/3rdparty/angle/src/libEGL/Surface.cpp -+++ b/src/3rdparty/angle/src/libEGL/Surface.cpp -@@ -22,10 +22,20 @@ - #include "libEGL/main.h" - #include "libEGL/Display.h" - -+#if defined(ANGLE_PLATFORM_WINRT) -+# include "wrl.h" -+# include "windows.graphics.display.h" -+# include "windows.ui.core.h" -+using namespace ABI::Windows::Graphics::Display; -+using namespace ABI::Windows::Foundation; -+using namespace ABI::Windows::UI::Core; -+using namespace Microsoft::WRL; -+#endif -+ - namespace egl - { - --Surface::Surface(Display *display, const Config *config, HWND window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported) -+Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported) - : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported) - { - mRenderer = mDisplay->getRenderer(); -@@ -43,6 +53,17 @@ Surface::Surface(Display *display, const Config *config, HWND window, EGLint fix - mHeight = height; - setSwapInterval(1); - mFixedSize = fixedSize; -+ mSwapFlags = rx::SWAP_NORMAL; -+#if defined(ANGLE_PLATFORM_WINRT) -+ if (mWindow) -+ mWindow->AddRef(); -+ mScaleFactor = 1.0; -+ mSizeToken.value = 0; -+ mDpiToken.value = 0; -+# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP -+ mOrientationToken.value = 0; -+# endif -+#endif - - subclassWindow(); - } -@@ -64,16 +85,86 @@ Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGL - setSwapInterval(1); - // This constructor is for offscreen surfaces, which are always fixed-size. - mFixedSize = EGL_TRUE; -+ mSwapFlags = rx::SWAP_NORMAL; -+#if defined(ANGLE_PLATFORM_WINRT) -+ mScaleFactor = 1.0; -+ mSizeToken.value = 0; -+ mDpiToken.value = 0; -+# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP -+ mOrientationToken.value = 0; -+# endif -+#endif - } - - Surface::~Surface() - { -+#if defined(ANGLE_PLATFORM_WINRT) -+ if (mSizeToken.value) { -+ ComPtr coreWindow; -+ HRESULT hr = mWindow->QueryInterface(coreWindow.GetAddressOf()); -+ ASSERT(SUCCEEDED(hr)); -+ -+ hr = coreWindow->remove_SizeChanged(mSizeToken); -+ ASSERT(SUCCEEDED(hr)); -+ } -+ if (mDpiToken.value) { -+ ComPtr displayInformation; -+ HRESULT hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf()); -+ ASSERT(SUCCEEDED(hr)); -+ -+ hr = displayInformation->remove_DpiChanged(mDpiToken); -+ ASSERT(SUCCEEDED(hr)); -+ } -+# if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP -+ if (mOrientationToken.value) { -+ ComPtr displayInformation; -+ HRESULT hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf()); -+ ASSERT(SUCCEEDED(hr)); -+ -+ hr = displayInformation->remove_OrientationChanged(mOrientationToken); -+ ASSERT(SUCCEEDED(hr)); -+ } -+# endif -+#endif - unsubclassWindow(); - release(); - } - - bool Surface::initialize() - { -+#if defined(ANGLE_PLATFORM_WINRT) -+ if (!mFixedSize) { -+ HRESULT hr; -+ ComPtr displayInformation; -+ hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf()); -+ ASSERT(SUCCEEDED(hr)); -+ onDpiChanged(displayInformation.Get(), 0); -+ hr = displayInformation->add_DpiChanged(Callback>(this, &Surface::onDpiChanged).Get(), -+ &mDpiToken); -+ ASSERT(SUCCEEDED(hr)); -+ -+# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP -+ onOrientationChanged(displayInformation.Get(), 0); -+ hr = displayInformation->add_OrientationChanged(Callback>(this, &Surface::onOrientationChanged).Get(), -+ &mOrientationToken); -+ ASSERT(SUCCEEDED(hr)); -+# endif -+ -+ ComPtr coreWindow; -+ hr = mWindow->QueryInterface(coreWindow.GetAddressOf()); -+ ASSERT(SUCCEEDED(hr)); -+ -+ Rect rect; -+ hr = coreWindow->get_Bounds(&rect); -+ ASSERT(SUCCEEDED(hr)); -+ mWidth = rect.Width * mScaleFactor; -+ mHeight = rect.Height * mScaleFactor; -+ hr = coreWindow->add_SizeChanged(Callback>(this, &Surface::onSizeChanged).Get(), -+ &mSizeToken); -+ ASSERT(SUCCEEDED(hr)); -+ } -+#endif -+ - if (!resetSwapChain()) - return false; - -@@ -90,6 +181,11 @@ void Surface::release() - mTexture->releaseTexImage(); - mTexture = NULL; - } -+ -+#if defined(ANGLE_PLATFORM_WINRT) -+ if (mWindow) -+ mWindow->Release(); -+#endif - } - - bool Surface::resetSwapChain() -@@ -99,6 +195,7 @@ bool Surface::resetSwapChain() - int width; - int height; - -+#if !defined(ANGLE_PLATFORM_WINRT) - if (!mFixedSize) - { - RECT windowRect; -@@ -114,6 +211,7 @@ bool Surface::resetSwapChain() - height = windowRect.bottom - windowRect.top; - } - else -+#endif - { - // non-window surface - size is determined at creation - width = mWidth; -@@ -207,7 +305,7 @@ bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) - return true; - } - -- EGLint status = mSwapChain->swapRect(x, y, width, height); -+ EGLint status = mSwapChain->swapRect(x, y, width, height, mSwapFlags); - - if (status == EGL_CONTEXT_LOST) - { -@@ -224,7 +322,7 @@ bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) - return true; - } - --HWND Surface::getWindowHandle() -+EGLNativeWindowType Surface::getWindowHandle() - { - return mWindow; - } -@@ -233,6 +331,7 @@ HWND Surface::getWindowHandle() - #define kSurfaceProperty _TEXT("Egl::SurfaceOwner") - #define kParentWndProc _TEXT("Egl::SurfaceParentWndProc") - -+#if !defined(ANGLE_PLATFORM_WINRT) - static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) - { - if (message == WM_SIZE) -@@ -246,9 +345,11 @@ static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam - WNDPROC prevWndFunc = reinterpret_cast(GetProp(hwnd, kParentWndProc)); - return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam); - } -+#endif - - void Surface::subclassWindow() - { -+#if !defined(ANGLE_PLATFORM_WINRT) - if (!mWindow) - { - return; -@@ -272,10 +373,14 @@ void Surface::subclassWindow() - SetProp(mWindow, kSurfaceProperty, reinterpret_cast(this)); - SetProp(mWindow, kParentWndProc, reinterpret_cast(oldWndProc)); - mWindowSubclassed = true; -+#else -+ mWindowSubclassed = false; -+#endif - } - - void Surface::unsubclassWindow() - { -+#if !defined(ANGLE_PLATFORM_WINRT) - if(!mWindowSubclassed) - { - return; -@@ -299,16 +404,18 @@ void Surface::unsubclassWindow() - RemoveProp(mWindow, kSurfaceProperty); - RemoveProp(mWindow, kParentWndProc); - mWindowSubclassed = false; -+#endif - } - - bool Surface::checkForOutOfDateSwapChain() - { -- RECT client; - int clientWidth = getWidth(); - int clientHeight = getHeight(); - bool sizeDirty = false; -+#if !defined(ANGLE_PLATFORM_WINRT) - if (!mFixedSize && !IsIconic(getWindowHandle())) - { -+ RECT client; - // 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. - if (!GetClientRect(getWindowHandle(), &client)) -@@ -322,6 +429,7 @@ bool Surface::checkForOutOfDateSwapChain() - clientHeight = client.bottom - client.top; - sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); - } -+#endif - - bool wasDirty = (mSwapIntervalDirty || sizeDirty); - -@@ -446,4 +554,73 @@ EGLenum Surface::getFormat() const - { - return mConfig->mRenderTargetFormat; - } -+ -+#if defined(ANGLE_PLATFORM_WINRT) -+ -+HRESULT Surface::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *args) -+{ -+ HRESULT hr; -+ Size size; -+ hr = args->get_Size(&size); -+ ASSERT(SUCCEEDED(hr)); -+ -+ resizeSwapChain(std::floor(size.Width * mScaleFactor + 0.5), -+ std::floor(size.Height * mScaleFactor + 0.5)); -+ -+ if (static_cast(getCurrentDrawSurface()) == this) -+ { -+ glMakeCurrent(glGetCurrentContext(), static_cast(getCurrentDisplay()), this); -+ } -+ -+ return S_OK; -+} -+ -+HRESULT Surface::onDpiChanged(IDisplayInformation *displayInformation, IInspectable *) -+{ -+ HRESULT hr; -+# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP -+ ComPtr displayInformation2; -+ hr = displayInformation->QueryInterface(displayInformation2.GetAddressOf()); -+ ASSERT(SUCCEEDED(hr)); -+ -+ hr = displayInformation2->get_RawPixelsPerViewPixel(&mScaleFactor); -+ ASSERT(SUCCEEDED(hr)); -+# else -+ ResolutionScale resolutionScale; -+ hr = displayInformation->get_ResolutionScale(&resolutionScale); -+ ASSERT(SUCCEEDED(hr)); -+ -+ mScaleFactor = double(resolutionScale) / 100.0; -+# endif -+ return S_OK; -+} -+ -+# if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP -+HRESULT Surface::onOrientationChanged(IDisplayInformation *displayInformation, IInspectable *) -+{ -+ HRESULT hr; -+ DisplayOrientations orientation; -+ hr = displayInformation->get_CurrentOrientation(&orientation); -+ ASSERT(SUCCEEDED(hr)); -+ switch (orientation) { -+ default: -+ case DisplayOrientations_Portrait: -+ mSwapFlags = rx::SWAP_NORMAL; -+ break; -+ case DisplayOrientations_Landscape: -+ mSwapFlags = rx::SWAP_ROTATE_90; -+ break; -+ case DisplayOrientations_LandscapeFlipped: -+ mSwapFlags = rx::SWAP_ROTATE_270; -+ break; -+ case DisplayOrientations_PortraitFlipped: -+ mSwapFlags = rx::SWAP_ROTATE_180; -+ break; -+ } -+ return S_OK; -+} -+# endif -+ -+#endif -+ - } -diff --git a/src/3rdparty/angle/src/libEGL/Surface.h b/src/3rdparty/angle/src/libEGL/Surface.h -index 24c66b7..ebffce8fe 100644 ---- a/src/3rdparty/angle/src/libEGL/Surface.h -+++ b/src/3rdparty/angle/src/libEGL/Surface.h -@@ -15,6 +15,20 @@ - - #include "common/angleutils.h" - -+#if defined(ANGLE_PLATFORM_WINRT) -+#include -+namespace ABI { namespace Windows { -+ namespace UI { namespace Core { -+ struct ICoreWindow; -+ struct IWindowSizeChangedEventArgs; -+ } } -+ namespace Graphics { namespace Display { -+ struct IDisplayInformation; -+ } } -+} } -+struct IInspectable; -+#endif -+ - namespace gl - { - class Texture2D; -@@ -33,7 +47,7 @@ class Config; - class Surface - { - public: -- Surface(Display *display, const egl::Config *config, HWND window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported); -+ Surface(Display *display, const egl::Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported); - Surface(Display *display, const egl::Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget); - - virtual ~Surface(); -@@ -42,7 +56,7 @@ class Surface - void release(); - bool resetSwapChain(); - -- HWND getWindowHandle(); -+ EGLNativeWindowType getWindowHandle(); - bool swap(); - bool postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height); - -@@ -71,6 +85,14 @@ class Surface - private: - DISALLOW_COPY_AND_ASSIGN(Surface); - -+#if defined(ANGLE_PLATFORM_WINRT) -+ HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *); -+ HRESULT onDpiChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *); -+# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP -+ HRESULT onOrientationChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *); -+# endif -+#endif -+ - Display *const mDisplay; - rx::Renderer *mRenderer; - -@@ -83,7 +105,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. - 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 -@@ -104,9 +126,18 @@ private: - EGLint mSwapInterval; - EGLint mPostSubBufferSupported; - EGLint mFixedSize; -+ EGLint mSwapFlags; - - bool mSwapIntervalDirty; - gl::Texture2D *mTexture; -+#if defined(ANGLE_PLATFORM_WINRT) -+ double mScaleFactor; -+ EventRegistrationToken mSizeToken; -+ EventRegistrationToken mDpiToken; -+# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP -+ EventRegistrationToken mOrientationToken; -+# endif -+#endif - }; - } - -diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp -index 7ce2b93..7ea11c5 100644 ---- a/src/3rdparty/angle/src/libEGL/libEGL.cpp -+++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp -@@ -13,6 +13,7 @@ - - #include "common/debug.h" - #include "common/version.h" -+#include "common/platform.h" - #include "libGLESv2/Context.h" - #include "libGLESv2/Texture.h" - #include "libGLESv2/main.h" -@@ -120,12 +121,13 @@ EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_dis - } - - EGLNativeDisplayType displayId = static_cast(native_display); -- -+#if !defined(ANGLE_PLATFORM_WINRT) - // Validate the display device context - if (WindowFromDC(displayId) == NULL) - { - return egl::success(EGL_NO_DISPLAY); - } -+#endif - - EGLint requestedDisplayType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE; - if (attrib_list) -@@ -327,14 +329,16 @@ EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EG - return EGL_NO_SURFACE; - } - -+#if !defined(ANGLE_PLATFORM_WINRT) - HWND window = (HWND)win; - - if (!IsWindow(window)) - { - return egl::error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); - } -+#endif - -- return display->createWindowSurface(window, config, attrib_list); -+ return display->createWindowSurface(win, config, attrib_list); - } - - EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) -diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp -index 8a1baef..e74737e 100644 ---- a/src/3rdparty/angle/src/libEGL/main.cpp -+++ b/src/3rdparty/angle/src/libEGL/main.cpp -@@ -11,6 +11,9 @@ - #include "common/debug.h" - #include "common/tls.h" - -+#if defined(ANGLE_PLATFORM_WINRT) -+__declspec(thread) -+#endif - static TLSIndex currentTLS = TLS_OUT_OF_INDEXES; - - namespace egl -@@ -18,6 +21,12 @@ namespace egl - - Current *AllocateCurrent() - { -+#if defined(ANGLE_PLATFORM_WINRT) -+ if (currentTLS == TLS_OUT_OF_INDEXES) -+ { -+ currentTLS = CreateTLSIndex(); -+ } -+#endif - ASSERT(currentTLS != TLS_OUT_OF_INDEXES); - if (currentTLS == TLS_OUT_OF_INDEXES) - { -@@ -42,6 +51,12 @@ Current *AllocateCurrent() - - void DeallocateCurrent() - { -+#if defined(ANGLE_PLATFORM_WINRT) -+ if (currentTLS == TLS_OUT_OF_INDEXES) -+ { -+ return; -+ } -+#endif - Current *current = reinterpret_cast(GetTLSValue(currentTLS)); - SafeDelete(current); - SetTLSValue(currentTLS, NULL); -@@ -72,6 +87,10 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved - } +-#if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PC_APP /* Windows Store */ ++#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) /* Windows Store */ + #include ++typedef IInspectable* EGLNativeDisplayType; + typedef IInspectable* EGLNativeWindowType; + #else ++typedef HDC EGLNativeDisplayType; + typedef HWND EGLNativeWindowType; #endif -+#if defined(ANGLE_PLATFORM_WINRT) // On WinRT, don't handle TLS from DllMain -+ return DisableThreadLibraryCalls(instance); -+#endif -+ - currentTLS = CreateTLSIndex(); - if (currentTLS == TLS_OUT_OF_INDEXES) - { -@@ -86,7 +105,9 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved - break; - case DLL_THREAD_DETACH: - { -+#if !defined(ANGLE_PLATFORM_WINRT) - egl::DeallocateCurrent(); -+#endif - } - break; - case DLL_PROCESS_DETACH: -diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp -index 1c577bc..51447e2 100644 ---- a/src/3rdparty/angle/src/libGLESv2/main.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/main.cpp -@@ -11,6 +11,9 @@ - - #include "common/tls.h" - -+#if defined(ANGLE_PLATFORM_WINRT) -+__declspec(thread) -+#endif - static TLSIndex currentTLS = TLS_OUT_OF_INDEXES; - - namespace gl -@@ -18,6 +21,12 @@ namespace gl - - Current *AllocateCurrent() - { -+#if defined(ANGLE_PLATFORM_WINRT) -+ if (currentTLS == TLS_OUT_OF_INDEXES) -+ { -+ currentTLS = CreateTLSIndex(); -+ } -+#endif - ASSERT(currentTLS != TLS_OUT_OF_INDEXES); - if (currentTLS == TLS_OUT_OF_INDEXES) - { -@@ -39,6 +48,12 @@ Current *AllocateCurrent() - - void DeallocateCurrent() - { -+#if defined(ANGLE_PLATFORM_WINRT) -+ if (currentTLS == TLS_OUT_OF_INDEXES) -+ { -+ return; -+ } -+#endif - Current *current = reinterpret_cast(GetTLSValue(currentTLS)); - SafeDelete(current); - SetTLSValue(currentTLS, NULL); -@@ -54,6 +69,9 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved - { - case DLL_PROCESS_ATTACH: - { -+#if defined(ANGLE_PLATFORM_WINRT) // On WinRT, don't handle TLS from DllMain -+ return DisableThreadLibraryCalls(instance); -+#endif - currentTLS = CreateTLSIndex(); - if (currentTLS == TLS_OUT_OF_INDEXES) - { -@@ -73,8 +91,10 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved - break; - case DLL_PROCESS_DETACH: - { -+#if !defined(ANGLE_PLATFORM_WINRT) - gl::DeallocateCurrent(); - DestroyTLSIndex(currentTLS); -+#endif - } - break; - default: -diff --git a/src/3rdparty/angle/src/libGLESv2/main.h b/src/3rdparty/angle/src/libGLESv2/main.h -index 684c302..c30ad33 100644 ---- a/src/3rdparty/angle/src/libGLESv2/main.h -+++ b/src/3rdparty/angle/src/libGLESv2/main.h -@@ -14,6 +14,10 @@ - #include - #include - -+#ifndef Sleep -+#define Sleep(ms) WaitForSingleObjectEx(GetCurrentThread(), ms, FALSE) -+#endif -+ - namespace egl - { - class Display; -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h -index 7adbea2..b224974 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h -@@ -107,7 +107,7 @@ class Renderer - - virtual void sync(bool block) = 0; - -- virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0; -+ virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0; - - virtual gl::Error generateSwizzle(gl::Texture *texture) = 0; - virtual gl::Error setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler) = 0; -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h -index 12be9b3..1ec702f 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h -@@ -15,14 +15,23 @@ - - #include - #include -+#include +diff --git a/src/3rdparty/angle/src/common/NativeWindow.h b/src/3rdparty/angle/src/common/NativeWindow.h +index dc5fc8f..9e93aea 100644 +--- a/src/3rdparty/angle/src/common/NativeWindow.h ++++ b/src/3rdparty/angle/src/common/NativeWindow.h +@@ -44,10 +44,11 @@ typedef IDXGIFactory DXGIFactory; namespace rx { - -+enum SwapFlags -+{ -+ SWAP_NORMAL = 0, -+ SWAP_ROTATE_90 = 1, -+ SWAP_ROTATE_270 = 2, -+ SWAP_ROTATE_180 = SWAP_ROTATE_90|SWAP_ROTATE_270, -+}; + - class SwapChain + class NativeWindow { - 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) - { - } -@@ -31,13 +40,13 @@ class SwapChain +- public: +- explicit NativeWindow(EGLNativeWindowType window); ++public: ++ explicit NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display); - virtual EGLint resize(EGLint backbufferWidth, EGLint backbufferSize) = 0; - virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) = 0; -- virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height) = 0; -+ virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint flags) = 0; - virtual void recreate() = 0; + bool initialize(); + bool getClientRect(LPRECT rect); +@@ -58,9 +59,11 @@ class NativeWindow + DXGISwapChain** swapChain); - virtual HANDLE getShareHandle() {return mShareHandle;}; + inline EGLNativeWindowType getNativeWindow() const { return mWindow; } ++ inline EGLNativeDisplayType getNativeDisplay() const { return mDisplay; } - 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; + private: + EGLNativeWindowType mWindow; ++ EGLNativeDisplayType mDisplay; -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp -index 5715d5f..d013197 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp -@@ -9,6 +9,7 @@ - #include "libGLESv2/main.h" + #if defined(ANGLE_ENABLE_WINDOWS_STORE) + std::shared_ptr mImpl; +diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h +index cd12dba..0065ec7 100644 +--- a/src/3rdparty/angle/src/common/platform.h ++++ b/src/3rdparty/angle/src/common/platform.h +@@ -34,7 +34,7 @@ + #endif - #include "common/utilities.h" -+#include "common/platform.h" - - #if defined(__MINGW32__) && !defined(D3DCOMPILER_DLL) - -@@ -45,11 +46,7 @@ HLSLCompiler::~HLSLCompiler() - - bool HLSLCompiler::initialize() - { --<<<<<<< HEAD -- TRACE_EVENT0("gpu", "initializeCompiler"); --======= - #if !defined(ANGLE_PLATFORM_WINRT) -->>>>>>> 429814a... ANGLE: remove event tracing - #if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES) - // Find a D3DCompiler module that had already been loaded based on a predefined list of versions. - static const char *d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES; -@@ -94,7 +91,9 @@ bool HLSLCompiler::initialize() - - mD3DCompileFunc = reinterpret_cast(GetProcAddress(mD3DCompilerModule, "D3DCompile")); - ASSERT(mD3DCompileFunc); -- -+#else -+ mD3DCompileFunc = reinterpret_cast(&D3DCompile); -+#endif - return mD3DCompileFunc != NULL; + #ifdef ANGLE_PLATFORM_WINDOWS +-# if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PC_APP ++# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + # define ANGLE_ENABLE_WINDOWS_STORE 1 + # endif + # ifndef STRICT +@@ -67,7 +67,9 @@ + # if defined(ANGLE_ENABLE_WINDOWS_STORE) + # include + # if defined(_DEBUG) ++# if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) + # include ++# endif + # include + # endif + # endif +diff --git a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp +index aa2bfa4..2440747 100644 +--- a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp ++++ b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp +@@ -16,7 +16,7 @@ bool IsValidEGLNativeWindowType(EGLNativeWindowType window) + return (IsWindow(window) == TRUE); } -@@ -111,7 +110,9 @@ void HLSLCompiler::release() - ShaderBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, - const UINT optimizationFlags[], const char *flagNames[], int attempts) const +-NativeWindow::NativeWindow(EGLNativeWindowType window) : mWindow(window) ++NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display) : mWindow(window), mDisplay(display) { -+#if !defined(ANGLE_PLATFORM_WINRT) - ASSERT(mD3DCompilerModule && mD3DCompileFunc); -+#endif + } - if (!hlsl) +diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp +index 0e63fa5..9b65c15 100644 +--- a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp ++++ b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp +@@ -6,21 +6,25 @@ + + // CoreWindowNativeWindow.cpp: NativeWindow for managing ICoreWindow native window types. + +-#include ++#include + #include "common/winrt/CoreWindowNativeWindow.h" + using namespace ABI::Windows::Foundation::Collections; + + namespace rx + { ++ ++typedef ITypedEventHandler SizeChangedHandler; ++ + CoreWindowNativeWindow::~CoreWindowNativeWindow() + { + unregisterForSizeChangeEvents(); + } + +-bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet) ++bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) + { + ComPtr props = propertySet; + ComPtr win = window; ++ ComPtr displayInformation = display; + SIZE swapChainSize = {}; + bool swapChainSizeSpecified = false; + HRESULT result = S_OK; +@@ -47,6 +51,29 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet + + if (SUCCEEDED(result)) { -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -index ed880c3..0bb7489 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -@@ -6,6 +6,7 @@ - - // Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer. - -+#include "common/platform.h" - #include "libGLESv2/main.h" - #include "libGLESv2/Buffer.h" - #include "libGLESv2/FramebufferAttachment.h" -@@ -135,6 +136,7 @@ EGLint Renderer11::initialize() - return EGL_NOT_INITIALIZED; - } - -+#if !defined(ANGLE_PLATFORM_WINRT) - mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); - mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); - -@@ -153,6 +155,7 @@ EGLint Renderer11::initialize() - ERR("Could not retrieve D3D11CreateDevice address - aborting!\n"); - return EGL_NOT_INITIALIZED; - } ++ result = displayInformation.As(&mDisplayInformation); ++ } ++ ++ if (SUCCEEDED(result)) ++ { ++#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP ++ ComPtr displayInformation2; ++ result = mDisplayInformation.As(&displayInformation2); ++ ASSERT(SUCCEEDED(result)); ++ ++ result = displayInformation2->get_RawPixelsPerViewPixel(&mScaleFactor); ++ ASSERT(SUCCEEDED(result)); ++#else ++ ABI::Windows::Graphics::Display::ResolutionScale resolutionScale; ++ result = mDisplayInformation->get_ResolutionScale(&resolutionScale); ++ ASSERT(SUCCEEDED(result)); ++ ++ mScaleFactor = DOUBLE(resolutionScale) / 100.0; +#endif - - D3D_FEATURE_LEVEL featureLevels[] = - { -@@ -207,7 +210,7 @@ EGLint Renderer11::initialize() ++ } ++ ++ if (SUCCEEDED(result)) ++ { + // If a swapchain size is specfied, then the automatic resize + // behaviors implemented by the host should be disabled. The swapchain + // will be still be scaled when being rendered to fit the bounds +@@ -60,7 +87,14 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet + } + else + { +- result = GetCoreWindowSizeInPixels(mCoreWindow, &mClientRect); ++ ABI::Windows::Foundation::Rect rect; ++ HRESULT result = mCoreWindow->get_Bounds(&rect); ++ if (SUCCEEDED(result)) ++ { ++ LONG width = std::floor(rect.Width * mScaleFactor + 0.5); ++ LONG height = std::floor(rect.Height * mScaleFactor + 0.5); ++ mClientRect = { 0, 0, width, height }; ++ } } } --#if !ANGLE_SKIP_DXGI_1_2_CHECK -+#if !ANGLE_SKIP_DXGI_1_2_CHECK && !defined(ANGLE_PLATFORM_WINRT) - // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required. - // The easiest way to check is to query for a IDXGIDevice2. - bool requireDXGI1_2 = false; -@@ -237,8 +240,12 @@ EGLint Renderer11::initialize() - } - #endif +@@ -76,12 +110,8 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet -+#if !defined(ANGLE_PLATFORM_WINRT) - IDXGIDevice *dxgiDevice = NULL; -- result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); -+#else -+ IDXGIDevice1 *dxgiDevice = NULL; -+#endif -+ result = mDevice->QueryInterface(IID_PPV_ARGS(&dxgiDevice)); - - if (FAILED(result)) - { -@@ -408,7 +415,7 @@ void Renderer11::sync(bool block) - } - } - --SwapChain *Renderer11::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) -+SwapChain *Renderer11::createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) + bool CoreWindowNativeWindow::registerForSizeChangeEvents() { - return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat); +- ComPtr sizeChangedHandler; +- HRESULT result = Microsoft::WRL::MakeAndInitialize(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this()); +- if (SUCCEEDED(result)) +- { +- result = mCoreWindow->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken); +- } ++ HRESULT result = mCoreWindow->add_SizeChanged(Callback(this, &CoreWindowNativeWindow::onSizeChanged).Get(), ++ &mSizeChangedEventToken); + + if (SUCCEEDED(result)) + { +@@ -126,7 +156,7 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactor + if (SUCCEEDED(result)) + { + +-#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) ++#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) // This block is disabled for Qt applications, as the resize events are expected + // Test if swapchain supports resize. On Windows Phone devices, this will return DXGI_ERROR_UNSUPPORTED. On + // other devices DXGI_ERROR_INVALID_CALL should be returned because the combination of flags passed + // (DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) are invalid flag combinations. +@@ -152,36 +182,19 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactor + return result; } + +-HRESULT GetCoreWindowSizeInPixels(const ComPtr& coreWindow, RECT *windowSize) ++// Basically, this shouldn't be used on Phone ++HRESULT CoreWindowNativeWindow::onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *e) + { +- ABI::Windows::Foundation::Rect bounds; +- HRESULT result = coreWindow->get_Bounds(&bounds); +- if (SUCCEEDED(result)) ++ ABI::Windows::Foundation::Size size; ++ if (SUCCEEDED(e->get_Size(&size))) + { +- *windowSize = { 0, 0, ConvertDipsToPixels(bounds.Width), ConvertDipsToPixels(bounds.Height) }; ++ SIZE windowSizeInPixels = { ++ std::floor(size.Width * mScaleFactor + 0.5), ++ std::floor(size.Height * mScaleFactor + 0.5) ++ }; ++ setNewClientSize(windowSizeInPixels); + } + +- return result; +-} +- +-static float GetLogicalDpi() +-{ +- ComPtr displayProperties; +- float dpi = 96.0f; +- +- if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), displayProperties.GetAddressOf()))) +- { +- if (SUCCEEDED(displayProperties->get_LogicalDpi(&dpi))) +- { +- return dpi; +- } +- } +- return dpi; +-} +- +-long ConvertDipsToPixels(float dips) +-{ +- static const float dipsPerInch = 96.0f; +- return lround((dips * GetLogicalDpi() / dipsPerInch)); ++ return S_OK; + } + } +diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h +index 0c6222d..1c55124 100644 +--- a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h ++++ b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h +@@ -11,67 +11,29 @@ + + #include "common/winrt/InspectableNativeWindow.h" + #include +- +-typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs_t IWindowSizeChangedEventHandler; ++#include + + namespace rx + { +-long ConvertDipsToPixels(float dips); + + class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this + { + public: + ~CoreWindowNativeWindow(); + +- bool initialize(EGLNativeWindowType window, IPropertySet *propertySet); ++ bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet); + bool registerForSizeChangeEvents(); + void unregisterForSizeChangeEvents(); + HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain); + + private: ++ HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *); ++ + ComPtr mCoreWindow; ++ ComPtr mDisplayInformation; + ComPtr> mPropertyMap; + }; + +-[uuid(7F924F66-EBAE-40E5-A10B-B8F35E245190)] +-class CoreWindowSizeChangedHandler : +- public Microsoft::WRL::RuntimeClass, IWindowSizeChangedEventHandler> +-{ +- public: +- CoreWindowSizeChangedHandler() { } +- HRESULT RuntimeClassInitialize(std::shared_ptr host) +- { +- if (!host) +- { +- return E_INVALIDARG; +- } +- +- mHost = host; +- return S_OK; +- } +- +- // IWindowSizeChangedEventHandler +- IFACEMETHOD(Invoke)(ABI::Windows::UI::Core::ICoreWindow *sender, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *sizeChangedEventArgs) +- { +- std::shared_ptr host = mHost.lock(); +- if (host) +- { +- ABI::Windows::Foundation::Size windowSize; +- if (SUCCEEDED(sizeChangedEventArgs->get_Size(&windowSize))) +- { +- SIZE windowSizeInPixels = { ConvertDipsToPixels(windowSize.Width), ConvertDipsToPixels(windowSize.Height) }; +- host->setNewClientSize(windowSizeInPixels); +- } +- } +- +- return S_OK; +- } +- +- private: +- std::weak_ptr mHost; +-}; +- +-HRESULT GetCoreWindowSizeInPixels(const ComPtr& coreWindow, RECT *windowSize); + } + + #endif // COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_ +diff --git a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp +index c062a48..0589f6d 100644 +--- a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp ++++ b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp +@@ -11,9 +11,9 @@ + + namespace rx + { +-NativeWindow::NativeWindow(EGLNativeWindowType window) ++NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display) ++ : mWindow(window), mDisplay(display) + { +- mWindow = window; + } + + bool NativeWindow::initialize() +@@ -40,7 +40,7 @@ bool NativeWindow::initialize() + mImpl = std::make_shared(); + if (mImpl) + { +- return mImpl->initialize(mWindow, propertySet.Get()); ++ return mImpl->initialize(mWindow, mDisplay, propertySet.Get()); + } + } + else if (IsSwapChainPanel(mWindow, &swapChainPanel)) +@@ -48,7 +48,7 @@ bool NativeWindow::initialize() + mImpl = std::make_shared(); + if (mImpl) + { +- return mImpl->initialize(mWindow, propertySet.Get()); ++ return mImpl->initialize(mWindow, mDisplay, propertySet.Get()); + } + } + else +diff --git a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h +index c625348..402941a 100644 +--- a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h ++++ b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h +@@ -32,13 +32,14 @@ class InspectableNativeWindow + mRequiresSwapChainScaling(false), + mClientRectChanged(false), + mClientRect({0,0,0,0}), +- mNewClientRect({0,0,0,0}) ++ mNewClientRect({0,0,0,0}), ++ mScaleFactor(1.0) + { + mSizeChangedEventToken.value = 0; + } + virtual ~InspectableNativeWindow(){} + +- virtual bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) = 0; ++ virtual bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) = 0; + virtual HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) = 0; + virtual bool registerForSizeChangeEvents() = 0; + virtual void unregisterForSizeChangeEvents() = 0; +@@ -49,6 +50,7 @@ class InspectableNativeWindow + if (mClientRectChanged && mSupportsSwapChainResize) + { + mClientRect = mNewClientRect; ++ mClientRectChanged = false; + } + + *rect = mClientRect; +@@ -76,6 +78,7 @@ protected: + RECT mClientRect; + RECT mNewClientRect; + bool mClientRectChanged; ++ DOUBLE mScaleFactor; + + EventRegistrationToken mSizeChangedEventToken; + }; +diff --git a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp +index 4e4fb6d..268dfbd 100644 +--- a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp ++++ b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp +@@ -18,7 +18,7 @@ SwapChainPanelNativeWindow::~SwapChainPanelNativeWindow() + unregisterForSizeChangeEvents(); + } + +-bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet) ++bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) + { + ComPtr props = propertySet; + ComPtr win = window; +diff --git a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h +index e88f554..5bbf274 100644 +--- a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h ++++ b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h +@@ -18,7 +18,7 @@ class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::e + public: + ~SwapChainPanelNativeWindow(); + +- bool initialize(EGLNativeWindowType window, IPropertySet *propertySet); ++ bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet); + bool registerForSizeChangeEvents(); + void unregisterForSizeChangeEvents(); + HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain); +diff --git a/src/3rdparty/angle/src/libEGL/Display.h b/src/3rdparty/angle/src/libEGL/Display.h +index 378323a..b3ffcc8 100644 +--- a/src/3rdparty/angle/src/libEGL/Display.h ++++ b/src/3rdparty/angle/src/libEGL/Display.h +@@ -67,6 +67,7 @@ class Display + + const char *getExtensionString() const; + const char *getVendorString() const; ++ EGLNativeDisplayType getDisplayId() const { return mDisplayId; } + + private: + DISALLOW_COPY_AND_ASSIGN(Display); +diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp +index 3414656..b664a85 100644 +--- a/src/3rdparty/angle/src/libEGL/Surface.cpp ++++ b/src/3rdparty/angle/src/libEGL/Surface.cpp +@@ -31,7 +31,7 @@ namespace egl + { + + Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported) +- : mDisplay(display), mConfig(config), mNativeWindow(window), mPostSubBufferSupported(postSubBufferSupported) ++ : mDisplay(display), mConfig(config), mNativeWindow(window, display->getDisplayId()), mPostSubBufferSupported(postSubBufferSupported) + { + //TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues) + mRenderer = static_cast(mDisplay->getRenderer()); +@@ -47,6 +47,8 @@ Surface::Surface(Display *display, const Config *config, EGLNativeWindowType win + mSwapInterval = -1; + mWidth = width; + mHeight = height; ++ mFixedWidth = mWidth; ++ mFixedHeight = mHeight; + setSwapInterval(1); + mFixedSize = fixedSize; + +@@ -54,7 +56,7 @@ Surface::Surface(Display *display, const Config *config, EGLNativeWindowType win + } + + Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType) +- : mDisplay(display), mNativeWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE) ++ : mDisplay(display), mNativeWindow(NULL, NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE) + { + //TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues) + mRenderer = static_cast(mDisplay->getRenderer()); +@@ -71,6 +73,8 @@ Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGL + setSwapInterval(1); + // This constructor is for offscreen surfaces, which are always fixed-size. + mFixedSize = EGL_TRUE; ++ mFixedWidth = mWidth; ++ mFixedHeight = mHeight; + } + + Surface::~Surface() +@@ -157,10 +161,13 @@ Error Surface::resetSwapChain() + + Error Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight) + { +- ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); + ASSERT(mSwapChain); + +- EGLint status = mSwapChain->resize(std::max(1, backbufferWidth), std::max(1, backbufferHeight)); ++#if !defined(ANGLE_ENABLE_WINDOWS_STORE) ++ backbufferWidth = std::max(1, backbufferWidth); ++ backbufferHeight = std::max(1, backbufferHeight); ++#endif ++ EGLint status = mSwapChain->resize(backbufferWidth, backbufferHeight); + + if (status == EGL_CONTEXT_LOST) + { +@@ -209,14 +216,14 @@ Error Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) + return Error(EGL_SUCCESS); + } + +- if (x + width > mWidth) ++ if (x + width > abs(mWidth)) + { +- width = mWidth - x; ++ width = abs(mWidth) - x; + } + +- if (y + height > mHeight) ++ if (y + height > abs(mHeight)) + { +- height = mHeight - y; ++ height = abs(mHeight) - y; + } + + if (width == 0 || height == 0) +@@ -224,6 +231,9 @@ Error Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) + return Error(EGL_SUCCESS); + } + ++ ASSERT(width > 0); ++ ASSERT(height > 0); ++ + EGLint status = mSwapChain->swapRect(x, y, width, height); + + if (status == EGL_CONTEXT_LOST) +@@ -352,6 +362,13 @@ bool Surface::checkForOutOfDateSwapChain() + sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); + } + ++ if (mFixedSize && (mWidth != mFixedWidth || mHeight != mFixedHeight)) ++ { ++ clientWidth = mFixedWidth; ++ clientHeight = mFixedHeight; ++ sizeDirty = true; ++ } ++ + bool wasDirty = (mSwapIntervalDirty || sizeDirty); + + if (mSwapIntervalDirty) +@@ -378,7 +395,7 @@ bool Surface::checkForOutOfDateSwapChain() + + Error Surface::swap() + { +- return swapRect(0, 0, mWidth, mHeight); ++ return swapRect(0, 0, abs(mWidth), abs(mHeight)); + } + + Error Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) +@@ -471,6 +488,16 @@ EGLint Surface::isFixedSize() const + return mFixedSize; + } + ++void Surface::setFixedWidth(EGLint width) ++{ ++ mFixedWidth = width; ++} ++ ++void Surface::setFixedHeight(EGLint height) ++{ ++ mFixedHeight = height; ++} ++ + EGLenum Surface::getFormat() const + { + return mConfig->mRenderTargetFormat; +diff --git a/src/3rdparty/angle/src/libEGL/Surface.h b/src/3rdparty/angle/src/libEGL/Surface.h +index 662fe21..46382d0 100644 +--- a/src/3rdparty/angle/src/libEGL/Surface.h ++++ b/src/3rdparty/angle/src/libEGL/Surface.h +@@ -70,6 +70,8 @@ class Surface + virtual gl::Texture2D *getBoundTexture() const; + + EGLint isFixedSize() const; ++ void setFixedWidth(EGLint width); ++ void setFixedHeight(EGLint height); + + private: + DISALLOW_COPY_AND_ASSIGN(Surface); +@@ -91,6 +93,8 @@ class Surface + const egl::Config *mConfig; // EGL config surface was created with + EGLint mHeight; // Height of surface + EGLint mWidth; // Width of surface ++ EGLint mFixedHeight; // Pending height of the surface ++ EGLint mFixedWidth; // Pending width of the surface + // EGLint horizontalResolution; // Horizontal dot pitch + // EGLint verticalResolution; // Vertical dot pitch + // EGLBoolean largestPBuffer; // If true, create largest pbuffer possible +diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp +index 6110698..dc20d85 100644 +--- a/src/3rdparty/angle/src/libEGL/libEGL.cpp ++++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp +@@ -706,6 +706,26 @@ EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint + return EGL_FALSE; + } + ++ switch (attribute) ++ { ++ case EGL_WIDTH: ++ if (!eglSurface->isFixedSize() || !value) { ++ recordError(egl::Error(EGL_BAD_PARAMETER)); ++ return EGL_FALSE; ++ } ++ eglSurface->setFixedWidth(value); ++ return EGL_TRUE; ++ case EGL_HEIGHT: ++ if (!eglSurface->isFixedSize() || !value) { ++ recordError(egl::Error(EGL_BAD_PARAMETER)); ++ return EGL_FALSE; ++ } ++ eglSurface->setFixedHeight(value); ++ return EGL_TRUE; ++ default: ++ break; ++ } ++ + UNIMPLEMENTED(); // FIXME + + recordError(egl::Error(EGL_SUCCESS)); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h -index d309f14..b86f5e5 100644 +index 1655f1d..c789cae 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h -@@ -57,7 +57,7 @@ class Renderer11 : public Renderer - - virtual void sync(bool block); - -- virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); -+ virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); - - virtual gl::Error generateSwizzle(gl::Texture *texture); - virtual gl::Error setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler); -@@ -222,7 +222,7 @@ class Renderer11 : public Renderer +@@ -231,7 +231,7 @@ class Renderer11 : public RendererD3D HMODULE mD3d11Module; HMODULE mDxgiModule; - HDC mDc; + EGLNativeDisplayType mDc; - EGLint mRequestedDisplay; + std::vector mAvailableFeatureLevels; + D3D_DRIVER_TYPE mDriverType; - HLSLCompiler mCompiler; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp -index 50dae4e..787c511 100644 +index 834b7bd..52c8a81 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp -@@ -6,6 +6,7 @@ - - // SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain. - -+#include "common/platform.h" - #include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h" - #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" - #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -@@ -18,7 +19,7 @@ - namespace rx - { - --SwapChain11::SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle, -+SwapChain11::SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle, - GLenum backBufferFormat, GLenum depthBufferFormat) - : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat) - { -@@ -38,6 +39,8 @@ SwapChain11::SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle, +@@ -42,6 +42,8 @@ SwapChain11::SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE mPassThroughPS = NULL; mWidth = -1; mHeight = -1; -+ mViewportWidth = -1; -+ mViewportHeight = -1; ++ mRotateL = false; ++ mRotateR = false; mSwapInterval = 0; mAppCreatedShareHandle = mShareHandle != NULL; mPassThroughResourcesInit = false; -@@ -92,6 +95,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei - ASSERT(backbufferHeight >= 1); +@@ -92,10 +94,11 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei + ASSERT(device != NULL); + + // D3D11 does not allow zero size textures +- ASSERT(backbufferWidth >= 1); +- ASSERT(backbufferHeight >= 1); ++ ASSERT(backbufferWidth != 0); ++ ASSERT(backbufferHeight != 0); // Preserve the render target content -+#if !defined(ANGLE_PLATFORM_WINRT) ++#if !defined(ANGLE_ENABLE_WINDOWS_STORE) ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture; if (previousOffscreenTexture) { -@@ -99,6 +103,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei +@@ -103,6 +106,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei } const int previousWidth = mWidth; const int previousHeight = mHeight; @@ -1128,112 +675,107 @@ index 50dae4e..787c511 100644 releaseOffscreenTexture(); -@@ -281,7 +286,12 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei +@@ -136,8 +140,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei + D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; + mOffscreenTexture->GetDesc(&offscreenTextureDesc); +- if (offscreenTextureDesc.Width != (UINT)backbufferWidth || +- offscreenTextureDesc.Height != (UINT)backbufferHeight || ++ if (offscreenTextureDesc.Width != UINT(abs(backbufferWidth)) || ++ offscreenTextureDesc.Height != UINT(abs(backbufferHeight)) || + offscreenTextureDesc.Format != backbufferFormatInfo.texFormat || + offscreenTextureDesc.MipLevels != 1 || + offscreenTextureDesc.ArraySize != 1) +@@ -152,8 +156,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei + const bool useSharedResource = !mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport(); + + D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; +- offscreenTextureDesc.Width = backbufferWidth; +- offscreenTextureDesc.Height = backbufferHeight; ++ offscreenTextureDesc.Width = abs(backbufferWidth); ++ offscreenTextureDesc.Height = abs(backbufferHeight); + offscreenTextureDesc.Format = backbufferFormatInfo.texFormat; + offscreenTextureDesc.MipLevels = 1; + offscreenTextureDesc.ArraySize = 1; +@@ -233,8 +237,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei + if (mDepthBufferFormat != GL_NONE) + { + D3D11_TEXTURE2D_DESC depthStencilTextureDesc; +- depthStencilTextureDesc.Width = backbufferWidth; +- depthStencilTextureDesc.Height = backbufferHeight; ++ depthStencilTextureDesc.Width = abs(backbufferWidth); ++ depthStencilTextureDesc.Height = abs(backbufferHeight); + depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat; + depthStencilTextureDesc.MipLevels = 1; + depthStencilTextureDesc.ArraySize = 1; +@@ -286,6 +290,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei mWidth = backbufferWidth; mHeight = backbufferHeight; -+#if !defined(ANGLE_PLATFORM_WINRT) || WINAPI_FAMILY==WINAPI_FAMILY_PC_APP -+ mViewportWidth = backbufferWidth; -+ mViewportHeight = backbufferHeight; -+#endif -+#if !defined(ANGLE_PLATFORM_WINRT) ++#if !defined(ANGLE_ENABLE_WINDOWS_STORE) if (previousOffscreenTexture != NULL) { D3D11_BOX sourceBox = {0}; -@@ -300,9 +310,10 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei - - if (mSwapChain) - { -- swapRect(0, 0, mWidth, mHeight); -+ swapRect(0, 0, mWidth, mHeight, SWAP_NORMAL); +@@ -307,6 +312,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei + swapRect(0, 0, mWidth, mHeight); } } +#endif return EGL_SUCCESS; } -@@ -329,8 +340,15 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) +@@ -320,8 +326,16 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) + return EGL_BAD_ACCESS; + } + ++ // Windows Phone works around the rotation limitation by using negative values for the swap chain size ++#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) ++ mRotateL = backbufferWidth < 0; // Landscape/InvertedLandscape ++ mRotateR = backbufferHeight < 0; // InvertedPortrait/InvertedLandscape ++ backbufferWidth = abs(backbufferWidth); ++ backbufferHeight = abs(backbufferHeight); ++#endif ++ + // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains +- if (backbufferWidth < 1 || backbufferHeight < 1) ++ if (backbufferWidth == 0 || backbufferHeight == 0) + { + return EGL_SUCCESS; + } +@@ -329,6 +343,7 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) + // Can only call resize if we have already created our swap buffer and resources + ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView); + ++#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) // The swap chain is not directly resized on Windows Phone + SafeRelease(mBackBufferTexture); SafeRelease(mBackBufferRTView); - // Resize swap chain -+ HRESULT result; -+#if !defined(ANGLE_PLATFORM_WINRT) || WINAPI_FAMILY==WINAPI_FAMILY_PC_APP // Windows phone swap chain is never resized, only the texture is -+#if !defined(ANGLE_PLATFORM_WINRT) -+ const int bufferCount = 1; -+#else -+ const int bufferCount = 2; -+#endif - const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat); -- HRESULT result = mSwapChain->ResizeBuffers(1, backbufferWidth, backbufferHeight, backbufferFormatInfo.texFormat, 0); -+ result = mSwapChain->ResizeBuffers(bufferCount, backbufferWidth, backbufferHeight, backbufferFormatInfo.texFormat, 0); - - if (FAILED(result)) +@@ -366,6 +381,7 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) { -@@ -346,6 +364,7 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) - return EGL_BAD_ALLOC; - } + d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); } +#endif - result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); - ASSERT(SUCCEEDED(result)); -@@ -399,6 +418,7 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap - - IDXGIFactory *factory = mRenderer->getDxgiFactory(); - -+#if !defined(ANGLE_PLATFORM_WINRT) - DXGI_SWAP_CHAIN_DESC swapChainDesc = {0}; - swapChainDesc.BufferDesc.Width = backbufferWidth; - swapChainDesc.BufferDesc.Height = backbufferHeight; -@@ -417,7 +437,37 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap - swapChainDesc.Flags = 0; - - HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain); -+#else -+ IDXGIFactory2 *factory2; -+ HRESULT result = factory->QueryInterface(IID_PPV_ARGS(&factory2)); -+ ASSERT(SUCCEEDED(result)); -+ -+ DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; -+ swapChainDesc.Width = 0; -+ swapChainDesc.Height = 0; -+ swapChainDesc.Format = backbufferFormatInfo.texFormat; -+ swapChainDesc.SampleDesc.Count = 1; -+ swapChainDesc.SampleDesc.Quality = 0; -+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; -+ swapChainDesc.Stereo = FALSE; -+ swapChainDesc.Flags = 0; -+#if WINAPI_FAMILY==WINAPI_FAMILY_PC_APP -+ swapChainDesc.Scaling = DXGI_SCALING_NONE; -+ swapChainDesc.BufferCount = 2; -+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; -+#elif WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP -+ swapChainDesc.BufferCount = 1; -+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; -+#endif - -+ IDXGISwapChain1 *swapChain; -+ result = factory2->CreateSwapChainForCoreWindow(device, mWindow, &swapChainDesc, NULL, &swapChain); -+ mSwapChain = swapChain; -+ HRESULT hr = swapChain->GetDesc1(&swapChainDesc); -+ ASSERT(SUCCEEDED(hr)); -+ mViewportWidth = swapChainDesc.Width; -+ mViewportHeight = swapChainDesc.Height; -+#endif - if (FAILED(result)) - { - ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); -@@ -513,7 +563,7 @@ void SwapChain11::initPassThroughResources() + return resetOffscreenTexture(backbufferWidth, backbufferHeight); } +@@ -512,16 +528,6 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - // parameters should be validated/clamped by caller --EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) -+EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint flags) - { - if (!mSwapChain) - { -@@ -544,10 +594,13 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) +- // Set vertices +- D3D11_MAPPED_SUBRESOURCE mappedResource; +- HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); +- if (FAILED(result)) +- { +- return EGL_BAD_ACCESS; +- } +- +- d3d11::PositionTexCoordVertex *vertices = static_cast(mappedResource.pData); +- + // Create a quad in homogeneous coordinates + float x1 = (x / float(mWidth)) * 2.0f - 1.0f; + float y1 = (y / float(mHeight)) * 2.0f - 1.0f; +@@ -533,10 +539,23 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) float u2 = (x + width) / float(mWidth); float v2 = (y + height) / float(mHeight); @@ -1241,8 +783,18 @@ index 50dae4e..787c511 100644 - d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2); - d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1); - d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2); -+ const int rotateL = flags & SWAP_ROTATE_90; -+ const int rotateR = flags & SWAP_ROTATE_270; ++ const bool rotateL = mRotateL; ++ const bool rotateR = mRotateR; ++ ++ // Set vertices ++ D3D11_MAPPED_SUBRESOURCE mappedResource; ++ HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); ++ if (FAILED(result)) ++ { ++ return EGL_BAD_ACCESS; ++ } ++ ++ d3d11::PositionTexCoordVertex *vertices = static_cast(mappedResource.pData); + + d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, rotateL ? u2 : u1, rotateR ? v2 : v1); + d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, rotateR ? u2 : u1, rotateL ? v1 : v2); @@ -1251,72 +803,35 @@ index 50dae4e..787c511 100644 deviceContext->Unmap(mQuadVB, 0); -@@ -577,8 +630,8 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) +@@ -564,10 +583,11 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) + + // Set the viewport D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; +- viewport.TopLeftX = 0; +- viewport.TopLeftY = 0; - viewport.Width = mWidth; - viewport.Height = mHeight; -+ viewport.Width = mViewportWidth; -+ viewport.Height = mViewportHeight; ++ viewport.TopLeftX = 0.0f; ++ viewport.TopLeftY = 0.0f; ++ const bool invertViewport = (mRotateL || mRotateR) && !(mRotateL && mRotateR); ++ viewport.Width = FLOAT(invertViewport ? mHeight : mWidth); ++ viewport.Height = FLOAT(invertViewport ? mWidth : mHeight); viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; deviceContext->RSSetViewports(1, &viewport); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h -index fb0afd7..b30b785 100644 +index 22401d8..77509ed 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h -@@ -19,13 +19,13 @@ class Renderer11; - class SwapChain11 : public SwapChain - { - public: -- SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle, -+ SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle, - GLenum backBufferFormat, GLenum depthBufferFormat); - virtual ~SwapChain11(); - - EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); - virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval); -- virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height); -+ virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint flags); - virtual void recreate(); - - virtual ID3D11Texture2D *getOffscreenTexture(); @@ -52,6 +52,8 @@ class SwapChain11 : public SwapChain Renderer11 *mRenderer; EGLint mHeight; EGLint mWidth; -+ EGLint mViewportWidth; -+ EGLint mViewportHeight; ++ bool mRotateL; ++ bool mRotateR; bool mAppCreatedShareHandle; unsigned int mSwapInterval; bool mPassThroughResourcesInit; -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp -index f702b79..0aeaabb 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp -@@ -238,7 +238,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI - } - - // parameters should be validated/clamped by caller --EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) -+EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint) - { - if (!mSwapChain) - { -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h -index 16a62bd..4d756f8 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h -@@ -25,7 +25,7 @@ class SwapChain9 : public SwapChain - - EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); - virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval); -- virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height); -+ virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint); - virtual void recreate(); - - virtual IDirect3DSurface9 *getRenderTarget(); -- -1.9.0.msysgit.0 +1.9.4.msysgit.1 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 index 297d5adc841..dd2768cf3ed 100644 --- 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 @@ -1,6 +1,6 @@ -From 0e8aa60332e17f284804dc1b89a9db5795a92ecb Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Wed, 17 Sep 2014 21:17:39 +0300 +From 829bf86c57357d3c8ec598b92fcfdb1849e84075 Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Tue, 11 Nov 2014 17:11:54 +0200 Subject: [PATCH 10/16] ANGLE: Enable D3D11 for feature level 9 cards Enable use of ANGLE on lower-end hardware, such as Surface RT and @@ -8,23 +8,32 @@ Windows Phone 8. Change-Id: Ice536802e4eedc1d264abd0dd65960638fce59e4 --- - src/3rdparty/angle/src/libGLESv2/angletypes.cpp | 4 +- - .../src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp | 73 +++---- + src/3rdparty/angle/src/libGLESv2/angletypes.cpp | 6 +- + .../src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp | 69 ++++--- .../src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp | 4 +- - .../src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp | 8 +- - .../renderer/d3d/d3d11/PixelTransfer11.cpp | 7 +- - .../libGLESv2/renderer/d3d/d3d11/Renderer11.cpp | 209 +++++++++++++-------- + .../src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp | 7 +- + .../renderer/d3d/d3d11/PixelTransfer11.cpp | 9 +- + .../libGLESv2/renderer/d3d/d3d11/Renderer11.cpp | 226 +++++++++++++-------- .../src/libGLESv2/renderer/d3d/d3d11/Renderer11.h | 1 + - .../renderer/d3d/d3d11/TextureStorage11.cpp | 2 +- + .../renderer/d3d/d3d11/TextureStorage11.cpp | 4 +- .../libGLESv2/renderer/d3d/d3d11/formatutils11.cpp | 4 +- .../renderer/d3d/d3d11/renderer11_utils.cpp | 2 +- - 10 files changed, 190 insertions(+), 124 deletions(-) + 10 files changed, 208 insertions(+), 124 deletions(-) diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp b/src/3rdparty/angle/src/libGLESv2/angletypes.cpp -index 06618d5..bb6425d 100644 +index 6fd02e0..5a0cfc5 100644 --- a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp +++ b/src/3rdparty/angle/src/libGLESv2/angletypes.cpp -@@ -22,8 +22,8 @@ SamplerState::SamplerState() +@@ -12,6 +12,8 @@ + #include "libGLESv2/State.h" + #include "libGLESv2/VertexArray.h" + ++#include ++ + namespace gl + { + +@@ -24,8 +26,8 @@ SamplerState::SamplerState() maxAnisotropy(1.0f), baseLevel(0), maxLevel(1000), @@ -36,28 +45,28 @@ index 06618d5..bb6425d 100644 compareFunc(GL_LEQUAL), swizzleRed(GL_RED), diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp -index 72820a4..d43e65e 100644 +index 91e7552..06aea9b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp -@@ -209,7 +209,7 @@ Blit11::Blit11(rx::Renderer11 *renderer) +@@ -209,7 +209,7 @@ Blit11::Blit11(Renderer11 *renderer) pointSamplerDesc.BorderColor[2] = 0.0f; pointSamplerDesc.BorderColor[3] = 0.0f; pointSamplerDesc.MinLOD = 0.0f; - pointSamplerDesc.MaxLOD = 0.0f; -+ pointSamplerDesc.MaxLOD = mRenderer->isLevel9() ? FLT_MAX : 0.0f; ++ pointSamplerDesc.MaxLOD = mRenderer->isLevel9() ? D3D11_FLOAT32_MAX : 0.0f; result = device->CreateSamplerState(&pointSamplerDesc, &mPointSampler); ASSERT(SUCCEEDED(result)); -@@ -228,7 +228,7 @@ Blit11::Blit11(rx::Renderer11 *renderer) +@@ -228,7 +228,7 @@ Blit11::Blit11(Renderer11 *renderer) linearSamplerDesc.BorderColor[2] = 0.0f; linearSamplerDesc.BorderColor[3] = 0.0f; linearSamplerDesc.MinLOD = 0.0f; - linearSamplerDesc.MaxLOD = 0.0f; -+ linearSamplerDesc.MaxLOD = mRenderer->isLevel9() ? FLT_MAX : 0.0f; ++ linearSamplerDesc.MaxLOD = mRenderer->isLevel9() ? D3D11_FLOAT32_MAX : 0.0f; result = device->CreateSamplerState(&linearSamplerDesc, &mLinearSampler); ASSERT(SUCCEEDED(result)); -@@ -290,28 +290,31 @@ Blit11::Blit11(rx::Renderer11 *renderer) +@@ -290,28 +290,31 @@ Blit11::Blit11(Renderer11 *renderer) ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mQuad2DVS, "Blit11 2D vertex shader"); @@ -76,14 +85,14 @@ index 72820a4..d43e65e 100644 - result = device->CreateInputLayout(quad3DLayout, ArraySize(quad3DLayout), g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), &mQuad3DIL); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mQuad3DIL, "Blit11 3D input layout"); +- +- result = device->CreateVertexShader(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), NULL, &mQuad3DVS); +- ASSERT(SUCCEEDED(result)); +- d3d11::SetDebugName(mQuad3DVS, "Blit11 3D vertex shader"); + result = device->CreatePixelShader(g_PS_PassthroughDepth2D, ArraySize(g_PS_PassthroughDepth2D), NULL, &mDepthPS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mDepthPS, "Blit11 2D depth pixel shader"); -- result = device->CreateVertexShader(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), NULL, &mQuad3DVS); -- ASSERT(SUCCEEDED(result)); -- d3d11::SetDebugName(mQuad3DVS, "Blit11 3D vertex shader"); -- - result = device->CreateGeometryShader(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), NULL, &mQuad3DGS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mQuad3DGS, "Renderer11 copy 3D texture geometry shader"); @@ -109,7 +118,7 @@ index 72820a4..d43e65e 100644 buildShaderMap(); -@@ -972,40 +975,44 @@ void Blit11::buildShaderMap() +@@ -970,22 +973,27 @@ void Blit11::buildShaderMap() ID3D11Device *device = mRenderer->getDevice(); add2DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D RGBA pixel shader" )); @@ -145,19 +154,7 @@ index 72820a4..d43e65e 100644 add3DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D RGBA pixel shader" )); add3DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DUI, "Blit11 3D UI RGBA pixel shader" )); add3DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI, "Blit11 3D I RGBA pixel shader" )); - add3DBlitShaderToMap(GL_BGRA_EXT, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D BGRA pixel shader" )); - add3DBlitShaderToMap(GL_RGB, false, d3d11::CompilePS(device, g_PS_PassthroughRGB3D, "Blit11 3D RGB pixel shader" )); -+ add3DBlitShaderToMap(GL_RG, false, d3d11::CompilePS(device, g_PS_PassthroughRG3D, "Blit11 3D RG pixel shader" )); - add3DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB3DUI, "Blit11 3D RGB UI pixel shader" )); - add3DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB3DI, "Blit11 3D RGB I pixel shader" )); -- add3DBlitShaderToMap(GL_RG, false, d3d11::CompilePS(device, g_PS_PassthroughRG3D, "Blit11 3D RG pixel shader" )); -+ add3DBlitShaderToMap(GL_RED, false, d3d11::CompilePS(device, g_PS_PassthroughR3D, "Blit11 3D R pixel shader" )); - add3DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG3DUI, "Blit11 3D RG UI pixel shader" )); - add3DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG3DI, "Blit11 3D RG I pixel shader" )); -- add3DBlitShaderToMap(GL_RED, false, d3d11::CompilePS(device, g_PS_PassthroughR3D, "Blit11 3D R pixel shader" )); - add3DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR3DUI, "Blit11 3D R UI pixel shader" )); - add3DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR3DI, "Blit11 3D R I pixel shader" )); - add3DBlitShaderToMap(GL_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D alpha pixel shader" )); +@@ -1003,7 +1011,6 @@ void Blit11::buildShaderMap() add3DBlitShaderToMap(GL_LUMINANCE, false, d3d11::CompilePS(device, g_PS_PassthroughLum3D, "Blit11 3D luminance pixel shader" )); add3DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha3D, "Blit11 3D luminance alpha pixel shader")); @@ -166,22 +163,22 @@ index 72820a4..d43e65e 100644 addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleI2D, "Blit11 2D I swizzle pixel shader" )); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp -index 43ce5ba..ecd4d46 100644 +index 2d5fa3c..5aab379 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp -@@ -747,7 +747,9 @@ void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Ren +@@ -753,7 +753,9 @@ void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Ren case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK: bufferDesc->Usage = D3D11_USAGE_DEFAULT; - bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_STREAM_OUTPUT; + bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER; -+ if (!static_cast(renderer)->isLevel9()) ++ if (!renderer->isLevel9()) + bufferDesc->BindFlags |= D3D11_BIND_STREAM_OUTPUT; bufferDesc->CPUAccessFlags = 0; break; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp -index 5caa427..765d34f 100644 +index 4630762..7185a05 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp @@ -104,7 +104,7 @@ Clear11::Clear11(Renderer11 *renderer) @@ -189,11 +186,11 @@ index 5caa427..765d34f 100644 rsDesc.DepthBiasClamp = 0.0f; rsDesc.SlopeScaledDepthBias = 0.0f; - rsDesc.DepthClipEnable = FALSE; -+ rsDesc.DepthClipEnable = mRenderer->isLevel9(); ++ rsDesc.DepthClipEnable = renderer->isLevel9(); rsDesc.ScissorEnable = FALSE; rsDesc.MultisampleEnable = FALSE; rsDesc.AntialiasedLineEnable = FALSE; -@@ -114,6 +114,12 @@ Clear11::Clear11(Renderer11 *renderer) +@@ -114,6 +114,11 @@ Clear11::Clear11(Renderer11 *renderer) d3d11::SetDebugName(mRasterizerState, "Clear11 masked clear rasterizer state"); mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat); @@ -202,53 +199,63 @@ index 5caa427..765d34f 100644 + memset(&mIntClearShader, 0, sizeof(ClearShader)); + return; + } -+ mUintClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_UINT, g_VS_ClearUint, g_PS_ClearUint ); mIntClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_SINT, g_VS_ClearSint, g_PS_ClearSint ); } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp -index edaafec..a4e84f9 100644 +index a4072d8..6a3d347 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp -@@ -88,13 +88,16 @@ PixelTransfer11::PixelTransfer11(Renderer11 *renderer) - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mParamsConstantBuffer, "PixelTransfer11 constant buffer"); +@@ -133,10 +133,13 @@ gl::Error PixelTransfer11::loadResources() + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture vertex shader."); + } -+ StructZero(&mParamsData); -+ - // init shaders -+ if (mRenderer->isLevel9()) -+ return; -+ - mBufferToTextureVS = d3d11::CompileVS(device, g_VS_BufferToTexture, "BufferToTexture VS"); - mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS"); +- mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS"); +- if (!mBufferToTextureGS) ++ if (!mRenderer->isLevel9()) + { +- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture geometry shader."); ++ mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS"); ++ if (!mBufferToTextureGS) ++ { ++ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture geometry shader."); ++ } + } - buildShaderMap(); -- -- StructZero(&mParamsData); - } - - PixelTransfer11::~PixelTransfer11() + gl::Error error = buildShaderMap(); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -index 0bb7489..b4b26a8 100644 +index ffc6cc9..f6ba930 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -@@ -162,6 +162,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 - }; +@@ -153,6 +153,24 @@ Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, const eg + } + } - D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_HARDWARE; -@@ -1112,6 +1117,84 @@ gl::Error Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, cons ++#if !defined(ANGLE_ENABLE_D3D9) ++ if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9) ++ { ++ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3) ++ { ++ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); ++ } ++ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 2) ++ { ++ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2); ++ } ++ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) ++ { ++ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1); ++ } ++ } ++#endif ++ + mDriverType = (attributes.get(EGL_PLATFORM_ANGLE_USE_WARP_ANGLE, EGL_FALSE) == EGL_TRUE) ? D3D_DRIVER_TYPE_WARP + : D3D_DRIVER_TYPE_HARDWARE; + } +@@ -1170,6 +1188,83 @@ gl::Error Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, cons + return gl::Error(GL_NO_ERROR); } } - +template +static void fillLineLoopIndices(GLenum type, GLsizei count, const GLvoid *indices, T *data) +{ @@ -326,12 +333,11 @@ index 0bb7489..b4b26a8 100644 + default: UNREACHABLE(); + } +} -+ + gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) { - // Get the raw indices for an indexed draw -@@ -1123,10 +1206,13 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind - indices = static_cast(storage->getData()) + offset; +@@ -1189,10 +1284,13 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind + indices = bufferData + offset; } + // TODO: some level 9 hardware supports 32-bit indices; test and store support instead @@ -345,7 +351,7 @@ index 0bb7489..b4b26a8 100644 if (error.isError()) { SafeDelete(mLineLoopIB); -@@ -1137,7 +1223,8 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind +@@ -1203,7 +1301,8 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind // Checked by Renderer11::applyPrimitiveType ASSERT(count >= 0); @@ -355,7 +361,7 @@ index 0bb7489..b4b26a8 100644 { return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); } -@@ -1157,42 +1244,12 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind +@@ -1223,42 +1322,12 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind return error; } @@ -402,8 +408,8 @@ index 0bb7489..b4b26a8 100644 error = mLineLoopIB->unmapBuffer(); if (error.isError()) { -@@ -1227,10 +1284,12 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * - indices = static_cast(storage->getData()) + offset; +@@ -1300,10 +1369,12 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * + indices = bufferData + offset; } + const int indexType = isLevel9() ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; @@ -416,7 +422,7 @@ index 0bb7489..b4b26a8 100644 if (error.isError()) { SafeDelete(mTriangleFanIB); -@@ -1243,13 +1302,14 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * +@@ -1316,13 +1387,14 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * const unsigned int numTris = count - 2; @@ -434,7 +440,7 @@ index 0bb7489..b4b26a8 100644 if (error.isError()) { return error; -@@ -1263,45 +1323,12 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * +@@ -1336,45 +1408,12 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * return error; } @@ -485,7 +491,7 @@ index 0bb7489..b4b26a8 100644 error = mTriangleFanIB->unmapBuffer(); if (error.isError()) -@@ -1549,7 +1576,7 @@ gl::Error Renderer11::applyUniforms(const gl::ProgramBinary &programBinary) +@@ -1634,7 +1673,7 @@ gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vecto } // needed for the point sprite geometry shader @@ -494,19 +500,7 @@ index 0bb7489..b4b26a8 100644 { mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); mCurrentGeometryConstantBuffer = mDriverConstantBufferPS; -@@ -1711,6 +1738,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; -@@ -1862,7 +1894,10 @@ int Renderer11::getMajorShaderModel() const +@@ -1938,7 +1977,10 @@ 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 @@ -518,7 +512,7 @@ index 0bb7489..b4b26a8 100644 default: UNREACHABLE(); return 0; } } -@@ -1873,7 +1908,10 @@ int Renderer11::getMinorShaderModel() const +@@ -1949,7 +1991,10 @@ 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 @@ -530,49 +524,81 @@ index 0bb7489..b4b26a8 100644 default: UNREACHABLE(); return 0; } } -@@ -2387,6 +2425,15 @@ ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const ch - case D3D_FEATURE_LEVEL_10_0: - profileVersion = "4_0"; +@@ -2455,6 +2500,7 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::strin + + unsigned int profileMajorVersion = 0; + unsigned int profileMinorVersion = 0; ++ const char *profileSuffix = NULL; + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: +@@ -2469,12 +2515,30 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::strin + profileMajorVersion = 4; + profileMinorVersion = 0; break; + case D3D_FEATURE_LEVEL_9_3: -+ profileVersion = "4_0_level_9_3"; ++ profileMajorVersion = 4; ++ profileMinorVersion = 0; ++ profileSuffix = "_level_9_3"; + break; + case D3D_FEATURE_LEVEL_9_2: -+ profileVersion = "4_0_level_9_2"; ++ profileMajorVersion = 4; ++ profileMinorVersion = 0; ++ profileSuffix = "_level_9_2"; + break; + case D3D_FEATURE_LEVEL_9_1: -+ profileVersion = "4_0_level_9_1"; ++ profileMajorVersion = 4; ++ profileMinorVersion = 0; ++ profileSuffix = "_level_9_1"; + break; ++ break; default: UNREACHABLE(); - return NULL; + return gl::Error(GL_INVALID_OPERATION); + } + + std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion); ++ if (profileSuffix) ++ profile += profileSuffix; + + UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2; + diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h -index b86f5e5..2a53fa1 100644 +index c789cae..d44bd2f 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h -@@ -184,6 +184,7 @@ class Renderer11 : public Renderer +@@ -188,6 +188,7 @@ class Renderer11 : public RendererD3D ID3D11Device *getDevice() { return mDevice; } ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; }; - IDXGIFactory *getDxgiFactory() { return mDxgiFactory; }; + DXGIFactory *getDxgiFactory() { return mDxgiFactory; }; + bool isLevel9() { return mFeatureLevel <= D3D_FEATURE_LEVEL_9_3; } Blit11 *getBlitter() { return mBlit; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp -index 3f0cd5b..91e7147 100644 +index 4287918..74af27e 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp -@@ -472,7 +472,7 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalform +@@ -744,7 +744,7 @@ gl::Error TextureStorage11_2D::getResource(ID3D11Resource **outResource) D3D11_TEXTURE2D_DESC desc; - desc.Width = width; // Compressed texture size constraints? - desc.Height = height; -- desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0); -+ desc.MipLevels = desc.MipLevels = mRenderer->isLevel9() ? 1 : ((levels > 0) ? (mTopLevel + levels) : 0); + desc.Width = mTextureWidth; // Compressed texture size constraints? + desc.Height = mTextureHeight; +- desc.MipLevels = mMipLevels; ++ desc.MipLevels = mRenderer->isLevel9() ? 1 : mMipLevels; desc.ArraySize = 1; desc.Format = mTextureFormat; desc.SampleDesc.Count = 1; +@@ -863,7 +863,7 @@ gl::Error TextureStorage11_2D::createSRV(int baseLevel, int mipLevels, DXGI_FORM + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel; +- srvDesc.Texture2D.MipLevels = mipLevels; ++ srvDesc.Texture2D.MipLevels = mRenderer->isLevel9() ? -1 : mipLevels; + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp -index 1ea916d..c078287 100644 +index 1ea916d..90a879e 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp @@ -557,7 +557,7 @@ D3D11LoadFunctionMap BuildD3D11LoadFunctionMap() @@ -589,15 +615,15 @@ index 1ea916d..c078287 100644 // From GL_EXT_texture_storage // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | - InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_UNKNOWN ); -+ InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ); ++ InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ); InsertD3D11FormatInfo(&map, GL_LUMINANCE8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ); InsertD3D11FormatInfo(&map, GL_ALPHA32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ); InsertD3D11FormatInfo(&map, GL_LUMINANCE32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp -index b1867fb..06a22eb 100644 +index 9ffc32e..cbfe557 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp -@@ -283,7 +283,7 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) +@@ -284,7 +284,7 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx case D3D_FEATURE_LEVEL_9_3: case D3D_FEATURE_LEVEL_9_2: @@ -607,5 +633,5 @@ index b1867fb..06a22eb 100644 default: UNREACHABLE(); return false; } -- -1.9.0.msysgit.0 +1.9.4.msysgit.1 diff --git a/src/angle/patches/0012-ANGLE-fix-semantic-index-lookup.patch b/src/angle/patches/0012-ANGLE-fix-semantic-index-lookup.patch index 35d525fb2d6..afc9f256a1e 100644 --- a/src/angle/patches/0012-ANGLE-fix-semantic-index-lookup.patch +++ b/src/angle/patches/0012-ANGLE-fix-semantic-index-lookup.patch @@ -1,6 +1,6 @@ -From 9e167b788cc9de1d963fd3fc2145848a6ccc0fa8 Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Mon, 22 Sep 2014 23:13:16 +0300 +From bbfd3cfcf6e1195d86368b61ce39504ce6acda50 Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Wed, 12 Nov 2014 17:09:23 +0200 Subject: [PATCH 12/16] ANGLE: fix semantic index lookup The sorted semantic index table was returning a direct mapping to the @@ -14,10 +14,10 @@ Change-Id: I75d05ed707f56c45210e3dcbc277f894e3dc5a48 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 1085346..3f6d9e0 100644 +index 0619023..6d64b38 100644 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp +++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp -@@ -2788,7 +2788,7 @@ void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MA +@@ -1216,7 +1216,7 @@ void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MA for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) { int oldIndex = mAttributesByLayout[i]; @@ -27,10 +27,10 @@ index 1085346..3f6d9e0 100644 } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp -index b006c04..d835e4f 100644 +index e41f238..ff90a6a 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp -@@ -112,10 +112,10 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl +@@ -113,10 +113,10 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl // 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; @@ -44,5 +44,5 @@ index b006c04..d835e4f 100644 ilKey.elements[ilKey.elementCount].desc.InputSlot = i; ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0; -- -1.9.0.msysgit.0 +1.9.4.msysgit.1 diff --git a/src/angle/patches/0013-ANGLE-Add-support-for-querying-platform-device.patch b/src/angle/patches/0013-ANGLE-Add-support-for-querying-platform-device.patch index 00e32186f00..b43dcc368b0 100644 --- a/src/angle/patches/0013-ANGLE-Add-support-for-querying-platform-device.patch +++ b/src/angle/patches/0013-ANGLE-Add-support-for-querying-platform-device.patch @@ -1,6 +1,6 @@ -From 3499339ab768017458d3b5295af3742a0f6015db Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Mon, 22 Sep 2014 23:15:26 +0300 +From 5ef9348de2624c21be1c9fddd265fec5a0851d25 Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Thu, 13 Nov 2014 15:34:26 +0200 Subject: [PATCH 13/16] ANGLE: Add support for querying platform device The EGL_EXT_device_base extension allows for querying the platform @@ -16,14 +16,14 @@ the IDXGIDevice3::Trim() calls required by the Windows Store. Change-Id: Ibdf228d81d6604e56db9dd8597d7cd2983ebc428 --- - src/3rdparty/angle/src/libEGL/libEGL.cpp | 47 +++++++++++++++++++++++++------- - 1 file changed, 37 insertions(+), 10 deletions(-) + src/3rdparty/angle/src/libEGL/libEGL.cpp | 50 +++++++++++++++++++++++++------- + 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp -index 7ea11c5..c2e0fd6 100644 +index dc20d85..68399d6 100644 --- a/src/3rdparty/angle/src/libEGL/libEGL.cpp +++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp -@@ -18,6 +18,9 @@ +@@ -17,6 +17,9 @@ #include "libGLESv2/Texture.h" #include "libGLESv2/main.h" #include "libGLESv2/renderer/SwapChain.h" @@ -33,7 +33,7 @@ index 7ea11c5..c2e0fd6 100644 #include "libEGL/main.h" #include "libEGL/Display.h" -@@ -484,24 +487,48 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf +@@ -582,25 +585,50 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf egl::Display *display = static_cast(dpy); egl::Surface *eglSurface = (egl::Surface*)surface; @@ -44,7 +44,8 @@ index 7ea11c5..c2e0fd6 100644 - - if (surface == EGL_NO_SURFACE) - { -- return egl::error(EGL_BAD_SURFACE, EGL_FALSE); +- recordError(egl::Error(EGL_BAD_SURFACE)); +- return EGL_FALSE; - } - switch (attribute) @@ -58,7 +59,8 @@ index 7ea11c5..c2e0fd6 100644 + + if (surface == EGL_NO_SURFACE) + { -+ return egl::error(EGL_BAD_SURFACE, EGL_FALSE); ++ recordError(egl::Error(EGL_BAD_SURFACE)); ++ return EGL_FALSE; + } + rx::SwapChain *swapchain = eglSurface->getSwapChain(); @@ -82,7 +84,8 @@ index 7ea11c5..c2e0fd6 100644 + + if (renderer->getMajorShaderModel() < 4) + { -+ return egl::error(EGL_BAD_CONTEXT, EGL_FALSE); ++ recordError(egl::Error(EGL_BAD_CONTEXT)); ++ return EGL_FALSE; + } + + *value = static_cast(renderer)->getDevice(); @@ -90,8 +93,8 @@ index 7ea11c5..c2e0fd6 100644 + break; +#endif default: - return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); - } + recordError(egl::Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; -- -1.9.0.msysgit.0 +1.9.4.msysgit.1 diff --git a/src/angle/patches/0014-Let-ANGLE-use-multithreaded-devices-if-necessary.patch b/src/angle/patches/0014-Let-ANGLE-use-multithreaded-devices-if-necessary.patch index b884f7b549f..9ceb34d964a 100644 --- a/src/angle/patches/0014-Let-ANGLE-use-multithreaded-devices-if-necessary.patch +++ b/src/angle/patches/0014-Let-ANGLE-use-multithreaded-devices-if-necessary.patch @@ -1,6 +1,6 @@ -From a3046fef7f754f06937161e779ce0a651e77317b Mon Sep 17 00:00:00 2001 +From 5b3bc73210ed1847d9bd7a94f06cc0d5de8e0b89 Mon Sep 17 00:00:00 2001 From: Michael Bruning -Date: Mon, 22 Sep 2014 23:23:40 +0300 +Date: Thu, 13 Nov 2014 15:40:10 +0200 Subject: [PATCH 14/16] Let ANGLE use multithreaded devices if necessary. This is needed to prevent lock-ups in application that use ANGLE from @@ -11,13 +11,13 @@ communicate this from the QtWebEngine module. Change-Id: Ibd5a5c75eb68af567d420d9a35efb3490c93b27c --- - src/3rdparty/angle/src/common/platform.h | 1 + - .../angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp | 13 +++++++++++++ - .../angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp | 4 ++++ - 3 files changed, 18 insertions(+) + src/3rdparty/angle/src/common/platform.h | 1 + + .../angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp | 10 ++++++++++ + .../angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp | 4 ++++ + 3 files changed, 15 insertions(+) diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h -index 387ba41..7d0d957 100644 +index 0065ec7..8b2190d 100644 --- a/src/3rdparty/angle/src/common/platform.h +++ b/src/3rdparty/angle/src/common/platform.h @@ -57,6 +57,7 @@ @@ -26,17 +26,16 @@ index 387ba41..7d0d957 100644 # include +# include # include + # include # include - # include diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -index b4b26a8..bd07ee1 100644 +index f6ba930..46b9984 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -@@ -301,6 +301,19 @@ EGLint Renderer11::initialize() +@@ -258,6 +258,16 @@ EGLint Renderer11::initialize() } - #endif -+#if !defined(ANGLE_PLATFORM_WINRT) + #if !defined(ANGLE_ENABLE_WINDOWS_STORE) + static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED"); + if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1")) + { @@ -47,16 +46,14 @@ index b4b26a8..bd07ee1 100644 + ASSERT(SUCCEEDED(result)); + multithread->Release(); + } -+#endif -+ - initializeDevice(); - - return EGL_SUCCESS; + #if !ANGLE_SKIP_DXGI_1_2_CHECK + // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required. + // The easiest way to check is to query for a IDXGIDevice2. diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp -index e8564bd..1d52705 100644 +index 82963ec..4c552b2 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp -@@ -304,6 +304,10 @@ EGLint Renderer9::initialize() +@@ -299,6 +299,10 @@ EGLint Renderer9::initialize() D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES; @@ -68,5 +65,5 @@ index e8564bd..1d52705 100644 result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice); } -- -1.9.0.msysgit.0 +1.9.4.msysgit.1 diff --git a/src/angle/patches/0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch b/src/angle/patches/0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch index 7d914766a0c..f78474f11a5 100644 --- a/src/angle/patches/0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch +++ b/src/angle/patches/0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch @@ -1,23 +1,28 @@ -From 373b3f67352e9a6f599c6a9dd9aee3b4836e0a3f Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Mon, 22 Sep 2014 23:41:48 +0300 +From d9a9219ea2181dd4c1939d05747a21b67f16a906 Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Thu, 13 Nov 2014 16:33:53 +0200 Subject: [PATCH 15/16] ANGLE: Fix -angle-d3d11 on MSVC2010 Allow the D3D11 renderer to build with the June 2010 DirectX SDK. Change-Id: I2343acedab16845d6a0d4a53cf3145f583efc4a7 --- - src/3rdparty/angle/src/common/platform.h | 6 ++ - .../renderer/d3d/d3d11/renderer11_utils.cpp | 89 ++++++++++++++++++++++ - 2 files changed, 95 insertions(+) + src/3rdparty/angle/src/common/platform.h | 8 +- + src/3rdparty/angle/src/libGLESv2/Context.cpp | 8 +- + src/3rdparty/angle/src/libGLESv2/Data.h | 2 +- + src/3rdparty/angle/src/libGLESv2/State.cpp | 6 +- + .../src/libGLESv2/renderer/d3d/RendererD3D.cpp | 4 +- + .../libGLESv2/renderer/d3d/d3d11/Renderer11.cpp | 4 +- + .../renderer/d3d/d3d11/renderer11_utils.cpp | 137 +++++++++++++++++++++ + 7 files changed, 156 insertions(+), 13 deletions(-) diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h -index 7d0d957..3c619f3 100644 +index 8b2190d..972eee2 100644 --- a/src/3rdparty/angle/src/common/platform.h +++ b/src/3rdparty/angle/src/common/platform.h -@@ -52,7 +52,9 @@ +@@ -52,17 +52,23 @@ - # if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_PERF) + # if defined(ANGLE_ENABLE_D3D9) # include +# if !defined(COMPILER_IMPLEMENTATION) # include @@ -25,11 +30,13 @@ index 7d0d957..3c619f3 100644 # endif # if defined(ANGLE_ENABLE_D3D11) -@@ -60,8 +62,12 @@ + # include # include # include +-# include # include -+# if _MSC_VER >= 1700 ++# if defined(_MSC_VER) && (_MSC_VER >= 1700) ++# include # include +# endif +# if !defined(COMPILER_IMPLEMENTATION) @@ -37,12 +44,118 @@ index 7d0d957..3c619f3 100644 +# endif # endif - # undef near + # if defined(ANGLE_ENABLE_WINDOWS_STORE) +diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp +index fe9b1a2..b87689c 100644 +--- a/src/3rdparty/angle/src/libGLESv2/Context.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp +@@ -168,9 +168,9 @@ Context::~Context() + } + mIncompleteTextures.clear(); + +- for (auto &zeroTexture : mZeroTextures) ++ for (TextureMap::iterator i = mZeroTextures.begin(); i != mZeroTextures.end(); i++) + { +- zeroTexture.second.set(NULL); ++ i->second.set(NULL); + } + mZeroTextures.clear(); + +@@ -354,7 +354,7 @@ void Context::deleteFenceSync(GLsync fenceSync) + + void Context::deleteVertexArray(GLuint vertexArray) + { +- auto vertexArrayObject = mVertexArrayMap.find(vertexArray); ++ VertexArrayMap::iterator vertexArrayObject = mVertexArrayMap.find(vertexArray); + + if (vertexArrayObject != mVertexArrayMap.end()) + { +@@ -460,7 +460,7 @@ FenceSync *Context::getFenceSync(GLsync handle) const + + VertexArray *Context::getVertexArray(GLuint handle) const + { +- auto vertexArray = mVertexArrayMap.find(handle); ++ VertexArrayMap::const_iterator vertexArray = mVertexArrayMap.find(handle); + + if (vertexArray == mVertexArrayMap.end()) + { +diff --git a/src/3rdparty/angle/src/libGLESv2/Data.h b/src/3rdparty/angle/src/libGLESv2/Data.h +index cff872a..9234403 100644 +--- a/src/3rdparty/angle/src/libGLESv2/Data.h ++++ b/src/3rdparty/angle/src/libGLESv2/Data.h +@@ -14,7 +14,7 @@ + namespace gl + { + +-struct Data final ++struct Data + { + public: + Data(GLint clientVersion, const State &state, const Caps &caps, +diff --git a/src/3rdparty/angle/src/libGLESv2/State.cpp b/src/3rdparty/angle/src/libGLESv2/State.cpp +index e7acda2..b5b62f5 100644 +--- a/src/3rdparty/angle/src/libGLESv2/State.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/State.cpp +@@ -665,13 +665,13 @@ void State::detachTexture(const TextureMap &zeroTextures, GLuint texture) + + void State::initializeZeroTextures(const TextureMap &zeroTextures) + { +- for (const auto &zeroTexture : zeroTextures) ++ for (TextureMap::const_iterator i = zeroTextures.begin(); i != zeroTextures.end(); i++) + { +- auto &samplerTextureArray = mSamplerTextures[zeroTexture.first]; ++ TextureBindingVector &samplerTextureArray = mSamplerTextures[i->first]; + + for (size_t textureUnit = 0; textureUnit < samplerTextureArray.size(); ++textureUnit) + { +- samplerTextureArray[textureUnit].set(zeroTexture.second.get()); ++ samplerTextureArray[textureUnit].set(i->second.get()); + } + } + } +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp +index 6f58243..97da6da 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp +@@ -27,9 +27,9 @@ RendererD3D::RendererD3D(egl::Display *display) + + RendererD3D::~RendererD3D() + { +- for (auto &incompleteTexture : mIncompleteTextures) ++ for (gl::TextureMap::iterator i = mIncompleteTextures.begin(); i != mIncompleteTextures.end(); ++i) + { +- incompleteTexture.second.set(NULL); ++ i->second.set(NULL); + } + mIncompleteTextures.clear(); + } +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp +index 46b9984..a28fd78 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp +@@ -873,7 +873,7 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count) + + void Renderer11::unsetSRVsWithResource(gl::SamplerType samplerType, const ID3D11Resource *resource) + { +- auto ¤tSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); ++ std::vector ¤tSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); + + for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex) + { +@@ -3398,7 +3398,7 @@ Workarounds Renderer11::generateWorkarounds() const + + void Renderer11::setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv) + { +- auto ¤tSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); ++ std::vector ¤tSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); + + ASSERT(static_cast(resourceSlot) < currentSRVs.size()); + diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp -index 06a22eb..345fd24 100644 +index cbfe557..5831c57 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp -@@ -17,6 +17,37 @@ +@@ -18,6 +18,85 @@ #include @@ -76,300 +189,348 @@ index 06a22eb..345fd24 100644 +#ifndef D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION +# define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096 +#endif ++#ifndef D3D11_REQ_TEXTURECUBE_DIMENSION ++# define D3D11_REQ_TEXTURECUBE_DIMENSION 16384 ++#endif ++#ifndef D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION ++# define D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION 2048 ++#endif ++#ifndef D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION ++# define D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 2048 ++#endif ++#ifndef D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP ++# define D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP 32 ++#endif ++#ifndef D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP ++# define D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP 32 ++#endif ++#ifndef D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT ++# define D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT 32 ++#endif ++#ifndef D3D11_STANDARD_VERTEX_ELEMENT_COUNT ++# define D3D11_STANDARD_VERTEX_ELEMENT_COUNT 32 ++#endif ++#ifndef D3D10_1_SO_BUFFER_SLOT_COUNT ++# define D3D10_1_SO_BUFFER_SLOT_COUNT 4 ++#endif ++#ifndef D3D11_SO_BUFFER_SLOT_COUNT ++# define D3D11_SO_BUFFER_SLOT_COUNT 4 ++#endif ++#ifndef D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT ++# define D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT 14 ++#endif ++#ifndef D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT ++# define D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT 16 ++#endif ++#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE ++# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE -8 ++#endif ++#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE ++# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE 7 ++#endif ++#ifndef D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT ++# define D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT 4096 ++#endif ++#ifndef D3D11_PS_INPUT_REGISTER_COUNT ++# define D3D11_PS_INPUT_REGISTER_COUNT 32 ++#endif ++#ifndef D3D10_1_VS_OUTPUT_REGISTER_COUNT ++# define D3D10_1_VS_OUTPUT_REGISTER_COUNT 32 ++#endif + namespace rx { -@@ -275,7 +306,9 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) +@@ -276,7 +355,9 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return true; -@@ -293,7 +326,9 @@ static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel) +@@ -294,7 +375,9 @@ static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_MAX_MAXANISOTROPY; case D3D_FEATURE_LEVEL_10_1: -@@ -313,7 +348,9 @@ static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel) +@@ -314,7 +397,9 @@ static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return true; -@@ -333,7 +370,9 @@ static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel) +@@ -334,7 +419,9 @@ static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: -@@ -351,7 +390,9 @@ static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel) +@@ -352,7 +439,9 @@ static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: -@@ -374,7 +415,9 @@ static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel) +@@ -375,7 +464,9 @@ static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: -@@ -392,7 +435,9 @@ static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel +@@ -393,7 +484,9 @@ static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; case D3D_FEATURE_LEVEL_10_1: -@@ -410,7 +455,9 @@ static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel) +@@ -411,7 +504,9 @@ static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; case D3D_FEATURE_LEVEL_10_1: -@@ -428,7 +475,9 @@ static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel) +@@ -429,7 +524,9 @@ static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION; case D3D_FEATURE_LEVEL_10_1: -@@ -446,7 +495,9 @@ static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel) +@@ -447,7 +544,9 @@ static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; case D3D_FEATURE_LEVEL_10_1: -@@ -464,7 +515,9 @@ static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel) +@@ -465,7 +564,9 @@ static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; case D3D_FEATURE_LEVEL_10_1: -@@ -482,7 +535,9 @@ static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel) +@@ -483,7 +584,9 @@ static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX; case D3D_FEATURE_LEVEL_10_1: -@@ -506,7 +561,9 @@ static size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel) +@@ -507,7 +610,9 @@ static size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return std::numeric_limits::max(); -@@ -528,7 +585,9 @@ static size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel) +@@ -529,7 +634,9 @@ static size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return std::numeric_limits::max(); -@@ -545,7 +604,9 @@ static size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel) +@@ -546,7 +653,9 @@ static size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_STANDARD_VERTEX_ELEMENT_COUNT; case D3D_FEATURE_LEVEL_10_1: return D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT; -@@ -565,7 +626,9 @@ static size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel) +@@ -566,7 +675,9 @@ static size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel) // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; case D3D_FEATURE_LEVEL_10_1: -@@ -590,7 +653,9 @@ static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel) +@@ -591,7 +702,9 @@ static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers(); case D3D_FEATURE_LEVEL_10_1: -@@ -617,7 +682,9 @@ static size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) +@@ -618,7 +731,9 @@ static size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); case D3D_FEATURE_LEVEL_10_1: return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); -@@ -636,7 +703,9 @@ static size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel) +@@ -637,7 +752,9 @@ static size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; case D3D_FEATURE_LEVEL_10_1: -@@ -658,7 +727,9 @@ static size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel) +@@ -659,7 +776,9 @@ static size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel) // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; case D3D_FEATURE_LEVEL_10_1: -@@ -683,7 +754,9 @@ static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel) +@@ -684,7 +803,9 @@ static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers(); case D3D_FEATURE_LEVEL_10_1: -@@ -702,7 +775,9 @@ static size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel) +@@ -703,7 +824,9 @@ static size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); case D3D_FEATURE_LEVEL_10_1: -@@ -721,7 +796,9 @@ static size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel) +@@ -722,7 +845,9 @@ static size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; case D3D_FEATURE_LEVEL_10_1: -@@ -740,7 +817,9 @@ static int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel) +@@ -741,7 +866,9 @@ static int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE; case D3D_FEATURE_LEVEL_10_1: -@@ -759,7 +838,9 @@ static int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel) +@@ -760,7 +887,9 @@ static int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE; case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE; -@@ -782,7 +863,9 @@ static size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel) +@@ -783,7 +912,9 @@ static size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; case D3D_FEATURE_LEVEL_10_1: -@@ -801,7 +884,9 @@ static size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel) +@@ -802,7 +933,9 @@ static size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_SO_BUFFER_SLOT_COUNT; case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SO_BUFFER_SLOT_COUNT; -@@ -819,7 +904,9 @@ static size_t GetMaximumStreamOutputInterleavedComponenets(D3D_FEATURE_LEVEL fea +@@ -820,7 +953,9 @@ static size_t GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL feat { switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: -@@ -837,7 +924,9 @@ static size_t GetMaximumStreamOutputSeparateCompeonents(D3D_FEATURE_LEVEL featur +@@ -838,7 +973,9 @@ static size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL feature { switch (featureLevel) { -+#if _MSC_VER >= 1700 ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) case D3D_FEATURE_LEVEL_11_1: +#endif - case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponenets(featureLevel) / + case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponents(featureLevel) / GetMaximumStreamOutputBuffers(featureLevel); -- -1.9.0.msysgit.0 +1.9.4.msysgit.1 diff --git a/src/angle/patches/0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch b/src/angle/patches/0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch index 2ea528018d9..e3df95d8bf7 100644 --- a/src/angle/patches/0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch +++ b/src/angle/patches/0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch @@ -1,35 +1,29 @@ -From 75c39e9020f062d155097f6b49aebbc12970b1e8 Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Tue, 23 Sep 2014 23:39:14 +0300 +From 43c8ceb17ccd6d5ae13a07c6d01b45eb40983917 Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Tue, 11 Nov 2014 14:36:43 +0200 Subject: [PATCH 16/16] ANGLE: Fix compilation with MinGW + D3D11 -Provide workarounds for things GCC doesn't like, and define a number -of macros not found in the MinGW headers. +Provide workarounds for things GCC doesn't like, and define a few +missing definitions not found in the MinGW headers. Change-Id: I254c208209c0071fae5efb6727f2b3cfd5542da6 --- - src/3rdparty/angle/src/common/platform.h | 11 +++++ - src/3rdparty/angle/src/libEGL/Display.cpp | 1 + - src/3rdparty/angle/src/libGLESv2/Context.cpp | 5 +- - src/3rdparty/angle/src/libGLESv2/angletypes.h | 1 + - .../angle/src/libGLESv2/renderer/copyimage.inl | 2 +- - .../src/libGLESv2/renderer/d3d/TextureD3D.cpp | 4 +- + src/3rdparty/angle/src/common/platform.h | 73 ++++++++++++++++++++++ + .../src/libGLESv2/renderer/d3d/HLSLCompiler.cpp | 6 ++ .../libGLESv2/renderer/d3d/d3d11/Renderer11.cpp | 2 +- - .../libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp | 2 +- - .../renderer/d3d/d3d11/renderer11_utils.cpp | 53 +++++++++++++++++++++- + .../renderer/d3d/d3d11/renderer11_utils.cpp | 2 +- .../src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp | 4 +- - src/3rdparty/angle/src/libGLESv2/validationES.cpp | 2 +- - 11 files changed, 76 insertions(+), 11 deletions(-) + 5 files changed, 83 insertions(+), 4 deletions(-) diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h -index 3c619f3..b53394f 100644 +index 972eee2..0001e71 100644 --- a/src/3rdparty/angle/src/common/platform.h +++ b/src/3rdparty/angle/src/common/platform.h -@@ -68,6 +68,17 @@ - # if !defined(COMPILER_IMPLEMENTATION) - # include - # endif -+# if defined(__MINGW32__) +@@ -81,6 +81,79 @@ + # endif + # endif + ++# if defined(__MINGW32__) // Missing defines on MinGW +typedef enum D3D11_MAP_FLAG +{ + D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000L @@ -39,202 +33,121 @@ index 3c619f3..b53394f 100644 + UINT64 NumPrimitivesWritten; + UINT64 PrimitivesStorageNeeded; +} D3D11_QUERY_DATA_SO_STATISTICS; -+# endif - # endif - ++typedef HRESULT (WINAPI *PFN_D3D11_CREATE_DEVICE)( ++ IDXGIAdapter *, D3D_DRIVER_TYPE, HMODULE, UINT, CONST D3D_FEATURE_LEVEL *, ++ UINT FeatureLevels, UINT, ID3D11Device **, D3D_FEATURE_LEVEL *, ID3D11DeviceContext **); ++#define D3D11_MESSAGE_CATEGORY UINT ++#define D3D11_MESSAGE_SEVERITY UINT ++#define D3D11_MESSAGE_ID UINT ++struct D3D11_MESSAGE; ++typedef struct D3D11_INFO_QUEUE_FILTER_DESC ++{ ++ UINT NumCategories; ++ D3D11_MESSAGE_CATEGORY *pCategoryList; ++ UINT NumSeverities; ++ D3D11_MESSAGE_SEVERITY *pSeverityList; ++ UINT NumIDs; ++ D3D11_MESSAGE_ID *pIDList; ++} D3D11_INFO_QUEUE_FILTER_DESC; ++typedef struct D3D11_INFO_QUEUE_FILTER ++{ ++ D3D11_INFO_QUEUE_FILTER_DESC AllowList; ++ D3D11_INFO_QUEUE_FILTER_DESC DenyList; ++} D3D11_INFO_QUEUE_FILTER; ++static const IID IID_ID3D11InfoQueue = { 0x6543dbb6, 0x1b48, 0x42f5, 0xab, 0x82, 0xe9, 0x7e, 0xc7, 0x43, 0x26, 0xf6 }; ++MIDL_INTERFACE("6543dbb6-1b48-42f5-ab82-e97ec74326f6") ID3D11InfoQueue : public IUnknown ++{ ++public: ++ virtual HRESULT __stdcall SetMessageCountLimit(UINT64) = 0; ++ virtual void __stdcall ClearStoredMessages() = 0; ++ virtual HRESULT __stdcall GetMessage(UINT64, D3D11_MESSAGE *, SIZE_T *) = 0; ++ virtual UINT64 __stdcall GetNumMessagesAllowedByStorageFilter() = 0; ++ virtual UINT64 __stdcall GetNumMessagesDeniedByStorageFilter() = 0; ++ virtual UINT64 __stdcall GetNumStoredMessages() = 0; ++ virtual UINT64 __stdcall GetNumStoredMessagesAllowedByRetrievalFilter() = 0; ++ virtual UINT64 __stdcall GetNumMessagesDiscardedByMessageCountLimit() = 0; ++ virtual UINT64 __stdcall GetMessageCountLimit() = 0; ++ virtual HRESULT __stdcall AddStorageFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0; ++ virtual HRESULT __stdcall GetStorageFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0; ++ virtual void __stdcall ClearStorageFilter() = 0; ++ virtual HRESULT __stdcall PushEmptyStorageFilter() = 0; ++ virtual HRESULT __stdcall PushCopyOfStorageFilter() = 0; ++ virtual HRESULT __stdcall PushStorageFilter(D3D11_INFO_QUEUE_FILTER *) = 0; ++ virtual void __stdcall PopStorageFilter() = 0; ++ virtual UINT __stdcall GetStorageFilterStackSize() = 0; ++ virtual HRESULT __stdcall AddRetrievalFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0; ++ virtual HRESULT __stdcall GetRetrievalFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0; ++ virtual void __stdcall ClearRetrievalFilter() = 0; ++ virtual HRESULT __stdcall PushEmptyRetrievalFilter() = 0; ++ virtual HRESULT __stdcall PushCopyOfRetrievalFilter() = 0; ++ virtual HRESULT __stdcall PushRetrievalFilter(D3D11_INFO_QUEUE_FILTER *) = 0; ++ virtual void __stdcall PopRetrievalFilter() = 0; ++ virtual UINT __stdcall GetRetrievalFilterStackSize() = 0; ++ virtual HRESULT __stdcall AddMessage(D3D11_MESSAGE_CATEGORY, D3D11_MESSAGE_SEVERITY, D3D11_MESSAGE_ID, LPCSTR) = 0; ++ virtual HRESULT __stdcall AddApplicationMessage(D3D11_MESSAGE_SEVERITY, LPCSTR) = 0; ++ virtual HRESULT __stdcall SetBreakOnCategory(D3D11_MESSAGE_CATEGORY, BOOL) = 0; ++ virtual HRESULT __stdcall SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY, BOOL) = 0; ++ virtual HRESULT __stdcall SetBreakOnID(D3D11_MESSAGE_ID, BOOL) = 0; ++ virtual BOOL __stdcall GetBreakOnCategory(D3D11_MESSAGE_CATEGORY) = 0; ++ virtual BOOL __stdcall GetBreakOnSeverity(D3D11_MESSAGE_SEVERITY) = 0; ++ virtual BOOL __stdcall GetBreakOnID(D3D11_MESSAGE_ID) = 0; ++ virtual void __stdcall SetMuteDebugOutput(BOOL) = 0; ++ virtual BOOL __stdcall GetMuteDebugOutput() = 0; ++}; ++#endif // __MINGW32__ ++ # undef near -diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp -index ba09631..5a50e4b 100644 ---- a/src/3rdparty/angle/src/libEGL/Display.cpp -+++ b/src/3rdparty/angle/src/libEGL/Display.cpp -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include + # undef far + #endif +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp +index 9d003b4..776d92b 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp +@@ -14,6 +14,12 @@ + #ifndef QT_D3DCOMPILER_DLL + #define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL + #endif ++#ifndef D3DCOMPILE_RESERVED16 ++#define D3DCOMPILE_RESERVED16 (1 << 16) ++#endif ++#ifndef D3DCOMPILE_RESERVED17 ++#define D3DCOMPILE_RESERVED17 (1 << 17) ++#endif - #include "common/debug.h" - #include "common/mathutil.h" -diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp -index 04c7616..5342de1 100644 ---- a/src/3rdparty/angle/src/libGLESv2/Context.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp -@@ -33,6 +33,7 @@ - #include "libEGL/Surface.h" - - #include -+#include - - namespace gl - { -@@ -354,7 +355,7 @@ void Context::deleteFenceSync(GLsync fenceSync) - // wait commands finish. However, since the name becomes invalid, we cannot query the fence, - // and since our API is currently designed for being called from a single thread, we can delete - // the fence immediately. -- mResourceManager->deleteFenceSync(reinterpret_cast(fenceSync)); -+ mResourceManager->deleteFenceSync(uintptr_t(fenceSync)); - } - - void Context::deleteVertexArray(GLuint vertexArray) -@@ -460,7 +461,7 @@ Renderbuffer *Context::getRenderbuffer(GLuint handle) - - FenceSync *Context::getFenceSync(GLsync handle) const - { -- return mResourceManager->getFenceSync(reinterpret_cast(handle)); -+ return mResourceManager->getFenceSync(uintptr_t(handle)); - } - - VertexArray *Context::getVertexArray(GLuint handle) const -diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.h b/src/3rdparty/angle/src/libGLESv2/angletypes.h -index 922053e..642a6ec 100644 ---- a/src/3rdparty/angle/src/libGLESv2/angletypes.h -+++ b/src/3rdparty/angle/src/libGLESv2/angletypes.h -@@ -11,6 +11,7 @@ - - #include "libGLESv2/constants.h" - #include "common/RefCountObject.h" -+#include - - namespace gl - { -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.inl b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.inl -index ea6970c..0498cf7 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.inl -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.inl -@@ -24,7 +24,7 @@ inline void WriteColor(const uint8_t *source, uint8_t *dest) - template - inline void CopyPixel(const uint8_t *source, uint8_t *dest) - { -- colorType temp; -+ colorDataType temp; - ReadColor(source, &temp); - WriteColor(&temp, dest); - } -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp -index 2650913..96c8497 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp -@@ -129,7 +129,7 @@ bool TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei w - if (unpack.pixelBuffer.id() != 0) - { - gl::Buffer *pixelBuffer = unpack.pixelBuffer.get(); -- unsigned int offset = reinterpret_cast(pixels); -+ ptrdiff_t offset = reinterpret_cast(pixels); - // TODO: setImage/subImage is the only place outside of renderer that asks for a buffers raw data. - // This functionality should be moved into renderer and the getData method of BufferImpl removed. - const void *bufferData = pixelBuffer->getImplementation()->getData(); -@@ -186,7 +186,7 @@ bool TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const void - // to create a render target. - ASSERT(mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat)); - -- unsigned int offset = reinterpret_cast(pixels); -+ ptrdiff_t offset = reinterpret_cast(pixels); - - return mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea); - } + // Definitions local to the translation unit + namespace diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -index bd07ee1..b29b2ef 100644 +index a28fd78..e6d7f30 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -@@ -281,7 +281,7 @@ EGLint Renderer11::initialize() - } - +@@ -333,7 +333,7 @@ EGLint Renderer11::initialize() // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log --#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG) -+#if !defined(__MINGW32__) && defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG) + #if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG) ID3D11InfoQueue *infoQueue; - result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue); +- result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue); ++ result = mDevice->QueryInterface(IID_ID3D11InfoQueue, (void **)&infoQueue); -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp -index 787c511..4b29be0 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp -@@ -537,7 +537,7 @@ void SwapChain11::initPassThroughResources() - samplerDesc.BorderColor[2] = 0.0f; - samplerDesc.BorderColor[3] = 0.0f; - samplerDesc.MinLOD = 0; -- samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; -+ samplerDesc.MaxLOD = FLT_MAX; - - result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler); - ASSERT(SUCCEEDED(result)); + if (SUCCEEDED(result)) + { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp -index 345fd24..2af97e7 100644 +index 5831c57..121aa3b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp -@@ -47,6 +47,57 @@ - #ifndef D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION - # define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096 - #endif -+#ifndef D3D11_REQ_TEXTURECUBE_DIMENSION -+# define D3D11_REQ_TEXTURECUBE_DIMENSION 16384 -+#endif -+#ifndef D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION -+# define D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION 2048 -+#endif -+#ifndef D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION -+# define D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 2048 -+#endif -+#ifndef D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP -+# define D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP 32 -+#endif -+#ifndef D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP -+# define D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP 32 -+#endif -+#ifndef D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT -+# define D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT 32 -+#endif -+#ifndef D3D11_STANDARD_VERTEX_ELEMENT_COUNT -+# define D3D11_STANDARD_VERTEX_ELEMENT_COUNT 32 -+#endif -+#ifndef D3D10_1_SO_BUFFER_SLOT_COUNT -+# define D3D10_1_SO_BUFFER_SLOT_COUNT 4 -+#endif -+#ifndef D3D11_SO_BUFFER_SLOT_COUNT -+# define D3D11_SO_BUFFER_SLOT_COUNT 4 -+#endif -+#ifndef D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -+# define D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT 14 -+#endif -+#ifndef D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT -+# define D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT 16 -+#endif -+#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE -+# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE -8 -+#endif -+#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE -+# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE 7 -+#endif -+#ifndef D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT -+# define D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT 4096 -+#endif -+#ifndef D3D11_PS_INPUT_REGISTER_COUNT -+# define D3D11_PS_INPUT_REGISTER_COUNT 32 -+#endif -+#ifndef D3D10_1_VS_OUTPUT_REGISTER_COUNT -+# define D3D10_1_VS_OUTPUT_REGISTER_COUNT 32 -+#endif -+#ifndef D3D11_VS_OUTPUT_REGISTER_COUNT -+# define D3D11_VS_OUTPUT_REGISTER_COUNT 32 -+#endif - - namespace rx - { -@@ -1147,7 +1198,7 @@ void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, flo +@@ -1196,7 +1196,7 @@ void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, flo HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) { -#if defined(_DEBUG) -+#if !defined(__MINGW32__) && defined(_DEBUG) ++#if defined(_DEBUG) && !defined(__MINGW32__) return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name); #else return S_OK; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp -index 1d52705..d63f9b8 100644 +index 4c552b2..601cd24 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp -@@ -205,7 +205,7 @@ EGLint Renderer9::initialize() - if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) +@@ -200,7 +200,7 @@ EGLint Renderer9::initialize() + if (ANGLE_D3D9EX == ANGLE_ENABLED && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) { ASSERT(mD3d9Ex); - mD3d9Ex->QueryInterface(__uuidof(IDirect3D9), reinterpret_cast(&mD3d9)); @@ -242,7 +155,7 @@ index 1d52705..d63f9b8 100644 ASSERT(mD3d9); } else -@@ -329,7 +329,7 @@ EGLint Renderer9::initialize() +@@ -324,7 +324,7 @@ EGLint Renderer9::initialize() if (mD3d9Ex) { @@ -251,19 +164,6 @@ index 1d52705..d63f9b8 100644 ASSERT(SUCCEEDED(result)); } -diff --git a/src/3rdparty/angle/src/libGLESv2/validationES.cpp b/src/3rdparty/angle/src/libGLESv2/validationES.cpp -index 1b6180d..f79bc97 100644 ---- a/src/3rdparty/angle/src/libGLESv2/validationES.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/validationES.cpp -@@ -1667,7 +1667,7 @@ bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum t - // TODO: also disable index checking on back-ends that are robust to out-of-range accesses. - if (elementArrayBuffer) - { -- unsigned int offset = reinterpret_cast(indices); -+ GLint64 offset = reinterpret_cast(indices); - if (!elementArrayBuffer->getIndexRangeCache()->findRange(type, offset, count, indexRangeOut, NULL)) - { - const void *dataPointer = elementArrayBuffer->getImplementation()->getData(); -- -1.9.0.msysgit.0 +1.9.4.msysgit.1 diff --git a/src/angle/patches/0017-ANGLE-Fix-compilation-with-D3D9.patch b/src/angle/patches/0017-ANGLE-Fix-compilation-with-D3D9.patch new file mode 100644 index 00000000000..4ada6d41d26 --- /dev/null +++ b/src/angle/patches/0017-ANGLE-Fix-compilation-with-D3D9.patch @@ -0,0 +1,62 @@ +From d7839cc052de126cc3b457fe41963fd9c7e91846 Mon Sep 17 00:00:00 2001 +From: Kai Koehne +Date: Mon, 17 Nov 2014 15:10:10 +0100 +Subject: [PATCH] ANGLE: Fix compilation with D3D9 + +Fixes a regression introduced in c6df5fe3ed0f2a722 that +broke compilation with d3d9 (namely, -target xp). + +Task-number: QTBUG-42714 +Change-Id: I1a5e9682d5463bfa082a5d0c062399a131a7cf52 +--- + src/3rdparty/angle/src/common/NativeWindow.h | 7 ++++++- + src/3rdparty/angle/src/common/platform.h | 1 + + src/3rdparty/angle/src/common/win32/NativeWindow.cpp | 2 +- + 3 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/src/3rdparty/angle/src/common/NativeWindow.h b/src/3rdparty/angle/src/common/NativeWindow.h +index 9e93aea..c4a0e42 100644 +--- a/src/3rdparty/angle/src/common/NativeWindow.h ++++ b/src/3rdparty/angle/src/common/NativeWindow.h +@@ -54,7 +54,12 @@ public: + bool getClientRect(LPRECT rect); + bool isIconic(); + +- HRESULT createSwapChain(ID3D11Device* device, DXGIFactory* factory, ++# if defined(ANGLE_ENABLE_D3D11) ++ typedef ID3D11Device Device; ++#else ++ typedef IDirect3DDevice9 Device; ++#endif ++ HRESULT createSwapChain(Device* device, DXGIFactory* factory, + DXGI_FORMAT format, UINT width, UINT height, + DXGISwapChain** swapChain); + +diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h +index 0001e71..5bf97f9 100644 +--- a/src/3rdparty/angle/src/common/platform.h ++++ b/src/3rdparty/angle/src/common/platform.h +@@ -52,6 +52,7 @@ + + # if defined(ANGLE_ENABLE_D3D9) + # include ++# include + # if !defined(COMPILER_IMPLEMENTATION) + # include + # endif +diff --git a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp +index 2440747..46082a2 100644 +--- a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp ++++ b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp +@@ -35,7 +35,7 @@ bool NativeWindow::isIconic() + return IsIconic(mWindow) == TRUE; + } + +-HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory, ++HRESULT NativeWindow::createSwapChain(NativeWindow::Device* device, DXGIFactory* factory, + DXGI_FORMAT format, unsigned int width, unsigned int height, + DXGISwapChain** swapChain) + { +-- +1.9.4.msysgit.0 + diff --git a/src/angle/src/libEGL/libEGL.pro b/src/angle/src/libEGL/libEGL.pro index 48ce7055fd8..a16249309f4 100644 --- a/src/angle/src/libEGL/libEGL.pro +++ b/src/angle/src/libEGL/libEGL.pro @@ -6,20 +6,40 @@ winrt: LIBS_PRIVATE += -ld3d11 LIBS_PRIVATE += -ldxguid -L$$QT_BUILD_TREE/lib -l$$qtLibraryTarget(libGLESv2) HEADERS += \ + $$ANGLE_DIR/src/common/NativeWindow.h \ + $$ANGLE_DIR/src/libEGL/AttributeMap.h \ $$ANGLE_DIR/src/libEGL/Config.h \ $$ANGLE_DIR/src/libEGL/Display.h \ + $$ANGLE_DIR/src/libEGL/Error.h \ $$ANGLE_DIR/src/libEGL/main.h \ $$ANGLE_DIR/src/libEGL/resource.h \ $$ANGLE_DIR/src/libEGL/ShaderCache.h \ $$ANGLE_DIR/src/libEGL/Surface.h SOURCES += \ + $$ANGLE_DIR/src/libEGL/AttributeMap.cpp \ $$ANGLE_DIR/src/libEGL/Config.cpp \ $$ANGLE_DIR/src/libEGL/Display.cpp \ + $$ANGLE_DIR/src/libEGL/Error.cpp \ $$ANGLE_DIR/src/libEGL/libEGL.cpp \ $$ANGLE_DIR/src/libEGL/main.cpp \ $$ANGLE_DIR/src/libEGL/Surface.cpp +!winrt { + SOURCES += \ + $$ANGLE_DIR/src/common/win32/NativeWindow.cpp +} else { + HEADERS += \ + $$ANGLE_DIR/src/common/winrt/CoreWindowNativeWindow.h \ + $$ANGLE_DIR/src/common/winrt/InspectableNativeWindow.h \ + $$ANGLE_DIR/src/common/winrt/SwapChainPanelNativeWindow.h + + SOURCES += \ + $$ANGLE_DIR/src/common/winrt/CoreWindowNativeWindow.cpp \ + $$ANGLE_DIR/src/common/winrt/InspectableNativeWindow.cpp \ + $$ANGLE_DIR/src/common/winrt/SwapChainPanelNativeWindow.cpp +} + !static { DEF_FILE = $$ANGLE_DIR/src/libEGL/$${TARGET}.def mingw:equals(QT_ARCH, i386): DEF_FILE = $$ANGLE_DIR/src/libEGL/$${TARGET}_mingw32.def diff --git a/src/angle/src/libGLESv2/libGLESv2.pro b/src/angle/src/libGLESv2/libGLESv2.pro index c0f7982e6c6..705768d17d7 100644 --- a/src/angle/src/libGLESv2/libGLESv2.pro +++ b/src/angle/src/libGLESv2/libGLESv2.pro @@ -24,11 +24,13 @@ HEADERS += \ $$ANGLE_DIR/src/common/blocklayout.h \ $$ANGLE_DIR/src/common/shadervars.h \ $$ANGLE_DIR/src/common/utilities.h \ + $$ANGLE_DIR/src/common/NativeWindow.h \ $$ANGLE_DIR/src/libGLESv2/angletypes.h \ $$ANGLE_DIR/src/libGLESv2/BinaryStream.h \ $$ANGLE_DIR/src/libGLESv2/Buffer.h \ $$ANGLE_DIR/src/libGLESv2/Caps.h \ $$ANGLE_DIR/src/libGLESv2/Context.h \ + $$ANGLE_DIR/src/libGLESv2/Data.h \ $$ANGLE_DIR/src/libGLESv2/Error.h \ $$ANGLE_DIR/src/libGLESv2/Fence.h \ $$ANGLE_DIR/src/libGLESv2/formatutils.h \ @@ -53,6 +55,8 @@ HEADERS += \ $$ANGLE_DIR/src/libGLESv2/renderer/d3d/IndexDataManager.h \ $$ANGLE_DIR/src/libGLESv2/renderer/d3d/MemoryBuffer.h \ $$ANGLE_DIR/src/libGLESv2/renderer/d3d/ProgramD3D.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d/RenderbufferD3D.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d/RendererD3D.h \ $$ANGLE_DIR/src/libGLESv2/renderer/d3d/ShaderD3D.h \ $$ANGLE_DIR/src/libGLESv2/renderer/d3d/TextureD3D.h \ $$ANGLE_DIR/src/libGLESv2/renderer/d3d/TextureStorage.h \ @@ -69,6 +73,7 @@ HEADERS += \ $$ANGLE_DIR/src/libGLESv2/renderer/loadimage.h \ $$ANGLE_DIR/src/libGLESv2/renderer/ProgramImpl.h \ $$ANGLE_DIR/src/libGLESv2/renderer/QueryImpl.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/RenderbufferImpl.h \ $$ANGLE_DIR/src/libGLESv2/renderer/Renderer.h \ $$ANGLE_DIR/src/libGLESv2/renderer/RenderTarget.h \ $$ANGLE_DIR/src/libGLESv2/renderer/ShaderExecutable.h \ @@ -77,6 +82,7 @@ HEADERS += \ $$ANGLE_DIR/src/libGLESv2/renderer/TextureImpl.h \ $$ANGLE_DIR/src/libGLESv2/renderer/TextureFeedbackImpl.h \ $$ANGLE_DIR/src/libGLESv2/renderer/VertexDeclarationCache.h \ + $$ANGLE_DIR/src/libGLESv2/renderer/Workarounds.h \ $$ANGLE_DIR/src/libGLESv2/resource.h \ $$ANGLE_DIR/src/libGLESv2/ResourceManager.h \ $$ANGLE_DIR/src/libGLESv2/Sampler.h \ @@ -102,6 +108,7 @@ SOURCES += \ $$ANGLE_DIR/src/libGLESv2/Buffer.cpp \ $$ANGLE_DIR/src/libGLESv2/Caps.cpp \ $$ANGLE_DIR/src/libGLESv2/Context.cpp \ + $$ANGLE_DIR/src/libGLESv2/Data.cpp \ $$ANGLE_DIR/src/libGLESv2/Error.cpp \ $$ANGLE_DIR/src/libGLESv2/Fence.cpp \ $$ANGLE_DIR/src/libGLESv2/Float16ToFloat32.cpp \ @@ -131,10 +138,12 @@ SOURCES += \ $$ANGLE_DIR/src/libGLESv2/VertexAttribute.cpp \ $$ANGLE_DIR/src/libGLESv2/renderer/copyimage.cpp \ $$ANGLE_DIR/src/libGLESv2/renderer/loadimage.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/loadimageSSE2.cpp \ $$ANGLE_DIR/src/libGLESv2/renderer/Image.cpp \ $$ANGLE_DIR/src/libGLESv2/renderer/IndexRangeCache.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/ProgramImpl.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/RenderbufferImpl.cpp \ $$ANGLE_DIR/src/libGLESv2/renderer/Renderer.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/RenderTarget.cpp \ $$ANGLE_DIR/src/libGLESv2/renderer/d3d/BufferD3D.cpp \ $$ANGLE_DIR/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp \ $$ANGLE_DIR/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp \ @@ -143,6 +152,8 @@ SOURCES += \ $$ANGLE_DIR/src/libGLESv2/renderer/d3d/IndexDataManager.cpp \ $$ANGLE_DIR/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp \ $$ANGLE_DIR/src/libGLESv2/renderer/d3d/ProgramD3D.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d/RenderbufferD3D.cpp \ + $$ANGLE_DIR/src/libGLESv2/renderer/d3d/RendererD3D.cpp \ $$ANGLE_DIR/src/libGLESv2/renderer/d3d/ShaderD3D.cpp \ $$ANGLE_DIR/src/libGLESv2/renderer/d3d/TextureD3D.cpp \ $$ANGLE_DIR/src/libGLESv2/renderer/d3d/TextureStorage.cpp \ @@ -192,6 +203,8 @@ angle_d3d11 { $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp } +SSE2_SOURCES += $$ANGLE_DIR/src/libGLESv2/renderer/loadimageSSE2.cpp + !winrt { HEADERS += \ $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Blit9.h \ @@ -211,6 +224,7 @@ angle_d3d11 { $$ANGLE_DIR/src/third_party/systeminfo/SystemInfo.h SOURCES += \ + $$ANGLE_DIR/src/common/win32/NativeWindow.cpp \ $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp \ $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp \ $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp \ @@ -227,6 +241,16 @@ angle_d3d11 { $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp \ $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp \ $$ANGLE_DIR/src/third_party/systeminfo/SystemInfo.cpp +} else { + HEADERS += \ + $$ANGLE_DIR/src/common/winrt/CoreWindowNativeWindow.h \ + $$ANGLE_DIR/src/common/winrt/InspectableNativeWindow.h \ + $$ANGLE_DIR/src/common/winrt/SwapChainPanelNativeWindow.h + + SOURCES += \ + $$ANGLE_DIR/src/common/winrt/CoreWindowNativeWindow.cpp \ + $$ANGLE_DIR/src/common/winrt/InspectableNativeWindow.cpp \ + $$ANGLE_DIR/src/common/winrt/SwapChainPanelNativeWindow.cpp } !static { diff --git a/src/corelib/animation/qanimationgroup.cpp b/src/corelib/animation/qanimationgroup.cpp index 0f87d7263e5..241501d60d4 100644 --- a/src/corelib/animation/qanimationgroup.cpp +++ b/src/corelib/animation/qanimationgroup.cpp @@ -62,7 +62,7 @@ QAnimationGroup provides methods for adding and retrieving animations. Besides that, you can remove animations by calling - remove(), and clear the animation group by calling + \l removeAnimation(), and clear the animation group by calling clear(). You may keep track of changes in the group's animations by listening to QEvent::ChildAdded and QEvent::ChildRemoved events. diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp index dcbf55f28b8..f47dec6ce09 100644 --- a/src/corelib/animation/qvariantanimation.cpp +++ b/src/corelib/animation/qvariantanimation.cpp @@ -79,7 +79,7 @@ QT_BEGIN_NAMESPACE There are two ways to affect how QVariantAnimation interpolates the values. You can set an easing curve by calling setEasingCurve(), and configure the duration by calling - setDuration(). You can change how the QVariants are interpolated + setDuration(). You can change how the \l{QVariant}s are interpolated by creating a subclass of QVariantAnimation, and reimplementing the virtual interpolated() function. @@ -110,7 +110,7 @@ QT_BEGIN_NAMESPACE If you need to interpolate other variant types, including custom types, you have to implement interpolation for these yourself. To do this, you can register an interpolator function for a given - type. This function takes 3 parameters: the start value, the end value + type. This function takes 3 parameters: the start value, the end value, and the current progress. Example: @@ -378,8 +378,8 @@ QVariantAnimation::~QVariantAnimation() keyValues are referring to this effective progress. The easing curve is used with the interpolator, the interpolated() - virtual function, the animation's duration, and iterationCount, to - control how the current value changes as the animation progresses. + virtual function, and the animation's duration to control how the + current value changes as the animation progresses. */ QEasingCurve QVariantAnimation::easingCurve() const { diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp index 9d13e1b8929..d2857c03b6a 100644 --- a/src/corelib/codecs/qtextcodec.cpp +++ b/src/corelib/codecs/qtextcodec.cpp @@ -253,9 +253,10 @@ static QTextCodec *setupLocaleMapper() // textCodecsMutex need to be locked to enter this function static void setup() { - QCoreGlobalData *globalData = QCoreGlobalData::instance(); - if (!globalData->allCodecs.isEmpty()) + static bool initialized = false; + if (initialized) return; + initialized = true; #if !defined(QT_NO_CODECS) && !defined(QT_BOOTSTRAPPED) (void)new QTsciiCodec; @@ -441,7 +442,7 @@ QTextCodec::ConverterState::~ConverterState() an empty list. For example, "ISO-8859-1" has "latin1", "CP819", "IBM819", and "iso-ir-100" as aliases. - \row \li mibEnum() + \row \li \l{QTextCodec::mibEnum()}{mibEnum()} \li Return the MIB enum for the encoding if it is listed in the \l{IANA character-sets encoding file}. @@ -465,7 +466,11 @@ QTextCodec::QTextCodec() { QMutexLocker locker(textCodecsMutex()); - QCoreGlobalData::instance()->allCodecs.prepend(this); + QCoreGlobalData *globalInstance = QCoreGlobalData::instance(); + if (globalInstance->allCodecs.isEmpty()) + setup(); + + globalInstance->allCodecs.prepend(this); } @@ -503,7 +508,7 @@ QTextCodec *QTextCodec::codecForName(const QByteArray &name) QCoreGlobalData *globalData = QCoreGlobalData::instance(); if (!globalData) return 0; - setup(); + setup(); #ifndef QT_USE_ICU QTextCodecCache *cache = &globalData->codecCache; @@ -704,7 +709,7 @@ QTextCodec* QTextCodec::codecForLocale() \fn int QTextCodec::mibEnum() const Subclasses of QTextCodec must reimplement this function. It - returns the MIBenum (see \l{IANA character-sets encoding file} + returns the \l{QTextCodec::mibEnum()}{MIBenum} (see \l{IANA character-sets encoding file} for more information). It is important that each QTextCodec subclass returns the correct unique value for this function. */ @@ -733,7 +738,7 @@ QList QTextCodec::aliases() const \a state can be 0, in which case the conversion is stateless and default conversion rules should be used. If state is not 0, the codec should save the state after the conversion in \a state, and - adjust the remainingChars and invalidChars members of the struct. + adjust the \c remainingChars and \c invalidChars members of the struct. */ /*! @@ -749,7 +754,7 @@ QList QTextCodec::aliases() const \a state can be 0 in which case the conversion is stateless and default conversion rules should be used. If state is not 0, the codec should save the state after the conversion in \a state, and - adjust the remainingChars and invalidChars members of the struct. + adjust the \c remainingChars and \c invalidChars members of the struct. */ /*! @@ -1049,7 +1054,10 @@ QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba, QTextCodec *defaultCo while (++pos2 < header.size()) { char ch = header.at(pos2); if (ch == '\"' || ch == '\'' || ch == '>') { - c = QTextCodec::codecForName(header.mid(pos, pos2 - pos)); + QByteArray name = header.mid(pos, pos2 - pos); + if (name == "unicode") // QTBUG-41998, ICU will return UTF-16. + name = QByteArrayLiteral("UTF-8"); + c = QTextCodec::codecForName(name); return c ? c : defaultCodec; } } diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp index 9210d2737f6..97be1312035 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp @@ -354,10 +354,10 @@ text.toBase64(); // returns "UXQgaXMgZ3JlYXQh" //! [39bis] QByteArray text("

Hello?

"); -text.toBase64(QByteArray::Base64 | QByteArray::OmitTrailingEquals); // returns "PHA+SGVsbG8/PC9wPg" -text.toBase64(QByteArray::Base64); // returns "PHA+SGVsbG8/PC9wPg==" -text.toBase64(QByteArray::Base64Url); // returns "PHA-SGVsbG8_PC9wPg==" -text.toBase64(QByteArray::Base64Url | QByteArray::OmitTrailingEquals); // returns "PHA-SGVsbG8_PC9wPg" +text.toBase64(QByteArray::Base64Encoding | QByteArray::OmitTrailingEquals); // returns "PHA+SGVsbG8/PC9wPg" +text.toBase64(QByteArray::Base64Encoding); // returns "PHA+SGVsbG8/PC9wPg==" +text.toBase64(QByteArray::Base64UrlEncoding); // returns "PHA-SGVsbG8_PC9wPg==" +text.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals); // returns "PHA-SGVsbG8_PC9wPg" //! [39bis] diff --git a/src/corelib/doc/snippets/qstring/main.cpp b/src/corelib/doc/snippets/qstring/main.cpp index f5c6b696952..17d0adf0976 100644 --- a/src/corelib/doc/snippets/qstring/main.cpp +++ b/src/corelib/doc/snippets/qstring/main.cpp @@ -774,14 +774,6 @@ void Widget::splitCaseSensitiveFunction() void Widget::sprintfFunction() { - //! [63] - size_t BufSize; - char buf[BufSize]; - - ::snprintf(buf, BufSize, "%lld", 123456789LL); - QString str = QString::fromUtf8(buf); - //! [63] - //! [64] QString result; QTextStream(&result) << "pi = " << 3.14; diff --git a/src/corelib/doc/src/animation.qdoc b/src/corelib/doc/src/animation.qdoc index 6910b18937a..9385c089952 100644 --- a/src/corelib/doc/src/animation.qdoc +++ b/src/corelib/doc/src/animation.qdoc @@ -27,6 +27,7 @@ /*! \group animation + \brief Provides an easy way for creating animated GUIs. \title Animation Framework This page lists classes belonging to \l{Qt Core}'s @@ -46,8 +47,8 @@ \keyword Animation The animation framework aims to provide an easy way for creating animated - and smooth GUI's. By animating Qt properties, the framework provides great - freedom for animating widgets and other \l{QObject}s. The framework can + and smooth GUIs. By animating Qt properties, the framework provides great + freedom for animating widgets and other {QObject}s. The framework can also be used with the Graphics View framework. Many of the concepts available in the animation framework are also available in \l{Qt Quick}, where it offers a declarative way of defining animations. Much of the @@ -56,7 +57,7 @@ In this overview, we explain the basics of its architecture. We also show examples of the most common techniques that the - framework allows for animating QObjects and graphics items. + framework allows for animating {QObject}s and graphics items. \tableofcontents @@ -84,7 +85,7 @@ over the property using an easing curve. So when you want to animate a value, you can declare it as a property and make your class a QObject. Note that this gives us great freedom in - animating already existing widgets and other \l{QObject}s. + animating already existing widgets and other {QObject}s. Complex animations can be constructed by building a tree structure of \l{QAbstractAnimation}s. The tree is built by using diff --git a/src/corelib/doc/src/containers.qdoc b/src/corelib/doc/src/containers.qdoc index 6017269272b..a517ca32d39 100644 --- a/src/corelib/doc/src/containers.qdoc +++ b/src/corelib/doc/src/containers.qdoc @@ -386,7 +386,7 @@ \l{QMapIterator::hasPrevious()}{hasPrevious()}, \l{QMapIterator::previous()}{previous()}, and \l{QMapIterator::peekPrevious()}{peekPrevious()}. The key and - value components are extracted by calling key() and value() on + value components are extracted by calling \l{QMapIterator::key()}{key()} and \l{QMapIterator::value()}{value()} on the object returned by next(), peekNext(), previous(), or peekPrevious(). @@ -395,7 +395,7 @@ \snippet code/doc_src_containers.cpp 7 - QMapIterator also provides a key() and a value() function that + QMapIterator also provides a \l{QMapIterator::key()}{key()} and a \l{QMapIterator::value()}{value()} function that operate directly on the iterator and that return the key and value of the last item that the iterator jumped above. For example, the following code copies the contents of a QMap into a @@ -459,13 +459,13 @@ \snippet code/doc_src_containers.cpp 10 Unlike \l{Java-style iterators}, STL-style iterators point - directly at items. The begin() function of a container returns an + directly at items. The \l{QList::begin()}{begin()} function of a container returns an iterator that points to the first item in the container. The - end() function of a container returns an iterator to the + \l{QList::end()}{end()} function of a container returns an iterator to the imaginary item one position past the last item in the container. - end() marks an invalid position; it must never be dereferenced. + \l {QList::end()}{end()} marks an invalid position; it must never be dereferenced. It is typically used in a loop's break condition. If the list is - empty, begin() equals end(), so we never execute the loop. + empty, \l{QList::begin}{begin()} equals \l{QList:end()}{end()}, so we never execute the loop. The diagram below shows the valid iterator positions as red arrows for a vector containing four items: @@ -484,8 +484,8 @@ compilers also allow us to write \c{i->toLower()}, but some don't. - For read-only access, you can use const_iterator, constBegin(), - and constEnd(). For example: + For read-only access, you can use const_iterator, \l{QList::constBegin}{constBegin()}, + and \l{QList::constEnd()}{constEnd()}. For example: \snippet code/doc_src_containers.cpp 12 @@ -759,7 +759,7 @@ QString. QVector also uses that algorithm for data types that can be - moved around in memory using memcpy() (including the basic C++ + moved around in memory using \c memcpy() (including the basic C++ types, the pointer types, and Qt's \l{shared classes}) but uses a different algorithm for data types that can only be moved by calling the copy constructor and a destructor. Since the cost of @@ -790,7 +790,7 @@ \endlist If you know approximately how many items you will store in a - container, you can start by calling reserve(), and when you are - done populating the container, you can call squeeze() to release + container, you can start by calling \l{QString::reserve()}{reserve()}, and when you are + done populating the container, you can call \l{QString::squeeze()}{squeeze()} to release the extra preallocated memory. */ diff --git a/src/corelib/doc/src/datastreamformat.qdoc b/src/corelib/doc/src/datastreamformat.qdoc index b6efe6aa336..56a6d0aafa6 100644 --- a/src/corelib/doc/src/datastreamformat.qdoc +++ b/src/corelib/doc/src/datastreamformat.qdoc @@ -173,7 +173,7 @@ \li If the image is null a "null image" marker is saved; otherwise the image is saved in PNG or BMP format (depending on the stream version). If you want control of the format, - stream the image into a QBuffer (using QImageIO) and stream + stream the image into a QBuffer (using QImageIOHandler/QImageIOPlugin) and stream that. \endlist \row \li QKeySequence diff --git a/src/corelib/doc/src/filestorage.qdoc b/src/corelib/doc/src/filestorage.qdoc index 394d9209230..a60c5846ffd 100644 --- a/src/corelib/doc/src/filestorage.qdoc +++ b/src/corelib/doc/src/filestorage.qdoc @@ -86,8 +86,8 @@ read console input and write console output. There are three general ways to use QTextStream when reading text files: \list - \li Chunk by chunk, by calling readLine() or readAll(). - \li Word by word. QTextStream supports streaming into QStrings, QByteArrays + \li Chunk by chunk, by calling \l{QBuffer::readLine()}{readLine()} or \l{QBuffer::readAll()}{readAll()}. + \li Word by word. QTextStream supports streaming into {QString}s, {QByteArray}s and char* buffers. Words are delimited by space, and leading white space is automatically skipped. \li Character by character, by streaming into QChar or char types. This diff --git a/src/corelib/doc/src/implicit-sharing.qdoc b/src/corelib/doc/src/implicit-sharing.qdoc index 1185fe83487..ec8edb4b6bf 100644 --- a/src/corelib/doc/src/implicit-sharing.qdoc +++ b/src/corelib/doc/src/implicit-sharing.qdoc @@ -30,6 +30,7 @@ /*! \group shared + \brief How to maximize resource usage by implicit data sharing. \title Implicitly Shared Classes These \l{Qt Core} classes provides a safe and efficient way of sharing and diff --git a/src/corelib/doc/src/objectmodel/signalsandslots.qdoc b/src/corelib/doc/src/objectmodel/signalsandslots.qdoc index f79e8a7dca7..b9b1874d0f5 100644 --- a/src/corelib/doc/src/objectmodel/signalsandslots.qdoc +++ b/src/corelib/doc/src/objectmodel/signalsandslots.qdoc @@ -242,7 +242,7 @@ By default, for every connection you make, a signal is emitted; two signals are emitted for duplicate connections. You can break - all of these connections with a single disconnect() call. + all of these connections with a single \l{QObject::disconnect()}{disconnect()} call. If you pass the Qt::UniqueConnection \a type, the connection will only be made if it is not a duplicate. If there is already a duplicate (exact same signal to the exact same slot on the same objects), @@ -251,9 +251,7 @@ This example illustrates that objects can work together without needing to know any information about each other. To enable this, the objects only need to be connected together, and this can be achieved with some simple - QObject::connect() function calls, or with \c{uic}'s - \l{Using a Designer UI File in Your Application#Automatic Connections} - {automatic connections} feature. + QObject::connect() function calls, or with \c{uic}'s {automatic connections} feature. \section1 A Real Example @@ -354,7 +352,7 @@ connect(sender, &QObject::destroyed, this, &MyObject::objectDestroyed); \endcode - There are several advantages to using connect() with function pointers. + There are several advantages to using QObject::connect() with function pointers. First, it allows the compiler to check that the signal's arguments are compatible with the slot's arguments. Arguments can also be implicitly converted by the compiler, if needed. @@ -407,7 +405,7 @@ will open: "Tax File", "Accounts File", or "Report File". In order to open the correct file, you use QSignalMapper::setMapping() to - map all the clicked() signals to a QSignalMapper object. Then you connect + map all the QPushButton::clicked() signals to a QSignalMapper object. Then you connect the file's QPushButton::clicked() signal to the QSignalMapper::map() slot. \snippet signalmapper/filereader.cpp 0 diff --git a/src/corelib/doc/src/statemachine.qdoc b/src/corelib/doc/src/statemachine.qdoc index b281eb177b1..846eb7d1f05 100644 --- a/src/corelib/doc/src/statemachine.qdoc +++ b/src/corelib/doc/src/statemachine.qdoc @@ -27,6 +27,7 @@ /*! \group statemachine + \brief How to create and execute state graphs. \title State Machine Classes These \l{Qt Core} classes are part of the \l{The State Machine Framework}{ diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 8ac84599f20..ee396409d85 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -78,7 +78,7 @@ # define Q_NO_USING_KEYWORD #elif defined(_MSC_VER) -# define Q_CC_MSVC +# define Q_CC_MSVC (_MSC_VER) # define Q_CC_MSVC_NET # define Q_OUTOFLINE_TEMPLATE inline # if _MSC_VER < 1600 @@ -137,14 +137,14 @@ # endif #elif defined(__GNUC__) -# define Q_CC_GNU +# define Q_CC_GNU (__GNUC__ * 100 + __GNUC_MINOR__) # define Q_C_CALLBACKS # if defined(__MINGW32__) # define Q_CC_MINGW # endif # if defined(__INTEL_COMPILER) /* Intel C++ also masquerades as GCC */ -# define Q_CC_INTEL +# define Q_CC_INTEL (__INTEL_COMPILER) # define Q_ASSUME_IMPL(expr) __assume(expr) # define Q_UNREACHABLE_IMPL() __builtin_unreachable() # if __INTEL_COMPILER >= 1300 && !defined(__APPLE__) @@ -152,7 +152,26 @@ # endif # elif defined(__clang__) /* Clang also masquerades as GCC */ -# define Q_CC_CLANG +# if defined(__apple_build_version__) +# /* http://en.wikipedia.org/wiki/Xcode#Toolchain_Versions */ +# if __apple_build_version__ >= 600051 +# define Q_CC_CLANG 305 +# elif __apple_build_version__ >= 503038 +# define Q_CC_CLANG 304 +# elif __apple_build_version__ >= 500275 +# define Q_CC_CLANG 303 +# elif __apple_build_version__ >= 425024 +# define Q_CC_CLANG 302 +# elif __apple_build_version__ >= 318045 +# define Q_CC_CLANG 301 +# elif __apple_build_version__ >= 211101 +# define Q_CC_CLANG 300 +# else +# error "Unknown Apple Clang version" +# endif +# else +# define Q_CC_CLANG ((__clang_major__ * 100) + __clang_minor__) +# endif # define Q_ASSUME_IMPL(expr) if (expr){} else __builtin_unreachable() # define Q_UNREACHABLE_IMPL() __builtin_unreachable() # if !defined(__has_extension) @@ -168,7 +187,7 @@ # endif # else /* Plain GCC */ -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 +# if Q_CC_GNU >= 405 # define Q_ASSUME_IMPL(expr) if (expr){} else __builtin_unreachable() # define Q_UNREACHABLE_IMPL() __builtin_unreachable() # define Q_DECL_DEPRECATED_X(text) __attribute__ ((__deprecated__(text))) @@ -202,7 +221,7 @@ # define QT_NO_ARM_EABI # endif # endif -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 403 && !defined(Q_CC_CLANG) +# if Q_CC_GNU >= 403 && !defined(Q_CC_CLANG) # define Q_ALLOC_SIZE(x) __attribute__((alloc_size(x))) # endif @@ -308,7 +327,7 @@ /* Using the `using' keyword avoids Intel C++ for Linux warnings */ # elif defined(__INTEL_COMPILER) -# define Q_CC_INTEL +# define Q_CC_INTEL (__INTEL_COMPILER) /* Uses CFront, make sure to read the manual how to tweak templates. */ # elif defined(__ghs) @@ -566,7 +585,7 @@ # endif // Variadic macros are supported for gnu++98, c++11, c99 ... since 2.9 -# if ((__clang_major__ * 100) + __clang_minor__) >= 209 +# if Q_CC_CLANG >= 209 # if !defined(__STRICT_ANSI__) || defined(__GXX_EXPERIMENTAL_CXX0X__) \ || (defined(__cplusplus) && (__cplusplus >= 201103L)) \ || (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) @@ -581,7 +600,7 @@ # define Q_COMPILER_ALIGNAS # define Q_COMPILER_ALIGNOF # endif -# if 0 /* not implemented in clang yet */ +# if __has_feature(cxx_atomic) && __has_include() # define Q_COMPILER_ATOMICS # endif # if __has_feature(cxx_attributes) @@ -668,7 +687,7 @@ # define Q_COMPILER_VARIADIC_TEMPLATES # endif /* Features that have no __has_feature() check */ -# if ((__clang_major__ * 100) + __clang_minor__) >= 209 /* since clang 2.9 */ +# if Q_CC_CLANG >= 209 /* since clang 2.9 */ # define Q_COMPILER_EXTERN_TEMPLATES # endif # endif @@ -709,7 +728,7 @@ #if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG) # define Q_COMPILER_RESTRICTED_VLA # define Q_COMPILER_THREADSAFE_STATICS -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 403 +# if Q_CC_GNU >= 403 // GCC supports binary literals in C, C++98 and C++11 modes # define Q_COMPILER_BINARY_LITERALS # endif @@ -720,13 +739,13 @@ # define Q_COMPILER_VARIADIC_MACROS # endif # if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 403 +# if Q_CC_GNU >= 403 /* C++11 features supported in GCC 4.3: */ # define Q_COMPILER_DECLTYPE # define Q_COMPILER_RVALUE_REFS # define Q_COMPILER_STATIC_ASSERT # endif -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 +# if Q_CC_GNU >= 404 /* C++11 features supported in GCC 4.4: */ # define Q_COMPILER_AUTO_FUNCTION # define Q_COMPILER_AUTO_TYPE @@ -735,7 +754,7 @@ # define Q_COMPILER_UNICODE_STRINGS # define Q_COMPILER_VARIADIC_TEMPLATES # endif -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 +# if Q_CC_GNU >= 405 /* C++11 features supported in GCC 4.5: */ # define Q_COMPILER_EXPLICIT_CONVERSIONS /* GCC 4.4 implements initializer_list but does not define typedefs required @@ -745,7 +764,7 @@ # define Q_COMPILER_RAW_STRINGS # define Q_COMPILER_CLASS_ENUM # endif -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 +# if Q_CC_GNU >= 406 /* Pre-4.6 compilers implement a non-final snapshot of N2346, hence default and delete * functions are supported only if they are public. Starting from 4.6, GCC handles * final version - the access modifier is not relevant. */ @@ -757,7 +776,7 @@ # define Q_COMPILER_UNRESTRICTED_UNIONS # define Q_COMPILER_RANGE_FOR # endif -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 +# if Q_CC_GNU >= 407 /* GCC 4.4 implemented and std::atomic using its old intrinsics. * However, the implementation is incomplete for most platforms until GCC 4.7: * instead, std::atomic would use an external lock. Since we need an std::atomic @@ -773,20 +792,20 @@ # define Q_COMPILER_TEMPLATE_ALIAS # define Q_COMPILER_UDL # endif -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 +# if Q_CC_GNU >= 408 # define Q_COMPILER_ATTRIBUTES # define Q_COMPILER_ALIGNAS # define Q_COMPILER_ALIGNOF # define Q_COMPILER_INHERITING_CONSTRUCTORS # define Q_COMPILER_THREAD_LOCAL -# if (__GNUC__ * 100 + __GNUC_MINOR__) > 408 || __GNUC_PATCHLEVEL__ >= 1 +# if Q_CC_GNU > 408 || __GNUC_PATCHLEVEL__ >= 1 # define Q_COMPILER_REF_QUALIFIERS # endif # endif /* C++11 features are complete as of GCC 4.8.1 */ # endif # if __cplusplus > 201103L -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 +# if Q_CC_GNU >= 409 /* C++1y features in GCC 4.9 - deprecated, do not update this list */ //# define Q_COMPILER_BINARY_LITERALS // already supported since GCC 4.3 as an extension # define Q_COMPILER_LAMBDA_CAPTURES @@ -880,6 +899,15 @@ # undef Q_COMPILER_INITIALIZER_LISTS # undef Q_COMPILER_RVALUE_REFS # undef Q_COMPILER_REF_QUALIFIERS +// Also disable , since it's clearly not there +# undef Q_COMPILER_ATOMICS +# endif +# if defined(_LIBCPP_VERSION) +// libc++ uses __has_feature(cxx_atomic), so disable the feature if the compiler +// doesn't support it. That's required for the Intel compiler on OS X, for example. +# if !__has_feature(cxx_atomic) +# undef Q_COMPILER_ATOMICS +# endif # endif # if defined(Q_COMPILER_THREADSAFE_STATICS) && defined(Q_OS_MAC) // Mac OS X: Apple's low-level implementation of the C++ support library diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 4a21ab88d89..4e8721f7d75 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -877,7 +877,7 @@ public: // (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#382). // GCC 4.3 and 4.4 have support for decltype, but are affected by DR 382. # if defined(Q_COMPILER_DECLTYPE) && \ - (defined(Q_CC_CLANG) || defined(Q_CC_INTEL) || !defined(Q_CC_GNU) || (__GNUC__ * 100 + __GNUC_MINOR__) >= 405) + (defined(Q_CC_CLANG) || defined(Q_CC_INTEL) || !defined(Q_CC_GNU) || Q_CC_GNU >= 405) # define QT_FOREACH_DECLTYPE(x) typename QtPrivate::remove_reference::type # else # define QT_FOREACH_DECLTYPE(x) __typeof__((x)) diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index c3ec2bc7f67..7ca0aa7f0bf 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -84,14 +84,7 @@ class QLibraryInfoPrivate { public: static QSettings *findConfiguration(); -#ifndef QT_BOOTSTRAPPED - static void cleanup() - { - QLibrarySettings *ls = qt_library_settings(); - if (ls) - ls->settings.reset(0); - } -#else +#ifdef QT_BOOTSTRAPPED static bool haveGroup(QLibraryInfo::PathGroup group) { QLibrarySettings *ls = qt_library_settings(); @@ -114,7 +107,6 @@ QLibrarySettings::QLibrarySettings() : settings(QLibraryInfoPrivate::findConfiguration()) { #ifndef QT_BOOTSTRAPPED - qAddPostRoutine(QLibraryInfoPrivate::cleanup); bool haveEffectivePaths; bool havePaths; #endif diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index f356bab42d7..39c5ac602ee 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -1101,14 +1101,9 @@ QString qFormatLogMessage(QtMsgType type, const QMessageLogContext &context, con if (!pattern) { // after destruction of static QMessagePattern instance message.append(str); - message.append(QLatin1Char('\n')); return message; } - // don't print anything if pattern was empty - if (pattern->tokens[0] == 0) - return message; - bool skip = false; // we do not convert file, function, line literals to local encoding due to overhead @@ -1227,7 +1222,6 @@ QString qFormatLogMessage(QtMsgType type, const QMessageLogContext &context, con message.append(QLatin1String(token)); } } - message.append(QLatin1Char('\n')); return message; } @@ -1289,7 +1283,7 @@ static void android_default_message_handler(QtMsgType type, case QtFatalMsg: priority = ANDROID_LOG_FATAL; break; }; - __android_log_print(priority, "Qt", "%s:%d (%s): %s", + __android_log_print(priority, "Qt", "%s:%d (%s): %s\n", context.file, context.line, context.function, qPrintable(message)); } @@ -1303,16 +1297,21 @@ static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &con { QString logMessage = qFormatLogMessage(type, context, buf); + // print nothing if message pattern didn't apply / was empty. + // (still print empty lines, e.g. because message itself was empty) + if (logMessage.isNull()) + return; + if (!qt_logging_to_console()) { #if defined(Q_OS_WIN) + logMessage.append(QLatin1Char('\n')); OutputDebugString(reinterpret_cast(logMessage.utf16())); return; #elif defined(QT_USE_SLOG2) + logMessage.append(QLatin1Char('\n')); slog2_default_handler(type, logMessage.toLocal8Bit().constData()); return; #elif defined(QT_USE_JOURNALD) && !defined(QT_BOOTSTRAPPED) - // remove trailing \n, systemd appears to want them newline-less - logMessage.chop(1); systemd_default_message_handler(type, context, logMessage); return; #elif defined(Q_OS_ANDROID) @@ -1320,7 +1319,7 @@ static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &con return; #endif } - fprintf(stderr, "%s", logMessage.toLocal8Bit().constData()); + fprintf(stderr, "%s\n", logMessage.toLocal8Bit().constData()); fflush(stderr); } @@ -1380,7 +1379,7 @@ static void qt_message_print(QtMsgType msgType, const QMessageLogContext &contex } ungrabMessageHandler(); } else { - fprintf(stderr, "%s", message.toLocal8Bit().constData()); + fprintf(stderr, "%s\n", message.toLocal8Bit().constData()); } } @@ -1579,7 +1578,7 @@ void qErrnoWarning(int code, const char *msg, ...) The default \a pattern is "%{if-category}%{category}: %{endif}%{message}". The \a pattern can also be changed at runtime by setting the QT_MESSAGE_PATTERN - environment variable; if both qSetMessagePattern() is called and QT_MESSAGE_PATTERN is + environment variable; if both \l qSetMessagePattern() is called and QT_MESSAGE_PATTERN is set, the environment variable takes precedence. Custom message handlers can use qFormatLogMessage() to take \a pattern into account. diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 4e074bcdb5e..53d2b7b58b5 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -134,7 +134,7 @@ \value AA_MacDontSwapCtrlAndMeta On Mac OS X by default, Qt swaps the Control and Meta (Command) keys (i.e., whenever Control is pressed, Qt sends Meta, and whenever Meta is pressed Control is sent). When this - attribute is true, Qt will not do the flip. QKeySequence::StandardShortcuts + attribute is true, Qt will not do the flip. \l QKeySequence::StandardKey will also flip accordingly (i.e., QKeySequence::Copy will be Command+C on the keyboard regardless of the value set, though what is output for QKeySequence::toString(QKeySequence::PortableText) will be different). @@ -144,7 +144,7 @@ to be consistent in pixels-per-point across devices rather than defining 1 point as 1/72 inch. - \value AA_X11InitThreads Calls XInitThreads() as part of the QApplication + \value AA_X11InitThreads Calls \c XInitThreads() as part of the QApplication construction in order to make Xlib calls thread-safe. This attribute must be set before QApplication is constructed. @@ -159,10 +159,11 @@ \value AA_UseHighDpiPixmaps Make QIcon::pixmap() generate high-dpi pixmaps that can be larger than the requested size. Such pixmaps will have - devicePixelRatio set to a value higher than 1. After setting this - attribute application code that uses pixmap sizes in layout geometry - calculations should typically divide by QPixmap::devicePixelRatio() - to get device-independent layout geometry. + \l {QPixmap::devicePixelRatio}{devicePixelRatio()} set to a value higher than 1. + + After setting this attribute, application code that uses pixmap + sizes in layout geometry calculations should typically divide by + \l {QPixmap::devicePixelRatio}{devicePixelRatio()} to get device-independent layout geometry. \value AA_ForceRasterWidgets Make top-level widgets use pure raster surfaces, and do not support non-native GL-based child widgets. @@ -182,7 +183,7 @@ \l{http://www.mesa3d.org/llvmpipe.html}{Mesa llvmpipe}, providing OpenGL 2.1. The value may have no effect if no such OpenGL implementation is available. The default name of this library is - opengl32sw.dll and can be overridden by setting the environment + \c opengl32sw.dll and can be overridden by setting the environment variable \e QT_OPENGL_DLL. See the platform-specific pages, for instance \l{Qt for Windows}, for more information. This value has been added in Qt 5.4. @@ -221,7 +222,7 @@ \value AllButtons This value corresponds to a mask of all possible mouse buttons. Use to set the 'acceptedButtons' - property of a mouseArea to accept ALL mouse buttons. + property of a MouseArea to accept ALL mouse buttons. \value LeftButton The left button is pressed, or an event refers to the left button. (The left button may be the right button on @@ -2443,7 +2444,7 @@ \value ImhExclusiveInputMask This mask yields nonzero if any of the exclusive flags are used. - \note If several exclusive flags are ORed together, the resulting character set will + \note If several exclusive flags are OR-ed together, the resulting character set will consist of the union of the specified sets. For instance specifying \c ImhNumbersOnly and \c ImhUppercaseOnly would yield a set consisting of numbers and uppercase letters. @@ -2803,11 +2804,11 @@ This enum type describes the state of a gesture. + \value NoGesture No gesture has been detected. \value GestureStarted A continuous gesture has started. \value GestureUpdated A gesture continues. \value GestureFinished A gesture has finished. \value GestureCanceled A gesture was canceled. - \omitvalue NoGesture \sa QGesture */ @@ -2969,8 +2970,8 @@ This enum provides additional information concerning a QMouseEvent. \value MouseEventCreatedDoubleClick Indicates that Qt has created a - MouseButtonDblClick event from this event. The flag is set in the causing - MouseButtonPress, and not in the resulting MouseButtonDblCLick. + \l {QEvent::MouseButtonDblClick}{MouseButtonDblClick} event from this event. The flag is set in the causing + \l {QEvent::MouseButtonPress}{MouseButtonPress}, and not in the resulting \l {QEvent::MouseButtonDblClick}{MouseButtonDblClick}. \omitvalue MouseEventFlagMask */ diff --git a/src/corelib/global/qprocessordetection.h b/src/corelib/global/qprocessordetection.h index 26ac56396b7..55cb31c62b9 100644 --- a/src/corelib/global/qprocessordetection.h +++ b/src/corelib/global/qprocessordetection.h @@ -87,9 +87,9 @@ ARM is bi-endian, detect using __ARMEL__ or __ARMEB__, falling back to auto-detection implemented below. */ -#if defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_M_ARM) || defined(__arm64__) +#if defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_M_ARM) || defined(__aarch64__) # define Q_PROCESSOR_ARM -# if defined(__arm64__) +# if defined(__aarch64__) # define Q_PROCESSOR_ARM_64 # else # define Q_PROCESSOR_ARM_32 diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index bdc362ef22f..77788e3cca3 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -148,9 +148,8 @@ win32 { HEADERS += io/qfilesystemwatcher_fsevents_p.h } macx { - SOURCES += \ - io/qstorageinfo_mac.cpp \ - io/qstandardpaths_mac.cpp + SOURCES += io/qstorageinfo_mac.cpp + OBJECTIVE_SOURCES += io/qstandardpaths_mac.mm LIBS += -framework DiskArbitration -framework IOKit } else:ios { OBJECTIVE_SOURCES += io/qstandardpaths_ios.mm diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp index 8d757a77733..60f04ce4f10 100644 --- a/src/corelib/io/qdatastream.cpp +++ b/src/corelib/io/qdatastream.cpp @@ -261,12 +261,6 @@ QDataStream::QDataStream() /*! Constructs a data stream that uses the I/O device \a d. - \warning If you use QSocket or QSocketDevice as the I/O device \a d - for reading data, you must make sure that enough data is available - on the socket for the operation to successfully proceed; - QDataStream does not have any means to handle or recover from - short-reads. - \sa setDevice(), device() */ diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index 42250b629dc..a1266902406 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -73,6 +73,17 @@ QT_BEGIN_NAMESPACE # endif #endif +#ifdef Q_OS_WIN +// on Windows, read() and write() use int and unsigned int +typedef int SignedIOType; +typedef unsigned int UnsignedIOType; +#else +typedef ssize_t SignedIOType; +typedef size_t UnsignedIOType; +Q_STATIC_ASSERT_X(sizeof(SignedIOType) == sizeof(UnsignedIOType), + "Unsupported: read/write return a type with different size as the len parameter"); +#endif + /*! \class QFSFileEngine \inmodule QtCore \brief The QFSFileEngine class implements Qt's default file engine. @@ -605,13 +616,16 @@ qint64 QFSFileEnginePrivate::readFdFh(char *data, qint64 len) } else if (fd != -1) { // Unbuffered stdio mode. -#ifdef Q_OS_WIN - int result; -#else - ssize_t result; -#endif + SignedIOType result; do { - result = QT_READ(fd, data + readBytes, size_t(len - readBytes)); + // calculate the chunk size + // on Windows or 32-bit no-largefile Unix, we'll need to read in chunks + // we limit to the size of the signed type, otherwise we could get a negative number as a result + quint64 wantedBytes = quint64(len) - quint64(readBytes); + UnsignedIOType chunkSize = std::numeric_limits::max(); + if (chunkSize > wantedBytes) + chunkSize = wantedBytes; + result = QT_READ(fd, data + readBytes, chunkSize); } while (result > 0 && (readBytes += result) < len); eof = !(result == -1); @@ -722,13 +736,16 @@ qint64 QFSFileEnginePrivate::writeFdFh(const char *data, qint64 len) } else if (fd != -1) { // Unbuffered stdio mode. -#ifdef Q_OS_WIN - int result; -#else - ssize_t result; -#endif + SignedIOType result; do { - result = QT_WRITE(fd, data + writtenBytes, size_t(len - writtenBytes)); + // calculate the chunk size + // on Windows or 32-bit no-largefile Unix, we'll need to read in chunks + // we limit to the size of the signed type, otherwise we could get a negative number as a result + quint64 wantedBytes = quint64(len) - quint64(writtenBytes); + UnsignedIOType chunkSize = std::numeric_limits::max(); + if (chunkSize > wantedBytes) + chunkSize = wantedBytes; + result = QT_WRITE(fd, data + writtenBytes, chunkSize); } while (result > 0 && (writtenBytes += result) < len); } diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 08964328377..36f88f27744 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -788,7 +788,7 @@ qint64 QIODevice::read(char *data, qint64 maxSize) char *readPtr = data; forever { // Try reading from the buffer. - int bufferReadChunkSize = d->buffer.read(data, maxSize); + qint64 bufferReadChunkSize = d->buffer.read(data, maxSize); if (bufferReadChunkSize > 0) { *d->pPos += bufferReadChunkSize; readSoFar += bufferReadChunkSize; diff --git a/src/corelib/io/qiodevice_p.h b/src/corelib/io/qiodevice_p.h index 10d92a896d7..d764cb0fbb0 100644 --- a/src/corelib/io/qiodevice_p.h +++ b/src/corelib/io/qiodevice_p.h @@ -98,19 +98,19 @@ public: first++; return ch; } - int read(char* target, qint64 size) { - int r = qMin(size, len); + qint64 read(char* target, qint64 size) { + qint64 r = qMin(size, len); memcpy(target, first, r); len -= r; first += r; return r; } - int peek(char* target, qint64 size) { - int r = qMin(size, len); + qint64 peek(char* target, qint64 size) { + qint64 r = qMin(size, len); memcpy(target, first, r); return r; } - char* reserve(int size) { + char* reserve(qint64 size) { makeSpace(size + len, freeSpaceAtEnd); char* writePtr = first + len; len += size; @@ -128,16 +128,16 @@ public: clear(); return retVal; } - int readLine(char* target, qint64 size) { - int r = qMin(size, len); + qint64 readLine(char* target, qint64 size) { + qint64 r = qMin(size, len); char* eol = static_cast(memchr(first, '\n', r)); if (eol) r = 1+(eol-first); memcpy(target, first, r); len -= r; first += r; - return int(r); - } + return r; + } bool canReadLine() const { return memchr(first, '\n', len); } diff --git a/src/corelib/io/qlockfile.cpp b/src/corelib/io/qlockfile.cpp index 18a782a8f3e..c2565074308 100644 --- a/src/corelib/io/qlockfile.cpp +++ b/src/corelib/io/qlockfile.cpp @@ -287,7 +287,7 @@ bool QLockFilePrivate::getLockInfo(qint64 *pid, QString *hostname, QString *appn appNameLine.chop(1); QByteArray hostNameLine = reader.readLine(); hostNameLine.chop(1); - if (pidLine.isEmpty() || appNameLine.isEmpty()) + if (pidLine.isEmpty()) return false; qint64 thePid = pidLine.toLongLong(); diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index 2fe93f0af65..3ed973494bf 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -183,7 +183,7 @@ bool QLockFilePrivate::isApparentlyStale() const QString hostname, appname; if (!getLockInfo(&pid, &hostname, &appname)) return false; - if (hostname == QString::fromLocal8Bit(localHostName())) { + if (hostname.isEmpty() || hostname == QString::fromLocal8Bit(localHostName())) { if (::kill(pid, 0) == -1 && errno == ESRCH) return true; // PID doesn't exist anymore } diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index d896da176ae..ebca7d57ffa 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -1637,6 +1637,15 @@ bool QConfFileSettingsPrivate::readIniFile(const QByteArray &data, int sectionPosition = 0; bool ok = true; +#ifndef QT_NO_TEXTCODEC + // detect utf8 BOM + const uchar *dd = (const uchar *)data.constData(); + if (data.size() >= 3 && dd[0] == 0xef && dd[1] == 0xbb && dd[2] == 0xbf) { + iniCodec = QTextCodec::codecForName("UTF-8"); + dataPos = 3; + } +#endif + while (readIniLine(data, dataPos, lineStart, lineLen, equalsPos)) { char ch = data.at(lineStart); if (ch == '[') { diff --git a/src/corelib/io/qsettings_mac.cpp b/src/corelib/io/qsettings_mac.cpp index 4752077f876..344bec03090 100644 --- a/src/corelib/io/qsettings_mac.cpp +++ b/src/corelib/io/qsettings_mac.cpp @@ -235,8 +235,10 @@ static QVariant qtValue(CFPropertyListRef cfvalue) int i; qint64 ll; - if (CFNumberGetValue(cfnumber, kCFNumberIntType, &i)) + if (CFNumberGetType(cfnumber) == kCFNumberIntType) { + CFNumberGetValue(cfnumber, kCFNumberIntType, &i); return i; + } CFNumberGetValue(cfnumber, kCFNumberLongLongType, &ll); return ll; } diff --git a/src/corelib/io/qsettings_p.h b/src/corelib/io/qsettings_p.h index cb29b4c83a4..715f13530a3 100644 --- a/src/corelib/io/qsettings_p.h +++ b/src/corelib/io/qsettings_p.h @@ -282,7 +282,7 @@ public: bool isWritable() const; QString fileName() const; - static bool readIniFile(const QByteArray &data, UnparsedSettingsMap *unparsedIniSections); + bool readIniFile(const QByteArray &data, UnparsedSettingsMap *unparsedIniSections); static bool readIniSection(const QSettingsKey §ion, const QByteArray &data, ParsedSettingsMap *settingsMap, QTextCodec *codec); static bool readIniLine(const QByteArray &data, int &dataPos, int &lineStart, int &lineLen, diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp index 2583e46ad85..6950d58fdae 100644 --- a/src/corelib/io/qstandardpaths.cpp +++ b/src/corelib/io/qstandardpaths.cpp @@ -195,7 +195,7 @@ QT_BEGIN_NAMESPACE \li "~/Library/Preferences" \li "C:/Users//AppData/Local", "C:/ProgramData" \row \li DownloadLocation - \li "~/Documents" + \li "~/Downloads" \li "C:/Users//Documents" \row \li GenericCacheLocation \li "~/Library/Caches", "/Library/Caches" @@ -526,7 +526,7 @@ QString QStandardPaths::findExecutable(const QString &executableName, const QStr an empty QString if no relevant location can be found. */ -#if !defined(Q_OS_MAC) && !defined(QT_BOOTSTRAPPED) +#if !defined(Q_OS_OSX) && !defined(QT_BOOTSTRAPPED) QString QStandardPaths::displayName(StandardLocation type) { switch (type) { diff --git a/src/corelib/io/qstandardpaths_ios.mm b/src/corelib/io/qstandardpaths_ios.mm index cdca28b8b56..9b500f4623d 100644 --- a/src/corelib/io/qstandardpaths_ios.mm +++ b/src/corelib/io/qstandardpaths_ios.mm @@ -92,6 +92,8 @@ QString QStandardPaths::writableLocation(StandardLocation type) break; case AppDataLocation: case AppLocalDataLocation: + location = pathForDirectory(NSApplicationSupportDirectory); + break; case GenericDataLocation: location = pathForDirectory(NSDocumentDirectory); break; diff --git a/src/corelib/io/qstandardpaths_mac.cpp b/src/corelib/io/qstandardpaths_mac.mm similarity index 94% rename from src/corelib/io/qstandardpaths_mac.cpp rename to src/corelib/io/qstandardpaths_mac.mm index 673b734d40a..01d1c01f784 100644 --- a/src/corelib/io/qstandardpaths_mac.cpp +++ b/src/corelib/io/qstandardpaths_mac.mm @@ -33,6 +33,7 @@ #include "qstandardpaths.h" #include +#include #include #ifndef QT_BOOTSTRAPPED @@ -55,8 +56,6 @@ OSType translateLocation(QStandardPaths::StandardLocation type) return kPreferencesFolderType; case QStandardPaths::DesktopLocation: return kDesktopFolderType; - case QStandardPaths::DownloadLocation: // needs NSSearchPathForDirectoriesInDomains with NSDownloadsDirectory - // which needs an objective-C *.mm file... case QStandardPaths::DocumentsLocation: return kDocumentsFolderType; case QStandardPaths::FontsLocation: @@ -113,6 +112,15 @@ static void appendOrganizationAndApp(QString &path) static QString macLocation(QStandardPaths::StandardLocation type, short domain) { + // https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/index.html + if (type == QStandardPaths::DownloadLocation) { + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSURL *url = [fileManager URLForDirectory:NSDownloadsDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil]; + if (!url) + return QString(); + return QString::fromNSString([url path]); + } + // http://developer.apple.com/documentation/Carbon/Reference/Folder_Manager/Reference/reference.html FSRef ref; OSErr err = FSFindFolder(domain, translateLocation(type), false, &ref); diff --git a/src/corelib/io/qstandardpaths_unix.cpp b/src/corelib/io/qstandardpaths_unix.cpp index 469c223b000..2ad6dfa1214 100644 --- a/src/corelib/io/qstandardpaths_unix.cpp +++ b/src/corelib/io/qstandardpaths_unix.cpp @@ -131,10 +131,13 @@ QString QStandardPaths::writableLocation(StandardLocation type) return QString(); } // "and he MUST be the only one having read and write access to it. Its Unix access mode MUST be 0700." + // since the current user is the owner, set both xxxUser and xxxOwner QFile file(xdgRuntimeDir); - const QFile::Permissions wantedPerms = QFile::ReadUser | QFile::WriteUser | QFile::ExeUser; + const QFile::Permissions wantedPerms = QFile::ReadUser | QFile::WriteUser | QFile::ExeUser + | QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner; if (file.permissions() != wantedPerms && !file.setPermissions(wantedPerms)) { - qWarning("QStandardPaths: wrong permissions on runtime directory %s", qPrintable(xdgRuntimeDir)); + qWarning("QStandardPaths: could not set correct permissions on runtime directory %s: %s", + qPrintable(xdgRuntimeDir), qPrintable(file.errorString())); return QString(); } return xdgRuntimeDir; diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp index ca5903ae36d..bec7420dc79 100644 --- a/src/corelib/io/qstorageinfo_unix.cpp +++ b/src/corelib/io/qstorageinfo_unix.cpp @@ -90,17 +90,16 @@ static bool isPseudoFs(const QString &mountDir, const QByteArray &type) { if (mountDir.startsWith(QLatin1String("/dev")) || mountDir.startsWith(QLatin1String("/proc")) - || mountDir.startsWith(QLatin1String("/run")) || mountDir.startsWith(QLatin1String("/sys")) || mountDir.startsWith(QLatin1String("/var/run")) || mountDir.startsWith(QLatin1String("/var/lock"))) { return true; } -#if defined(Q_OS_LINUX) - if (type == "rootfs") + if (type == "tmpfs") + return true; +#if defined(Q_OS_LINUX) + if (type == "rootfs" || type == "rpc_pipefs") return true; -#else - Q_UNUSED(type); #endif return false; diff --git a/src/corelib/io/qstorageinfo_win.cpp b/src/corelib/io/qstorageinfo_win.cpp index 1ab34e56d4a..51a268f58c2 100644 --- a/src/corelib/io/qstorageinfo_win.cpp +++ b/src/corelib/io/qstorageinfo_win.cpp @@ -45,7 +45,7 @@ #include #include -#include +#include QT_BEGIN_NAMESPACE diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index d4c5e030586..b21e9b51e16 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -403,6 +403,7 @@ #include "qdebug.h" #include "qhash.h" #include "qdir.h" // for QDir::fromNativeSeparators +#include "qdatastream.h" #include "qtldurl_p.h" #include "private/qipaddress_p.h" #include "qurlquery.h" @@ -429,6 +430,16 @@ static inline QString fileScheme() return QStringLiteral("file"); } +static inline QString webDavScheme() +{ + return QStringLiteral("webdavs"); +} + +static inline QString webDavSslTag() +{ + return QStringLiteral("@SSL"); +} + #ifdef Q_COMPILER_CLASS_ENUM # define colon_uchar : uchar #else @@ -992,10 +1003,15 @@ inline bool QUrlPrivate::setScheme(const QString &value, int len, bool doSetErro } // did we set to the file protocol? - if (scheme == fileScheme()) + if (scheme == fileScheme() +#ifdef Q_OS_WIN + || scheme == webDavScheme() +#endif + ) { flags |= IsLocalFile; - else + } else { flags &= ~IsLocalFile; + } return true; } @@ -3738,7 +3754,7 @@ QUrl QUrl::fromLocalFile(const QString &localFile) QUrl url; if (localFile.isEmpty()) return url; - url.setScheme(fileScheme()); + QString scheme = fileScheme(); QString deslashified = QDir::fromNativeSeparators(localFile); // magic for drives on windows @@ -3747,13 +3763,21 @@ QUrl QUrl::fromLocalFile(const QString &localFile) } else if (deslashified.startsWith(QLatin1String("//"))) { // magic for shared drive on windows int indexOfPath = deslashified.indexOf(QLatin1Char('/'), 2); - url.setHost(deslashified.mid(2, indexOfPath - 2)); + QString hostSpec = deslashified.mid(2, indexOfPath - 2); + // Check for Windows-specific WebDAV specification: "//host@SSL/path". + if (hostSpec.endsWith(webDavSslTag(), Qt::CaseInsensitive)) { + hostSpec.chop(4); + scheme = webDavScheme(); + } + url.setHost(hostSpec); + if (indexOfPath > 2) deslashified = deslashified.right(deslashified.length() - indexOfPath); else deslashified.clear(); } + url.setScheme(scheme); url.setPath(deslashified, DecodedMode); return url; } @@ -3783,8 +3807,14 @@ QString QUrl::toLocalFile() const // magic for shared drive on windows if (!d->host.isEmpty()) { - tmp = QStringLiteral("//") + host() + (ourPath.length() > 0 && ourPath.at(0) != QLatin1Char('/') - ? QLatin1Char('/') + ourPath : ourPath); + tmp = QStringLiteral("//") + host(); +#ifdef Q_OS_WIN // QTBUG-42346, WebDAV is visible as local file on Windows only. + if (scheme() == webDavScheme()) + tmp += webDavSslTag(); +#endif + if (!ourPath.isEmpty() && !ourPath.startsWith(QLatin1Char('/'))) + tmp += QLatin1Char('/'); + tmp += ourPath; } else { tmp = ourPath; #ifdef Q_OS_WIN diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp index 74a7ea19889..a9cfa3e7cae 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.cpp +++ b/src/corelib/itemmodels/qabstractitemmodel.cpp @@ -1552,13 +1552,13 @@ QAbstractItemModel::~QAbstractItemModel() */ /*! - \fn void QAbstractItemModel::rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow) + \fn void QAbstractItemModel::rowsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row) \since 4.6 This signal is emitted after rows have been moved within the - model. The items between \a sourceStart and \a sourceEnd - inclusive, under the given \a sourceParent item have been moved to \a destinationParent - starting at the row \a destinationRow. + model. The items between \a start and \a end + inclusive, under the given \a parent item have been moved to \a destination + starting at the row \a row. \b{Note:} Components connected to this signal use it to adapt to changes in the model's dimensions. It can only be emitted by the QAbstractItemModel @@ -1584,13 +1584,13 @@ QAbstractItemModel::~QAbstractItemModel() */ /*! - \fn void QAbstractItemModel::columnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn) + \fn void QAbstractItemModel::columnsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int column) \since 4.6 This signal is emitted after columns have been moved within the - model. The items between \a sourceStart and \a sourceEnd - inclusive, under the given \a sourceParent item have been moved to \a destinationParent - starting at the column \a destinationColumn. + model. The items between \a start and \a end + inclusive, under the given \a parent item have been moved to \a destination + starting at the column \a column. \b{Note:} Components connected to this signal use it to adapt to changes in the model's dimensions. It can only be emitted by the QAbstractItemModel @@ -1842,7 +1842,9 @@ QMimeData *QAbstractItemModel::mimeData(const QModelIndexList &indexes) const /*! Returns \c{true} if a model can accept a drop of the \a data. This - default implementation always returns \c{true}. + default implementation only checks if \a data has at least one format + in the list of mimeTypes() and if \a action is among the + model's supportedDropActions(). Reimplement this function in your custom model, if you want to test whether the \a data can be dropped at \a row, \a column, @@ -1855,12 +1857,19 @@ bool QAbstractItemModel::canDropMimeData(const QMimeData *data, Qt::DropAction a int row, int column, const QModelIndex &parent) const { - Q_UNUSED(data) - Q_UNUSED(action) Q_UNUSED(row) Q_UNUSED(column) Q_UNUSED(parent) - return true; + + if (!(action & supportedDropActions())) + return false; + + const QStringList modelTypes = mimeTypes(); + for (int i = 0; i < modelTypes.count(); ++i) { + if (data->hasFormat(modelTypes.at(i))) + return true; + } + return false; } /*! @@ -2711,7 +2720,7 @@ bool QAbstractItemModelPrivate::allowMove(const QModelIndex &srcParent, int star persistent indexes in the model, which you would otherwise be required to do yourself. Using beginMoveRows and endMoveRows is an alternative to emitting layoutAboutToBeChanged and - layoutChanged directly along with changePersistentIndexes. + layoutChanged directly along with changePersistentIndex. The \a sourceParent index corresponds to the parent from which the rows are moved; \a sourceFirst and \a sourceLast are the first and last @@ -2978,7 +2987,7 @@ void QAbstractItemModel::endRemoveColumns() persistent indexes in the model, which you would otherwise be required to do yourself. Using beginMoveRows and endMoveRows is an alternative to emitting layoutAboutToBeChanged and - layoutChanged directly along with changePersistentIndexes. + layoutChanged directly along with changePersistentIndex. The \a sourceParent index corresponds to the parent from which the columns are moved; \a sourceFirst and \a sourceLast are the first and last @@ -3165,11 +3174,11 @@ void QAbstractItemModel::changePersistentIndex(const QModelIndex &from, const QM /*! \since 4.1 - Changes the QPersistentModelIndexes that is equal to the indexes in the + Changes the {QPersistentModelIndex}es that are equal to the indexes in the given \a from model index list to the given \a to model index list. If no persistent model indexes equal to the indexes in the given \a from - model index list was found, nothing is changed. + model index list are found, nothing is changed. \sa persistentIndexList(), changePersistentIndex() */ diff --git a/src/corelib/itemmodels/qabstractproxymodel.cpp b/src/corelib/itemmodels/qabstractproxymodel.cpp index ce262931834..b7f988ef7c4 100644 --- a/src/corelib/itemmodels/qabstractproxymodel.cpp +++ b/src/corelib/itemmodels/qabstractproxymodel.cpp @@ -384,6 +384,26 @@ QMimeData* QAbstractProxyModel::mimeData(const QModelIndexList &indexes) const return d->model->mimeData(list); } +void QAbstractProxyModelPrivate::mapDropCoordinatesToSource(int row, int column, const QModelIndex &parent, + int *sourceRow, int *sourceColumn, QModelIndex *sourceParent) const +{ + Q_Q(const QAbstractProxyModel); + *sourceRow = -1; + *sourceColumn = -1; + if (row == -1 && column == -1) { + *sourceParent = q->mapToSource(parent); + } else if (row == q->rowCount(parent)) { + *sourceParent = q->mapToSource(parent); + *sourceRow = model->rowCount(*sourceParent); + } else { + QModelIndex proxyIndex = q->index(row, column, parent); + QModelIndex sourceIndex = q->mapToSource(proxyIndex); + *sourceRow = sourceIndex.row(); + *sourceColumn = sourceIndex.column(); + *sourceParent = sourceIndex.parent(); + } +} + /*! \reimp \since 5.4 @@ -392,8 +412,11 @@ bool QAbstractProxyModel::canDropMimeData(const QMimeData *data, Qt::DropAction int row, int column, const QModelIndex &parent) const { Q_D(const QAbstractProxyModel); - const QModelIndex source = mapToSource(index(row, column, parent)); - return d->model->canDropMimeData(data, action, source.row(), source.column(), source.parent()); + int sourceDestinationRow; + int sourceDestinationColumn; + QModelIndex sourceParent; + d->mapDropCoordinatesToSource(row, column, parent, &sourceDestinationRow, &sourceDestinationColumn, &sourceParent); + return d->model->canDropMimeData(data, action, sourceDestinationRow, sourceDestinationColumn, sourceParent); } /*! @@ -404,8 +427,11 @@ bool QAbstractProxyModel::dropMimeData(const QMimeData *data, Qt::DropAction act int row, int column, const QModelIndex &parent) { Q_D(QAbstractProxyModel); - const QModelIndex source = mapToSource(index(row, column, parent)); - return d->model->dropMimeData(data, action, source.row(), source.column(), source.parent()); + int sourceDestinationRow; + int sourceDestinationColumn; + QModelIndex sourceParent; + d->mapDropCoordinatesToSource(row, column, parent, &sourceDestinationRow, &sourceDestinationColumn, &sourceParent); + return d->model->dropMimeData(data, action, sourceDestinationRow, sourceDestinationColumn, sourceParent); } /*! diff --git a/src/corelib/itemmodels/qabstractproxymodel_p.h b/src/corelib/itemmodels/qabstractproxymodel_p.h index 9402092fa85..24af5afc649 100644 --- a/src/corelib/itemmodels/qabstractproxymodel_p.h +++ b/src/corelib/itemmodels/qabstractproxymodel_p.h @@ -59,6 +59,8 @@ public: QAbstractProxyModelPrivate() : QAbstractItemModelPrivate(), model(0) {} QAbstractItemModel *model; virtual void _q_sourceModelDestroyed(); + void mapDropCoordinatesToSource(int row, int column, const QModelIndex &parent, + int *source_row, int *source_column, QModelIndex *source_parent) const; }; QT_END_NAMESPACE diff --git a/src/corelib/itemmodels/qitemselectionmodel.cpp b/src/corelib/itemmodels/qitemselectionmodel.cpp index db78af8cf8e..5395fd5d096 100644 --- a/src/corelib/itemmodels/qitemselectionmodel.cpp +++ b/src/corelib/itemmodels/qitemselectionmodel.cpp @@ -1076,7 +1076,7 @@ void QItemSelectionModelPrivate::_q_layoutChanged(const QListmapFromSource(source_parent); emit q->layoutAboutToBeChanged(parents, QAbstractItemModel::VerticalSortHint); QModelIndexPairList source_indexes = store_persistent_indexes(); - remove_source_items(m->proxy_rows, m->source_rows, source_rows_resort, - source_parent, Qt::Vertical, false); - sort_source_rows(source_rows_resort, source_parent); - insert_source_items(m->proxy_rows, m->source_rows, source_rows_resort, - source_parent, Qt::Vertical, false); + sort_source_rows(m->source_rows, source_parent); update_persistent_indexes(source_indexes); emit q->layoutChanged(parents, QAbstractItemModel::VerticalSortHint); // Make sure we also emit dataChanged for the rows @@ -2034,30 +2030,14 @@ Qt::DropActions QSortFilterProxyModel::supportedDropActions() const return d->model->supportedDropActions(); } +// Qt6: remove unnecessary reimplementation /*! \reimp */ bool QSortFilterProxyModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) { - Q_D(QSortFilterProxyModel); - if ((row == -1) && (column == -1)) - return d->model->dropMimeData(data, action, -1, -1, mapToSource(parent)); - int source_destination_row = -1; - int source_destination_column = -1; - QModelIndex source_parent; - if (row == rowCount(parent)) { - source_parent = mapToSource(parent); - source_destination_row = d->model->rowCount(source_parent); - } else { - QModelIndex proxy_index = index(row, column, parent); - QModelIndex source_index = mapToSource(proxy_index); - source_destination_row = source_index.row(); - source_destination_column = source_index.column(); - source_parent = source_index.parent(); - } - return d->model->dropMimeData(data, action, source_destination_row, - source_destination_column, source_parent); + return QAbstractProxyModel::dropMimeData(data, action, row, column, parent); } /*! diff --git a/src/corelib/json/qjsonarray.cpp b/src/corelib/json/qjsonarray.cpp index fd407af2cdc..73c53ea649b 100644 --- a/src/corelib/json/qjsonarray.cpp +++ b/src/corelib/json/qjsonarray.cpp @@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE removing QJsonValue's from the array. A QJsonArray can be converted to and from a QVariantList. You can query the - number of entries with size(), insert(), and remove() entries from it + number of entries with size(), insert(), and removeAt() entries from it and iterate over its content using the standard C++ iterator pattern. QJsonArray is an implicitly shared class and shares the data with the document diff --git a/src/corelib/json/qjsonarray.h b/src/corelib/json/qjsonarray.h index 87d14a7703f..a8307ae5aab 100644 --- a/src/corelib/json/qjsonarray.h +++ b/src/corelib/json/qjsonarray.h @@ -105,6 +105,7 @@ public: typedef int difference_type; typedef QJsonValue value_type; typedef QJsonValueRef reference; + typedef QJsonValueRefPtr pointer; inline iterator() : a(0), i(0) { } explicit inline iterator(QJsonArray *array, int index) : a(array), i(index) { } @@ -149,6 +150,7 @@ public: typedef qptrdiff difference_type; typedef QJsonValue value_type; typedef QJsonValue reference; + typedef QJsonValuePtr pointer; inline const_iterator() : a(0), i(0) { } explicit inline const_iterator(const QJsonArray *array, int index) : a(array), i(index) { } diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 45647f2056d..77900ba906c 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -714,9 +714,7 @@ void QCoreApplication::init() Q_ASSERT_X(!self, "QCoreApplication", "there should be only one application object"); QCoreApplication::self = this; -#ifndef QT_BOOTSTRAPPED QLoggingRegistry::instance()->init(); -#endif #ifndef QT_NO_QOBJECT // use the event dispatcher created by the app programmer (if any) diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index a3d00faf31f..1a8bb381aa9 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -307,8 +307,9 @@ static void resolveTimerAPI() } QEventDispatcherWin32Private::QEventDispatcherWin32Private() - : threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0), getMessageHook(0), - serialNumber(0), lastSerialNumber(0), sendPostedEventsWindowsTimerId(0), wakeUps(0) + : threadId(GetCurrentThreadId()), interrupt(false), closingDown(false), internalHwnd(0), + getMessageHook(0), serialNumber(0), lastSerialNumber(0), sendPostedEventsWindowsTimerId(0), + wakeUps(0) { resolveTimerAPI(); } @@ -434,9 +435,10 @@ static inline UINT inputTimerMask() LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp) { + QEventDispatcherWin32 *q = qobject_cast(QAbstractEventDispatcher::instance()); + Q_ASSERT(q != 0); + if (wp == PM_REMOVE) { - QEventDispatcherWin32 *q = qobject_cast(QAbstractEventDispatcher::instance()); - Q_ASSERT(q != 0); if (q) { MSG *msg = (MSG *) lp; QEventDispatcherWin32Private *d = q->d_func(); @@ -472,7 +474,7 @@ LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp) #ifdef Q_OS_WINCE return 0; #else - return CallNextHookEx(0, code, wp, lp); + return q->d_func()->getMessageHook ? CallNextHookEx(0, code, wp, lp) : 0; #endif } @@ -643,15 +645,7 @@ void QEventDispatcherWin32::createInternalHwnd() return; d->internalHwnd = qt_create_internal_window(this); -#ifndef Q_OS_WINCE - // setup GetMessage hook needed to drive our posted events - d->getMessageHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC) qt_GetMessageHook, NULL, GetCurrentThreadId()); - if (!d->getMessageHook) { - int errorCode = GetLastError(); - qFatal("Qt: INTERNAL ERROR: failed to install GetMessage hook: %d, %s", - errorCode, qPrintable(qt_error_string(errorCode))); - } -#endif + installMessageHook(); // register all socket notifiers QList sockets = (d->sn_read.keys().toSet() @@ -665,6 +659,35 @@ void QEventDispatcherWin32::createInternalHwnd() d->registerTimer(d->timerVec.at(i)); } +void QEventDispatcherWin32::installMessageHook() +{ + Q_D(QEventDispatcherWin32); + + if (d->getMessageHook) + return; + +#ifndef Q_OS_WINCE + // setup GetMessage hook needed to drive our posted events + d->getMessageHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC) qt_GetMessageHook, NULL, GetCurrentThreadId()); + if (!d->getMessageHook) { + int errorCode = GetLastError(); + qFatal("Qt: INTERNAL ERROR: failed to install GetMessage hook: %d, %s", + errorCode, qPrintable(qt_error_string(errorCode))); + } +#endif +} + +void QEventDispatcherWin32::uninstallMessageHook() +{ + Q_D(QEventDispatcherWin32); + +#ifndef Q_OS_WINCE + if (d->getMessageHook) + UnhookWindowsHookEx(d->getMessageHook); +#endif + d->getMessageHook = 0; +} + QEventDispatcherWin32::QEventDispatcherWin32(QObject *parent) : QAbstractEventDispatcher(*new QEventDispatcherWin32Private, parent) { @@ -750,10 +773,9 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) } } if (haveMessage) { -#ifdef Q_OS_WINCE // WinCE doesn't support hooks at all, so we have to call this by hand :( - (void) qt_GetMessageHook(0, PM_REMOVE, (LPARAM) &msg); -#endif + if (!d->getMessageHook) + (void) qt_GetMessageHook(0, PM_REMOVE, (LPARAM) &msg); if (d->internalHwnd == msg.hwnd && msg.message == WM_QT_SENDPOSTEDEVENTS) { if (seenWM_QT_SENDPOSTEDEVENTS) { @@ -910,6 +932,11 @@ void QEventDispatcherWin32::registerTimer(int timerId, int interval, Qt::TimerTy Q_D(QEventDispatcherWin32); + // exiting ... do not register new timers + // (QCoreApplication::closingDown() is set too late to be used here) + if (d->closingDown) + return; + WinTimerInfo *t = new WinTimerInfo; t->dispatcher = this; t->timerId = timerId; @@ -1134,11 +1161,9 @@ void QEventDispatcherWin32::closingDown() d->timerVec.clear(); d->timerDict.clear(); -#ifndef Q_OS_WINCE - if (d->getMessageHook) - UnhookWindowsHookEx(d->getMessageHook); - d->getMessageHook = 0; -#endif + d->closingDown = true; + + uninstallMessageHook(); } bool QEventDispatcherWin32::event(QEvent *e) diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index 369c2766150..8022299a769 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -67,6 +67,8 @@ class Q_CORE_EXPORT QEventDispatcherWin32 : public QAbstractEventDispatcher protected: void createInternalHwnd(); + void installMessageHook(); + void uninstallMessageHook(); public: explicit QEventDispatcherWin32(QObject *parent = 0); @@ -145,6 +147,7 @@ public: DWORD threadId; bool interrupt; + bool closingDown; // internal window handle used for socketnotifiers/timers/etc HWND internalHwnd; diff --git a/src/corelib/kernel/qjni.cpp b/src/corelib/kernel/qjni.cpp index 452e3464d65..b179323fdc0 100644 --- a/src/corelib/kernel/qjni.cpp +++ b/src/corelib/kernel/qjni.cpp @@ -311,7 +311,7 @@ QJNIObjectPrivate::QJNIObjectPrivate(const char *className, const char *sig, ... } } -QJNIObjectPrivate::QJNIObjectPrivate(const char *className, const char *sig, va_list args) +QJNIObjectPrivate::QJNIObjectPrivate(const char *className, const char *sig, const QVaListPrivate &args) : d(new QJNIObjectData()) { QJNIEnvironmentPrivate env; @@ -369,7 +369,7 @@ QJNIObjectPrivate::QJNIObjectPrivate(jclass clazz, const char *sig, ...) } } -QJNIObjectPrivate::QJNIObjectPrivate(jclass clazz, const char *sig, va_list args) +QJNIObjectPrivate::QJNIObjectPrivate(jclass clazz, const char *sig, const QVaListPrivate &args) : d(new QJNIObjectData()) { QJNIEnvironmentPrivate env; @@ -402,7 +402,7 @@ QJNIObjectPrivate::QJNIObjectPrivate(jobject obj) } template <> -void QJNIObjectPrivate::callMethod(const char *methodName, const char *sig, va_list args) const +void QJNIObjectPrivate::callMethodV(const char *methodName, const char *sig, va_list args) const { QJNIEnvironmentPrivate env; jmethodID id = getCachedMethodID(env, d->m_jclass, methodName, sig); @@ -416,12 +416,12 @@ void QJNIObjectPrivate::callMethod(const char *methodName, const char *sig { va_list args; va_start(args, sig); - callMethod(methodName, sig, args); + callMethodV(methodName, sig, args); va_end(args); } template <> -jboolean QJNIObjectPrivate::callMethod(const char *methodName, const char *sig, va_list args) const +jboolean QJNIObjectPrivate::callMethodV(const char *methodName, const char *sig, va_list args) const { QJNIEnvironmentPrivate env; jboolean res = 0; @@ -437,13 +437,13 @@ jboolean QJNIObjectPrivate::callMethod(const char *methodName, const c { va_list args; va_start(args, sig); - jboolean res = callMethod(methodName, sig, args); + jboolean res = callMethodV(methodName, sig, args); va_end(args); return res; } template <> -jbyte QJNIObjectPrivate::callMethod(const char *methodName, const char *sig, va_list args) const +jbyte QJNIObjectPrivate::callMethodV(const char *methodName, const char *sig, va_list args) const { QJNIEnvironmentPrivate env; jbyte res = 0; @@ -459,13 +459,13 @@ jbyte QJNIObjectPrivate::callMethod(const char *methodName, const char *s { va_list args; va_start(args, sig); - jbyte res = callMethod(methodName, sig, args); + jbyte res = callMethodV(methodName, sig, args); va_end(args); return res; } template <> -jchar QJNIObjectPrivate::callMethod(const char *methodName, const char *sig, va_list args) const +jchar QJNIObjectPrivate::callMethodV(const char *methodName, const char *sig, va_list args) const { QJNIEnvironmentPrivate env; jchar res = 0; @@ -481,13 +481,13 @@ jchar QJNIObjectPrivate::callMethod(const char *methodName, const char *s { va_list args; va_start(args, sig); - jchar res = callMethod(methodName, sig, args); + jchar res = callMethodV(methodName, sig, args); va_end(args); return res; } template <> -jshort QJNIObjectPrivate::callMethod(const char *methodName, const char *sig, va_list args) const +jshort QJNIObjectPrivate::callMethodV(const char *methodName, const char *sig, va_list args) const { QJNIEnvironmentPrivate env; jshort res = 0; @@ -503,13 +503,13 @@ jshort QJNIObjectPrivate::callMethod(const char *methodName, const char { va_list args; va_start(args, sig); - jshort res = callMethod(methodName, sig, args); + jshort res = callMethodV(methodName, sig, args); va_end(args); return res; } template <> -jint QJNIObjectPrivate::callMethod(const char *methodName, const char *sig, va_list args) const +jint QJNIObjectPrivate::callMethodV(const char *methodName, const char *sig, va_list args) const { QJNIEnvironmentPrivate env; jint res = 0; @@ -525,13 +525,13 @@ jint QJNIObjectPrivate::callMethod(const char *methodName, const char *sig { va_list args; va_start(args, sig); - jint res = callMethod(methodName, sig, args); + jint res = callMethodV(methodName, sig, args); va_end(args); return res; } template <> -jlong QJNIObjectPrivate::callMethod(const char *methodName, const char *sig, va_list args) const +jlong QJNIObjectPrivate::callMethodV(const char *methodName, const char *sig, va_list args) const { QJNIEnvironmentPrivate env; jlong res = 0; @@ -547,13 +547,13 @@ jlong QJNIObjectPrivate::callMethod(const char *methodName, const char *s { va_list args; va_start(args, sig); - jlong res = callMethod(methodName, sig, args); + jlong res = callMethodV(methodName, sig, args); va_end(args); return res; } template <> -jfloat QJNIObjectPrivate::callMethod(const char *methodName, const char *sig, va_list args) const +jfloat QJNIObjectPrivate::callMethodV(const char *methodName, const char *sig, va_list args) const { QJNIEnvironmentPrivate env; jfloat res = 0.f; @@ -569,13 +569,13 @@ jfloat QJNIObjectPrivate::callMethod(const char *methodName, const char { va_list args; va_start(args, sig); - jfloat res = callMethod(methodName, sig, args); + jfloat res = callMethodV(methodName, sig, args); va_end(args); return res; } template <> -jdouble QJNIObjectPrivate::callMethod(const char *methodName, const char *sig, va_list args) const +jdouble QJNIObjectPrivate::callMethodV(const char *methodName, const char *sig, va_list args) const { QJNIEnvironmentPrivate env; jdouble res = 0.; @@ -591,7 +591,7 @@ jdouble QJNIObjectPrivate::callMethod(const char *methodName, const cha { va_list args; va_start(args, sig); - jdouble res = callMethod(methodName, sig, args); + jdouble res = callMethodV(methodName, sig, args); va_end(args); return res; } @@ -651,10 +651,10 @@ jdouble QJNIObjectPrivate::callMethod(const char *methodName) const } template <> -void QJNIObjectPrivate::callStaticMethod(const char *className, - const char *methodName, - const char *sig, - va_list args) +void QJNIObjectPrivate::callStaticMethodV(const char *className, + const char *methodName, + const char *sig, + va_list args) { QJNIEnvironmentPrivate env; jclass clazz = loadClass(className, env); @@ -674,15 +674,15 @@ void QJNIObjectPrivate::callStaticMethod(const char *className, { va_list args; va_start(args, sig); - callStaticMethod(className, methodName, sig, args); + callStaticMethodV(className, methodName, sig, args); va_end(args); } template <> -void QJNIObjectPrivate::callStaticMethod(jclass clazz, - const char *methodName, - const char *sig, - va_list args) +void QJNIObjectPrivate::callStaticMethodV(jclass clazz, + const char *methodName, + const char *sig, + va_list args) { QJNIEnvironmentPrivate env; jmethodID id = getCachedMethodID(env, clazz, methodName, sig, true); @@ -699,15 +699,15 @@ void QJNIObjectPrivate::callStaticMethod(jclass clazz, { va_list args; va_start(args, sig); - callStaticMethod(clazz, methodName, sig, args); + callStaticMethodV(clazz, methodName, sig, args); va_end(args); } template <> -jboolean QJNIObjectPrivate::callStaticMethod(const char *className, - const char *methodName, - const char *sig, - va_list args) +jboolean QJNIObjectPrivate::callStaticMethodV(const char *className, + const char *methodName, + const char *sig, + va_list args) { QJNIEnvironmentPrivate env; jboolean res = 0; @@ -730,16 +730,16 @@ jboolean QJNIObjectPrivate::callStaticMethod(const char *className, { va_list args; va_start(args, sig); - jboolean res = callStaticMethod(className, methodName, sig, args); + jboolean res = callStaticMethodV(className, methodName, sig, args); va_end(args); return res; } template <> -jboolean QJNIObjectPrivate::callStaticMethod(jclass clazz, - const char *methodName, - const char *sig, - va_list args) +jboolean QJNIObjectPrivate::callStaticMethodV(jclass clazz, + const char *methodName, + const char *sig, + va_list args) { QJNIEnvironmentPrivate env; jboolean res = 0; @@ -759,16 +759,16 @@ jboolean QJNIObjectPrivate::callStaticMethod(jclass clazz, { va_list args; va_start(args, sig); - jboolean res = callStaticMethod(clazz, methodName, sig, args); + jboolean res = callStaticMethodV(clazz, methodName, sig, args); va_end(args); return res; } template <> -jbyte QJNIObjectPrivate::callStaticMethod(const char *className, - const char *methodName, - const char *sig, - va_list args) +jbyte QJNIObjectPrivate::callStaticMethodV(const char *className, + const char *methodName, + const char *sig, + va_list args) { QJNIEnvironmentPrivate env; jbyte res = 0; @@ -791,16 +791,16 @@ jbyte QJNIObjectPrivate::callStaticMethod(const char *className, { va_list args; va_start(args, sig); - jbyte res = callStaticMethod(className, methodName, sig, args); + jbyte res = callStaticMethodV(className, methodName, sig, args); va_end(args); return res; } template <> -jbyte QJNIObjectPrivate::callStaticMethod(jclass clazz, - const char *methodName, - const char *sig, - va_list args) +jbyte QJNIObjectPrivate::callStaticMethodV(jclass clazz, + const char *methodName, + const char *sig, + va_list args) { QJNIEnvironmentPrivate env; jbyte res = 0; @@ -820,16 +820,16 @@ jbyte QJNIObjectPrivate::callStaticMethod(jclass clazz, { va_list args; va_start(args, sig); - jbyte res = callStaticMethod(clazz, methodName, sig, args); + jbyte res = callStaticMethodV(clazz, methodName, sig, args); va_end(args); return res; } template <> -jchar QJNIObjectPrivate::callStaticMethod(const char *className, - const char *methodName, - const char *sig, - va_list args) +jchar QJNIObjectPrivate::callStaticMethodV(const char *className, + const char *methodName, + const char *sig, + va_list args) { QJNIEnvironmentPrivate env; jchar res = 0; @@ -852,16 +852,16 @@ jchar QJNIObjectPrivate::callStaticMethod(const char *className, { va_list args; va_start(args, sig); - jchar res = callStaticMethod(className, methodName, sig, args); + jchar res = callStaticMethodV(className, methodName, sig, args); va_end(args); return res; } template <> -jchar QJNIObjectPrivate::callStaticMethod(jclass clazz, - const char *methodName, - const char *sig, - va_list args) +jchar QJNIObjectPrivate::callStaticMethodV(jclass clazz, + const char *methodName, + const char *sig, + va_list args) { QJNIEnvironmentPrivate env; jchar res = 0; @@ -881,16 +881,16 @@ jchar QJNIObjectPrivate::callStaticMethod(jclass clazz, { va_list args; va_start(args, sig); - jchar res = callStaticMethod(clazz, methodName, sig, args); + jchar res = callStaticMethodV(clazz, methodName, sig, args); va_end(args); return res; } template <> -jshort QJNIObjectPrivate::callStaticMethod(const char *className, - const char *methodName, - const char *sig, - va_list args) +jshort QJNIObjectPrivate::callStaticMethodV(const char *className, + const char *methodName, + const char *sig, + va_list args) { QJNIEnvironmentPrivate env; jshort res = 0; @@ -913,16 +913,16 @@ jshort QJNIObjectPrivate::callStaticMethod(const char *className, { va_list args; va_start(args, sig); - jshort res = callStaticMethod(className, methodName, sig, args); + jshort res = callStaticMethodV(className, methodName, sig, args); va_end(args); return res; } template <> -jshort QJNIObjectPrivate::callStaticMethod(jclass clazz, - const char *methodName, - const char *sig, - va_list args) +jshort QJNIObjectPrivate::callStaticMethodV(jclass clazz, + const char *methodName, + const char *sig, + va_list args) { QJNIEnvironmentPrivate env; jshort res = 0; @@ -942,16 +942,16 @@ jshort QJNIObjectPrivate::callStaticMethod(jclass clazz, { va_list args; va_start(args, sig); - jshort res = callStaticMethod(clazz, methodName, sig, args); + jshort res = callStaticMethodV(clazz, methodName, sig, args); va_end(args); return res; } template <> -jint QJNIObjectPrivate::callStaticMethod(const char *className, - const char *methodName, - const char *sig, - va_list args) +jint QJNIObjectPrivate::callStaticMethodV(const char *className, + const char *methodName, + const char *sig, + va_list args) { QJNIEnvironmentPrivate env; jint res = 0; @@ -974,16 +974,16 @@ jint QJNIObjectPrivate::callStaticMethod(const char *className, { va_list args; va_start(args, sig); - jint res = callStaticMethod(className, methodName, sig, args); + jint res = callStaticMethodV(className, methodName, sig, args); va_end(args); return res; } template <> -jint QJNIObjectPrivate::callStaticMethod(jclass clazz, - const char *methodName, - const char *sig, - va_list args) +jint QJNIObjectPrivate::callStaticMethodV(jclass clazz, + const char *methodName, + const char *sig, + va_list args) { QJNIEnvironmentPrivate env; jint res = 0; @@ -1003,16 +1003,16 @@ jint QJNIObjectPrivate::callStaticMethod(jclass clazz, { va_list args; va_start(args, sig); - jint res = callStaticMethod(clazz, methodName, sig, args); + jint res = callStaticMethodV(clazz, methodName, sig, args); va_end(args); return res; } template <> -jlong QJNIObjectPrivate::callStaticMethod(const char *className, - const char *methodName, - const char *sig, - va_list args) +jlong QJNIObjectPrivate::callStaticMethodV(const char *className, + const char *methodName, + const char *sig, + va_list args) { QJNIEnvironmentPrivate env; jlong res = 0; @@ -1035,16 +1035,16 @@ jlong QJNIObjectPrivate::callStaticMethod(const char *className, { va_list args; va_start(args, sig); - jlong res = callStaticMethod(className, methodName, sig, args); + jlong res = callStaticMethodV(className, methodName, sig, args); va_end(args); return res; } template <> -jlong QJNIObjectPrivate::callStaticMethod(jclass clazz, - const char *methodName, - const char *sig, - va_list args) +jlong QJNIObjectPrivate::callStaticMethodV(jclass clazz, + const char *methodName, + const char *sig, + va_list args) { QJNIEnvironmentPrivate env; jlong res = 0; @@ -1064,16 +1064,16 @@ jlong QJNIObjectPrivate::callStaticMethod(jclass clazz, { va_list args; va_start(args, sig); - jlong res = callStaticMethod(clazz, methodName, sig, args); + jlong res = callStaticMethodV(clazz, methodName, sig, args); va_end(args); return res; } template <> -jfloat QJNIObjectPrivate::callStaticMethod(const char *className, - const char *methodName, - const char *sig, - va_list args) +jfloat QJNIObjectPrivate::callStaticMethodV(const char *className, + const char *methodName, + const char *sig, + va_list args) { QJNIEnvironmentPrivate env; jfloat res = 0.f; @@ -1096,16 +1096,16 @@ jfloat QJNIObjectPrivate::callStaticMethod(const char *className, { va_list args; va_start(args, sig); - jfloat res = callStaticMethod(className, methodName, sig, args); + jfloat res = callStaticMethodV(className, methodName, sig, args); va_end(args); return res; } template <> -jfloat QJNIObjectPrivate::callStaticMethod(jclass clazz, - const char *methodName, - const char *sig, - va_list args) +jfloat QJNIObjectPrivate::callStaticMethodV(jclass clazz, + const char *methodName, + const char *sig, + va_list args) { QJNIEnvironmentPrivate env; jfloat res = 0.f; @@ -1125,16 +1125,16 @@ jfloat QJNIObjectPrivate::callStaticMethod(jclass clazz, { va_list args; va_start(args, sig); - jfloat res = callStaticMethod(clazz, methodName, sig, args); + jfloat res = callStaticMethodV(clazz, methodName, sig, args); va_end(args); return res; } template <> -jdouble QJNIObjectPrivate::callStaticMethod(const char *className, - const char *methodName, - const char *sig, - va_list args) +jdouble QJNIObjectPrivate::callStaticMethodV(const char *className, + const char *methodName, + const char *sig, + va_list args) { QJNIEnvironmentPrivate env; jdouble res = 0.; @@ -1157,16 +1157,16 @@ jdouble QJNIObjectPrivate::callStaticMethod(const char *className, { va_list args; va_start(args, sig); - jdouble res = callStaticMethod(className, methodName, sig, args); + jdouble res = callStaticMethodV(className, methodName, sig, args); va_end(args); return res; } template <> -jdouble QJNIObjectPrivate::callStaticMethod(jclass clazz, - const char *methodName, - const char *sig, - va_list args) +jdouble QJNIObjectPrivate::callStaticMethodV(jclass clazz, + const char *methodName, + const char *sig, + va_list args) { QJNIEnvironmentPrivate env; jdouble res = 0.; @@ -1186,7 +1186,7 @@ jdouble QJNIObjectPrivate::callStaticMethod(jclass clazz, { va_list args; va_start(args, sig); - jdouble res = callStaticMethod(clazz, methodName, sig, args); + jdouble res = callStaticMethodV(clazz, methodName, sig, args); va_end(args); return res; } @@ -1299,9 +1299,9 @@ jdouble QJNIObjectPrivate::callStaticMethod(jclass clazz, const char *m return callStaticMethod(clazz, methodName, "()D"); } -QJNIObjectPrivate QJNIObjectPrivate::callObjectMethod(const char *methodName, - const char *sig, - va_list args) const +QJNIObjectPrivate QJNIObjectPrivate::callObjectMethodV(const char *methodName, + const char *sig, + va_list args) const { QJNIEnvironmentPrivate env; jobject res = 0; @@ -1323,7 +1323,7 @@ QJNIObjectPrivate QJNIObjectPrivate::callObjectMethod(const char *methodName, { va_list args; va_start(args, sig); - QJNIObjectPrivate res = callObjectMethod(methodName, sig, args); + QJNIObjectPrivate res = callObjectMethodV(methodName, sig, args); va_end(args); return res; } @@ -1376,10 +1376,10 @@ QJNIObjectPrivate QJNIObjectPrivate::callObjectMethod(const char * return callObjectMethod(methodName, "()[D"); } -QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethod(const char *className, - const char *methodName, - const char *sig, - va_list args) +QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethodV(const char *className, + const char *methodName, + const char *sig, + va_list args) { QJNIEnvironmentPrivate env; jobject res = 0; @@ -1405,15 +1405,15 @@ QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethod(const char *classNam { va_list args; va_start(args, sig); - QJNIObjectPrivate res = callStaticObjectMethod(className, methodName, sig, args); + QJNIObjectPrivate res = callStaticObjectMethodV(className, methodName, sig, args); va_end(args); return res; } -QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethod(jclass clazz, - const char *methodName, - const char *sig, - va_list args) +QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethodV(jclass clazz, + const char *methodName, + const char *sig, + va_list args) { QJNIEnvironmentPrivate env; jobject res = 0; @@ -1436,7 +1436,7 @@ QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethod(jclass clazz, { va_list args; va_start(args, sig); - QJNIObjectPrivate res = callStaticObjectMethod(clazz, methodName, sig, args); + QJNIObjectPrivate res = callStaticObjectMethodV(clazz, methodName, sig, args); va_end(args); return res; } diff --git a/src/corelib/kernel/qjni_p.h b/src/corelib/kernel/qjni_p.h index 19f2cf76012..5f573624c68 100644 --- a/src/corelib/kernel/qjni_p.h +++ b/src/corelib/kernel/qjni_p.h @@ -186,31 +186,37 @@ public: private: friend class QAndroidJniObject; - QJNIObjectPrivate(const char *className, const char *sig, va_list args); - QJNIObjectPrivate(jclass clazz, const char *sig, va_list args); + struct QVaListPrivate { operator va_list &() const { return m_args; } va_list &m_args; }; + + QJNIObjectPrivate(const char *className, const char *sig, const QVaListPrivate &args); + QJNIObjectPrivate(jclass clazz, const char *sig, const QVaListPrivate &args); template - T callMethod(const char *methodName, - const char *sig, - va_list args) const; - QJNIObjectPrivate callObjectMethod(const char *methodName, - const char *sig, - va_list args) const; + T callMethodV(const char *methodName, + const char *sig, + va_list args) const; + QJNIObjectPrivate callObjectMethodV(const char *methodName, + const char *sig, + va_list args) const; template - static T callStaticMethod(const char *className, - const char *methodName, - const char *sig, va_list args); + static T callStaticMethodV(const char *className, + const char *methodName, + const char *sig, + va_list args); template - static T callStaticMethod(jclass clazz, - const char *methodName, - const char *sig, va_list args); - static QJNIObjectPrivate callStaticObjectMethod(const char *className, - const char *methodName, - const char *sig, va_list args); + static T callStaticMethodV(jclass clazz, + const char *methodName, + const char *sig, + va_list args); + static QJNIObjectPrivate callStaticObjectMethodV(const char *className, + const char *methodName, + const char *sig, + va_list args); - static QJNIObjectPrivate callStaticObjectMethod(jclass clazz, - const char *methodName, - const char *sig, va_list args); + static QJNIObjectPrivate callStaticObjectMethodV(jclass clazz, + const char *methodName, + const char *sig, + va_list args); bool isSameObject(jobject obj) const; bool isSameObject(const QJNIObjectPrivate &other) const; diff --git a/src/corelib/kernel/qjnihelpers.cpp b/src/corelib/kernel/qjnihelpers.cpp index c82b5ca033c..d3bbce305ac 100644 --- a/src/corelib/kernel/qjnihelpers.cpp +++ b/src/corelib/kernel/qjnihelpers.cpp @@ -34,6 +34,7 @@ #include "qjnihelpers_p.h" #include "qmutex.h" #include "qlist.h" +#include QT_BEGIN_NAMESPACE @@ -41,6 +42,19 @@ static JavaVM *g_javaVM = Q_NULLPTR; static jobject g_jActivity = Q_NULLPTR; static jobject g_jClassLoader = Q_NULLPTR; static jint g_androidSdkVersion = 0; +static jclass g_jNativeClass = Q_NULLPTR; +static jmethodID g_runQtOnUiThreadMethodID = Q_NULLPTR; + +static void onAndroidUiThread(JNIEnv *, jclass, jlong thiz) +{ + QRunnable *runnable = reinterpret_cast(thiz); + if (runnable == 0) + return; + + runnable->run(); + if (runnable->autoDelete()) + delete runnable; +} namespace { class ActivityResultListeners @@ -140,6 +154,22 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env) env->DeleteLocalRef(activity); g_javaVM = vm; + static const JNINativeMethod methods[] = { + {"onAndroidUiThread", "(J)V", reinterpret_cast(onAndroidUiThread)} + }; + + const bool regOk = (env->RegisterNatives(jQtNative, methods, sizeof(methods) / sizeof(methods[0])) == JNI_OK); + + if (!regOk && exceptionCheck(env)) + return JNI_ERR; + + g_runQtOnUiThreadMethodID = env->GetStaticMethodID(jQtNative, + "runQtOnUiThread", + "(J)V"); + + g_jNativeClass = static_cast(env->NewGlobalRef(jQtNative)); + env->DeleteLocalRef(jQtNative); + return JNI_OK; } @@ -164,4 +194,12 @@ jint QtAndroidPrivate::androidSdkVersion() return g_androidSdkVersion; } +void QtAndroidPrivate::runOnUiThread(QRunnable *runnable, JNIEnv *env) +{ + Q_ASSERT(runnable != 0); + env->CallStaticVoidMethod(g_jNativeClass, g_runQtOnUiThreadMethodID, reinterpret_cast(runnable)); + if (exceptionCheck(env) && runnable != 0 && runnable->autoDelete()) + delete runnable; +} + QT_END_NAMESPACE diff --git a/src/corelib/kernel/qjnihelpers_p.h b/src/corelib/kernel/qjnihelpers_p.h index 80c50ba6115..6456dce4c45 100644 --- a/src/corelib/kernel/qjnihelpers_p.h +++ b/src/corelib/kernel/qjnihelpers_p.h @@ -50,6 +50,8 @@ QT_BEGIN_NAMESPACE +class QRunnable; + namespace QtAndroidPrivate { class Q_CORE_EXPORT ActivityResultListener @@ -64,6 +66,7 @@ namespace QtAndroidPrivate Q_CORE_EXPORT jint initJNI(JavaVM *vm, JNIEnv *env); jobject classLoader(); Q_CORE_EXPORT jint androidSdkVersion(); + Q_CORE_EXPORT void runOnUiThread(QRunnable *runnable, JNIEnv *env); Q_CORE_EXPORT void handleActivityResult(jint requestCode, jint resultCode, jobject data); Q_CORE_EXPORT void registerActivityResultListener(ActivityResultListener *listener); diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index e68b8992800..1faead84957 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -48,7 +48,7 @@ template class QList; class Q_CORE_EXPORT QMetaMethod { public: - inline QMetaMethod() : mobj(0),handle(0) {} + Q_DECL_CONSTEXPR inline QMetaMethod() : mobj(0),handle(0) {} QByteArray methodSignature() const; QByteArray name() const; @@ -204,7 +204,7 @@ inline bool operator!=(const QMetaMethod &m1, const QMetaMethod &m2) class Q_CORE_EXPORT QMetaEnum { public: - inline QMetaEnum() : mobj(0),handle(0) {} + Q_DECL_CONSTEXPR inline QMetaEnum() : mobj(0),handle(0) {} const char *name() const; bool isFlag() const; @@ -286,7 +286,7 @@ private: class Q_CORE_EXPORT QMetaClassInfo { public: - inline QMetaClassInfo() : mobj(0),handle(0) {} + Q_DECL_CONSTEXPR inline QMetaClassInfo() : mobj(0),handle(0) {} const char *name() const; const char *value() const; inline const QMetaObject *enclosingMetaObject() const { return mobj; } diff --git a/src/corelib/kernel/qsystemerror.cpp b/src/corelib/kernel/qsystemerror.cpp index 5c185e1d62d..3b1d8085201 100644 --- a/src/corelib/kernel/qsystemerror.cpp +++ b/src/corelib/kernel/qsystemerror.cpp @@ -61,11 +61,11 @@ namespace { // version in portable code. However, it's impossible to do that if // _GNU_SOURCE is defined so we use C++ overloading to decide what to do // depending on the return type - static inline QString fromstrerror_helper(int, const QByteArray &buf) + static inline Q_DECL_UNUSED QString fromstrerror_helper(int, const QByteArray &buf) { return QString::fromLocal8Bit(buf); } - static inline QString fromstrerror_helper(const char *str, const QByteArray &) + static inline Q_DECL_UNUSED QString fromstrerror_helper(const char *str, const QByteArray &) { return QString::fromLocal8Bit(str); } diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp index 5687a6c3a35..a2cf4a7813a 100644 --- a/src/corelib/kernel/qtranslator.cpp +++ b/src/corelib/kernel/qtranslator.cpp @@ -427,9 +427,8 @@ QTranslator::~QTranslator() directory. Returns \c true if the translation is successfully loaded; otherwise returns \c false. - If \a directory is not specified, the directory of the - application's executable is used (i.e., as - \l{QCoreApplication::}{applicationDirPath()}). + If \a directory is not specified, the current directory is used + (i.e., as \l{QDir::}{currentPath()}). The previous contents of this translator object are discarded. diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 57e0523f7c2..7dce813bb50 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -703,14 +703,15 @@ namespace QtPrivate { { static QSequentialIterable invoke(const QVariant &v) { - if (v.userType() == qMetaTypeId()) { + const int typeId = v.userType(); + if (typeId == qMetaTypeId()) { return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast(v.constData()))); } - if (v.userType() == qMetaTypeId()) { + if (typeId == qMetaTypeId()) { return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast(v.constData()))); } #ifndef QT_BOOTSTRAPPED - if (v.userType() == qMetaTypeId()) { + if (typeId == qMetaTypeId()) { return QSequentialIterable(QtMetaTypePrivate::QSequentialIterableImpl(reinterpret_cast(v.constData()))); } #endif @@ -722,10 +723,11 @@ namespace QtPrivate { { static QAssociativeIterable invoke(const QVariant &v) { - if (v.userType() == qMetaTypeId()) { + const int typeId = v.userType(); + if (typeId == qMetaTypeId()) { return QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl(reinterpret_cast(v.constData()))); } - if (v.userType() == qMetaTypeId()) { + if (typeId == qMetaTypeId()) { return QAssociativeIterable(QtMetaTypePrivate::QAssociativeIterableImpl(reinterpret_cast(v.constData()))); } return QAssociativeIterable(v.value()); @@ -736,7 +738,8 @@ namespace QtPrivate { { static QVariantList invoke(const QVariant &v) { - if (QtMetaTypePrivate::isBuiltinSequentialType(v.userType()) || QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId())) { + const int typeId = v.userType(); + if (QtMetaTypePrivate::isBuiltinSequentialType(typeId) || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId())) { QSequentialIterable iter = QVariantValueHelperInterface::invoke(v); QVariantList l; l.reserve(iter.size()); @@ -752,7 +755,8 @@ namespace QtPrivate { { static QVariantHash invoke(const QVariant &v) { - if (QtMetaTypePrivate::isBuiltinAssociativeType(v.userType()) || QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId())) { + const int typeId = v.userType(); + if (QtMetaTypePrivate::isBuiltinAssociativeType(typeId) || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId())) { QAssociativeIterable iter = QVariantValueHelperInterface::invoke(v); QVariantHash l; l.reserve(iter.size()); @@ -768,7 +772,8 @@ namespace QtPrivate { { static QVariantMap invoke(const QVariant &v) { - if (QtMetaTypePrivate::isBuiltinAssociativeType(v.userType()) || QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId())) { + const int typeId = v.userType(); + if (QtMetaTypePrivate::isBuiltinAssociativeType(typeId) || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId())) { QAssociativeIterable iter = QVariantValueHelperInterface::invoke(v); QVariantMap l; for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it) @@ -783,10 +788,11 @@ namespace QtPrivate { { static QPair invoke(const QVariant &v) { - if (v.userType() == qMetaTypeId >()) + const int typeId = v.userType(); + if (typeId == qMetaTypeId >()) return QVariantValueHelper >::invoke(v); - if (QMetaType::hasRegisteredConverterFunction(v.userType(), qMetaTypeId())) { + if (QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId())) { QtMetaTypePrivate::QPairVariantInterfaceImpl pi = v.value(); const QtMetaTypePrivate::VariantData d1 = pi.first(); diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp index 9d14e5f90b5..c5103ebe59e 100644 --- a/src/corelib/mimetypes/qmimedatabase.cpp +++ b/src/corelib/mimetypes/qmimedatabase.cpp @@ -248,7 +248,7 @@ bool QMimeDatabasePrivate::inherits(const QString &mime, const QString &parent) \endcode On a typical Unix system, this will be /usr/share/mime/packages/, but it is also possible to extend the list of directories by setting the environment variable - XDG_DATA_DIRS. For instance adding /opt/myapp/share to XDG_DATA_DIRS will result + \c XDG_DATA_DIRS. For instance adding /opt/myapp/share to \c XDG_DATA_DIRS will result in /opt/myapp/share/mime/packages/ being searched for MIME definitions. Here is an example of MIME XML: @@ -575,7 +575,7 @@ QMimeType QMimeDatabase::mimeTypeForFileNameAndData(const QString &fileName, con This can be useful for showing all MIME types to the user, for instance in a MIME type editor. Do not use unless really necessary in other cases - though, prefer using the mimeTypeFor* methods for performance reasons. + though, prefer using the \l {mimeTypeForData()}{mimeTypeForXxx()} methods for performance reasons. */ QList QMimeDatabase::allMimeTypes() const { diff --git a/src/corelib/mimetypes/qmimetype.cpp b/src/corelib/mimetypes/qmimetype.cpp index d1bf27eae03..1ad2a449c16 100644 --- a/src/corelib/mimetypes/qmimetype.cpp +++ b/src/corelib/mimetypes/qmimetype.cpp @@ -89,8 +89,8 @@ void QMimeTypePrivate::addGlobPattern(const QString &pattern) Determining the MIME type of a file can be useful to make sure your application supports it. It is also useful in file-manager-like applications - or widgets, in order to display an appropriate icon() for the file, or even - the descriptive comment() in detailed views. + or widgets, in order to display an appropriate \l {QMimeType::iconName}{icon} for the file, or even + the descriptive \l {QMimeType::comment()}{comment} in detailed views. To check if a file has the expected MIME type, you should use inherits() rather than a simple string comparison based on the name(). This is because diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h index 4e9a60504a5..c424344c3a2 100644 --- a/src/corelib/plugin/qplugin.h +++ b/src/corelib/plugin/qplugin.h @@ -71,7 +71,7 @@ Q_DECLARE_TYPEINFO(QStaticPlugin, Q_PRIMITIVE_TYPE); void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin); -#if defined (Q_OF_ELF) && (defined (Q_CC_GNU) || defined(Q_CC_CLANG)) +#if (defined(Q_OF_ELF) || defined(Q_OS_WIN)) && (defined (Q_CC_GNU) || defined(Q_CC_CLANG)) # define QT_PLUGIN_METADATA_SECTION \ __attribute__ ((section (".qtmetadata"))) __attribute__((used)) #elif defined(Q_OS_MAC) diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h index 09500e92d76..be293f58e34 100644 --- a/src/corelib/thread/qbasicatomic.h +++ b/src/corelib/thread/qbasicatomic.h @@ -84,13 +84,9 @@ QT_END_NAMESPACE // New atomics #if defined(Q_COMPILER_CONSTEXPR) && defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS) -# if defined(Q_CC_CLANG) && ((((__clang_major__ * 100) + __clang_minor__) < 303) \ - || defined(__apple_build_version__) \ - ) - /* Do not define QT_BASIC_ATOMIC_HAS_CONSTRUCTORS for "stock" clang before version 3.3. - Apple's version has different (higher!) version numbers, so disable it for all of them for now. - (The only way to distinguish between them seems to be a check for __apple_build_version__ .) - +# if defined(Q_CC_CLANG) && Q_CC_CLANG < 303 + /* + Do not define QT_BASIC_ATOMIC_HAS_CONSTRUCTORS for Clang before version 3.3. For details about the bug: see http://llvm.org/bugs/show_bug.cgi?id=12670 */ # else diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 625b78d0019..36acfc4c093 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -785,7 +785,7 @@ static inline char qToLower(char c) occurrences of a particular value with another, use one of the two-parameter replace() overloads. - QByteArrays can be compared using overloaded operators such as + {QByteArray}s can be compared using overloaded operators such as operator<(), operator<=(), operator==(), operator>=(), and so on. The comparison is based exclusively on the numeric values of the characters and is very fast, but is not what a human would @@ -830,7 +830,7 @@ static inline char qToLower(char c) lastIndexOf(), operator<(), operator<=(), operator>(), operator>=(), toLower() and toUpper(). - This issue does not apply to QStrings since they represent + This issue does not apply to {QString}s since they represent characters using Unicode. \sa QString, QBitArray @@ -3203,6 +3203,7 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba) replaced with a single space. Whitespace means any character for which the standard C++ + \c isspace() function returns \c true in the C locale. This includes the ASCII isspace() function returns \c true in the C locale. This includes the ASCII characters '\\t', '\\n', '\\v', '\\f', '\\r', and ' '. @@ -3228,13 +3229,13 @@ QByteArray QByteArray::simplified_helper(QByteArray &a) and the end. Whitespace means any character for which the standard C++ - isspace() function returns \c true in the C locale. This includes the ASCII + \c isspace() function returns \c true in the C locale. This includes the ASCII characters '\\t', '\\n', '\\v', '\\f', '\\r', and ' '. Example: \snippet code/src_corelib_tools_qbytearray.cpp 33 - Unlike simplified(), trimmed() leaves internal whitespace alone. + Unlike simplified(), \l {QByteArray::trimmed()}{trimmed()} leaves internal whitespace alone. \sa simplified() */ diff --git a/src/corelib/tools/qbytearraylist.h b/src/corelib/tools/qbytearraylist.h index 9d7e776028e..dd84ec642ca 100644 --- a/src/corelib/tools/qbytearraylist.h +++ b/src/corelib/tools/qbytearraylist.h @@ -63,6 +63,7 @@ class QByteArrayList : public QList template <> struct QListSpecialMethods #endif { +public: inline QByteArray join() const { return QtPrivate::QByteArrayList_join(self(), 0, 0); } inline QByteArray join(const QByteArray &sep) const diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h index ec1e78c358d..5bcd01a5876 100644 --- a/src/corelib/tools/qdatetime.h +++ b/src/corelib/tools/qdatetime.h @@ -118,7 +118,8 @@ QT_DEPRECATED inline bool setYMD(int y, int m, int d) inline qint64 toJulianDay() const { return jd; } private: - static inline qint64 nullJd() { return std::numeric_limits::min(); } + // using extra parentheses around min to avoid expanding it if it is a macro + static inline qint64 nullJd() { return (std::numeric_limits::min)(); } static inline qint64 minJd() { return Q_INT64_C(-784350574879); } static inline qint64 maxJd() { return Q_INT64_C( 784354017364); } diff --git a/src/corelib/tools/qelapsedtimer.h b/src/corelib/tools/qelapsedtimer.h index d72a50f127c..d21081f815a 100644 --- a/src/corelib/tools/qelapsedtimer.h +++ b/src/corelib/tools/qelapsedtimer.h @@ -51,8 +51,8 @@ public: }; Q_DECL_CONSTEXPR QElapsedTimer() - : t1(Q_INT64_C(0x8000000000000000)) - , t2(Q_INT64_C(0x8000000000000000)) + : t1(Q_INT64_C(0x8000000000000000)), + t2(Q_INT64_C(0x8000000000000000)) { } diff --git a/src/corelib/tools/qelapsedtimer_unix.cpp b/src/corelib/tools/qelapsedtimer_unix.cpp index 02d60cc60c0..61bd7f1f219 100644 --- a/src/corelib/tools/qelapsedtimer_unix.cpp +++ b/src/corelib/tools/qelapsedtimer_unix.cpp @@ -35,8 +35,12 @@ #define _POSIX_C_SOURCE 200809L #include "qelapsedtimer.h" -#ifdef Q_OS_VXWORKS +#if defined(Q_OS_VXWORKS) #include "qfunctions_vxworks.h" +#elif defined(Q_OS_QNX) +#include +#include +#include #else #include #include @@ -84,7 +88,18 @@ QT_BEGIN_NAMESPACE * see http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html */ -#ifndef CLOCK_REALTIME +#if defined(Q_OS_QNX) +static inline void qt_clock_gettime(clockid_t clock, struct timespec *ts) +{ + // The standard POSIX clock calls only have 1ms accuracy on QNX. To get + // higher accuracy, this platform-specific function must be used instead + quint64 cycles_per_sec = SYSPAGE_ENTRY(qtime)->cycles_per_sec; + quint64 cycles = ClockCycles(); + ts->tv_sec = cycles / cycles_per_sec; + quint64 mod = cycles % cycles_per_sec; + ts->tv_nsec = mod * Q_INT64_C(1000000000) / cycles_per_sec; +} +#elif !defined(CLOCK_REALTIME) # define CLOCK_REALTIME 0 static inline void qt_clock_gettime(int, struct timespec *ts) { diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index f32cd788012..b91fd38a5f2 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -1365,7 +1365,7 @@ void **QListData::erase(void **xi) \sa operator*() */ -/*! \fn T &QList::iterator::operator[](int j) const +/*! \fn T &QList::iterator::operator[](difference_type j) const Returns a modifiable reference to the item at position *this + \a{j}. @@ -1466,7 +1466,7 @@ void **QListData::erase(void **xi) current and returns an iterator to the previously current item. */ -/*! \fn QList::iterator &QList::iterator::operator+=(int j) +/*! \fn QList::iterator &QList::iterator::operator+=(difference_type j) Advances the iterator by \a j items. (If \a j is negative, the iterator goes backward.) @@ -1474,7 +1474,7 @@ void **QListData::erase(void **xi) \sa operator-=(), operator+() */ -/*! \fn QList::iterator &QList::iterator::operator-=(int j) +/*! \fn QList::iterator &QList::iterator::operator-=(difference_type j) Makes the iterator go back by \a j items. (If \a j is negative, the iterator goes forward.) @@ -1482,7 +1482,7 @@ void **QListData::erase(void **xi) \sa operator+=(), operator-() */ -/*! \fn QList::iterator QList::iterator::operator+(int j) const +/*! \fn QList::iterator QList::iterator::operator+(difference_type j) const Returns an iterator to the item at \a j positions forward from this iterator. (If \a j is negative, the iterator goes backward.) @@ -1490,7 +1490,7 @@ void **QListData::erase(void **xi) \sa operator-(), operator+=() */ -/*! \fn QList::iterator QList::iterator::operator-(int j) const +/*! \fn QList::iterator QList::iterator::operator-(difference_type j) const Returns an iterator to the item at \a j positions backward from this iterator. (If \a j is negative, the iterator goes forward.) @@ -1620,7 +1620,7 @@ void **QListData::erase(void **xi) \sa operator*() */ -/*! \fn const T &QList::const_iterator::operator[](int j) const +/*! \fn const T &QList::const_iterator::operator[](difference_type j) const Returns the item at position *this + \a{j}. @@ -1712,7 +1712,7 @@ void **QListData::erase(void **xi) current and returns an iterator to the previously current item. */ -/*! \fn QList::const_iterator &QList::const_iterator::operator+=(int j) +/*! \fn QList::const_iterator &QList::const_iterator::operator+=(difference_type j) Advances the iterator by \a j items. (If \a j is negative, the iterator goes backward.) @@ -1720,7 +1720,7 @@ void **QListData::erase(void **xi) \sa operator-=(), operator+() */ -/*! \fn QList::const_iterator &QList::const_iterator::operator-=(int j) +/*! \fn QList::const_iterator &QList::const_iterator::operator-=(difference_type j) Makes the iterator go back by \a j items. (If \a j is negative, the iterator goes forward.) @@ -1728,7 +1728,7 @@ void **QListData::erase(void **xi) \sa operator+=(), operator-() */ -/*! \fn QList::const_iterator QList::const_iterator::operator+(int j) const +/*! \fn QList::const_iterator QList::const_iterator::operator+(difference_type j) const Returns an iterator to the item at \a j positions forward from this iterator. (If \a j is negative, the iterator goes backward.) @@ -1736,7 +1736,7 @@ void **QListData::erase(void **xi) \sa operator-(), operator+=() */ -/*! \fn QList::const_iterator QList::const_iterator::operator-(int j) const +/*! \fn QList::const_iterator QList::const_iterator::operator-(difference_type j) const Returns an iterator to the item at \a j positions backward from this iterator. (If \a j is negative, the iterator goes forward.) diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 9704c7b9538..5b459269c1d 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -188,6 +188,7 @@ public: public: Node *i; typedef std::random_access_iterator_tag iterator_category; + // ### Qt6: use int typedef qptrdiff difference_type; typedef T value_type; typedef T *pointer; @@ -198,7 +199,7 @@ public: inline iterator(const iterator &o): i(o.i){} inline T &operator*() const { return i->t(); } inline T *operator->() const { return &i->t(); } - inline T &operator[](int j) const { return i[j].t(); } + inline T &operator[](difference_type j) const { return i[j].t(); } inline bool operator==(const iterator &o) const { return i == o.i; } inline bool operator!=(const iterator &o) const { return i != o.i; } inline bool operator<(const iterator& other) const { return i < other.i; } @@ -223,10 +224,10 @@ public: inline iterator operator++(int) { Node *n = i; ++i; return n; } inline iterator &operator--() { i--; return *this; } inline iterator operator--(int) { Node *n = i; i--; return n; } - inline iterator &operator+=(int j) { i+=j; return *this; } - inline iterator &operator-=(int j) { i-=j; return *this; } - inline iterator operator+(int j) const { return iterator(i+j); } - inline iterator operator-(int j) const { return iterator(i-j); } + inline iterator &operator+=(difference_type j) { i+=j; return *this; } + inline iterator &operator-=(difference_type j) { i-=j; return *this; } + inline iterator operator+(difference_type j) const { return iterator(i+j); } + inline iterator operator-(difference_type j) const { return iterator(i-j); } inline int operator-(iterator j) const { return int(i - j.i); } }; friend class iterator; @@ -235,6 +236,7 @@ public: public: Node *i; typedef std::random_access_iterator_tag iterator_category; + // ### Qt6: use int typedef qptrdiff difference_type; typedef T value_type; typedef const T *pointer; @@ -250,7 +252,7 @@ public: #endif inline const T &operator*() const { return i->t(); } inline const T *operator->() const { return &i->t(); } - inline const T &operator[](int j) const { return i[j].t(); } + inline const T &operator[](difference_type j) const { return i[j].t(); } inline bool operator==(const const_iterator &o) const { return i == o.i; } inline bool operator!=(const const_iterator &o) const { return i != o.i; } inline bool operator<(const const_iterator& other) const { return i < other.i; } @@ -261,10 +263,10 @@ public: inline const_iterator operator++(int) { Node *n = i; ++i; return n; } inline const_iterator &operator--() { i--; return *this; } inline const_iterator operator--(int) { Node *n = i; i--; return n; } - inline const_iterator &operator+=(int j) { i+=j; return *this; } - inline const_iterator &operator-=(int j) { i-=j; return *this; } - inline const_iterator operator+(int j) const { return const_iterator(i+j); } - inline const_iterator operator-(int j) const { return const_iterator(i-j); } + inline const_iterator &operator+=(difference_type j) { i+=j; return *this; } + inline const_iterator &operator-=(difference_type j) { i-=j; return *this; } + inline const_iterator operator+(difference_type j) const { return const_iterator(i+j); } + inline const_iterator operator-(difference_type j) const { return const_iterator(i-j); } inline int operator-(const_iterator j) const { return int(i - j.i); } }; friend class const_iterator; @@ -316,6 +318,7 @@ public: typedef const value_type *const_pointer; typedef value_type &reference; typedef const value_type &const_reference; + // ### Qt6: use int typedef qptrdiff difference_type; // comfort diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index a253057435d..a923be50c08 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -3144,7 +3144,7 @@ bool QLocaleData::numberToCLocale(const QChar *str, int len, } bool QLocaleData::validateChars(const QString &str, NumberMode numMode, QByteArray *buff, - int decDigits) const + int decDigits, bool rejectGroupSeparators) const { buff->clear(); buff->reserve(str.length()); @@ -3205,7 +3205,7 @@ bool QLocaleData::validateChars(const QString &str, NumberMode numMode, QByteArr case ',': //it can only be placed after a digit which is before the decimal point - if (!lastWasDigit || decPointCnt > 0) + if (rejectGroupSeparators || !lastWasDigit || decPointCnt > 0) return false; break; diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h index c33ced35d59..c5e62027c45 100644 --- a/src/corelib/tools/qlocale_p.h +++ b/src/corelib/tools/qlocale_p.h @@ -251,7 +251,9 @@ public: inline char digitToCLocale(QChar c) const; // this function is used in QIntValidator (QtGui) - Q_CORE_EXPORT bool validateChars(const QString &str, NumberMode numMode, QByteArray *buff, int decDigits = -1) const; + Q_CORE_EXPORT bool validateChars(const QString &str, NumberMode numMode, + QByteArray *buff, int decDigits = -1, + bool rejectGroupSeparators = false) const; public: quint16 m_language_id, m_script_id, m_country_id; diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index 0b3bbc0ad0d..5281723c5da 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -519,7 +519,7 @@ QBasicAtomicInt qt_cpu_features = Q_BASIC_ATOMIC_INITIALIZER(0); void qDetectCpuFeatures() { #if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) -# if (__GNUC__ * 100 + __GNUC_MINOR__) < 403 +# if Q_CC_GNU < 403 // GCC 4.2 (at least the one that comes with Apple's XCode, on Mac) is // known to be broken beyond repair in dealing with the inline assembly // above. It will generate bad code that could corrupt important registers diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index ee2ff99a80f..891a3ff0534 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -218,8 +218,8 @@ #endif // other x86 intrinsics -#if defined(Q_PROCESSOR_X86) && ((defined(Q_CC_GNU) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 404)) \ - || (defined(Q_CC_CLANG) && (__clang_major__ * 100 + __clang_minor__ >= 208)) \ +#if defined(Q_PROCESSOR_X86) && ((defined(Q_CC_GNU) && (Q_CC_GNU >= 404)) \ + || (defined(Q_CC_CLANG) && (Q_CC_CLANG >= 208)) \ || defined(Q_CC_INTEL)) # define QT_COMPILER_SUPPORTS_X86INTRIN # ifdef Q_CC_INTEL @@ -318,7 +318,7 @@ static inline uint qCpuFeatures() #ifdef Q_PROCESSOR_X86 // Bit scan functions for x86 -# ifdef Q_CC_MSVC +# if defined(Q_CC_MSVC) && !defined(Q_OS_WINCE) // MSVC calls it _BitScanReverse and returns the carry flag, which we don't need static __forceinline unsigned long _bit_scan_reverse(uint val) { @@ -332,7 +332,7 @@ static __forceinline unsigned long _bit_scan_forward(uint val) _BitScanForward(&result, val); return result; } -# elif (defined(Q_CC_CLANG) || (defined(Q_CC_GNU) && __GNUC__ * 100 + __GNUC_MINOR__ < 405)) \ +# elif (defined(Q_CC_CLANG) || (defined(Q_CC_GNU) && Q_CC_GNU < 405)) \ && !defined(Q_CC_INTEL) // Clang is missing the intrinsic for _bit_scan_reverse // GCC only added it in version 4.5 diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 0d13cccbec7..76069225eb1 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -3938,28 +3938,31 @@ QString QString::section(const QString &sep, int start, int end, SectionFlags fl { QStringList sections = split(sep, KeepEmptyParts, (flags & SectionCaseInsensitiveSeps) ? Qt::CaseInsensitive : Qt::CaseSensitive); - if (sections.isEmpty()) - return QString(); + const int sectionsSize = sections.size(); + if (!(flags & SectionSkipEmpty)) { if (start < 0) - start += sections.count(); + start += sectionsSize; if (end < 0) - end += sections.count(); + end += sectionsSize; } else { int skip = 0; - for (int k=0; k= sectionsSize || end < 0 || start > end) + return QString(); + int x = 0; QString ret; int first_i = start, last_i = end; - for (int i = 0; x <= end && i < sections.size(); ++i) { + for (int i = 0; x <= end && i < sectionsSize; ++i) { QString section = sections.at(i); const bool empty = section.isEmpty(); if (x >= start) { @@ -3967,16 +3970,16 @@ QString QString::section(const QString &sep, int start, int end, SectionFlags fl first_i = i; if(x == end) last_i = i; - if(x > start) + if (x > start && i > 0) ret += sep; ret += section; } if (!empty || !(flags & SectionSkipEmpty)) x++; } - if((flags & SectionIncludeLeadingSep) && first_i) + if ((flags & SectionIncludeLeadingSep) && first_i > 0) ret.prepend(sep); - if((flags & SectionIncludeTrailingSep) && last_i < sections.size()-1) + if ((flags & SectionIncludeTrailingSep) && last_i < sectionsSize - 1) ret += sep; return ret; } @@ -3996,15 +3999,32 @@ static QString extractSections(const QVector §ions, int end, QString::SectionFlags flags) { - if (start < 0) - start += sections.count(); - if (end < 0) - end += sections.count(); + const int sectionsSize = sections.size(); + + if (!(flags & QString::SectionSkipEmpty)) { + if (start < 0) + start += sectionsSize; + if (end < 0) + end += sectionsSize; + } else { + int skip = 0; + for (int k = 0; k < sectionsSize; ++k) { + const qt_section_chunk §ion = sections.at(k); + if (section.length == section.string.length()) + skip++; + } + if (start < 0) + start += sectionsSize - skip; + if (end < 0) + end += sectionsSize - skip; + } + if (start >= sectionsSize || end < 0 || start > end) + return QString(); QString ret; int x = 0; int first_i = start, last_i = end; - for (int i = 0; x <= end && i < sections.size(); ++i) { + for (int i = 0; x <= end && i < sectionsSize; ++i) { const qt_section_chunk §ion = sections.at(i); const bool empty = (section.length == section.string.length()); if (x >= start) { @@ -4021,12 +4041,13 @@ static QString extractSections(const QVector §ions, x++; } - if ((flags & QString::SectionIncludeLeadingSep) && first_i < sections.size()) { + if ((flags & QString::SectionIncludeLeadingSep) && first_i >= 0) { const qt_section_chunk §ion = sections.at(first_i); ret.prepend(section.string.left(section.length)); } - if ((flags & QString::SectionIncludeTrailingSep) && last_i+1 <= sections.size()-1) { + if ((flags & QString::SectionIncludeTrailingSep) + && last_i < sectionsSize - 1) { const qt_section_chunk §ion = sections.at(last_i+1); ret += section.string.left(section.length); } @@ -5650,21 +5671,18 @@ QString QString::toUpper_helper(QString &str) Safely builds a formatted string from the format string \a cformat and an arbitrary list of arguments. - The %lc escape sequence expects a unicode character of type ushort - (as returned by QChar::unicode()). The %ls escape sequence expects - a pointer to a zero-terminated array of unicode characters of type - ushort (as returned by QString::utf16()). + The format string supports the conversion specifiers, length modifiers, + and flags provided by printf() in the standard C++ library. The \a cformat + string and \c{%s} arguments must be UTF-8 encoded. - \note This function expects a UTF-8 string for %s and Latin-1 for - the format string. - - The format string supports most of the conversion specifiers - provided by printf() in the standard C++ library. It doesn't - honor the length modifiers (e.g. \c h for \c short, \c ll for - \c{long long}). If you need those, use the standard snprintf() - function instead: - - \snippet qstring/main.cpp 63 + \note The \c{%lc} escape sequence expects a unicode character of type + \c char16_t, or \c ushort (as returned by QChar::unicode()). + The \c{%ls} escape sequence expects a pointer to a zero-terminated array + of unicode characters of type \c char16_t, or ushort (as returned by + QString::utf16()). This is at odds with the printf() in the standard C++ + library, which defines \c {%lc} to print a wchar_t and \c{%ls} to print + a \c{wchar_t*}, and might also produce compiler warnings on platforms + where the size of \c {wchar_t} is not 16 bits. \warning We do not recommend using QString::sprintf() in new Qt code. Instead, consider using QTextStream or arg(), both of @@ -6284,8 +6302,7 @@ ushort QString::toUShort(bool *ok, int base) const \snippet qstring/main.cpp 66 - Various string formats for floating point numbers can be converted - to double values: + \warning The QString content may only contain valid numerical characters which includes the plus/minus sign, the characters g and e used in scientific notation, and the decimal point. Including the unit or additional characters leads to a conversion error. \snippet qstring/main.cpp 67 @@ -6294,7 +6311,7 @@ ushort QString::toUShort(bool *ok, int base) const \snippet qstring/main.cpp 68 - For historic reasons, this function does not handle + For historical reasons, this function does not handle thousands group separators. If you need to convert such numbers, use QLocale::toDouble(). diff --git a/src/corelib/tools/qversionnumber.cpp b/src/corelib/tools/qversionnumber.cpp index 4d148249c04..3c8a9db0862 100644 --- a/src/corelib/tools/qversionnumber.cpp +++ b/src/corelib/tools/qversionnumber.cpp @@ -40,7 +40,7 @@ ** ****************************************************************************/ -#include +#include #include #include #include @@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE /*! \class QVersionNumber \inmodule QtCore + \internal \since 5.4 \brief The QVersionNumber class contains a version number with an arbitrary number of segments. diff --git a/src/corelib/tools/qversionnumber.h b/src/corelib/tools/qversionnumber_p.h similarity index 100% rename from src/corelib/tools/qversionnumber.h rename to src/corelib/tools/qversionnumber_p.h diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 2e77f683a4d..6f6404f83ce 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -72,7 +72,7 @@ HEADERS += \ tools/qunicodetools_p.h \ tools/qvarlengtharray.h \ tools/qvector.h \ - tools/qversionnumber.h + tools/qversionnumber_p.h SOURCES += \ diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index b1ec11dc71f..00c3aced0e3 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -282,24 +282,18 @@ public: QStringList serverConnectionNames; ConnectionMode mode; - - // members accessed in unlocked mode (except for deletion) - // connection and server provide their own locking mechanisms - // busService doesn't have state to be changed - DBusConnection *connection; - DBusServer *server; QDBusConnectionInterface *busService; - // watchers and timeouts are accessed from any thread - // but the corresponding timer and QSocketNotifier must be handled - // only in the object's thread - QMutex watchAndTimeoutLock; + // the dispatch lock protects everything related to the DBusConnection or DBusServer + // including the timeouts and watches + QMutex dispatchLock; + DBusConnection *connection; + DBusServer *server; WatcherHash watchers; TimeoutHash timeouts; PendingTimeoutList timeoutsPendingAdd; - // members accessed through a lock - QMutex dispatchLock; + // the master lock protects our own internal state QReadWriteLock lock; QDBusError lastError; diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 8586bdd83c8..6fcdd5030a4 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -154,7 +154,7 @@ static dbus_bool_t qDBusAddTimeout(DBusTimeout *timeout, void *data) if (!q_dbus_timeout_get_enabled(timeout)) return true; - QDBusWatchAndTimeoutLocker locker(AddTimeoutAction, d); + QDBusDispatchLocker locker(AddTimeoutAction, d); if (QCoreApplication::instance() && QThread::currentThread() == d->thread()) { // correct thread return qDBusRealAddTimeout(d, timeout, q_dbus_timeout_get_interval(timeout)); @@ -189,7 +189,7 @@ static void qDBusRemoveTimeout(DBusTimeout *timeout, void *data) QDBusConnectionPrivate *d = static_cast(data); - QDBusWatchAndTimeoutLocker locker(RemoveTimeoutAction, d); + QDBusDispatchLocker locker(RemoveTimeoutAction, d); // is it pending addition? QDBusConnectionPrivate::PendingTimeoutList::iterator pit = d->timeoutsPendingAdd.begin(); @@ -262,7 +262,7 @@ static bool qDBusRealAddWatch(QDBusConnectionPrivate *d, DBusWatch *watch, int f { QDBusConnectionPrivate::Watcher watcher; - QDBusWatchAndTimeoutLocker locker(AddWatchAction, d); + QDBusDispatchLocker locker(AddWatchAction, d); if (flags & DBUS_WATCH_READABLE) { //qDebug("addReadWatch %d", fd); watcher.watch = watch; @@ -296,7 +296,7 @@ static void qDBusRemoveWatch(DBusWatch *watch, void *data) QDBusConnectionPrivate *d = static_cast(data); int fd = q_dbus_watch_get_unix_fd(watch); - QDBusWatchAndTimeoutLocker locker(RemoveWatchAction, d); + QDBusDispatchLocker locker(RemoveWatchAction, d); QDBusConnectionPrivate::WatcherHash::iterator i = d->watchers.find(fd); while (i != d->watchers.end() && i.key() == fd) { if (i.value().watch == watch) { @@ -340,7 +340,7 @@ static void qDBusToggleWatch(DBusWatch *watch, void *data) static void qDBusRealToggleWatch(QDBusConnectionPrivate *d, DBusWatch *watch, int fd) { - QDBusWatchAndTimeoutLocker locker(ToggleWatchAction, d); + QDBusDispatchLocker locker(ToggleWatchAction, d); QDBusConnectionPrivate::WatcherHash::iterator i = d->watchers.find(fd); while (i != d->watchers.end() && i.key() == fd) { @@ -1015,8 +1015,8 @@ void QDBusConnectionPrivate::deliverCall(QObject *object, int /*flags*/, const Q extern bool qDBusInitThreads(); QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p) - : QObject(p), ref(1), capabilities(0), mode(InvalidMode), connection(0), server(0), busService(0), - watchAndTimeoutLock(QMutex::Recursive), + : QObject(p), ref(1), capabilities(0), mode(InvalidMode), busService(0), + dispatchLock(QMutex::Recursive), connection(0), server(0), rootNode(QString(QLatin1Char('/'))), anonymousAuthenticationAllowed(false) { @@ -1126,7 +1126,7 @@ bool QDBusConnectionPrivate::handleError(const QDBusErrorInternal &error) void QDBusConnectionPrivate::timerEvent(QTimerEvent *e) { { - QDBusWatchAndTimeoutLocker locker(TimerEventAction, this); + QDBusDispatchLocker locker(TimerEventAction, this); DBusTimeout *timeout = timeouts.value(e->timerId(), 0); if (timeout) q_dbus_timeout_handle(timeout); @@ -1145,7 +1145,7 @@ void QDBusConnectionPrivate::customEvent(QEvent *e) switch (ev->subtype) { case QDBusConnectionCallbackEvent::AddTimeout: { - QDBusWatchAndTimeoutLocker locker(RealAddTimeoutAction, this); + QDBusDispatchLocker locker(RealAddTimeoutAction, this); while (!timeoutsPendingAdd.isEmpty()) { QPair entry = timeoutsPendingAdd.takeFirst(); qDBusRealAddTimeout(this, entry.first, entry.second); @@ -1178,41 +1178,29 @@ void QDBusConnectionPrivate::doDispatch() void QDBusConnectionPrivate::socketRead(int fd) { - QVarLengthArray pendingWatches; - - { - QDBusWatchAndTimeoutLocker locker(SocketReadAction, this); - WatcherHash::ConstIterator it = watchers.constFind(fd); - while (it != watchers.constEnd() && it.key() == fd) { - if (it->watch && it->read && it->read->isEnabled()) - pendingWatches.append(it.value().watch); - ++it; + QDBusDispatchLocker locker(SocketReadAction, this); + WatcherHash::ConstIterator it = watchers.constFind(fd); + while (it != watchers.constEnd() && it.key() == fd) { + if (it->watch && it->read && it->read->isEnabled()) { + if (!q_dbus_watch_handle(it.value().watch, DBUS_WATCH_READABLE)) + qDebug("OUT OF MEM"); } + ++it; } - - for (int i = 0; i < pendingWatches.size(); ++i) - if (!q_dbus_watch_handle(pendingWatches[i], DBUS_WATCH_READABLE)) - qDebug("OUT OF MEM"); doDispatch(); } void QDBusConnectionPrivate::socketWrite(int fd) { - QVarLengthArray pendingWatches; - - { - QDBusWatchAndTimeoutLocker locker(SocketWriteAction, this); - WatcherHash::ConstIterator it = watchers.constFind(fd); - while (it != watchers.constEnd() && it.key() == fd) { - if (it->watch && it->write && it->write->isEnabled()) - pendingWatches.append(it.value().watch); - ++it; + QDBusDispatchLocker locker(SocketWriteAction, this); + WatcherHash::ConstIterator it = watchers.constFind(fd); + while (it != watchers.constEnd() && it.key() == fd) { + if (it->watch && it->write && it->write->isEnabled()) { + if (!q_dbus_watch_handle(it.value().watch, DBUS_WATCH_WRITABLE)) + qDebug("OUT OF MEM"); } + ++it; } - - for (int i = 0; i < pendingWatches.size(); ++i) - if (!q_dbus_watch_handle(pendingWatches[i], DBUS_WATCH_WRITABLE)) - qDebug("OUT OF MEM"); } void QDBusConnectionPrivate::objectDestroyed(QObject *obj) @@ -1265,7 +1253,10 @@ void QDBusConnectionPrivate::relaySignal(QObject *obj, const QMetaObject *mo, in //qDBusDebug() << "Emitting signal" << message; //qDBusDebug() << "for paths:"; q_dbus_message_set_no_reply(msg, true); // the reply would not be delivered to anything - huntAndEmit(connection, msg, obj, rootNode, isScriptable, isAdaptor); + { + QDBusDispatchLocker locker(HuntAndEmitAction, this); + huntAndEmit(connection, msg, obj, rootNode, isScriptable, isAdaptor); + } q_dbus_message_unref(msg); } @@ -1922,7 +1913,11 @@ int QDBusConnectionPrivate::send(const QDBusMessage& message) qDBusDebug() << this << "sending message (no reply):" << message; checkThread(); - bool isOk = q_dbus_connection_send(connection, msg, 0); + bool isOk; + { + QDBusDispatchLocker locker(SendMessageAction, this); + isOk = q_dbus_connection_send(connection, msg, 0); + } int serial = 0; if (isOk) serial = q_dbus_message_get_serial(msg); @@ -2040,7 +2035,11 @@ QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message, qDBusDebug() << this << "sending message (blocking):" << message; QDBusErrorInternal error; - DBusMessage *reply = q_dbus_connection_send_with_reply_and_block(connection, msg, timeout, error); + DBusMessage *reply; + { + QDBusDispatchLocker locker(SendWithReplyAndBlockAction, this); + reply = q_dbus_connection_send_with_reply_and_block(connection, msg, timeout, error); + } q_dbus_message_unref(msg); diff --git a/src/dbus/qdbusmessage.cpp b/src/dbus/qdbusmessage.cpp index 8025636668c..25206b4bb72 100644 --- a/src/dbus/qdbusmessage.cpp +++ b/src/dbus/qdbusmessage.cpp @@ -605,6 +605,10 @@ QString QDBusMessage::signature() const */ bool QDBusMessage::isReplyRequired() const { + // Only method calls can have replies + if (d_ptr->type != DBUS_MESSAGE_TYPE_METHOD_CALL) + return false; + if (!d_ptr->msg) return d_ptr->localMessage; // if it's a local message, reply is required return !q_dbus_message_get_no_reply(d_ptr->msg); diff --git a/src/dbus/qdbusthreaddebug_p.h b/src/dbus/qdbusthreaddebug_p.h index 78db18f5c76..80410681340 100644 --- a/src/dbus/qdbusthreaddebug_p.h +++ b/src/dbus/qdbusthreaddebug_p.h @@ -86,6 +86,9 @@ enum ThreadAction { MessageResultReceivedAction = 26, ActivateSignalAction = 27, PendingCallBlockAction = 28, + SendMessageAction = 29, + SendWithReplyAndBlockAction = 30, + HuntAndEmitAction = 31, AddTimeoutAction = 50, RealAddTimeoutAction = 51, @@ -196,13 +199,6 @@ struct QDBusDispatchLocker: QDBusMutexLocker { } }; -struct QDBusWatchAndTimeoutLocker: QDBusMutexLocker -{ - inline QDBusWatchAndTimeoutLocker(ThreadAction a, QDBusConnectionPrivate *s) - : QDBusMutexLocker(a, s, &s->watchAndTimeoutLock) - { } -}; - #if QDBUS_THREAD_DEBUG # define SEM_ACQUIRE(action, sem) \ do { \ diff --git a/src/gui/doc/src/richtext.qdoc b/src/gui/doc/src/richtext.qdoc index 90248298d62..460018a52e9 100644 --- a/src/gui/doc/src/richtext.qdoc +++ b/src/gui/doc/src/richtext.qdoc @@ -27,6 +27,7 @@ /*! \group richtext-processing + \brief How to use Rich Text Processing APIs. \title Rich Text Processing APIs */ diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index f1a384af3a6..d885729cbde 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -1173,8 +1173,8 @@ QIcon QIcon::fromTheme(const QString &name, const QIcon &fallback) QIconEngine * const engine = platformTheme ? platformTheme->createIconEngine(name) : new QIconLoaderEngine(name); QIcon *cachedIcon = new QIcon(engine); - qtIconCache()->insert(name, cachedIcon); icon = *cachedIcon; + qtIconCache()->insert(name, cachedIcon); } // Note the qapp check is to allow lazy loading of static icons diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index 60099185216..2e8fc1963d3 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -2945,7 +2945,7 @@ void qInitImageConversions() } #endif -#ifdef __ARM_NEON__ +#if defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64) extern void convert_RGB888_to_RGB32_neon(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags); qimage_converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_neon; qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_neon; diff --git a/src/gui/image/qimage_neon.cpp b/src/gui/image/qimage_neon.cpp index e3930bbb4d2..88d1c87ee72 100644 --- a/src/gui/image/qimage_neon.cpp +++ b/src/gui/image/qimage_neon.cpp @@ -35,7 +35,7 @@ #include #include -#ifdef __ARM_NEON__ +#if defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64) QT_BEGIN_NAMESPACE @@ -103,4 +103,4 @@ void convert_RGB888_to_RGB32_neon(QImageData *dest, const QImageData *src, Qt::I QT_END_NAMESPACE -#endif // __ARM_NEON__ +#endif // defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64) diff --git a/src/gui/image/qjpeghandler.cpp b/src/gui/image/qjpeghandler.cpp index fbcc0608e28..ae30de634ae 100644 --- a/src/gui/image/qjpeghandler.cpp +++ b/src/gui/image/qjpeghandler.cpp @@ -729,7 +729,7 @@ public: }; QJpegHandlerPrivate(QJpegHandler *qq) - : quality(75), iod_src(0), state(Ready), q(qq) + : quality(75), exifOrientation(1), iod_src(0), state(Ready), q(qq) {} ~QJpegHandlerPrivate() @@ -744,8 +744,10 @@ public: bool readJpegHeader(QIODevice*); bool read(QImage *image); + void applyExifOrientation(QImage *image); int quality; + int exifOrientation; QVariant size; QImage::Format format; QSize scaledSize; @@ -763,6 +765,97 @@ public: QJpegHandler *q; }; +static bool readExifHeader(QDataStream &stream) +{ + char prefix[6]; + if (stream.readRawData(prefix, sizeof(prefix)) != sizeof(prefix)) + return false; + if (prefix[0] != 'E' || prefix[1] != 'x' || prefix[2] != 'i' || prefix[3] != 'f' || prefix[4] != 0 || prefix[5] != 0) + return false; + return true; +} + +/* + * Returns -1 on error + * Returns 0 if no Exif orientation was found + * Returns 1 orientation is horizontal (normal) + * Returns 2 mirror horizontal + * Returns 3 rotate 180 + * Returns 4 mirror vertical + * Returns 5 mirror horizontal and rotate 270 CCW + * Returns 6 rotate 90 CW + * Returns 7 mirror horizontal and rotate 90 CW + * Returns 8 rotate 270 CW + */ +static int getExifOrientation(QByteArray &exifData) +{ + QDataStream stream(&exifData, QIODevice::ReadOnly); + + if (!readExifHeader(stream)) + return -1; + + quint16 val; + quint32 offset; + + // read byte order marker + stream >> val; + if (val == 0x4949) // 'II' == Intel + stream.setByteOrder(QDataStream::LittleEndian); + else if (val == 0x4d4d) // 'MM' == Motorola + stream.setByteOrder(QDataStream::BigEndian); + else + return -1; // unknown byte order + + // read size + stream >> val; + if (val != 0x2a) + return -1; + + stream >> offset; + // we have already used 8 bytes of TIFF header + offset -= 8; + + // read IFD + while (!stream.atEnd()) { + quint16 numEntries; + + // skip offset bytes to get the next IFD + if (stream.skipRawData(offset) != (qint32)offset) + return -1; + + stream >> numEntries; + + for (;numEntries > 0; --numEntries) { + quint16 tag; + quint16 type; + quint32 components; + quint32 value; + + stream >> tag >> type >> components >> value; + + if (tag == 0x0112) { // Tag Exif.Image.Orientation + if (components !=1) + return -1; + if (type != 3) // we are expecting it to be an unsigned short + return -1; + if (value < 1 || value > 8) // check for valid range + return -1; + + // It is possible to include the orientation multiple times. + // Right now the first value is returned. + return value; + } + } + + // read offset to next IFD + stream >> offset; + if (offset == 0) // this is the last IFD + break; + } + + // No Exif orientation was found + return 0; +} /*! \internal */ @@ -782,6 +875,7 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device) if (!setjmp(err.setjmp_buffer)) { jpeg_save_markers(&info, JPEG_COM, 0xFFFF); + jpeg_save_markers(&info, JPEG_APP0+1, 0xFFFF); // Exif uses APP1 marker (void) jpeg_read_header(&info, TRUE); @@ -793,6 +887,8 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device) format = QImage::Format_Invalid; read_jpeg_format(format, &info); + QByteArray exifData; + for (jpeg_saved_marker_ptr marker = info.marker_list; marker != NULL; marker = marker->next) { if (marker->marker == JPEG_COM) { QString key, value; @@ -810,9 +906,18 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device) description += key + QLatin1String(": ") + value.simplified(); readTexts.append(key); readTexts.append(value); + } else if (marker->marker == JPEG_APP0+1) { + exifData.append((const char*)marker->data, marker->data_length); } } + if (exifData.size()) { + // Exif data present + int orientation = getExifOrientation(exifData); + if (orientation > 0) + exifOrientation = orientation; + } + state = ReadHeader; return true; } @@ -826,6 +931,48 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device) return true; } +void QJpegHandlerPrivate::applyExifOrientation(QImage *image) +{ + // This is not an optimized implementation, but easiest to maintain + QTransform transform; + + switch (exifOrientation) { + case 1: // normal + break; + case 2: // mirror horizontal + *image = image->mirrored(true, false); + break; + case 3: // rotate 180 + transform.rotate(180); + *image = image->transformed(transform); + break; + case 4: // mirror vertical + *image = image->mirrored(false, true); + break; + case 5: // mirror horizontal and rotate 270 CCW + *image = image->mirrored(true, false); + transform.rotate(270); + *image = image->transformed(transform); + break; + case 6: // rotate 90 CW + transform.rotate(90); + *image = image->transformed(transform); + break; + case 7: // mirror horizontal and rotate 90 CW + *image = image->mirrored(true, false); + transform.rotate(90); + *image = image->transformed(transform); + break; + case 8: // rotate 270 CW + transform.rotate(-90); + *image = image->transformed(transform); + break; + default: + qWarning("This should never happen"); + } + exifOrientation = 1; +} + bool QJpegHandlerPrivate::read(QImage *image) { if(state == Ready) @@ -837,6 +984,7 @@ bool QJpegHandlerPrivate::read(QImage *image) if (success) { for (int i = 0; i < readTexts.size()-1; i+=2) image->setText(readTexts.at(i), readTexts.at(i+1)); + applyExifOrientation(image); state = Ready; return true; @@ -856,12 +1004,13 @@ extern "C" void qt_convert_rgb888_to_rgb32_mips_dspr2_asm(quint32 *dst, const uc QJpegHandler::QJpegHandler() : d(new QJpegHandlerPrivate(this)) { -#if defined(__ARM_NEON__) +#if defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64) // from qimage_neon.cpp if (qCpuHasFeature(NEON)) rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32_neon; -#endif // __ARM_NEON__ +#endif + #if defined(QT_COMPILER_SUPPORTS_SSSE3) // from qimage_ssse3.cpp diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index c5e7fb523d1..e421f79e91b 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -163,7 +163,6 @@ QWindow *QGuiApplicationPrivate::focus_window = 0; static QBasicMutex applicationFontMutex; QFont *QGuiApplicationPrivate::app_font = 0; bool QGuiApplicationPrivate::obey_desktop_settings = true; -bool QGuiApplicationPrivate::noGrab = false; static qreal fontSmoothingGamma = 1.7; @@ -1191,20 +1190,10 @@ void QGuiApplicationPrivate::eventDispatcherReady() platform_integration->initialize(); } -#if defined(QT_DEBUG) && defined(Q_OS_LINUX) -// Find out if our parent process is gdb by looking at the 'exe' symlink under /proc. -static bool runningUnderDebugger() -{ - const QFileInfo parentProcExe(QStringLiteral("/proc/") + QString::number(getppid()) + QStringLiteral("/exe")); - return parentProcExe.isSymLink() && parentProcExe.symLinkTarget().endsWith(QLatin1String("/gdb")); -} -#endif - void QGuiApplicationPrivate::init() { QCoreApplicationPrivate::is_app_running = false; // Starting up. - bool doGrabUnderDebugger = false; bool loadTestability = false; QList pluginList; // Get command line params @@ -1239,10 +1228,6 @@ void QGuiApplicationPrivate::init() QDir::setCurrent(qbundlePath.section(QLatin1Char('/'), 0, -2)); } #endif - } else if (arg == "-nograb") { - QGuiApplicationPrivate::noGrab = true; - } else if (arg == "-dograb") { - doGrabUnderDebugger = true; #ifndef QT_NO_SESSIONMANAGER } else if (arg == "-session" && i < argc-1) { ++i; @@ -1268,16 +1253,6 @@ void QGuiApplicationPrivate::init() argc = j; } -#if defined(QT_DEBUG) && defined(Q_OS_LINUX) - if (!doGrabUnderDebugger && !QGuiApplicationPrivate::noGrab && runningUnderDebugger()) { - QGuiApplicationPrivate::noGrab = true; - qDebug("Qt: gdb: -nograb added to command-line options.\n" - "\t Use the -dograb option to enforce grabbing."); - } -#else - Q_UNUSED(doGrabUnderDebugger) -#endif - // Load environment exported generic plugins foreach (const QByteArray &plugin, qgetenv("QT_QPA_GENERIC_PLUGINS").split(',')) pluginList << plugin; diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index 8988bd461db..eed3d5c10ef 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -221,7 +221,6 @@ public: QStyleHints *styleHints; static bool obey_desktop_settings; - static bool noGrab; QInputMethod *inputMethod; QString firstWindowTitle; diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h index d5a31261766..975553e7cda 100644 --- a/src/gui/kernel/qopenglcontext_p.h +++ b/src/gui/kernel/qopenglcontext_p.h @@ -203,6 +203,7 @@ public: , workaround_brokenTexSubImage(false) , workaround_missingPrecisionQualifiers(false) , active_engine(0) + , qgl_current_fbo_invalid(false) { requestedFormat = QSurfaceFormat::defaultFormat(); } @@ -237,6 +238,8 @@ public: QPaintEngineEx *active_engine; + bool qgl_current_fbo_invalid; + QVariant nativeHandle; static QOpenGLContext *setCurrentContext(QOpenGLContext *context); diff --git a/src/gui/kernel/qshapedpixmapdndwindow.cpp b/src/gui/kernel/qshapedpixmapdndwindow.cpp index 55a8aae33c4..af60b36647c 100644 --- a/src/gui/kernel/qshapedpixmapdndwindow.cpp +++ b/src/gui/kernel/qshapedpixmapdndwindow.cpp @@ -52,6 +52,12 @@ QShapedPixmapWindow::QShapedPixmapWindow() m_backingStore = new QBackingStore(this); } +QShapedPixmapWindow::~QShapedPixmapWindow() +{ + delete m_backingStore; + m_backingStore = 0; +} + void QShapedPixmapWindow::render() { QRect rect(QPoint(), geometry().size()); diff --git a/src/gui/kernel/qshapedpixmapdndwindow_p.h b/src/gui/kernel/qshapedpixmapdndwindow_p.h index b59305f055f..04198c83cb7 100644 --- a/src/gui/kernel/qshapedpixmapdndwindow_p.h +++ b/src/gui/kernel/qshapedpixmapdndwindow_p.h @@ -56,6 +56,7 @@ class QShapedPixmapWindow : public QWindow Q_OBJECT public: QShapedPixmapWindow(); + ~QShapedPixmapWindow(); void render(); diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index a3b7f38c80a..fa99390af01 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -1127,6 +1127,10 @@ Qt::WindowState QWindow::windowState() const This is a hint to the window manager that this window is a dialog or pop-up on behalf of the given window. + In order to cause the window to be centered above its transient parent by + default, depending on the window manager, it may also be necessary to call + setFlags() with a suitable \l Qt::WindowType (such as \c Qt::Dialog). + \sa transientParent(), parent() */ void QWindow::setTransientParent(QWindow *parent) @@ -1644,8 +1648,6 @@ QPlatformSurface *QWindow::surfaceHandle() const bool QWindow::setKeyboardGrabEnabled(bool grab) { Q_D(QWindow); - if (grab && QGuiApplicationPrivate::noGrab) - return false; if (d->platformWindow) return d->platformWindow->setKeyboardGrabEnabled(grab); return false; @@ -1663,8 +1665,6 @@ bool QWindow::setKeyboardGrabEnabled(bool grab) bool QWindow::setMouseGrabEnabled(bool grab) { Q_D(QWindow); - if (grab && QGuiApplicationPrivate::noGrab) - return false; if (d->platformWindow) return d->platformWindow->setMouseGrabEnabled(grab); return false; @@ -2352,7 +2352,7 @@ QWindow *QWindow::fromWinId(WId id) /*! Causes an alert to be shown for \a msec miliseconds. If \a msec is \c 0 (the default), then the alert is shown indefinitely until the window becomes - active again. + active again. This function has no effect on an active window. In alert state, the window indicates that it demands attention, for example by flashing or bouncing the taskbar entry. @@ -2363,7 +2363,7 @@ QWindow *QWindow::fromWinId(WId id) void QWindow::alert(int msec) { Q_D(QWindow); - if (!d->platformWindow || d->platformWindow->isAlertState()) + if (!d->platformWindow || d->platformWindow->isAlertState() || isActive()) return; d->platformWindow->setAlertState(true); if (d->platformWindow->isAlertState() && msec) diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h index 6d9793ae3ff..2230ed88013 100644 --- a/src/gui/kernel/qwindow.h +++ b/src/gui/kernel/qwindow.h @@ -358,6 +358,19 @@ private: friend Q_GUI_EXPORT QWindowPrivate *qt_window_private(QWindow *window); }; +#ifndef Q_QDOC +template <> inline QWindow *qobject_cast(QObject *o) +{ + if (!o || !o->isWindowType()) return 0; + return static_cast(o); +} +template <> inline const QWindow *qobject_cast(const QObject *o) +{ + if (!o || !o->isWindowType()) return 0; + return static_cast(o); +} +#endif // !Q_QDOC + QT_END_NAMESPACE #endif // QWINDOW_H diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp index b185e332e68..124d9d53f66 100644 --- a/src/gui/opengl/qopenglframebufferobject.cpp +++ b/src/gui/opengl/qopenglframebufferobject.cpp @@ -469,6 +469,8 @@ void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *, const QSi funcs.glGenFramebuffers(1, &fbo); funcs.glBindFramebuffer(GL_FRAMEBUFFER, fbo); + QOpenGLContextPrivate::get(ctx)->qgl_current_fbo_invalid = true; + GLuint color_buffer = 0; QT_CHECK_GLERROR(); @@ -997,7 +999,11 @@ bool QOpenGLFramebufferObject::bind() if (current->shareGroup() != d->fbo_guard->group()) qWarning("QOpenGLFramebufferObject::bind() called from incompatible context"); #endif + d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo()); + + QOpenGLContextPrivate::get(current)->qgl_current_fbo_invalid = true; + if (d->texture_guard || d->format.samples() != 0) d->valid = d->checkFramebufferStatus(current); else @@ -1029,9 +1035,12 @@ bool QOpenGLFramebufferObject::release() qWarning("QOpenGLFramebufferObject::release() called from incompatible context"); #endif - if (current) + if (current) { d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->defaultFramebufferObject()); + QOpenGLContextPrivate::get(current)->qgl_current_fbo_invalid = true; + } + return true; } @@ -1194,9 +1203,23 @@ Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, If used together with QOpenGLPaintDevice, \a flipped should be the opposite of the value of QOpenGLPaintDevice::paintFlipped(). - Will try to return a premultiplied ARBG32 or RGB32 image. Since 5.2 it will fall back to - a premultiplied RGBA8888 or RGBx8888 image when reading to ARGB32 is not supported. Since 5.4 an - A2BGR30 image is returned if the internal format is RGB10_A2. + The returned image has a format of premultiplied ARGB32 or RGB32. The latter is used + only when internalTextureFormat() is set to \c GL_RGB. + + If the rendering in the framebuffer was not done with premultiplied alpha in mind, + create a wrapper QImage with a non-premultiplied format. This is necessary before + performing operations like QImage::save() because otherwise the image data would get + unpremultiplied, even though it was not premultiplied in the first place. To create + such a wrapper without performing a copy of the pixel data, do the following: + + \code + QImage fboImage(fbo.toImage()); + QImage image(fboImage.constBits(), fboImage.width(), fboImage.height(), QImage::Format_ARGB32); + \endcode + + Since Qt 5.2 the function will fall back to premultiplied RGBA8888 or RGBx8888 when + reading to (A)RGB32 is not supported. Since 5.4 an A2BGR30 image is returned if the + internal format is RGB10_A2. For multisampled framebuffer objects the samples are resolved using the \c{GL_EXT_framebuffer_blit} extension. If the extension is not available, the contents @@ -1272,8 +1295,10 @@ bool QOpenGLFramebufferObject::bindDefault() { QOpenGLContext *ctx = const_cast(QOpenGLContext::currentContext()); - if (ctx) + if (ctx) { ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject()); + QOpenGLContextPrivate::get(ctx)->qgl_current_fbo_invalid = true; + } #ifdef QT_DEBUG else qWarning("QOpenGLFramebufferObject::bindDefault() called without current context."); @@ -1342,6 +1367,7 @@ void QOpenGLFramebufferObject::setAttachment(QOpenGLFramebufferObject::Attachmen qWarning("QOpenGLFramebufferObject::setAttachment() called from incompatible context"); #endif d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo()); + QOpenGLContextPrivate::get(current)->qgl_current_fbo_invalid = true; d->initAttachments(current, attachment); } diff --git a/src/gui/opengl/qopenglpaintdevice.cpp b/src/gui/opengl/qopenglpaintdevice.cpp index e908fd8e915..a08d26f7081 100644 --- a/src/gui/opengl/qopenglpaintdevice.cpp +++ b/src/gui/opengl/qopenglpaintdevice.cpp @@ -138,8 +138,8 @@ QOpenGLPaintDevice::QOpenGLPaintDevice(int width, int height) /*! \internal */ -QOpenGLPaintDevice::QOpenGLPaintDevice(QOpenGLPaintDevicePrivate *dd) - : d_ptr(dd) +QOpenGLPaintDevice::QOpenGLPaintDevice(QOpenGLPaintDevicePrivate &dd) + : d_ptr(&dd) { } diff --git a/src/gui/opengl/qopenglpaintdevice.h b/src/gui/opengl/qopenglpaintdevice.h index dda3bfe43f6..10cee842ab0 100644 --- a/src/gui/opengl/qopenglpaintdevice.h +++ b/src/gui/opengl/qopenglpaintdevice.h @@ -53,7 +53,6 @@ public: QOpenGLPaintDevice(); explicit QOpenGLPaintDevice(const QSize &size); QOpenGLPaintDevice(int width, int height); - QOpenGLPaintDevice(QOpenGLPaintDevicePrivate *dd); virtual ~QOpenGLPaintDevice(); int devType() const { return QInternal::OpenGL; } @@ -76,6 +75,7 @@ public: virtual void ensureActiveTarget(); protected: + QOpenGLPaintDevice(QOpenGLPaintDevicePrivate &dd); int metric(QPaintDevice::PaintDeviceMetric metric) const; Q_DISABLE_COPY(QOpenGLPaintDevice) diff --git a/src/gui/opengl/qopengltextureglyphcache.cpp b/src/gui/opengl/qopengltextureglyphcache.cpp index 0f70a01014a..cd268cd685f 100644 --- a/src/gui/opengl/qopengltextureglyphcache.cpp +++ b/src/gui/opengl/qopengltextureglyphcache.cpp @@ -82,10 +82,12 @@ QOpenGLTextureGlyphCache::~QOpenGLTextureGlyphCache() clear(); } +#if !defined(QT_OPENGL_ES_2) static inline bool isCoreProfile() { return QOpenGLContext::currentContext()->format().profile() == QSurfaceFormat::CoreProfile; } +#endif void QOpenGLTextureGlyphCache::createTextureData(int width, int height) { diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp index d1201751086..d136f3a9035 100644 --- a/src/gui/painting/qbrush.cpp +++ b/src/gui/painting/qbrush.cpp @@ -708,6 +708,9 @@ void QBrush::setStyle(Qt::BrushStyle style) void QBrush::setColor(const QColor &c) { + if (d->color == c) + return; + detach(d->style); d->color = c; } diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 4c6dc958b25..a991b89f48e 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -6928,7 +6928,7 @@ void qInitDrawhelperAsm() qt_fetch_radial_gradient = qt_fetch_radial_gradient_neon; #endif -#ifdef Q_PROCESSOR_MIPS_32 +#if defined(Q_PROCESSOR_MIPS_32) && defined(QT_COMPILER_SUPPORTS_MIPS_DSP) qt_memfill32 = qt_memfill32_asm_mips_dsp; #endif // Q_PROCESSOR_MIPS_32 diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index 30421ea2fa1..8cf45863b81 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -2506,7 +2506,8 @@ void QPdfEnginePrivate::drawTextItem(const QPointF &p, const QTextItemInt &ti) QFontEngine::FaceId face_id = fe->faceId(); bool noEmbed = false; - if (face_id.filename.isEmpty() + if (!embedFonts + || face_id.filename.isEmpty() || fe->fsType & 0x200 /* bitmap embedding only */ || fe->fsType == 2 /* no embedding allowed */) { *currentPage << "Q\n"; @@ -2529,10 +2530,6 @@ void QPdfEnginePrivate::drawTextItem(const QPointF &p, const QTextItemInt &ti) qreal size = ti.fontEngine->fontDef.pixelSize; -#if defined(Q_OS_WIN) - size = (ti.fontEngine->ascent() + ti.fontEngine->descent()).toReal(); -#endif - QVarLengthArray glyphs; QVarLengthArray positions; QTransform m = QTransform::fromTranslate(p.x(), p.y()); diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index decf2fe1211..8fe6aff79fb 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -620,7 +620,7 @@ struct QtFontDesc static int match(int script, const QFontDef &request, const QString &family_name, const QString &foundry_name, int force_encoding_id, - QtFontDesc *desc, const QList &blacklisted, bool fallback); + QtFontDesc *desc, const QList &blacklisted); static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDef *fontDef, bool multi) { @@ -1110,7 +1110,7 @@ static bool matchFamilyName(const QString &familyName, QtFontFamily *f) */ static int match(int script, const QFontDef &request, const QString &family_name, const QString &foundry_name, int force_encoding_id, - QtFontDesc *desc, const QList &blacklistedFamilies, bool fallback = false) + QtFontDesc *desc, const QList &blacklistedFamilies) { Q_UNUSED(force_encoding_id); int result = -1; @@ -1163,7 +1163,7 @@ static int match(int script, const QFontDef &request, load(test.family->name, script); // Check if family is supported in the script we want - if (!fallback && script != QChar::Script_Common && !(test.family->writingSystems[writingSystem] & QtFontFamily::Supported)) + if (script != QChar::Script_Common && !(test.family->writingSystems[writingSystem] & QtFontFamily::Supported)) continue; // as we know the script is supported, we can be sure @@ -2490,7 +2490,7 @@ bool QFontDatabase::supportsThreadedFontRendering() */ QFontEngine * QFontDatabase::findFont(int script, const QFontPrivate *fp, - const QFontDef &request, bool multi, bool fallback) + const QFontDef &request, bool multi) { QMutexLocker locker(fontDatabaseMutex()); @@ -2518,7 +2518,7 @@ QFontDatabase::findFont(int script, const QFontPrivate *fp, QtFontDesc desc; QList blackListed; - int index = match(script, request, family_name, foundry_name, force_encoding_id, &desc, blackListed, fallback); + int index = match(script, request, family_name, foundry_name, force_encoding_id, &desc, blackListed); if (index >= 0) { engine = loadEngine(script, request, desc.family, desc.foundry, desc.style, desc.size); if (!engine) diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h index f1c479d0bbb..d7d8745f128 100644 --- a/src/gui/text/qfontdatabase.h +++ b/src/gui/text/qfontdatabase.h @@ -152,7 +152,7 @@ private: static void createDatabase(); static void parseFontName(const QString &name, QString &foundry, QString &family); static QString resolveFontFamilyAlias(const QString &family); - static QFontEngine *findFont(int script, const QFontPrivate *fp, const QFontDef &request, bool multi = false, bool fallback = false); + static QFontEngine *findFont(int script, const QFontPrivate *fp, const QFontDef &request, bool multi = false); static void load(const QFontPrivate *d, int script); friend struct QFontDef; diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index fe0f9fa943e..4c6fc7c1a69 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -373,8 +373,6 @@ bool QFontEngine::supportsScript(QChar::Script script) const if (!ret && script_tag_2 != HB_OT_TAG_DEFAULT_SCRIPT) ret = hb_ot_layout_table_find_script(face, HB_OT_TAG_GSUB, HB_OT_TAG_DEFAULT_SCRIPT, &script_index); } - - hb_face_destroy(face); } return ret; } @@ -2028,7 +2026,7 @@ void QFontEngineMultiBasicImpl::loadEngine(int at) request.family = fallbackFamilies.at(at-1); engines[at] = QFontDatabase::findFont(script, /*fontprivate = */0, - request, /*multi = */false, true); + request, /*multi = */false); Q_ASSERT(engines[at]); engines[at]->ref.ref(); engines[at]->fontDef = request; @@ -2098,4 +2096,8 @@ QFontEngine* QFontEngineMultiBasicImpl::createMultiFontEngine(QFontEngine *fe, i return engine; } +QTestFontEngine::QTestFontEngine(int size) + : QFontEngineBox(TestFontEngine, size) +{} + QT_END_NAMESPACE diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index b44eb43be5e..4c5bab77d6a 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -1459,10 +1459,7 @@ void QFontEngineFT::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_me bool QFontEngineFT::supportsTransformation(const QTransform &transform) const { - // The freetype engine falls back to QFontEngine for tranformed glyphs, - // which uses fast-tranform and produces very ugly results, so we claim - // to support just translations. - return transform.type() <= QTransform::TxTranslate; + return transform.type() <= QTransform::TxRotate; } void QFontEngineFT::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) @@ -1943,17 +1940,75 @@ void QFontEngineFT::unlockAlphaMapForGlyph() currentlyLockedAlphaMap = QImage(); } -QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format) +QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g, + QFixed subPixelPosition, + GlyphFormat format, + const QTransform &t) { - return defaultGlyphSet.outline_drawing ? 0 : - loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, g, subPixelPosition, format); + FT_Face face = 0; + QGlyphSet *glyphSet = 0; + FT_Matrix ftMatrix = QTransformToFTMatrix(t); + if (cacheEnabled) { + if (t.type() > QTransform::TxTranslate && FT_IS_SCALABLE(freetype->face)) { + for (int i = 0; i < transformedGlyphSets.count(); ++i) { + const QGlyphSet &g = transformedGlyphSets.at(i); + if (g.transformationMatrix.xx == ftMatrix.xx + && g.transformationMatrix.xy == ftMatrix.xy + && g.transformationMatrix.yx == ftMatrix.yx + && g.transformationMatrix.yy == ftMatrix.yy) { + + // found a match, move it to the front + transformedGlyphSets.move(i, 0); + glyphSet = &transformedGlyphSets[0]; + break; + } + } + + if (!glyphSet) { + // don't cache more than 10 transformations + if (transformedGlyphSets.count() >= 10) { + transformedGlyphSets.move(transformedGlyphSets.size() - 1, 0); + } else { + transformedGlyphSets.prepend(QGlyphSet()); + } + glyphSet = &transformedGlyphSets[0]; + glyphSet->clear(); + glyphSet->transformationMatrix = ftMatrix; + } + } else { + glyphSet = &defaultGlyphSet; + } + Q_ASSERT(glyphSet != 0); + } + + if (glyphSet != 0 && glyphSet->outline_drawing) + return 0; + + Glyph *glyph = glyphSet != 0 ? glyphSet->getGlyph(g, subPixelPosition) : 0; + if (!glyph || glyph->format != format) { + face = lockFace(); + FT_Matrix m = this->matrix; + FT_Matrix_Multiply(&ftMatrix, &m); + freetype->matrix = m; + glyph = loadGlyph(glyphSet, g, subPixelPosition, format, false); + } + + if (face) + unlockFace(); + + return glyph; } QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition) +{ + return alphaMapForGlyph(g, subPixelPosition, QTransform()); +} + +QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t) { lockFace(); - QScopedPointer glyph(loadGlyphFor(g, subPixelPosition, antialias ? Format_A8 : Format_Mono)); + QScopedPointer glyph(loadGlyphFor(g, subPixelPosition, antialias ? Format_A8 : Format_Mono, t)); if (!glyph || !glyph->data) { unlockFace(); return QFontEngine::alphaMapForGlyph(g); @@ -1982,12 +2037,12 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition) QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t) { - if (t.type() > QTransform::TxTranslate) + if (t.type() > QTransform::TxRotate) return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t); lockFace(); - QScopedPointer glyph(loadGlyphFor(g, subPixelPosition, Format_A32)); + QScopedPointer glyph(loadGlyphFor(g, subPixelPosition, Format_A32, t)); if (!glyph || !glyph->data) { unlockFace(); return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t); diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h index a73c281f1d7..1894d25d70b 100644 --- a/src/gui/text/qfontengine_ft_p.h +++ b/src/gui/text/qfontengine_ft_p.h @@ -233,6 +233,7 @@ private: virtual void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags flags) const; virtual QImage alphaMapForGlyph(glyph_t g) { return alphaMapForGlyph(g, 0); } virtual QImage alphaMapForGlyph(glyph_t, QFixed); + QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t); virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t); virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed subPixelPosition, @@ -265,7 +266,7 @@ private: inline Glyph *loadGlyph(uint glyph, QFixed subPixelPosition, GlyphFormat format = Format_None, bool fetchMetricsOnly = false) const { return loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyph, subPixelPosition, format, fetchMetricsOnly); } Glyph *loadGlyph(QGlyphSet *set, uint glyph, QFixed subPixelPosition, GlyphFormat = Format_None, bool fetchMetricsOnly = false) const; - Glyph *loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format); + Glyph *loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format, const QTransform &t); QGlyphSet *loadTransformedGlyphSet(const QTransform &matrix); bool loadGlyphs(QGlyphSet *gs, const glyph_t *glyphs, int num_glyphs, diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 50b1bb9e9d1..9364b82bed6 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -463,7 +463,7 @@ private: class QTestFontEngine : public QFontEngineBox { public: - inline QTestFontEngine(int size) : QFontEngineBox(TestFontEngine, size) {} + QTestFontEngine(int size); }; QT_END_NAMESPACE diff --git a/src/gui/text/qharfbuzzng.cpp b/src/gui/text/qharfbuzzng.cpp index eb7bca19746..16c45e642b3 100644 --- a/src/gui/text/qharfbuzzng.cpp +++ b/src/gui/text/qharfbuzzng.cpp @@ -632,7 +632,7 @@ hb_face_t *hb_qt_face_get_for_engine(QFontEngine *fe) fe->face_destroy_func = _hb_qt_face_release; } - return hb_face_reference((hb_face_t *)fe->face_); + return (hb_face_t *)fe->face_; } @@ -645,8 +645,6 @@ _hb_qt_font_create(QFontEngine *fe) hb_font_t *font = hb_font_create(face); - hb_face_destroy(face); // ref-ed in hb_qt_face_get_for_engine() - if (Q_UNLIKELY(hb_font_is_immutable(font))) { hb_font_destroy(font); return NULL; @@ -684,7 +682,7 @@ hb_font_t *hb_qt_font_get_for_engine(QFontEngine *fe) fe->font_destroy_func = _hb_qt_font_release; } - return hb_font_reference((hb_font_t *)fe->font_); + return (hb_font_t *)fe->font_; } QT_END_NAMESPACE diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 9fe1fd26e9f..d156124b984 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1168,8 +1168,6 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *st }; const int num_features = 1; shapedOk = hb_shape_full(hb_font, buffer, features, num_features, 0); - - hb_font_destroy(hb_font); } if (!shapedOk) { hb_buffer_destroy(buffer); diff --git a/src/gui/text/qtextimagehandler.cpp b/src/gui/text/qtextimagehandler.cpp index f6525448def..37c18e3624c 100644 --- a/src/gui/text/qtextimagehandler.cpp +++ b/src/gui/text/qtextimagehandler.cpp @@ -44,31 +44,49 @@ QT_BEGIN_NAMESPACE -static QString resolve2xFile(const QString &fileName, qreal targetDevicePixelRatio) +static QString resolveFileName(QString fileName, QUrl *url, qreal targetDevicePixelRatio) { + // We might use the fileName for loading if url loading fails + // try to make sure it is a valid file path. + // Also, QFile{Info}::exists works only on filepaths (not urls) + + if (url->isValid()) { + if (url->scheme() == QLatin1Literal("qrc")) { + fileName = fileName.right(fileName.length() - 3); + } + else if (url->scheme() == QLatin1Literal("file")) { + fileName = url->toLocalFile(); + } + } + if (targetDevicePixelRatio <= 1.0) return fileName; - int dotIndex = fileName.lastIndexOf(QLatin1Char('.')); + // try to find a 2x version + + const int dotIndex = fileName.lastIndexOf(QLatin1Char('.')); if (dotIndex != -1) { QString at2xfileName = fileName; at2xfileName.insert(dotIndex, QStringLiteral("@2x")); - if (QFile::exists(at2xfileName)) - return at2xfileName; + if (QFile::exists(at2xfileName)) { + fileName = at2xfileName; + *url = QUrl(fileName); + } } + return fileName; } -static QPixmap getPixmap(QTextDocument *doc, const QTextImageFormat &format) + +static QPixmap getPixmap(QTextDocument *doc, const QTextImageFormat &format, const qreal devicePixelRatio = 1.0) { QPixmap pm; QString name = format.name(); - if (name.startsWith(QLatin1String(":/"))) // auto-detect resources + if (name.startsWith(QLatin1String(":/"))) // auto-detect resources and convert them to url name.prepend(QLatin1String("qrc")); - QPaintDevice *pdev = doc->documentLayout()->paintDevice(); - name = resolve2xFile(name, pdev ? pdev->devicePixelRatio() : qApp->devicePixelRatio()); QUrl url = QUrl(name); + name = resolveFileName(name, &url, devicePixelRatio); const QVariant data = doc->resource(QTextDocument::ImageResource, url); if (data.type() == QVariant::Pixmap || data.type() == QVariant::Image) { pm = qvariant_cast(data); @@ -77,19 +95,18 @@ static QPixmap getPixmap(QTextDocument *doc, const QTextImageFormat &format) } if (pm.isNull()) { - QString context; #if 0 + QString context; // ### Qt5 QTextBrowser *browser = qobject_cast(doc->parent()); if (browser) context = browser->source().toString(); #endif + // try direct loading QImage img; - if (img.isNull()) { // try direct loading - name = format.name(); // remove qrc:/ prefix again - if (name.isEmpty() || !img.load(name)) - return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/file-16.png")); - } + if (name.isEmpty() || !img.load(name)) + return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/file-16.png")); + pm = QPixmap::fromImage(img); doc->addResource(QTextDocument::ImageResource, url, pm); } @@ -142,16 +159,15 @@ static QSize getPixmapSize(QTextDocument *doc, const QTextImageFormat &format) return size; } -static QImage getImage(QTextDocument *doc, const QTextImageFormat &format) +static QImage getImage(QTextDocument *doc, const QTextImageFormat &format, const qreal devicePixelRatio = 1.0) { QImage image; QString name = format.name(); if (name.startsWith(QLatin1String(":/"))) // auto-detect resources name.prepend(QLatin1String("qrc")); - QPaintDevice *pdev = doc->documentLayout()->paintDevice(); - name = resolve2xFile(name, pdev ? pdev->devicePixelRatio() : qApp->devicePixelRatio()); QUrl url = QUrl(name); + name = resolveFileName(name, &url, devicePixelRatio); const QVariant data = doc->resource(QTextDocument::ImageResource, url); if (data.type() == QVariant::Image) { image = qvariant_cast(data); @@ -160,19 +176,18 @@ static QImage getImage(QTextDocument *doc, const QTextImageFormat &format) } if (image.isNull()) { - QString context; - #if 0 + QString context; // ### Qt5 QTextBrowser *browser = qobject_cast(doc->parent()); if (browser) context = browser->source().toString(); #endif - if (image.isNull()) { // try direct loading - name = format.name(); // remove qrc:/ prefix again - if (name.isEmpty() || !image.load(name)) - return QImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/file-16.png")); - } + // try direct loading + + if (name.isEmpty() || !image.load(name)) + return QImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/file-16.png")); + doc->addResource(QTextDocument::ImageResource, url, image); } @@ -241,10 +256,10 @@ void QTextImageHandler::drawObject(QPainter *p, const QRectF &rect, QTextDocumen const QTextImageFormat imageFormat = format.toImageFormat(); if (QCoreApplication::instance()->thread() != QThread::currentThread()) { - const QImage image = getImage(doc, imageFormat); + const QImage image = getImage(doc, imageFormat, p->device()->devicePixelRatio()); p->drawImage(rect, image, image.rect()); } else { - const QPixmap pixmap = getPixmap(doc, imageFormat); + const QPixmap pixmap = getPixmap(doc, imageFormat, p->device()->devicePixelRatio()); p->drawPixmap(rect, pixmap, pixmap.rect()); } } diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index adc5663299f..1ac50d3e5ce 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -2256,8 +2256,10 @@ QList QTextLine::glyphRuns(int from, int length) const logClusters, iterator.itemStart, iterator.itemLength)); - for (int i = 0; i < subLayout.numGlyphs; ++i) - pos.rx() += subLayout.advances[i].toReal(); + for (int i = 0; i < subLayout.numGlyphs; ++i) { + QFixed justification = QFixed::fromFixed(subLayout.justifications[i].space_18d6); + pos.rx() += (subLayout.advances[i] + justification).toReal(); + } if (rtl) end = start; @@ -2559,6 +2561,10 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const } else itm = eng->findItem(pos); + if (itm < 0) { + *cursorPos = 0; + return x.toReal(); + } eng->shapeLine(line); const QScriptItem *si = &eng->layoutData->items[itm]; diff --git a/src/gui/util/qvalidator.cpp b/src/gui/util/qvalidator.cpp index 1b5a10f733d..f8798479354 100644 --- a/src/gui/util/qvalidator.cpp +++ b/src/gui/util/qvalidator.cpp @@ -316,7 +316,12 @@ void QValidator::fixup(QString &) const QIntValidator uses its locale() to interpret the number. For example, in Arabic locales, QIntValidator will accept Arabic digits. - \sa QDoubleValidator, QRegExpValidator, {Line Edits Example} + \note The QLocale::NumberOptions set on the locale() also affect the + way the number is interpreted. For example, since QLocale::RejectGroupSeparator + is not set by default, the validator will accept group separators. It is thus + recommended to use QLocale::toInt() to obtain the numeric value. + + \sa QDoubleValidator, QRegExpValidator, QLocale::toInt(), {Line Edits Example} */ /*! @@ -393,7 +398,8 @@ static qlonglong pow10(int exp) QValidator::State QIntValidator::validate(QString & input, int&) const { QByteArray buff; - if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff)) { + if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff, + -1, locale().numberOptions() & QLocale::RejectGroupSeparator)) { return Invalid; } @@ -432,7 +438,8 @@ QValidator::State QIntValidator::validate(QString & input, int&) const void QIntValidator::fixup(QString &input) const { QByteArray buff; - if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff)) { + if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff, + -1, locale().numberOptions() & QLocale::RejectGroupSeparator)) { return; } bool ok, overflow; @@ -548,7 +555,12 @@ public: in the German locale, "1,234" will be accepted as the fractional number 1.234. In Arabic locales, QDoubleValidator will accept Arabic digits. - \sa QIntValidator, QRegExpValidator, {Line Edits Example} + \note The QLocale::NumberOptions set on the locale() also affect the + way the number is interpreted. For example, since QLocale::RejectGroupSeparator + is not set by default, the validator will accept group separators. It is thus + recommended to use QLocale::toDouble() to obtain the numeric value. + + \sa QIntValidator, QRegExpValidator, QLocale::toDouble(), {Line Edits Example} */ /*! @@ -648,8 +660,10 @@ QValidator::State QDoubleValidatorPrivate::validateWithLocale(QString &input, QL { Q_Q(const QDoubleValidator); QByteArray buff; - if (!locale.d->m_data->validateChars(input, numMode, &buff, q->dec)) + if (!locale.d->m_data->validateChars(input, numMode, &buff, q->dec, + locale.numberOptions() & QLocale::RejectGroupSeparator)) { return QValidator::Invalid; + } if (buff.isEmpty()) return QValidator::Intermediate; @@ -1003,7 +1017,7 @@ QValidator::State QRegularExpressionValidator::validate(QString &input, int &pos const QRegularExpressionMatch m = d->usedRe.match(input, 0, QRegularExpression::PartialPreferCompleteMatch); if (m.hasMatch()) { return Acceptable; - } else if (m.hasPartialMatch()) { + } else if (input.isEmpty() || m.hasPartialMatch()) { return Intermediate; } else { pos = input.size(); diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp index f50a79b0614..66f093e4909 100644 --- a/src/network/access/qhttpnetworkrequest.cpp +++ b/src/network/access/qhttpnetworkrequest.cpp @@ -151,7 +151,7 @@ QByteArray QHttpNetworkRequestPrivate::header(const QHttpNetworkRequest &request } if (request.d->operation == QHttpNetworkRequest::Post) { // add content type, if not set in the request - if (request.headerField("content-type").isEmpty()) { + if (request.headerField("content-type").isEmpty() && ((request.d->uploadByteDevice && request.d->uploadByteDevice->size() > 0) || request.d->url.hasQuery())) { //Content-Type is mandatory. We can't say anything about the encoding, but x-www-form-urlencoded is the most likely to work. //This warning indicates a bug in application code not setting a required header. //Note that if using QHttpMultipart, the content-type is set in QNetworkAccessManagerPrivate::prepareMultipart already diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp index b13c21d6248..522f8d9891a 100644 --- a/src/network/access/qhttpthreaddelegate.cpp +++ b/src/network/access/qhttpthreaddelegate.cpp @@ -654,6 +654,7 @@ void QHttpThreadDelegate::encryptedSlot() if (!httpReply) return; + emit sslConfigurationChanged(httpReply->sslConfiguration()); emit encrypted(); } diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index f00b58a8ce7..52d56fb0716 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -1135,7 +1135,12 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera if (!d->networkSessionStrongRef && (d->initializeSession || !d->networkConfiguration.identifier().isEmpty())) { QNetworkConfigurationManager manager; if (!d->networkConfiguration.identifier().isEmpty()) { - d->createSession(d->networkConfiguration); + if ((d->networkConfiguration.state() & QNetworkConfiguration::Defined) + && d->networkConfiguration != manager.defaultConfiguration()) + d->createSession(manager.defaultConfiguration()); + else + d->createSession(d->networkConfiguration); + } else { if (manager.capabilities() & QNetworkConfigurationManager::NetworkSessionRequired) d->createSession(manager.defaultConfiguration()); @@ -1590,6 +1595,11 @@ void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline) if (customNetworkConfiguration) { online = (networkConfiguration.state() & QNetworkConfiguration::Active); } else { + if (isOnline && online != isOnline) { + networkSessionStrongRef.clear(); + networkSessionWeakRef.clear(); + } + online = isOnline; } } diff --git a/src/network/socket/qlocalserver_unix.cpp b/src/network/socket/qlocalserver_unix.cpp index 149d89c000e..a615dcc7b63 100644 --- a/src/network/socket/qlocalserver_unix.cpp +++ b/src/network/socket/qlocalserver_unix.cpp @@ -90,13 +90,14 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName) // Check any of the flags if (socketOptions & QLocalServer::WorldAccessOption) { - tempDir.reset(new QTemporaryDir(fullServerName)); + QFileInfo serverNameFileInfo(fullServerName); + tempDir.reset(new QTemporaryDir(serverNameFileInfo.absolutePath() + QLatin1Char('/'))); if (!tempDir->isValid()) { setError(QLatin1String("QLocalServer::listen")); return false; } tempPath = tempDir->path(); - tempPath += QLatin1Char('/') + requestedServerName; + tempPath += QLatin1String("/s"); } // create the unix socket @@ -124,13 +125,6 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName) } ::memcpy(addr.sun_path, tempPath.toLatin1().data(), tempPath.toLatin1().size() + 1); - - if (-1 == ::fchmod(listenSocket, 0)) { - setError(QLatin1String("QLocalServer::listen")); - closeServer(); - return false; - } - } else { ::memcpy(addr.sun_path, fullServerName.toLatin1().data(), fullServerName.toLatin1().size() + 1); @@ -160,30 +154,28 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName) } if (socketOptions & QLocalServer::WorldAccessOption) { - mode_t mode = 000; + mode_t mode = 000; - if (socketOptions & QLocalServer::UserAccessOption) { - mode |= S_IRWXU; - } - if (socketOptions & QLocalServer::GroupAccessOption) { - mode |= S_IRWXG; - } - if (socketOptions & QLocalServer::OtherAccessOption) { - mode |= S_IRWXO; - } + if (socketOptions & QLocalServer::UserAccessOption) + mode |= S_IRWXU; - if (mode) { - if (-1 == ::chmod(tempPath.toLatin1(), mode)) { - setError(QLatin1String("QLocalServer::listen")); - closeServer(); - return false; - } - } - if (-1 == ::rename(tempPath.toLatin1(), fullServerName.toLatin1())){ - setError(QLatin1String("QLocalServer::listen")); - closeServer(); - return false; - } + if (socketOptions & QLocalServer::GroupAccessOption) + mode |= S_IRWXG; + + if (socketOptions & QLocalServer::OtherAccessOption) + mode |= S_IRWXO; + + if (::chmod(tempPath.toLatin1(), mode) == -1) { + setError(QLatin1String("QLocalServer::listen")); + closeServer(); + return false; + } + + if (::rename(tempPath.toLatin1(), fullServerName.toLatin1()) == -1) { + setError(QLatin1String("QLocalServer::listen")); + closeServer(); + return false; + } } Q_ASSERT(!socketNotifier); diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index c3be3eb4081..cacfe11fead 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -529,41 +529,27 @@ qint64 QNativeSocketEngine::write(const char *data, qint64 len) qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QHostAddress *addr, quint16 *port) { Q_D(QNativeSocketEngine); - if (d->socketType != QAbstractSocket::UdpSocket) + if (d->socketType != QAbstractSocket::UdpSocket || d->pendingDatagrams.isEmpty()) return -1; - QHostAddress returnAddress; - quint16 returnPort; + WinRtDatagram datagram = d->pendingDatagrams.takeFirst(); + if (addr) + *addr = datagram.address; - for (int i = 0; i < d->pendingDatagrams.size(); ++i) { - IDatagramSocketMessageReceivedEventArgs *arg = d->pendingDatagrams.at(i); - ComPtr remoteHost; - HString remoteHostString; - HString remotePort; - arg->get_RemoteAddress(&remoteHost); - arg->get_RemotePort(remotePort.GetAddressOf()); - remoteHost->get_CanonicalName(remoteHostString.GetAddressOf()); - returnAddress.setAddress(qt_QStringFromHString(remoteHostString)); - returnPort = qt_QStringFromHString(remotePort).toInt(); - ComPtr reader; - arg->GetDataReader(&reader); - if (!reader) - continue; + if (port) + *port = datagram.port; - BYTE buffer[1024]; - reader->ReadBytes(maxlen, buffer); - *addr = returnAddress; - *port = returnPort; - arg = d->pendingDatagrams.takeFirst(); - arg->Release(); - - // TODO: fill data - Q_UNUSED(data); - --i; - return maxlen; + QByteArray readOrigin; + // Do not read the whole datagram. Put the rest of it back into the "queue" + if (maxlen < datagram.data.length()) { + QByteArray readOrigin = datagram.data.left(maxlen); + datagram.data = datagram.data.remove(0, maxlen); + d->pendingDatagrams.prepend(datagram); + } else { + readOrigin = datagram.data; } - - return -1; + strcpy(data, readOrigin); + return readOrigin.length(); } qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 len, const QHostAddress &addr, quint16 port) @@ -609,17 +595,10 @@ bool QNativeSocketEngine::hasPendingDatagrams() const qint64 QNativeSocketEngine::pendingDatagramSize() const { Q_D(const QNativeSocketEngine); - qint64 ret = 0; - foreach (IDatagramSocketMessageReceivedEventArgs *arg, d->pendingDatagrams) { - ComPtr reader; - UINT32 unconsumedBufferLength; - arg->GetDataReader(&reader); - if (!reader) - return -1; - reader->get_UnconsumedBufferLength(&unconsumedBufferLength); - ret += unconsumedBufferLength; - } - return ret; + if (d->pendingDatagrams.isEmpty()) + return -1; + + return d->pendingDatagrams.at(0).data.length(); } qint64 QNativeSocketEngine::bytesToWrite() const @@ -1236,7 +1215,32 @@ HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, I { Q_Q(QNativeSocketEngine); Q_UNUSED(socket); - pendingDatagrams.append(args); + + WinRtDatagram datagram; + QHostAddress returnAddress; + ComPtr remoteHost; + HRESULT hr = args->get_RemoteAddress(&remoteHost); + RETURN_OK_IF_FAILED("Could not obtain remote host"); + HString remoteHostString; + remoteHost->get_CanonicalName(remoteHostString.GetAddressOf()); + RETURN_OK_IF_FAILED("Could not obtain remote host's canonical name"); + returnAddress.setAddress(qt_QStringFromHString(remoteHostString)); + datagram.address = returnAddress; + HString remotePort; + hr = args->get_RemotePort(remotePort.GetAddressOf()); + RETURN_OK_IF_FAILED("Could not obtain remote port"); + datagram.port = qt_QStringFromHString(remotePort).toInt(); + + ComPtr reader; + hr = args->GetDataReader(&reader); + RETURN_OK_IF_FAILED("Could not obtain data reader"); + quint32 length; + hr = reader->get_UnconsumedBufferLength(&length); + RETURN_OK_IF_FAILED("Could not obtain unconsumed buffer length"); + datagram.data.resize(length); + hr = reader->ReadBytes(length, reinterpret_cast(datagram.data.data())); + RETURN_OK_IF_FAILED("Could not read datagram"); + pendingDatagrams.append(datagram); emit q->readReady(); return S_OK; diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h index 7652a09b170..716403097d1 100644 --- a/src/network/socket/qnativesocketengine_winrt_p.h +++ b/src/network/socket/qnativesocketengine_winrt_p.h @@ -55,6 +55,12 @@ QT_BEGIN_NAMESPACE class QNativeSocketEnginePrivate; +struct WinRtDatagram { + QByteArray data; + int port; + QHostAddress address; +}; + class Q_AUTOTEST_EXPORT QNativeSocketEngine : public QAbstractSocketEngine { Q_OBJECT @@ -197,7 +203,8 @@ private: Microsoft::WRL::ComPtr connectOp; QBuffer readBytes; QMutex readMutex; - QList pendingDatagrams; + + QList pendingDatagrams; QList pendingConnections; QList currentConnections; QEventLoop eventLoop; diff --git a/src/network/ssl/qsslkey_openssl.cpp b/src/network/ssl/qsslkey_openssl.cpp index 6b0fa954eb0..e4d30ff229b 100644 --- a/src/network/ssl/qsslkey_openssl.cpp +++ b/src/network/ssl/qsslkey_openssl.cpp @@ -95,7 +95,7 @@ bool QSslKeyPrivate::fromEVP_PKEY(EVP_PKEY *pkey) type = QSsl::PrivateKey; dsa = q_DSA_new(); - memcpy(rsa, q_EVP_PKEY_get1_DSA(pkey), sizeof(DSA)); + memcpy(dsa, q_EVP_PKEY_get1_DSA(pkey), sizeof(DSA)); return true; } diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index d919d8e934d..71b8237e031 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -63,6 +63,9 @@ #if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) #include #endif +#ifdef Q_OS_DARWIN +#include "private/qcore_mac_p.h" +#endif #include @@ -107,6 +110,8 @@ QT_BEGIN_NAMESPACE possibly with a different version of OpenSSL. */ +#ifndef QT_LINKED_OPENSSL + namespace { void qsslSocketUnresolvedSymbolWarning(const char *functionName) { @@ -119,6 +124,8 @@ void qsslSocketCannotResolveSymbolWarning(const char *functionName) } } +#endif // QT_LINKED_OPENSSL + #ifdef SSLEAY_MACROS DEFINEFUNC3(void *, ASN1_dup, i2d_of_void *a, a, d2i_of_void *b, b, char *c, c, return 0, return) #endif @@ -448,6 +455,15 @@ static QStringList libraryPathList() # ifdef Q_OS_DARWIN paths = QString::fromLatin1(qgetenv("DYLD_LIBRARY_PATH")) .split(QLatin1Char(':'), QString::SkipEmptyParts); + + // search in .app/Contents/Frameworks + UInt32 packageType; + CFBundleGetPackageInfo(CFBundleGetMainBundle(), &packageType, NULL); + if (packageType == FOUR_CHAR_CODE('APPL')) { + QUrl bundleUrl = QUrl::fromCFURL(QCFType(CFBundleCopyBundleURL(CFBundleGetMainBundle()))); + QUrl frameworksUrl = QUrl::fromCFURL(QCFType(CFBundleCopyPrivateFrameworksURL(CFBundleGetMainBundle()))); + paths << bundleUrl.resolved(frameworksUrl).path(); + } # else paths = QString::fromLatin1(qgetenv("LD_LIBRARY_PATH")) .split(QLatin1Char(':'), QString::SkipEmptyParts); @@ -597,7 +613,13 @@ static QPair loadOpenSsl() } #endif +#ifndef Q_OS_DARWIN // second attempt: find the development files libssl.so and libcrypto.so + // + // disabled on OS X/iOS: + // OS X's /usr/lib/libssl.dylib, /usr/lib/libcrypto.dylib will be picked up in the third + // attempt, _after_ /Contents/Frameworks has been searched. + // iOS does not ship a system libssl.dylib, libcrypto.dylib in the first place. libssl->setFileNameAndVersion(QLatin1String("ssl"), -1); libcrypto->setFileNameAndVersion(QLatin1String("crypto"), -1); if (libcrypto->load() && libssl->load()) { @@ -607,6 +629,7 @@ static QPair loadOpenSsl() libssl->unload(); libcrypto->unload(); } +#endif // third attempt: loop on the most common library paths and find libssl QStringList sslList = findAllLibSsl(); diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 43df3116364..1fa5723d85a 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -612,6 +612,21 @@ void QGL2PaintEngineExPrivate::resetGLState() #endif } +bool QGL2PaintEngineExPrivate::resetOpenGLContextActiveEngine() +{ + QOpenGLContext *guiGlContext = ctx->contextHandle(); + QOpenGLContextPrivate *guiGlContextPrivate = + guiGlContext ? QOpenGLContextPrivate::get(guiGlContext) : 0; + + if (guiGlContextPrivate && guiGlContextPrivate->active_engine) { + ctx->d_func()->refreshCurrentFbo(); + guiGlContextPrivate->active_engine = 0; + return true; + } + + return false; +} + void QGL2PaintEngineEx::endNativePainting() { Q_D(QGL2PaintEngineEx); @@ -2015,6 +2030,8 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) d->ctx = d->device->context(); d->ctx->d_ptr->active_engine = this; + d->resetOpenGLContextActiveEngine(); + const QSize sz = d->device->size(); d->width = sz.width(); d->height = sz.height(); @@ -2080,6 +2097,8 @@ bool QGL2PaintEngineEx::end() ctx->d_ptr->active_engine = 0; + d->resetOpenGLContextActiveEngine(); + d->resetGLState(); delete d->shaderManager; @@ -2105,7 +2124,7 @@ void QGL2PaintEngineEx::ensureActive() Q_D(QGL2PaintEngineEx); QGLContext *ctx = d->ctx; - if (isActive() && ctx->d_ptr->active_engine != this) { + if (isActive() && (ctx->d_ptr->active_engine != this || d->resetOpenGLContextActiveEngine())) { ctx->d_ptr->active_engine = this; d->needsSync = true; } diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 528bfdeeb98..ac1d63df17d 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -191,6 +191,7 @@ public: void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id = GLuint(-1)); void resetGLState(); + bool resetOpenGLContextActiveEngine(); // fill, stroke, drawTexture, drawPixmaps & drawCachedGlyphs are the main rendering entry-points, // however writeClip can also be thought of as en entry point as it does similar things. diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp index 211fad267fb..8cd26f1ea4f 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp @@ -167,6 +167,8 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) // ### the QTextureGlyphCache API needs to be reworked to allow // ### resizeTextureData to fail + ctx->d_ptr->refreshCurrentFbo(); + funcs->glBindFramebuffer(GL_FRAMEBUFFER, m_textureResource->m_fbo); GLuint tmp_texture; diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 1e49d950879..35f08e00929 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -510,6 +510,35 @@ void QGLContextPrivate::setupSharing() { } } +void QGLContextPrivate::refreshCurrentFbo() +{ + QOpenGLContextPrivate *guiGlContextPrivate = + guiGlContext ? QOpenGLContextPrivate::get(guiGlContext) : 0; + + // if QOpenGLFramebufferObjects have been used in the mean-time, we've lost our cached value + if (guiGlContextPrivate && guiGlContextPrivate->qgl_current_fbo_invalid) { + GLint current; + QOpenGLFunctions *funcs = qgl_functions(); + funcs->glGetIntegerv(GL_FRAMEBUFFER_BINDING, ¤t); + + current_fbo = current; + + guiGlContextPrivate->qgl_current_fbo_invalid = false; + } +} + +void QGLContextPrivate::setCurrentFbo(GLuint fbo) +{ + current_fbo = fbo; + + QOpenGLContextPrivate *guiGlContextPrivate = + guiGlContext ? QOpenGLContextPrivate::get(guiGlContext) : 0; + + if (guiGlContextPrivate) + guiGlContextPrivate->qgl_current_fbo_invalid = false; +} + + /*! \fn bool QGLFormat::doubleBuffer() const diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index c4151a3d344..4cf656fd86f 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -238,6 +238,8 @@ public: bool ownContext; void setupSharing(); + void refreshCurrentFbo(); + void setCurrentFbo(GLuint fbo); QGLFormat glFormat; QGLFormat reqFormat; diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index 4ef50e9334d..4537f5bfae0 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -472,6 +472,8 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, if (!funcs.hasOpenGLFeature(QOpenGLFunctions::Framebuffers)) return; + ctx->d_ptr->refreshCurrentFbo(); + size = sz; target = texture_target; // texture dimensions @@ -1027,7 +1029,7 @@ bool QGLFramebufferObject::bind() d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo()); d->valid = d->checkFramebufferStatus(); if (d->valid && current) - current->d_ptr->current_fbo = d->fbo(); + current->d_ptr->setCurrentFbo(d->fbo()); return d->valid; } @@ -1060,7 +1062,7 @@ bool QGLFramebufferObject::release() #endif if (current) { - current->d_ptr->current_fbo = current->d_ptr->default_fbo; + current->d_ptr->setCurrentFbo(current->d_ptr->default_fbo); d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->d_ptr->default_fbo); } @@ -1109,6 +1111,20 @@ QGLFramebufferObjectFormat QGLFramebufferObject::format() const Returns the contents of this framebuffer object as a QImage. + The returned image has a format of premultiplied ARGB32 or RGB32. The latter is used + only when internalTextureFormat() is set to \c GL_RGB. + + If the rendering in the framebuffer was not done with premultiplied alpha in mind, + create a wrapper QImage with a non-premultiplied format. This is necessary before + performing operations like QImage::save() because otherwise the image data would get + unpremultiplied, even though it was not premultiplied in the first place. To create + such a wrapper without performing a copy of the pixel data, do the following: + + \code + QImage fboImage(fbo.toImage()); + QImage image(fboImage.constBits(), fboImage.width(), fboImage.height(), QImage::Format_ARGB32); + \endcode + On QNX the back buffer is not preserved when a buffer swap occures. So this function might return old content. */ @@ -1173,7 +1189,7 @@ bool QGLFramebufferObject::bindDefault() if (!functions.hasOpenGLFeature(QOpenGLFunctions::Framebuffers)) return false; - ctx->d_ptr->current_fbo = ctx->d_ptr->default_fbo; + ctx->d_ptr->setCurrentFbo(ctx->d_ptr->default_fbo); functions.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_ptr->default_fbo); #ifdef QT_DEBUG } else { @@ -1320,7 +1336,12 @@ bool QGLFramebufferObject::isBound() const { Q_D(const QGLFramebufferObject); const QGLContext *current = QGLContext::currentContext(); - return current ? current->d_ptr->current_fbo == d->fbo() : false; + if (current) { + current->d_ptr->refreshCurrentFbo(); + return current->d_ptr->current_fbo == d->fbo(); + } + + return false; } /*! @@ -1400,6 +1421,8 @@ void QGLFramebufferObject::blitFramebuffer(QGLFramebufferObject *target, const Q const int ty0 = th - (targetRect.top() + targetRect.height()); const int ty1 = th - targetRect.top(); + ctx->d_ptr->refreshCurrentFbo(); + functions.glBindFramebuffer(GL_READ_FRAMEBUFFER, source ? source->handle() : 0); functions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target ? target->handle() : 0); diff --git a/src/opengl/qglpaintdevice.cpp b/src/opengl/qglpaintdevice.cpp index 40cc7bb71d6..c07d0a761bb 100644 --- a/src/opengl/qglpaintdevice.cpp +++ b/src/opengl/qglpaintdevice.cpp @@ -74,6 +74,8 @@ void QGLPaintDevice::beginPaint() QGLContext *ctx = context(); ctx->makeCurrent(); + ctx->d_func()->refreshCurrentFbo(); + // Record the currently bound FBO so we can restore it again // in endPaint() and bind this device's FBO // @@ -85,7 +87,7 @@ void QGLPaintDevice::beginPaint() m_previousFBO = ctx->d_func()->current_fbo; if (m_previousFBO != m_thisFBO) { - ctx->d_ptr->current_fbo = m_thisFBO; + ctx->d_func()->setCurrentFbo(m_thisFBO); ctx->contextHandle()->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_thisFBO); } @@ -102,8 +104,10 @@ void QGLPaintDevice::ensureActiveTarget() if (ctx != QGLContext::currentContext()) ctx->makeCurrent(); + ctx->d_func()->refreshCurrentFbo(); + if (ctx->d_ptr->current_fbo != m_thisFBO) { - ctx->d_ptr->current_fbo = m_thisFBO; + ctx->d_func()->setCurrentFbo(m_thisFBO); ctx->contextHandle()->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_thisFBO); } @@ -114,8 +118,11 @@ void QGLPaintDevice::endPaint() { // Make sure the FBO bound at beginPaint is re-bound again here: QGLContext *ctx = context(); + + ctx->d_func()->refreshCurrentFbo(); + if (m_previousFBO != ctx->d_func()->current_fbo) { - ctx->d_ptr->current_fbo = m_previousFBO; + ctx->d_func()->setCurrentFbo(m_previousFBO); ctx->contextHandle()->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_previousFBO); } diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp index 56bfaebe4f9..63b624aea2b 100644 --- a/src/opengl/qglpixelbuffer.cpp +++ b/src/opengl/qglpixelbuffer.cpp @@ -344,6 +344,8 @@ void QGLPixelBuffer::updateDynamicTexture(GLuint texture_id) const QOpenGLExtensions extensions(ctx->contextHandle()); + ctx->d_ptr->refreshCurrentFbo(); + if (d->blit_fbo) { QOpenGLFramebufferObject::blitFramebuffer(d->blit_fbo, d->fbo); extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, d->blit_fbo->handle()); diff --git a/src/platformsupport/clipboard/qmacmime.mm b/src/platformsupport/clipboard/qmacmime.mm index 27a490335bb..6fcd19e07bf 100644 --- a/src/platformsupport/clipboard/qmacmime.mm +++ b/src/platformsupport/clipboard/qmacmime.mm @@ -48,6 +48,7 @@ #include "qmacmime_p.h" #include "qguiapplication.h" +#include "private/qcore_mac_p.h" QT_BEGIN_NAMESPACE @@ -335,9 +336,9 @@ QVariant QMacPasteboardMimePlainTextFallback::convertToMime(const QString &mimet // Note that public.text is documented by Apple to have an undefined encoding. From // testing it seems that utf8 is normally used, at least by Safari on iOS. const QByteArray &firstData = data.first(); - return QString::fromCFString(CFStringCreateWithBytes(kCFAllocatorDefault, + return QString(QCFString(CFStringCreateWithBytes(kCFAllocatorDefault, reinterpret_cast(firstData.constData()), - firstData.size(), kCFStringEncodingUTF8, false)); + firstData.size(), kCFStringEncodingUTF8, false))); } else { qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype)); } @@ -410,9 +411,9 @@ QVariant QMacPasteboardMimeUnicodeText::convertToMime(const QString &mimetype, Q // I can only handle two types (system and unicode) so deal with them that way QVariant ret; if (flavor == QLatin1String("public.utf8-plain-text")) { - ret = QString::fromCFString(CFStringCreateWithBytes(kCFAllocatorDefault, + ret = QString(QCFString(CFStringCreateWithBytes(kCFAllocatorDefault, reinterpret_cast(firstData.constData()), - firstData.size(), CFStringGetSystemEncoding(), false)); + firstData.size(), CFStringGetSystemEncoding(), false))); } else if (flavor == QLatin1String("public.utf16-plain-text")) { ret = QString(reinterpret_cast(firstData.constData()), firstData.size() / sizeof(QChar)); diff --git a/src/platformsupport/eglconvenience/qeglconvenience.cpp b/src/platformsupport/eglconvenience/qeglconvenience.cpp index 80153cd18fe..f3a135a4998 100644 --- a/src/platformsupport/eglconvenience/qeglconvenience.cpp +++ b/src/platformsupport/eglconvenience/qeglconvenience.cpp @@ -37,8 +37,8 @@ #ifdef Q_OS_LINUX #include #include -#include #endif +#include #include "qeglconvenience_p.h" @@ -448,10 +448,13 @@ void q_printEglConfig(EGLDisplay display, EGLConfig config) } } -#ifdef Q_OS_LINUX +#ifdef Q_OS_UNIX QSizeF q_physicalScreenSizeFromFb(int framebufferDevice, const QSize &screenSize) { +#ifndef Q_OS_LINUX + Q_UNUSED(framebufferDevice) +#endif const int defaultPhysicalDpi = 100; static QSizeF size; @@ -466,10 +469,11 @@ QSizeF q_physicalScreenSizeFromFb(int framebufferDevice, const QSize &screenSize return size; } - struct fb_var_screeninfo vinfo; int w = -1; int h = -1; QSize screenResolution; +#ifdef Q_OS_LINUX + struct fb_var_screeninfo vinfo; if (framebufferDevice != -1) { if (ioctl(framebufferDevice, FBIOGET_VSCREENINFO, &vinfo) == -1) { @@ -479,7 +483,9 @@ QSizeF q_physicalScreenSizeFromFb(int framebufferDevice, const QSize &screenSize h = vinfo.height; screenResolution = QSize(vinfo.xres, vinfo.yres); } - } else { + } else +#endif + { // Use the provided screen size, when available, since some platforms may have their own // specific way to query it. Otherwise try querying it from the framebuffer. screenResolution = screenSize.isEmpty() ? q_screenSizeFromFb(framebufferDevice) : screenSize; @@ -499,6 +505,9 @@ QSizeF q_physicalScreenSizeFromFb(int framebufferDevice, const QSize &screenSize QSize q_screenSizeFromFb(int framebufferDevice) { +#ifndef Q_OS_LINUX + Q_UNUSED(framebufferDevice) +#endif const int defaultWidth = 800; const int defaultHeight = 600; static QSize size; @@ -513,6 +522,7 @@ QSize q_screenSizeFromFb(int framebufferDevice) return size; } +#ifdef Q_OS_LINUX struct fb_var_screeninfo vinfo; int xres = -1; int yres = -1; @@ -528,6 +538,10 @@ QSize q_screenSizeFromFb(int framebufferDevice) size.setWidth(xres <= 0 ? defaultWidth : xres); size.setHeight(yres <= 0 ? defaultHeight : yres); +#else + size.setWidth(defaultWidth); + size.setHeight(defaultHeight); +#endif } return size; @@ -535,10 +549,14 @@ QSize q_screenSizeFromFb(int framebufferDevice) int q_screenDepthFromFb(int framebufferDevice) { +#ifndef Q_OS_LINUX + Q_UNUSED(framebufferDevice) +#endif const int defaultDepth = 32; static int depth = qEnvironmentVariableIntValue("QT_QPA_EGLFS_DEPTH"); if (depth == 0) { +#ifdef Q_OS_LINUX struct fb_var_screeninfo vinfo; if (framebufferDevice != -1) { @@ -550,11 +568,14 @@ int q_screenDepthFromFb(int framebufferDevice) if (depth <= 0) depth = defaultDepth; +#else + depth = defaultDepth; +#endif } return depth; } -#endif // Q_OS_LINUX +#endif // Q_OS_UNIX QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/basic/basic.pri b/src/platformsupport/fontdatabases/basic/basic.pri index 88be809cd86..c2b882ed5aa 100644 --- a/src/platformsupport/fontdatabases/basic/basic.pri +++ b/src/platformsupport/fontdatabases/basic/basic.pri @@ -17,6 +17,7 @@ contains(QT_CONFIG, freetype) { $$QT_FREETYPE_DIR/src/base/ftbbox.c \ $$QT_FREETYPE_DIR/src/base/ftdebug.c \ $$QT_FREETYPE_DIR/src/base/ftglyph.c \ + $$QT_FREETYPE_DIR/src/base/ftlcdfil.c \ $$QT_FREETYPE_DIR/src/base/ftinit.c \ $$QT_FREETYPE_DIR/src/base/ftmm.c \ $$QT_FREETYPE_DIR/src/base/fttype1.c \ diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index 2b9883eb36c..5dec1d09156 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -409,7 +409,7 @@ static void populateFromPattern(FcPattern *pattern) #endif FontFile *fontFile = new FontFile; - fontFile->fileName = QLatin1String((const char *)file_value); + fontFile->fileName = QString::fromLocal8Bit((const char *)file_value); fontFile->indexValue = indexValue; QFont::Style style = (slant_value == FC_SLANT_ITALIC) diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 207b525664d..44f6be21c75 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -353,7 +353,10 @@ QFixed QCoreTextFontEngine::averageCharWidth() const qreal QCoreTextFontEngine::maxCharWidth() const { - return 0; + // ### FIXME: 'W' might not be the widest character, but this is better than nothing + const glyph_t glyph = glyphIndex('W'); + glyph_metrics_t bb = const_cast(this)->boundingBox(glyph); + return bb.xoff.toReal(); } qreal QCoreTextFontEngine::minLeftBearing() const diff --git a/src/plugins/bearer/connman/connman.pro b/src/plugins/bearer/connman/connman.pro index bc4efe8b621..efa13a6ebdc 100644 --- a/src/plugins/bearer/connman/connman.pro +++ b/src/plugins/bearer/connman/connman.pro @@ -8,14 +8,14 @@ QT = core network-private dbus CONFIG += link_pkgconfig HEADERS += qconnmanservice_linux_p.h \ - qofonoservice_linux_p.h \ + ../linux_common/qofonoservice_linux_p.h \ qconnmanengine.h \ ../qnetworksession_impl.h \ ../qbearerengine_impl.h SOURCES += main.cpp \ qconnmanservice_linux.cpp \ - qofonoservice_linux.cpp \ + ../linux_common/qofonoservice_linux.cpp \ qconnmanengine.cpp \ ../qnetworksession_impl.cpp diff --git a/src/plugins/bearer/connman/qconnmanengine.h b/src/plugins/bearer/connman/qconnmanengine.h index 52e8b384a04..a995d8ed25d 100644 --- a/src/plugins/bearer/connman/qconnmanengine.h +++ b/src/plugins/bearer/connman/qconnmanengine.h @@ -48,7 +48,7 @@ #include "../qbearerengine_impl.h" #include "qconnmanservice_linux_p.h" -#include "qofonoservice_linux_p.h" +#include "../linux_common/qofonoservice_linux_p.h" #include #include diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.mm b/src/plugins/bearer/corewlan/qcorewlanengine.mm index 6f9ea91799a..55847a04a4e 100644 --- a/src/plugins/bearer/corewlan/qcorewlanengine.mm +++ b/src/plugins/bearer/corewlan/qcorewlanengine.mm @@ -288,8 +288,6 @@ void QScanThread::getUserConfigurations() for (NSString *ifName in wifiInterfaces) { CWInterface *wifiInterface = [CWInterface interfaceWithName: ifName]; - if (!wifiInterface.powerOn) - continue; NSString *nsInterfaceName = wifiInterface.ssid; // add user configured system networks @@ -311,6 +309,21 @@ void QScanThread::getUserConfigurations() CFRelease(airportPlist); } + // remembered networks + CWConfiguration *userConfig = [wifiInterface configuration]; + NSOrderedSet *networkProfiles = [userConfig networkProfiles]; + NSEnumerator *enumerator = [networkProfiles objectEnumerator]; + CWNetworkProfile *wProfile; + while ((wProfile = [enumerator nextObject])) { + QString networkName = QCFString::toQString([wProfile ssid]); + + if (!userProfiles.contains(networkName)) { + QMap map; + map.insert(networkName, QCFString::toQString(nsInterfaceName)); + userProfiles.insert(networkName, map); + } + } + // 802.1X user profiles QString userProfilePath = QDir::homePath() + "/Library/Preferences/com.apple.eap.profiles.plist"; NSDictionary* eapDict = [[[NSDictionary alloc] initWithContentsOfFile: QCFString::toNSString(userProfilePath)] autorelease]; @@ -330,14 +343,14 @@ void QScanThread::getUserConfigurations() [itemKey getObjects:objects andKeys:keys]; QString networkName; QString ssid; - for(int i = 0; i < dictSize; i++) { + for (int i = 0; i < dictSize; i++) { if([nameStr isEqualToString:keys[i]]) { networkName = QCFString::toQString(objects[i]); } - if([networkSsidStr isEqualToString:keys[i]]) { + if ([networkSsidStr isEqualToString:keys[i]]) { ssid = QCFString::toQString(objects[i]); } - if(!userProfiles.contains(networkName) + if (!userProfiles.contains(networkName) && !ssid.isEmpty()) { QMap map; map.insert(ssid, QCFString::toQString(nsInterfaceName)); diff --git a/src/plugins/bearer/connman/qofonoservice_linux.cpp b/src/plugins/bearer/linux_common/qofonoservice_linux.cpp similarity index 72% rename from src/plugins/bearer/connman/qofonoservice_linux.cpp rename to src/plugins/bearer/linux_common/qofonoservice_linux.cpp index acc82bda048..f4460c1be00 100644 --- a/src/plugins/bearer/connman/qofonoservice_linux.cpp +++ b/src/plugins/bearer/linux_common/qofonoservice_linux.cpp @@ -95,14 +95,12 @@ QStringList QOfonoManagerInterface::getModems() { if (modemList.isEmpty()) { QList argumentList; - QDBusPendingReply reply = asyncCallWithArgumentList(QLatin1String("GetModems"), argumentList); + QDBusPendingReply reply = callWithArgumentList(QDBus::Block, QLatin1String("GetModems"), argumentList); reply.waitForFinished(); if (!reply.isError()) { foreach (ObjectPathProperties modem, reply.value()) { modemList << modem.path.path(); } - } else { - qDebug() << reply.error().message(); } } @@ -114,7 +112,8 @@ QString QOfonoManagerInterface::currentModem() QStringList modems = getModems(); foreach (const QString &modem, modems) { QOfonoModemInterface device(modem); - if (device.isPowered() && device.isOnline()) + if (device.isPowered() && device.isOnline() + && device.interfaces().contains(QStringLiteral("org.ofono.NetworkRegistration"))) return modem; } return QString(); @@ -171,11 +170,17 @@ bool QOfonoModemInterface::isOnline() return qdbus_cast(var); } +QStringList QOfonoModemInterface::interfaces() +{ + const QVariant var = getProperty(QStringLiteral("Interfaces")); + return var.toStringList(); +} + QVariantMap QOfonoModemInterface::getProperties() { if (propertiesMap.isEmpty()) { QList argumentList; - QDBusPendingReply reply = asyncCallWithArgumentList(QLatin1String("GetProperties"), argumentList); + QDBusPendingReply reply = callWithArgumentList(QDBus::Block, QLatin1String("GetProperties"), argumentList); if (!reply.isError()) { propertiesMap = reply.value(); } @@ -187,7 +192,8 @@ QVariant QOfonoModemInterface::getProperty(const QString &property) { QVariant var; QVariantMap map = getProperties(); - var = map.value(property); + if (map.contains(property)) + var = map.value(property); return var; } @@ -214,7 +220,8 @@ QVariant QOfonoNetworkRegistrationInterface::getProperty(const QString &property { QVariant var; QVariantMap map = getProperties(); - var = map.value(property); + if (map.contains(property)) + var = map.value(property); return var; } @@ -222,12 +229,10 @@ QVariantMap QOfonoNetworkRegistrationInterface::getProperties() { if (propertiesMap.isEmpty()) { QList argumentList; - QDBusPendingReply reply = asyncCallWithArgumentList(QLatin1String("GetProperties"), argumentList); + QDBusPendingReply reply = callWithArgumentList(QDBus::Block, QLatin1String("GetProperties"), argumentList); reply.waitForFinished(); if (!reply.isError()) { propertiesMap = reply.value(); - } else { - qDebug() << reply.error().message(); } } return propertiesMap; @@ -264,12 +269,30 @@ QStringList QOfonoDataConnectionManagerInterface::contexts() return contextList; } +PathPropertiesList QOfonoDataConnectionManagerInterface::contextsWithProperties() +{ + if (contextListProperties.isEmpty()) { + QDBusPendingReply reply = call(QLatin1String("GetContexts")); + reply.waitForFinished(); + if (!reply.isError()) { + contextListProperties = reply.value(); + } + } + return contextListProperties; +} + bool QOfonoDataConnectionManagerInterface::roamingAllowed() { QVariant var = getProperty(QStringLiteral("RoamingAllowed")); return qdbus_cast(var); } +QString QOfonoDataConnectionManagerInterface::bearer() +{ + QVariant var = getProperty(QStringLiteral("Bearer")); + return qdbus_cast(var); +} + QVariant QOfonoDataConnectionManagerInterface::getProperty(const QString &property) { return getProperties().value(property); @@ -279,7 +302,7 @@ QVariantMap &QOfonoDataConnectionManagerInterface::getProperties() { if (propertiesMap.isEmpty()) { QList argumentList; - QDBusPendingReply reply = asyncCallWithArgumentList(QLatin1String("GetProperties"), argumentList); + QDBusPendingReply reply = callWithArgumentList(QDBus::Block, QLatin1String("GetProperties"), argumentList); if (!reply.isError()) { propertiesMap = reply.value(); } @@ -294,6 +317,68 @@ void QOfonoDataConnectionManagerInterface::propertyChanged(const QString &name, Q_EMIT roamingAllowedChanged(value.variant().toBool()); } + +QOfonoConnectionContextInterface::QOfonoConnectionContextInterface(const QString &dbusPathName, QObject *parent) + : QDBusAbstractInterface(QLatin1String(OFONO_SERVICE), + dbusPathName, + OFONO_CONNECTION_CONTEXT_INTERFACE, + QDBusConnection::systemBus(), parent) +{ + QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE), + path(), + QLatin1String(OFONO_MODEM_INTERFACE), + QLatin1String("PropertyChanged"), + this,SLOT(propertyChanged(QString,QDBusVariant))); +} + +QOfonoConnectionContextInterface::~QOfonoConnectionContextInterface() +{ +} + +QVariantMap QOfonoConnectionContextInterface::getProperties() +{ + if (propertiesMap.isEmpty()) { + QList argumentList; + QDBusPendingReply reply = callWithArgumentList(QDBus::Block, QLatin1String("GetProperties"), argumentList); + if (!reply.isError()) { + propertiesMap = reply.value(); + } + } + return propertiesMap; +} + +void QOfonoConnectionContextInterface::propertyChanged(const QString &name, const QDBusVariant &value) +{ + propertiesMap[name] = value.variant(); +} + +QVariant QOfonoConnectionContextInterface::getProperty(const QString &property) +{ + QVariant var; + QVariantMap map = getProperties(); + if (map.contains(property)) + var = map.value(property); + return var; +} + +bool QOfonoConnectionContextInterface::active() +{ + QVariant var = getProperty(QStringLiteral("Active")); + return qdbus_cast(var); +} + +QString QOfonoConnectionContextInterface::accessPointName() +{ + QVariant var = getProperty(QStringLiteral("AccessPointName")); + return qdbus_cast(var); +} + +QString QOfonoConnectionContextInterface::name() +{ + QVariant var = getProperty(QStringLiteral("Name")); + return qdbus_cast(var); +} + QT_END_NAMESPACE #endif // QT_NO_DBUS diff --git a/src/plugins/bearer/connman/qofonoservice_linux_p.h b/src/plugins/bearer/linux_common/qofonoservice_linux_p.h similarity index 86% rename from src/plugins/bearer/connman/qofonoservice_linux_p.h rename to src/plugins/bearer/linux_common/qofonoservice_linux_p.h index 302d7543d43..8adb8db19c2 100644 --- a/src/plugins/bearer/connman/qofonoservice_linux_p.h +++ b/src/plugins/bearer/linux_common/qofonoservice_linux_p.h @@ -67,6 +67,7 @@ #define OFONO_MODEM_INTERFACE "org.ofono.Modem" #define OFONO_NETWORK_REGISTRATION_INTERFACE "org.ofono.NetworkRegistration" #define OFONO_DATA_CONNECTION_MANAGER_INTERFACE "org.ofono.ConnectionManager" +#define OFONO_CONNECTION_CONTEXT_INTERFACE "org.ofono.ConnectionContext" QT_BEGIN_NAMESPACE @@ -114,6 +115,7 @@ public: bool isPowered(); bool isOnline(); + QStringList interfaces(); private: QVariantMap getProperties(); QVariantMap propertiesMap; @@ -151,18 +153,42 @@ public: ~QOfonoDataConnectionManagerInterface(); QStringList contexts(); + PathPropertiesList contextsWithProperties(); bool roamingAllowed(); + QVariant getProperty(const QString &); + QString bearer(); Q_SIGNALS: void roamingAllowedChanged(bool); private: QVariantMap &getProperties(); QVariantMap propertiesMap; - QVariant getProperty(const QString &); QStringList contextList; + PathPropertiesList contextListProperties; private Q_SLOTS: void propertyChanged(const QString &, const QDBusVariant &value); }; +class QOfonoConnectionContextInterface : public QDBusAbstractInterface +{ + Q_OBJECT + +public: + + explicit QOfonoConnectionContextInterface(const QString &dbusPathName, QObject *parent = 0); + ~QOfonoConnectionContextInterface(); + + QVariant getProperty(const QString &); + bool active(); + QString accessPointName(); + QString name(); + +Q_SIGNALS: +private: + QVariantMap getProperties(); + QVariantMap propertiesMap; +private slots: + void propertyChanged(const QString &, const QDBusVariant &value); +}; QT_END_NAMESPACE diff --git a/src/plugins/bearer/networkmanager/main.cpp b/src/plugins/bearer/networkmanager/main.cpp index f416bb42a69..3576ddc37c4 100644 --- a/src/plugins/bearer/networkmanager/main.cpp +++ b/src/plugins/bearer/networkmanager/main.cpp @@ -66,10 +66,7 @@ QBearerEngine *QNetworkManagerEnginePlugin::create(const QString &key) const { if (key == QLatin1String("networkmanager")) { QNetworkManagerEngine *engine = new QNetworkManagerEngine; - if (engine->networkManagerAvailable()) - return engine; - else - delete engine; + return engine; } return 0; diff --git a/src/plugins/bearer/networkmanager/networkmanager.pro b/src/plugins/bearer/networkmanager/networkmanager.pro index 1ed9bfaa1b4..b3a270615cc 100644 --- a/src/plugins/bearer/networkmanager/networkmanager.pro +++ b/src/plugins/bearer/networkmanager/networkmanager.pro @@ -6,16 +6,16 @@ load(qt_plugin) QT = core network-private dbus -HEADERS += qnmdbushelper.h \ - qnetworkmanagerservice.h \ +HEADERS += qnetworkmanagerservice.h \ qnetworkmanagerengine.h \ + ../linux_common/qofonoservice_linux_p.h \ ../qnetworksession_impl.h \ ../qbearerengine_impl.h SOURCES += main.cpp \ - qnmdbushelper.cpp \ qnetworkmanagerservice.cpp \ qnetworkmanagerengine.cpp \ + ../linux_common/qofonoservice_linux.cpp \ ../qnetworksession_impl.cpp OTHER_FILES += networkmanager.json diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp index 5f49ea0b6de..f0977b47351 100644 --- a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp @@ -47,6 +47,7 @@ #include #include #include +#include "../linux_common/qofonoservice_linux_p.h" #ifndef QT_NO_BEARERMANAGEMENT #ifndef QT_NO_DBUS @@ -55,47 +56,85 @@ QT_BEGIN_NAMESPACE QNetworkManagerEngine::QNetworkManagerEngine(QObject *parent) : QBearerEngineImpl(parent), - managerInterface(new QNetworkManagerInterface(this)), - systemSettings(new QNetworkManagerSettings(NM_DBUS_SERVICE, this)), - userSettings(new QNetworkManagerSettings(NM_DBUS_SERVICE, this)) + managerInterface(NULL), + systemSettings(NULL), + ofonoManager(NULL), + nmAvailable(false) { - if (!managerInterface->isValid()) - return; - - managerInterface->setConnections(); - connect(managerInterface, SIGNAL(deviceAdded(QDBusObjectPath)), - this, SLOT(deviceAdded(QDBusObjectPath))); - connect(managerInterface, SIGNAL(deviceRemoved(QDBusObjectPath)), - this, SLOT(deviceRemoved(QDBusObjectPath))); - connect(managerInterface, SIGNAL(activationFinished(QDBusPendingCallWatcher*)), - this, SLOT(activationFinished(QDBusPendingCallWatcher*))); - connect(managerInterface, SIGNAL(propertiesChanged(QString,QMap)), - this, SLOT(interfacePropertiesChanged(QString,QMap))); - qDBusRegisterMetaType(); - systemSettings->setConnections(); - connect(systemSettings, SIGNAL(newConnection(QDBusObjectPath)), - this, SLOT(newConnection(QDBusObjectPath))); + nmWatcher = new QDBusServiceWatcher(NM_DBUS_SERVICE,QDBusConnection::systemBus(), + QDBusServiceWatcher::WatchForRegistration | + QDBusServiceWatcher::WatchForUnregistration, this); + connect(nmWatcher, SIGNAL(serviceRegistered(QString)), + this, SLOT(nmRegistered(QString))); + connect(nmWatcher, SIGNAL(serviceUnregistered(QString)), + this, SLOT(nmUnRegistered(QString))); - userSettings->setConnections(); - connect(userSettings, SIGNAL(newConnection(QDBusObjectPath)), - this, SLOT(newConnection(QDBusObjectPath))); + ofonoWatcher = new QDBusServiceWatcher("org.ofono",QDBusConnection::systemBus(), + QDBusServiceWatcher::WatchForRegistration | + QDBusServiceWatcher::WatchForUnregistration, this); + connect(ofonoWatcher, SIGNAL(serviceRegistered(QString)), + this, SLOT(ofonoRegistered(QString))); + connect(ofonoWatcher, SIGNAL(serviceUnregistered(QString)), + this, SLOT(ofonoUnRegistered(QString))); + + if (QDBusConnection::systemBus().interface()->isServiceRegistered("org.ofono")) + ofonoRegistered(); + + if (QDBusConnection::systemBus().interface()->isServiceRegistered(NM_DBUS_SERVICE)) + nmRegistered(); } QNetworkManagerEngine::~QNetworkManagerEngine() { qDeleteAll(connections); + connections.clear(); qDeleteAll(accessPoints); + accessPoints.clear(); qDeleteAll(wirelessDevices); - qDeleteAll(activeConnections); + wirelessDevices.clear(); + qDeleteAll(activeConnectionsList); + activeConnectionsList.clear(); + qDeleteAll(interfaceDevices); + interfaceDevices.clear(); + + connectionInterfaces.clear(); + + qDeleteAll(ofonoContextManagers); + ofonoContextManagers.clear(); + + qDeleteAll(wiredDevices); + wiredDevices.clear(); } void QNetworkManagerEngine::initialize() { - QMutexLocker locker(&mutex); + if (nmAvailable) + setupConfigurations(); +} - // Get current list of access points. +void QNetworkManagerEngine::setupConfigurations() +{ + QMutexLocker locker(&mutex); + // Get active connections. + foreach (const QDBusObjectPath &acPath, managerInterface->activeConnections()) { + + QNetworkManagerConnectionActive *activeConnection = + new QNetworkManagerConnectionActive(acPath.path(),this); + activeConnectionsList.insert(acPath.path(), activeConnection); + connect(activeConnection, SIGNAL(propertiesChanged(QMap)), + this, SLOT(activeConnectionPropertiesChanged(QMap))); + activeConnection->setConnections(); + + QStringList devices = activeConnection->devices(); + if (!devices.isEmpty()) { + QNetworkManagerInterfaceDevice device(devices.at(0),this); + connectionInterfaces.insert(activeConnection->connection().path(),device.networkInterface()); + } + } + + // Get current list of access points. foreach (const QDBusObjectPath &devicePath, managerInterface->getDevices()) { locker.unlock(); deviceAdded(devicePath); //add all accesspoints @@ -103,7 +142,6 @@ void QNetworkManagerEngine::initialize() } // Get connections. - foreach (const QDBusObjectPath &settingsPath, systemSettings->listConnections()) { locker.unlock(); if (!hasIdentifier(settingsPath.path())) @@ -111,57 +149,19 @@ void QNetworkManagerEngine::initialize() locker.relock(); } - foreach (const QDBusObjectPath &settingsPath, userSettings->listConnections()) { - locker.unlock(); - if (!hasIdentifier(settingsPath.path())) - newConnection(settingsPath, userSettings); - locker.relock(); - } - - // Get active connections. - foreach (const QDBusObjectPath &acPath, managerInterface->activeConnections()) { - QNetworkManagerConnectionActive *activeConnection = - new QNetworkManagerConnectionActive(acPath.path(),this); - activeConnections.insert(acPath.path(), activeConnection); - - activeConnection->setConnections(); - connect(activeConnection, SIGNAL(propertiesChanged(QString,QMap)), - this, SLOT(activeConnectionPropertiesChanged(QString,QMap))); - } Q_EMIT updateCompleted(); } bool QNetworkManagerEngine::networkManagerAvailable() const { - QMutexLocker locker(&mutex); - - return managerInterface->isValid(); + return nmAvailable; } -QString QNetworkManagerEngine::getInterfaceFromId(const QString &id) +QString QNetworkManagerEngine::getInterfaceFromId(const QString &settingsPath) { - QMutexLocker locker(&mutex); - - foreach (const QDBusObjectPath &acPath, managerInterface->activeConnections()) { - QNetworkManagerConnectionActive activeConnection(acPath.path()); - - const QString identifier = activeConnection.connection().path(); - - if (id == identifier) { - QList devices = activeConnection.devices(); - - if (devices.isEmpty()) - continue; - - QNetworkManagerInterfaceDevice device(devices.at(0).path()); - return device.networkInterface(); - } - } - - return QString(); + return connectionInterfaces.value(settingsPath); } - bool QNetworkManagerEngine::hasIdentifier(const QString &id) { QMutexLocker locker(&mutex); @@ -177,35 +177,37 @@ void QNetworkManagerEngine::connectToId(const QString &id) if (!connection) return; - QNmSettingsMap map = connection->getSettings(); - const QString connectionType = map.value("connection").value("type").toString(); + NMDeviceType connectionType = connection->getType(); QString dbusDevicePath; - foreach (const QDBusObjectPath &devicePath, managerInterface->getDevices()) { - QNetworkManagerInterfaceDevice device(devicePath.path()); - if (device.deviceType() == DEVICE_TYPE_ETHERNET && - connectionType == QLatin1String("802-3-ethernet")) { - dbusDevicePath = devicePath.path(); + const QString settingsPath = connection->connectionInterface()->path(); + QString specificPath = configuredAccessPoints.key(settingsPath); + + if (isConnectionActive(settingsPath)) + return; + + QHashIterator i(interfaceDevices); + while (i.hasNext()) { + i.next(); + if (i.value()->deviceType() == DEVICE_TYPE_ETHERNET && + connectionType == DEVICE_TYPE_ETHERNET) { + dbusDevicePath = i.key(); break; - } else if (device.deviceType() == DEVICE_TYPE_WIFI && - connectionType == QLatin1String("802-11-wireless")) { - dbusDevicePath = devicePath.path(); + } else if (i.value()->deviceType() == DEVICE_TYPE_WIFI && + connectionType == DEVICE_TYPE_WIFI) { + dbusDevicePath = i.key(); break; - } else if (device.deviceType() == DEVICE_TYPE_MODEM && - connectionType == QLatin1String("gsm")) { - dbusDevicePath = devicePath.path(); + } else if (i.value()->deviceType() == DEVICE_TYPE_MODEM && + connectionType == DEVICE_TYPE_MODEM) { + dbusDevicePath = i.key(); break; } } - const QString service = connection->connectionInterface()->service(); - const QString settingsPath = connection->connectionInterface()->path(); - QString specificPath = configuredAccessPoints.key(settingsPath); - if (specificPath.isEmpty()) specificPath = "/"; - managerInterface->activateConnection(service, QDBusObjectPath(settingsPath), + managerInterface->activateConnection(QDBusObjectPath(settingsPath), QDBusObjectPath(dbusDevicePath), QDBusObjectPath(specificPath)); } @@ -221,13 +223,11 @@ void QNetworkManagerEngine::disconnectFromId(const QString &id) return; } - foreach (const QDBusObjectPath &acPath, managerInterface->activeConnections()) { - QNetworkManagerConnectionActive activeConnection(acPath.path()); - - const QString identifier = activeConnection.connection().path(); - - if (id == identifier && accessPointConfigurations.contains(id)) { - managerInterface->deactivateConnection(acPath); + QHashIterator i(activeConnectionsList); + while (i.hasNext()) { + i.next(); + if (id == i.value()->connection().path() && accessPointConfigurations.contains(id)) { + managerInterface->deactivateConnection(QDBusObjectPath(i.key())); break; } } @@ -235,7 +235,7 @@ void QNetworkManagerEngine::disconnectFromId(const QString &id) void QNetworkManagerEngine::requestUpdate() { - if (managerInterface->wirelessEnabled()) { + if (managerInterface && managerInterface->wirelessEnabled()) { QHashIterator i(wirelessDevices); while (i.hasNext()) { i.next(); @@ -250,12 +250,9 @@ void QNetworkManagerEngine::scanFinished() QMetaObject::invokeMethod(this, "updateCompleted", Qt::QueuedConnection); } -void QNetworkManagerEngine::interfacePropertiesChanged(const QString &path, - const QMap &properties) +void QNetworkManagerEngine::interfacePropertiesChanged(const QMap &properties) { - Q_UNUSED(path) QMutexLocker locker(&mutex); - QMapIterator i(properties); while (i.hasNext()) { i.next(); @@ -267,22 +264,20 @@ void QNetworkManagerEngine::interfacePropertiesChanged(const QString &path, qdbus_cast >(i.value().value()); QStringList identifiers = accessPointConfigurations.keys(); - foreach (const QString &id, identifiers) - QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); - - QStringList priorActiveConnections = this->activeConnections.keys(); + QStringList priorActiveConnections = activeConnectionsList.keys(); foreach (const QDBusObjectPath &acPath, activeConnections) { priorActiveConnections.removeOne(acPath.path()); QNetworkManagerConnectionActive *activeConnection = - this->activeConnections.value(acPath.path()); + activeConnectionsList.value(acPath.path()); + if (!activeConnection) { activeConnection = new QNetworkManagerConnectionActive(acPath.path(),this); - this->activeConnections.insert(acPath.path(), activeConnection); + activeConnectionsList.insert(acPath.path(), activeConnection); + connect(activeConnection, SIGNAL(propertiesChanged(QMap)), + this, SLOT(activeConnectionPropertiesChanged(QMap))); activeConnection->setConnections(); - connect(activeConnection, SIGNAL(propertiesChanged(QString,QMap)), - this, SLOT(activeConnectionPropertiesChanged(QString,QMap))); } const QString id = activeConnection->connection().path(); @@ -293,8 +288,14 @@ void QNetworkManagerEngine::interfacePropertiesChanged(const QString &path, if (ptr) { ptr->mutex.lock(); if (activeConnection->state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED && - ptr->state != QNetworkConfiguration::Active) { - ptr->state = QNetworkConfiguration::Active; + (ptr->state & QNetworkConfiguration::Active) != QNetworkConfiguration::Active) { + + ptr->state |= QNetworkConfiguration::Active; + + if (activeConnectionsList.value(id) && activeConnectionsList.value(id)->defaultRoute() + && managerInterface->state() < QNetworkManagerInterface::NM_STATE_CONNECTED_GLOBAL) { + ptr->purpose = QNetworkConfiguration::PrivatePurpose; + } ptr->mutex.unlock(); locker.unlock(); @@ -307,7 +308,7 @@ void QNetworkManagerEngine::interfacePropertiesChanged(const QString &path, } while (!priorActiveConnections.isEmpty()) - delete this->activeConnections.take(priorActiveConnections.takeFirst()); + delete activeConnectionsList.take(priorActiveConnections.takeFirst()); while (!identifiers.isEmpty()) { QNetworkConfigurationPrivatePointer ptr = @@ -330,14 +331,13 @@ void QNetworkManagerEngine::interfacePropertiesChanged(const QString &path, } } -void QNetworkManagerEngine::activeConnectionPropertiesChanged(const QString &path, - const QMap &properties) +void QNetworkManagerEngine::activeConnectionPropertiesChanged(const QMap &properties) { QMutexLocker locker(&mutex); Q_UNUSED(properties) - QNetworkManagerConnectionActive *activeConnection = activeConnections.value(path); + QNetworkManagerConnectionActive *activeConnection = qobject_cast(sender()); if (!activeConnection) return; @@ -346,32 +346,34 @@ void QNetworkManagerEngine::activeConnectionPropertiesChanged(const QString &pat QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); if (ptr) { - ptr->mutex.lock(); - if (activeConnection->state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED && - ptr->state != QNetworkConfiguration::Active) { - ptr->state |= QNetworkConfiguration::Active; - ptr->mutex.unlock(); + if (properties.contains(QStringLiteral("State"))) { + ptr->mutex.lock(); + if (properties.value("State").toUInt() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { + QStringList devices = activeConnection->devices(); + if (!devices.isEmpty()) { + QNetworkManagerInterfaceDevice device(devices.at(0),this); + connectionInterfaces.insert(id,device.networkInterface()); + } - locker.unlock(); - emit configurationChanged(ptr); - locker.relock(); - } else { - ptr->mutex.unlock(); + ptr->state |= QNetworkConfiguration::Active; + ptr->mutex.unlock(); + + locker.unlock(); + emit configurationChanged(ptr); + locker.relock(); + } else { + connectionInterfaces.remove(id); + ptr->mutex.unlock(); + } } } } -void QNetworkManagerEngine::devicePropertiesChanged(const QString &/*path*/,quint32 /*state*/) -{ -// Q_UNUSED(path); -// Q_UNUSED(state) -} - -void QNetworkManagerEngine::deviceConnectionsChanged(const QStringList &activeConnectionsList) +void QNetworkManagerEngine::deviceConnectionsChanged(const QStringList &connectionsList) { QMutexLocker locker(&mutex); for (int i = 0; i < connections.count(); ++i) { - if (activeConnectionsList.contains(connections.at(i)->connectionInterface()->path())) + if (connectionsList.contains(connections.at(i)->connectionInterface()->path())) continue; const QString settingsPath = connections.at(i)->connectionInterface()->path(); @@ -392,33 +394,33 @@ void QNetworkManagerEngine::deviceConnectionsChanged(const QStringList &activeCo void QNetworkManagerEngine::deviceAdded(const QDBusObjectPath &path) { - QMutexLocker locker(&mutex); QNetworkManagerInterfaceDevice *iDevice; iDevice = new QNetworkManagerInterfaceDevice(path.path(),this); connect(iDevice,SIGNAL(connectionsChanged(QStringList)), this,SLOT(deviceConnectionsChanged(QStringList))); - connect(iDevice,SIGNAL(stateChanged(QString,quint32)), - this,SLOT(devicePropertiesChanged(QString,quint32))); iDevice->setConnections(); interfaceDevices.insert(path.path(),iDevice); - if (iDevice->deviceType() == DEVICE_TYPE_WIFI) { QNetworkManagerInterfaceDeviceWireless *wirelessDevice = new QNetworkManagerInterfaceDeviceWireless(iDevice->connectionInterface()->path(),this); - wirelessDevice->setConnections(); connect(wirelessDevice, SIGNAL(accessPointAdded(QString)), this, SLOT(newAccessPoint(QString))); connect(wirelessDevice, SIGNAL(accessPointRemoved(QString)), this, SLOT(removeAccessPoint(QString))); connect(wirelessDevice,SIGNAL(scanDone()),this,SLOT(scanFinished())); - - foreach (const QDBusObjectPath &apPath, wirelessDevice->getAccessPoints()) - newAccessPoint(apPath.path()); + wirelessDevice->setConnections(); wirelessDevices.insert(path.path(), wirelessDevice); } + + if (iDevice->deviceType() == DEVICE_TYPE_ETHERNET) { + QNetworkManagerInterfaceDeviceWired *wiredDevice = + new QNetworkManagerInterfaceDeviceWired(iDevice->connectionInterface()->path(),this); + connect(wiredDevice,SIGNAL(carrierChanged(bool)),this,SLOT(wiredCarrierChanged(bool))); + wiredDevices.insert(iDevice->connectionInterface()->path(), wiredDevice); + } } void QNetworkManagerEngine::deviceRemoved(const QDBusObjectPath &path) @@ -435,6 +437,41 @@ void QNetworkManagerEngine::deviceRemoved(const QDBusObjectPath &path) delete wirelessDevices.take(path.path()); locker.relock(); } + if (wiredDevices.contains(path.path())) { + locker.unlock(); + delete wiredDevices.take(path.path()); + locker.relock(); + } +} + +void QNetworkManagerEngine::wiredCarrierChanged(bool carrier) +{ + QNetworkManagerInterfaceDeviceWired *deviceWired = qobject_cast(sender()); + if (!deviceWired) + return; + QMutexLocker locker(&mutex); + foreach (const QDBusObjectPath &settingsPath, systemSettings->listConnections()) { + for (int i = 0; i < connections.count(); ++i) { + QNetworkManagerSettingsConnection *connection = connections.at(i); + if (connection->getType() == DEVICE_TYPE_ETHERNET + && settingsPath.path() == connection->connectionInterface()->path()) { + QNetworkConfigurationPrivatePointer ptr = + accessPointConfigurations.value(settingsPath.path()); + + if (ptr) { + ptr->mutex.lock(); + if (carrier) + ptr->state |= QNetworkConfiguration::Discovered; + else + ptr->state = QNetworkConfiguration::Defined; + ptr->mutex.unlock(); + locker.unlock(); + emit configurationChanged(ptr); + return; + } + } + } + } } void QNetworkManagerEngine::newConnection(const QDBusObjectPath &path, @@ -444,67 +481,102 @@ void QNetworkManagerEngine::newConnection(const QDBusObjectPath &path, if (!settings) settings = qobject_cast(sender()); - if (!settings) + if (!settings) { return; + } - settings->deleteLater(); QNetworkManagerSettingsConnection *connection = new QNetworkManagerSettingsConnection(settings->connectionInterface()->service(), path.path(),this); - QString apPath; - for (int i = 0; i < accessPoints.count(); ++i) { - if (connection->getSsid() == accessPoints.at(i)->ssid()) { - // remove the corresponding accesspoint from configurations - apPath = accessPoints.at(i)->connectionInterface()->path(); - - QNetworkConfigurationPrivatePointer ptr - = accessPointConfigurations.take(apPath); - if (ptr) { - locker.unlock(); - emit configurationRemoved(ptr); - locker.relock(); - } - } + const QString settingsPath = connection->connectionInterface()->path(); + if (accessPointConfigurations.contains(settingsPath)) { + return; } + connections.append(connection); connect(connection,SIGNAL(removed(QString)),this,SLOT(removeConnection(QString))); connect(connection,SIGNAL(updated()),this,SLOT(updateConnection())); connection->setConnections(); - const QString settingsPath = connection->connectionInterface()->path(); + NMDeviceType deviceType = connection->getType(); - if (connection->getType() == DEVICE_TYPE_WIFI - && !configuredAccessPoints.contains(settingsPath)) - configuredAccessPoints.insert(apPath,settingsPath); + if (deviceType == DEVICE_TYPE_WIFI) { + QString apPath; + for (int i = 0; i < accessPoints.count(); ++i) { + if (connection->getSsid() == accessPoints.at(i)->ssid()) { + // remove the corresponding accesspoint from configurations + apPath = accessPoints.at(i)->connectionInterface()->path(); + QNetworkConfigurationPrivatePointer ptr + = accessPointConfigurations.take(apPath); + if (ptr) { + locker.unlock(); + emit configurationRemoved(ptr); + locker.relock(); + } + } + } + if (!configuredAccessPoints.contains(settingsPath)) + configuredAccessPoints.insert(apPath,settingsPath); + } QNetworkConfigurationPrivate *cpPriv = parseConnection(settingsPath, connection->getSettings()); // Check if connection is active. - foreach (const QDBusObjectPath &acPath, managerInterface->activeConnections()) { - QNetworkManagerConnectionActive activeConnection(acPath.path()); + if (isConnectionActive(settingsPath)) + cpPriv->state |= QNetworkConfiguration::Active; + + if (deviceType == DEVICE_TYPE_ETHERNET) { + QHashIterator i(interfaceDevices); + while (i.hasNext()) { + i.next(); + if (i.value()->deviceType() == deviceType) { + QNetworkManagerInterfaceDeviceWired *wiredDevice + = wiredDevices.value(i.value()->connectionInterface()->path()); + if (wiredDevice->carrier()) { + cpPriv->state |= QNetworkConfiguration::Discovered; + } + } + } + } - if (activeConnection.defaultRoute() && - activeConnection.connection().path() == settingsPath && - activeConnection.state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { - cpPriv->state |= QNetworkConfiguration::Active; - break; - } - } QNetworkConfigurationPrivatePointer ptr(cpPriv); accessPointConfigurations.insert(ptr->id, ptr); - locker.unlock(); emit configurationAdded(ptr); } +bool QNetworkManagerEngine::isConnectionActive(const QString &settingsPath) +{ + QHashIterator i(activeConnectionsList); + while (i.hasNext()) { + i.next(); + if (i.value()->connection().path() == settingsPath) { + if (i.value()->state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATING + || i.value()->state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { + return true; + } else { + break; + } + } + } + + QNetworkManagerSettingsConnection *settingsConnection = connectionFromId(settingsPath); + if (settingsConnection->getType() == DEVICE_TYPE_MODEM) { + return isActiveContext(settingsConnection->connectionInterface()->path()); + } + + return false; +} + void QNetworkManagerEngine::removeConnection(const QString &path) { QMutexLocker locker(&mutex); QNetworkManagerSettingsConnection *connection = qobject_cast(sender()); + if (!connection) return; @@ -525,6 +597,7 @@ void QNetworkManagerEngine::removeConnection(const QString &path) while (i.hasNext()) { i.next(); if (i.value() == path) { + configuredAccessPoints.remove(i.key()); newAccessPoint(i.key()); } } @@ -538,8 +611,6 @@ void QNetworkManagerEngine::updateConnection() qobject_cast(sender()); if (!connection) return; - - connection->deleteLater(); const QString settingsPath = connection->connectionInterface()->path(); QNetworkConfigurationPrivate *cpPriv = parseConnection(settingsPath, connection->getSettings()); @@ -575,10 +646,9 @@ void QNetworkManagerEngine::updateConnection() void QNetworkManagerEngine::activationFinished(QDBusPendingCallWatcher *watcher) { QMutexLocker locker(&mutex); - + QDBusPendingReply reply(*watcher); watcher->deleteLater(); - QDBusPendingReply reply(*watcher); if (!reply.isError()) { QDBusObjectPath result = reply.value(); @@ -607,7 +677,6 @@ void QNetworkManagerEngine::activationFinished(QDBusPendingCallWatcher *watcher) void QNetworkManagerEngine::newAccessPoint(const QString &path) { QMutexLocker locker(&mutex); - QNetworkManagerInterfaceAccessPoint *accessPoint = new QNetworkManagerInterfaceAccessPoint(path,this); @@ -620,15 +689,14 @@ void QNetworkManagerEngine::newAccessPoint(const QString &path) if (okToAdd) { accessPoints.append(accessPoint); accessPoint->setConnections(); - connect(accessPoint, SIGNAL(propertiesChanged(QMap)), - this, SLOT(updateAccessPoint(QMap))); } - // Check if configuration exists for connection. if (!accessPoint->ssid().isEmpty()) { + for (int i = 0; i < connections.count(); ++i) { QNetworkManagerSettingsConnection *connection = connections.at(i); const QString settingsPath = connection->connectionInterface()->path(); + if (accessPoint->ssid() == connection->getSsid()) { if (!configuredAccessPoints.contains(path)) { configuredAccessPoints.insert(path,settingsPath); @@ -639,6 +707,9 @@ void QNetworkManagerEngine::newAccessPoint(const QString &path) ptr->mutex.lock(); QNetworkConfiguration::StateFlags flag = QNetworkConfiguration::Defined; ptr->state = (flag | QNetworkConfiguration::Discovered); + + if (isConnectionActive(settingsPath)) + ptr->state = (flag | QNetworkConfiguration::Active); ptr->mutex.unlock(); locker.unlock(); @@ -655,11 +726,7 @@ void QNetworkManagerEngine::newAccessPoint(const QString &path) ptr->isValid = true; ptr->id = path; ptr->type = QNetworkConfiguration::InternetAccessPoint; - if (accessPoint->flags() == NM_802_11_AP_FLAGS_PRIVACY) { - ptr->purpose = QNetworkConfiguration::PrivatePurpose; - } else { - ptr->purpose = QNetworkConfiguration::PublicPurpose; - } + ptr->purpose = QNetworkConfiguration::PublicPurpose; ptr->state = QNetworkConfiguration::Undefined; ptr->bearerType = QNetworkConfiguration::BearerWLAN; @@ -674,13 +741,13 @@ void QNetworkManagerEngine::removeAccessPoint(const QString &path) QMutexLocker locker(&mutex); for (int i = 0; i < accessPoints.count(); ++i) { QNetworkManagerInterfaceAccessPoint *accessPoint = accessPoints.at(i); - if (accessPoint->connectionInterface()->path() == path) { accessPoints.removeOne(accessPoint); if (configuredAccessPoints.contains(accessPoint->connectionInterface()->path())) { // find connection and change state to Defined configuredAccessPoints.remove(accessPoint->connectionInterface()->path()); + for (int i = 0; i < connections.count(); ++i) { QNetworkManagerSettingsConnection *connection = connections.at(i); @@ -705,8 +772,6 @@ void QNetworkManagerEngine::removeAccessPoint(const QString &path) accessPointConfigurations.take(path); if (ptr) { - locker.unlock(); - locker.unlock(); emit configurationRemoved(ptr); locker.relock(); @@ -718,46 +783,12 @@ void QNetworkManagerEngine::removeAccessPoint(const QString &path) } } -void QNetworkManagerEngine::updateAccessPoint(const QMap &map) -{ - QMutexLocker locker(&mutex); - - Q_UNUSED(map) - - QNetworkManagerInterfaceAccessPoint *accessPoint = - qobject_cast(sender()); - if (!accessPoint) - return; - accessPoint->deleteLater(); - for (int i = 0; i < connections.count(); ++i) { - QNetworkManagerSettingsConnection *connection = connections.at(i); - - if (accessPoint->ssid() == connection->getSsid()) { - const QString settingsPath = connection->connectionInterface()->path(); - const QString connectionId = settingsPath; - - QNetworkConfigurationPrivatePointer ptr = - accessPointConfigurations.value(connectionId); - ptr->mutex.lock(); - QNetworkConfiguration::StateFlags flag = QNetworkConfiguration::Defined; - ptr->state = (flag | QNetworkConfiguration::Discovered); - ptr->mutex.unlock(); - - locker.unlock(); - emit configurationChanged(ptr); - return; - } - } -} - QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QString &settingsPath, const QNmSettingsMap &map) { - // Q_UNUSED(service); QMutexLocker locker(&mutex); QNetworkConfigurationPrivate *cpPriv = new QNetworkConfigurationPrivate; cpPriv->name = map.value("connection").value("id").toString(); - cpPriv->isValid = true; cpPriv->id = settingsPath; cpPriv->type = QNetworkConfiguration::InternetAccessPoint; @@ -765,18 +796,16 @@ QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QStri cpPriv->purpose = QNetworkConfiguration::PublicPurpose; cpPriv->state = QNetworkConfiguration::Defined; - const QString connectionType = map.value("connection").value("type").toString(); if (connectionType == QLatin1String("802-3-ethernet")) { cpPriv->bearerType = QNetworkConfiguration::BearerEthernet; - cpPriv->purpose = QNetworkConfiguration::PublicPurpose; foreach (const QDBusObjectPath &devicePath, managerInterface->getDevices()) { - QNetworkManagerInterfaceDevice device(devicePath.path()); + QNetworkManagerInterfaceDevice device(devicePath.path(),this); if (device.deviceType() == DEVICE_TYPE_ETHERNET) { - QNetworkManagerInterfaceDeviceWired wiredDevice(device.connectionInterface()->path()); - if (wiredDevice.carrier()) { + QNetworkManagerInterfaceDeviceWired *wiredDevice = wiredDevices.value(device.connectionInterface()->path()); + if (wiredDevice->carrier()) { cpPriv->state |= QNetworkConfiguration::Discovered; break; } @@ -786,12 +815,6 @@ QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QStri cpPriv->bearerType = QNetworkConfiguration::BearerWLAN; const QString connectionSsid = map.value("802-11-wireless").value("ssid").toString(); - const QString connectionSecurity = map.value("802-11-wireless").value("security").toString(); - if (!connectionSecurity.isEmpty()) { - cpPriv->purpose = QNetworkConfiguration::PrivatePurpose; - } else { - cpPriv->purpose = QNetworkConfiguration::PublicPurpose; - } for (int i = 0; i < accessPoints.count(); ++i) { if (connectionSsid == accessPoints.at(i)->ssid() && map.value("802-11-wireless").value("seen-bssids").toStringList().contains(accessPoints.at(i)->hwAddress())) { @@ -814,35 +837,46 @@ QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QStri } } else if (connectionType == QLatin1String("gsm")) { - foreach (const QDBusObjectPath &devicePath, managerInterface->getDevices()) { - QNetworkManagerInterfaceDevice device(devicePath.path()); + const QString connectionPath = map.value("connection").value("id").toString(); + cpPriv->name = contextName(connectionPath); + cpPriv->bearerType = currentBearerType(connectionPath); - if (device.deviceType() == DEVICE_TYPE_MODEM) { - QNetworkManagerInterfaceDeviceModem deviceModem(device.connectionInterface()->path(),this); - switch (deviceModem.currentCapabilities()) { - case 2: - cpPriv->bearerType = QNetworkConfiguration::Bearer2G; + if (ofonoManager && ofonoManager->isValid()) { + const QString contextPart = connectionPath.section('/', -1); + QHashIterator i(ofonoContextManagers); + while (i.hasNext()) { + i.next(); + const QString path = i.key() +"/"+contextPart; + if (isActiveContext(path)) { + cpPriv->state |= QNetworkConfiguration::Active; break; - case 4: - cpPriv->bearerType = QNetworkConfiguration::Bearer3G; - break; - case 8: - cpPriv->bearerType = QNetworkConfiguration::Bearer4G; - break; - default: - cpPriv->bearerType = QNetworkConfiguration::BearerUnknown; - break; - }; + } } } - - cpPriv->purpose = QNetworkConfiguration::PrivatePurpose; - cpPriv->state |= QNetworkConfiguration::Discovered; } return cpPriv; } +bool QNetworkManagerEngine::isActiveContext(const QString &contextPath) +{ + if (ofonoManager && ofonoManager->isValid()) { + const QString contextPart = contextPath.section('/', -1); + QHashIterator i(ofonoContextManagers); + while (i.hasNext()) { + i.next(); + PathPropertiesList list = i.value()->contextsWithProperties(); + for (int i = 0; i < list.size(); ++i) { + if (list.at(i).path.path().contains(contextPart)) { + return list.at(i).properties.value(QStringLiteral("Active")).toBool(); + + } + } + } + } + return false; +} + QNetworkManagerSettingsConnection *QNetworkManagerEngine::connectionFromId(const QString &id) const { for (int i = 0; i < connections.count(); ++i) { @@ -857,7 +891,6 @@ QNetworkManagerSettingsConnection *QNetworkManagerEngine::connectionFromId(const QNetworkSession::State QNetworkManagerEngine::sessionStateForId(const QString &id) { QMutexLocker locker(&mutex); - QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); if (!ptr) @@ -866,8 +899,8 @@ QNetworkSession::State QNetworkManagerEngine::sessionStateForId(const QString &i if (!ptr->isValid) return QNetworkSession::Invalid; - foreach (const QString &acPath, activeConnections.keys()) { - QNetworkManagerConnectionActive *activeConnection = activeConnections.value(acPath); + foreach (const QString &acPath, activeConnectionsList.keys()) { + QNetworkManagerConnectionActive *activeConnection = activeConnectionsList.value(acPath); const QString identifier = activeConnection->connection().path(); @@ -899,7 +932,7 @@ quint64 QNetworkManagerEngine::bytesWritten(const QString &id) QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); if (ptr && (ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { - const QString networkInterface = getInterfaceFromId(id); + const QString networkInterface = connectionInterfaces.value(id); if (!networkInterface.isEmpty()) { const QString devFile = QLatin1String("/sys/class/net/") + networkInterface + @@ -927,7 +960,7 @@ quint64 QNetworkManagerEngine::bytesReceived(const QString &id) QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); if (ptr && (ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { - const QString networkInterface = getInterfaceFromId(id); + const QString networkInterface = connectionInterfaces.value(id); if (!networkInterface.isEmpty()) { const QString devFile = QLatin1String("/sys/class/net/") + networkInterface + @@ -974,9 +1007,125 @@ QNetworkSessionPrivate *QNetworkManagerEngine::createSessionBackend() QNetworkConfigurationPrivatePointer QNetworkManagerEngine::defaultConfiguration() { + QHashIterator i(activeConnectionsList); + while (i.hasNext()) { + i.next(); + QNetworkManagerConnectionActive *activeConnection = i.value(); + if ((activeConnection->defaultRoute() || activeConnection->default6Route())) { + return accessPointConfigurations.value(activeConnection->connection().path()); + } + } + return QNetworkConfigurationPrivatePointer(); } +QNetworkConfiguration::BearerType QNetworkManagerEngine::currentBearerType(const QString &id) +{ + QString contextPart = id.section('/', -1); + QHashIterator i(ofonoContextManagers); + while (i.hasNext()) { + i.next(); + QString contextPath = i.key() +"/"+contextPart; + + if (i.value()->contexts().contains(contextPath)) { + + QString bearer = i.value()->bearer(); + + if (bearer == QStringLiteral("gsm")) { + return QNetworkConfiguration::Bearer2G; + } else if (bearer == QStringLiteral("edge")) { + return QNetworkConfiguration::Bearer2G; + } else if (bearer == QStringLiteral("umts")) { + return QNetworkConfiguration::BearerWCDMA; + } else if (bearer == QStringLiteral("hspa") + || bearer == QStringLiteral("hsdpa") + || bearer == QStringLiteral("hsupa")) { + return QNetworkConfiguration::BearerHSPA; + } else if (bearer == QStringLiteral("lte")) { + return QNetworkConfiguration::BearerLTE; + } + } + } + + return QNetworkConfiguration::BearerUnknown; +} + +QString QNetworkManagerEngine::contextName(const QString &path) +{ + QString contextPart = path.section('/', -1); + QHashIterator i(ofonoContextManagers); + while (i.hasNext()) { + i.next(); + PathPropertiesList list = i.value()->contextsWithProperties(); + for (int i = 0; i < list.size(); ++i) { + if (list.at(i).path.path().contains(contextPart)) { + return list.at(i).properties.value(QStringLiteral("Name")).toString(); + } + } + } + return path; +} + +void QNetworkManagerEngine::nmRegistered(const QString &) +{ + if (ofonoManager) { + delete ofonoManager; + ofonoManager = NULL; + } + managerInterface = new QNetworkManagerInterface(this); + systemSettings = new QNetworkManagerSettings(NM_DBUS_SERVICE, this); + + connect(managerInterface, SIGNAL(deviceAdded(QDBusObjectPath)), + this, SLOT(deviceAdded(QDBusObjectPath))); + connect(managerInterface, SIGNAL(deviceRemoved(QDBusObjectPath)), + this, SLOT(deviceRemoved(QDBusObjectPath))); + connect(managerInterface, SIGNAL(activationFinished(QDBusPendingCallWatcher*)), + this, SLOT(activationFinished(QDBusPendingCallWatcher*))); + connect(managerInterface, SIGNAL(propertiesChanged(QMap)), + this, SLOT(interfacePropertiesChanged(QMap))); + managerInterface->setConnections(); + + connect(systemSettings, SIGNAL(newConnection(QDBusObjectPath)), + this, SLOT(newConnection(QDBusObjectPath))); + systemSettings->setConnections(); + nmAvailable = true; + + setupConfigurations(); +} + +void QNetworkManagerEngine::nmUnRegistered(const QString &) +{ + if (systemSettings) { + delete systemSettings; + systemSettings = NULL; + } + if (managerInterface) { + delete managerInterface; + managerInterface = NULL; + } +} + +void QNetworkManagerEngine::ofonoRegistered(const QString &) +{ + if (ofonoManager) { + delete ofonoManager; + ofonoManager = NULL; + } + ofonoManager = new QOfonoManagerInterface(this); + if (ofonoManager && ofonoManager->isValid()) { + Q_FOREACH (const QString &modem, ofonoManager->getModems()) { + QOfonoDataConnectionManagerInterface *ofonoContextManager + = new QOfonoDataConnectionManagerInterface(modem,this); + ofonoContextManagers.insert(modem, ofonoContextManager); + } + } +} + +void QNetworkManagerEngine::ofonoUnRegistered(const QString &) +{ + ofonoContextManagers.clear(); +} + QT_END_NAMESPACE #endif // QT_NO_DBUS diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h index ab1cfea71ef..da6af14c007 100644 --- a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h @@ -49,6 +49,8 @@ #include "qnetworkmanagerservice.h" +#include "../linux_common/qofonoservice_linux_p.h" + #include #include @@ -89,11 +91,8 @@ public: QNetworkConfigurationPrivatePointer defaultConfiguration(); private Q_SLOTS: - void interfacePropertiesChanged(const QString &path, - const QMap &properties); - void activeConnectionPropertiesChanged(const QString &path, - const QMap &properties); - void devicePropertiesChanged(const QString &path, quint32); + void interfacePropertiesChanged(const QMap &properties); + void activeConnectionPropertiesChanged(const QMap &properties); void deviceAdded(const QDBusObjectPath &path); void deviceRemoved(const QDBusObjectPath &path); @@ -106,9 +105,16 @@ private Q_SLOTS: void newAccessPoint(const QString &path); void removeAccessPoint(const QString &path); - void updateAccessPoint(const QMap &map); void scanFinished(); + void wiredCarrierChanged(bool); + + void nmRegistered(const QString &serviceName = QString()); + void nmUnRegistered(const QString &serviceName = QString()); + + void ofonoRegistered(const QString &serviceName = QString()); + void ofonoUnRegistered(const QString &serviceName = QString()); + private: QNetworkConfigurationPrivate *parseConnection(const QString &settingsPath, const QNmSettingsMap &map); @@ -116,14 +122,29 @@ private: QNetworkManagerInterface *managerInterface; QNetworkManagerSettings *systemSettings; - QNetworkManagerSettings *userSettings; + QHash wiredDevices; QHash wirelessDevices; - QHash activeConnections; + + QHash activeConnectionsList; QList connections; QList accessPoints; QHash interfaceDevices; QMap configuredAccessPoints; //ap, settings path + QHash connectionInterfaces; // ac, interface + + QOfonoManagerInterface *ofonoManager; + QHash ofonoContextManagers; + QNetworkConfiguration::BearerType currentBearerType(const QString &id); + QString contextName(const QString &path); + + bool isConnectionActive(const QString &settingsPath); + QDBusServiceWatcher *ofonoWatcher; + QDBusServiceWatcher *nmWatcher; + + bool isActiveContext(const QString &contextPath); + bool nmAvailable; + void setupConfigurations(); }; QT_END_NAMESPACE diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp index f249ac6100c..fad94f069dc 100644 --- a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp @@ -44,7 +44,6 @@ #include #include "qnetworkmanagerservice.h" -#include "qnmdbushelper.h" #ifndef QT_NO_DBUS @@ -64,18 +63,38 @@ QNetworkManagerInterface::QNetworkManagerInterface(QObject *parent) d->connectionInterface = new QDBusInterface(QLatin1String(NM_DBUS_SERVICE), QLatin1String(NM_DBUS_PATH), QLatin1String(NM_DBUS_INTERFACE), - QDBusConnection::systemBus()); + QDBusConnection::systemBus(),parent); if (!d->connectionInterface->isValid()) { d->valid = false; return; } d->valid = true; - nmDBusHelper = new QNmDBusHelper(this); - connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(QString,QMap)), - this,SIGNAL(propertiesChanged(QString,QMap))); - connect(nmDBusHelper,SIGNAL(pathForStateChanged(QString,quint32)), - this, SIGNAL(stateChanged(QString,quint32))); + QDBusInterface managerPropertiesInterface(QLatin1String(NM_DBUS_SERVICE), + QLatin1String(NM_DBUS_PATH), + QLatin1String("org.freedesktop.DBus.Properties"), + QDBusConnection::systemBus()); + QList argumentList; + argumentList << QLatin1String(NM_DBUS_INTERFACE); + QDBusPendingReply propsReply + = managerPropertiesInterface.callWithArgumentList(QDBus::Block,QLatin1String("GetAll"), + argumentList); + if (!propsReply.isError()) { + propertyMap = propsReply.value(); + } + + QDBusPendingReply > nmReply + = d->connectionInterface->call(QLatin1String("GetDevices")); + nmReply.waitForFinished(); + if (!nmReply.isError()) { + devicesPathList = nmReply.value(); + } + + QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), + QLatin1String(NM_DBUS_PATH), + QLatin1String(NM_DBUS_INTERFACE), + QLatin1String("PropertiesChanged"), + this,SLOT(propertiesSwap(QMap))); } QNetworkManagerInterface::~QNetworkManagerInterface() @@ -91,27 +110,24 @@ bool QNetworkManagerInterface::isValid() bool QNetworkManagerInterface::setConnections() { - if(!isValid() ) + if (!isValid()) return false; - QDBusConnection dbusConnection = QDBusConnection::systemBus(); - - bool allOk = false; - if (dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), + QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), QLatin1String(NM_DBUS_PATH), QLatin1String(NM_DBUS_INTERFACE), QLatin1String("PropertiesChanged"), - nmDBusHelper,SLOT(slotPropertiesChanged(QMap)))) { - allOk = true; - } - if (dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), + this,SLOT(propertiesSwap(QMap))); + + bool allOk = false; + if (QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), QLatin1String(NM_DBUS_PATH), QLatin1String(NM_DBUS_INTERFACE), QLatin1String("DeviceAdded"), this,SIGNAL(deviceAdded(QDBusObjectPath)))) { allOk = true; } - if (dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), + if (QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), QLatin1String(NM_DBUS_PATH), QLatin1String(NM_DBUS_INTERFACE), QLatin1String("DeviceRemoved"), @@ -127,14 +143,17 @@ QDBusInterface *QNetworkManagerInterface::connectionInterface() const return d->connectionInterface; } -QList QNetworkManagerInterface::getDevices() const +QList QNetworkManagerInterface::getDevices() { - QDBusReply > reply = d->connectionInterface->call(QLatin1String("GetDevices")); - return reply.value(); + if (devicesPathList.isEmpty()) { + qWarning() << "using blocking call!"; + QDBusReply > reply = d->connectionInterface->call(QLatin1String("GetDevices")); + devicesPathList = reply.value(); + } + return devicesPathList; } -void QNetworkManagerInterface::activateConnection( const QString &, - QDBusObjectPath connectionPath, +void QNetworkManagerInterface::activateConnection(QDBusObjectPath connectionPath, QDBusObjectPath devicePath, QDBusObjectPath specificObject) { @@ -150,28 +169,80 @@ void QNetworkManagerInterface::activateConnection( const QString &, void QNetworkManagerInterface::deactivateConnection(QDBusObjectPath connectionPath) const { - d->connectionInterface->call(QLatin1String("DeactivateConnection"), QVariant::fromValue(connectionPath)); + d->connectionInterface->asyncCall(QLatin1String("DeactivateConnection"), QVariant::fromValue(connectionPath)); } bool QNetworkManagerInterface::wirelessEnabled() const { - return d->connectionInterface->property("WirelessEnabled").toBool(); + if (propertyMap.contains("WirelessEnabled")) + return propertyMap.value("WirelessEnabled").toBool(); + return false; } bool QNetworkManagerInterface::wirelessHardwareEnabled() const { - return d->connectionInterface->property("WirelessHardwareEnabled").toBool(); + if (propertyMap.contains("WirelessHardwareEnabled")) + return propertyMap.value("WirelessHardwareEnabled").toBool(); + return false; } QList QNetworkManagerInterface::activeConnections() const { - QVariant prop = d->connectionInterface->property("ActiveConnections"); - return prop.value >(); + if (propertyMap.contains("ActiveConnections")) { + + const QDBusArgument &dbusArgs = propertyMap.value("ActiveConnections").value(); + QDBusObjectPath path; + QList list; + + dbusArgs.beginArray(); + while (!dbusArgs.atEnd()) { + dbusArgs >> path; + list.append(path); + } + dbusArgs.endArray(); + + return list; + } + + QList list; + list << QDBusObjectPath(); + return list; } -quint32 QNetworkManagerInterface::state() +QNetworkManagerInterface::NMState QNetworkManagerInterface::state() { - return d->connectionInterface->property("State").toUInt(); + if (propertyMap.contains("State")) + return static_cast(propertyMap.value("State").toUInt()); + return QNetworkManagerInterface::NM_STATE_UNKNOWN; +} + +QString QNetworkManagerInterface::version() const +{ + if (propertyMap.contains("Version")) + return propertyMap.value("Version").toString(); + return QString(); +} + +void QNetworkManagerInterface::propertiesSwap(QMap map) +{ + QMapIterator i(map); + while (i.hasNext()) { + i.next(); + propertyMap.insert(i.key(),i.value()); + + if (i.key() == QStringLiteral("State")) { + quint32 state = i.value().toUInt(); + if (state == NM_DEVICE_STATE_ACTIVATED + || state == NM_DEVICE_STATE_DISCONNECTED + || state == NM_DEVICE_STATE_UNAVAILABLE + || state == NM_DEVICE_STATE_FAILED) { + Q_EMIT propertiesChanged(map); + Q_EMIT stateChanged(state); + } + } else if (i.key() == QStringLiteral("ActiveConnections")) { + Q_EMIT propertiesChanged(map); + } + } } class QNetworkManagerInterfaceAccessPointPrivate @@ -183,18 +254,38 @@ public: }; QNetworkManagerInterfaceAccessPoint::QNetworkManagerInterfaceAccessPoint(const QString &dbusPathName, QObject *parent) - : QObject(parent), nmDBusHelper(0) + : QObject(parent) { d = new QNetworkManagerInterfaceAccessPointPrivate(); d->path = dbusPathName; d->connectionInterface = new QDBusInterface(QLatin1String(NM_DBUS_SERVICE), d->path, QLatin1String(NM_DBUS_INTERFACE_ACCESS_POINT), - QDBusConnection::systemBus()); + QDBusConnection::systemBus(),parent); if (!d->connectionInterface->isValid()) { d->valid = false; return; } + QDBusInterface accessPointPropertiesInterface(QLatin1String(NM_DBUS_SERVICE), + d->path, + QLatin1String("org.freedesktop.DBus.Properties"), + QDBusConnection::systemBus()); + + QList argumentList; + argumentList << QLatin1String(NM_DBUS_INTERFACE_ACCESS_POINT); + QDBusPendingReply propsReply + = accessPointPropertiesInterface.callWithArgumentList(QDBus::Block,QLatin1String("GetAll"), + argumentList); + if (!propsReply.isError()) { + propertyMap = propsReply.value(); + } + + QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), + d->path, + QLatin1String(NM_DBUS_INTERFACE_ACCESS_POINT), + QLatin1String("PropertiesChanged"), + this,SLOT(propertiesSwap(QMap))); + d->valid = true; } @@ -212,24 +303,10 @@ bool QNetworkManagerInterfaceAccessPoint::isValid() bool QNetworkManagerInterfaceAccessPoint::setConnections() { - if(!isValid() ) + if (!isValid()) return false; - bool allOk = false; - delete nmDBusHelper; - nmDBusHelper = new QNmDBusHelper(this); - connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(QString,QMap)), - this,SIGNAL(propertiesChanged(QString,QMap))); - - if (QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), - d->path, - QLatin1String(NM_DBUS_INTERFACE_ACCESS_POINT), - QLatin1String("PropertiesChanged"), - nmDBusHelper,SLOT(slotPropertiesChanged(QMap))) ) { - allOk = true; - - } - return allOk; + return true; } QDBusInterface *QNetworkManagerInterfaceAccessPoint::connectionInterface() const @@ -239,47 +316,74 @@ QDBusInterface *QNetworkManagerInterfaceAccessPoint::connectionInterface() const quint32 QNetworkManagerInterfaceAccessPoint::flags() const { - return d->connectionInterface->property("Flags").toUInt(); + if (propertyMap.contains("Flags")) + return propertyMap.value("Flags").toUInt(); + return 0; } quint32 QNetworkManagerInterfaceAccessPoint::wpaFlags() const { - return d->connectionInterface->property("WpaFlags").toUInt(); + if (propertyMap.contains("WpaFlags")) + return propertyMap.value("WpaFlags").toUInt(); + return 0; } quint32 QNetworkManagerInterfaceAccessPoint::rsnFlags() const { - return d->connectionInterface->property("RsnFlags").toUInt(); + if (propertyMap.contains("RsnFlags")) + return propertyMap.value("RsnFlags").toUInt(); + return 0; } QString QNetworkManagerInterfaceAccessPoint::ssid() const { - return d->connectionInterface->property("Ssid").toString(); + if (propertyMap.contains("Ssid")) + return propertyMap.value("Ssid").toString(); + return QString(); } quint32 QNetworkManagerInterfaceAccessPoint::frequency() const { - return d->connectionInterface->property("Frequency").toUInt(); + if (propertyMap.contains("Frequency")) + return propertyMap.value("Frequency").toUInt(); + return 0; } QString QNetworkManagerInterfaceAccessPoint::hwAddress() const { - return d->connectionInterface->property("HwAddress").toString(); + if (propertyMap.contains("HwAddress")) + return propertyMap.value("HwAddress").toString(); + return QString(); } quint32 QNetworkManagerInterfaceAccessPoint::mode() const { - return d->connectionInterface->property("Mode").toUInt(); + if (propertyMap.contains("Mode")) + return propertyMap.value("Mode").toUInt(); + return 0; } quint32 QNetworkManagerInterfaceAccessPoint::maxBitrate() const { - return d->connectionInterface->property("MaxBitrate").toUInt(); + if (propertyMap.contains("MaxBitrate")) + return propertyMap.value("MaxBitrate").toUInt(); + return 0; } quint32 QNetworkManagerInterfaceAccessPoint::strength() const { - return d->connectionInterface->property("Strength").toUInt(); + if (propertyMap.contains("Strength")) + return propertyMap.value("Strength").toUInt(); + return 0; +} + +void QNetworkManagerInterfaceAccessPoint::propertiesSwap(QMap map) +{ + QMapIterator i(map); + while (i.hasNext()) { + i.next(); + propertyMap.insert(i.key(),i.value()); + } } class QNetworkManagerInterfaceDevicePrivate @@ -291,18 +395,39 @@ public: }; QNetworkManagerInterfaceDevice::QNetworkManagerInterfaceDevice(const QString &deviceObjectPath, QObject *parent) - : QObject(parent), nmDBusHelper(0) + : QObject(parent) { + d = new QNetworkManagerInterfaceDevicePrivate(); d->path = deviceObjectPath; d->connectionInterface = new QDBusInterface(QLatin1String(NM_DBUS_SERVICE), d->path, QLatin1String(NM_DBUS_INTERFACE_DEVICE), - QDBusConnection::systemBus()); + QDBusConnection::systemBus(),parent); if (!d->connectionInterface->isValid()) { d->valid = false; return; } + QDBusInterface devicePropertiesInterface(QLatin1String(NM_DBUS_SERVICE), + d->path, + QLatin1String("org.freedesktop.DBus.Properties"), + QDBusConnection::systemBus(),parent); + + QList argumentList; + argumentList << QLatin1String(NM_DBUS_INTERFACE_DEVICE); + QDBusPendingReply propsReply + = devicePropertiesInterface.callWithArgumentList(QDBus::Block,QLatin1String("GetAll"), + argumentList); + + if (!propsReply.isError()) { + propertyMap = propsReply.value(); + } + + QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), + d->path, + QLatin1String(NM_DBUS_INTERFACE_DEVICE), + QLatin1String("PropertiesChanged"), + this,SLOT(propertiesSwap(QMap))); d->valid = true; } @@ -319,35 +444,10 @@ bool QNetworkManagerInterfaceDevice::isValid() bool QNetworkManagerInterfaceDevice::setConnections() { - if(!isValid() ) + if (!isValid()) return false; - bool allOk = true; - delete nmDBusHelper; - nmDBusHelper = new QNmDBusHelper(this); - connect(nmDBusHelper,SIGNAL(pathForStateChanged(QString,quint32)), - this, SIGNAL(stateChanged(QString,quint32))); - - if (QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), - d->path, - QLatin1String(NM_DBUS_INTERFACE_DEVICE), - QLatin1String("StateChanged"), - nmDBusHelper,SLOT(deviceStateChanged(quint32)))) { - allOk = false; - } - - connect(nmDBusHelper, SIGNAL(pathForConnectionsChanged(QStringList)), - this,SIGNAL(connectionsChanged(QStringList))); - - if (QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), - d->path, - QLatin1String(NM_DBUS_INTERFACE_ACCESS_POINT), - QLatin1String("PropertiesChanged"), - nmDBusHelper,SLOT(slotPropertiesChanged(QMap))) ) { - allOk = false; - } - - return allOk; + return true; } QDBusInterface *QNetworkManagerInterfaceDevice::connectionInterface() const @@ -357,33 +457,66 @@ QDBusInterface *QNetworkManagerInterfaceDevice::connectionInterface() const QString QNetworkManagerInterfaceDevice::udi() const { - return d->connectionInterface->property("Udi").toString(); + if (propertyMap.contains("Udi")) + return propertyMap.value("Udi").toString(); + return QString(); } QString QNetworkManagerInterfaceDevice::networkInterface() const { - return d->connectionInterface->property("Interface").toString(); + if (propertyMap.contains("Interface")) + return propertyMap.value("Interface").toString(); + return QString(); } quint32 QNetworkManagerInterfaceDevice::ip4Address() const { - return d->connectionInterface->property("Ip4Address").toUInt(); + if (propertyMap.contains("Ip4Address")) + return propertyMap.value("Ip4Address").toUInt(); + return 0; } quint32 QNetworkManagerInterfaceDevice::state() const { - return d->connectionInterface->property("State").toUInt(); + if (propertyMap.contains("State")) + return propertyMap.value("State").toUInt(); + return 0; } quint32 QNetworkManagerInterfaceDevice::deviceType() const { - return d->connectionInterface->property("DeviceType").toUInt(); + if (propertyMap.contains("DeviceType")) + return propertyMap.value("DeviceType").toUInt(); + return 0; } QDBusObjectPath QNetworkManagerInterfaceDevice::ip4config() const { - QVariant prop = d->connectionInterface->property("Ip4Config"); - return prop.value(); + if (propertyMap.contains("Ip4Config")) + return propertyMap.value("Ip4Config").value(); + return QDBusObjectPath(); +} + +void QNetworkManagerInterfaceDevice::propertiesSwap(QMap map) +{ + QMapIterator i(map); + while (i.hasNext()) { + i.next(); + if (i.key() == QStringLiteral("AvailableConnections")) { //Device + const QDBusArgument &dbusArgs = i.value().value(); + QDBusObjectPath path; + QStringList paths; + dbusArgs.beginArray(); + while (!dbusArgs.atEnd()) { + dbusArgs >> path; + paths << path.path(); + } + dbusArgs.endArray(); + Q_EMIT connectionsChanged(paths); + } + propertyMap.insert(i.key(),i.value()); + } + Q_EMIT propertiesChanged(map); } class QNetworkManagerInterfaceDeviceWiredPrivate @@ -395,7 +528,7 @@ public: }; QNetworkManagerInterfaceDeviceWired::QNetworkManagerInterfaceDeviceWired(const QString &ifaceDevicePath, QObject *parent) - : QObject(parent), nmDBusHelper(0) + : QObject(parent) { d = new QNetworkManagerInterfaceDeviceWiredPrivate(); d->path = ifaceDevicePath; @@ -407,6 +540,27 @@ QNetworkManagerInterfaceDeviceWired::QNetworkManagerInterfaceDeviceWired(const Q d->valid = false; return; } + QDBusInterface deviceWiredPropertiesInterface(QLatin1String(NM_DBUS_SERVICE), + d->path, + QLatin1String("org.freedesktop.DBus.Properties"), + QDBusConnection::systemBus(),parent); + + QList argumentList; + argumentList << QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRED); + QDBusPendingReply propsReply + = deviceWiredPropertiesInterface.callWithArgumentList(QDBus::Block,QLatin1String("GetAll"), + argumentList); + + if (!propsReply.isError()) { + propertyMap = propsReply.value(); + } + + QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), + d->path, + QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRED), + QLatin1String("PropertiesChanged"), + this,SLOT(propertiesSwap(QMap))); + d->valid = true; } @@ -424,23 +578,9 @@ bool QNetworkManagerInterfaceDeviceWired::isValid() bool QNetworkManagerInterfaceDeviceWired::setConnections() { - if(!isValid() ) + if (!isValid()) return false; - - bool allOk = true; - - delete nmDBusHelper; - nmDBusHelper = new QNmDBusHelper(this); - connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(QString,QMap)), - this,SIGNAL(propertiesChanged(QString,QMap))); - if (!QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), - d->path, - QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRED), - QLatin1String("PropertiesChanged"), - nmDBusHelper,SLOT(slotPropertiesChanged(QMap))) ) { - allOk = false; - } - return allOk; + return true; } QDBusInterface *QNetworkManagerInterfaceDeviceWired::connectionInterface() const @@ -450,17 +590,53 @@ QDBusInterface *QNetworkManagerInterfaceDeviceWired::connectionInterface() const QString QNetworkManagerInterfaceDeviceWired::hwAddress() const { - return d->connectionInterface->property("HwAddress").toString(); + if (propertyMap.contains("HwAddress")) + return propertyMap.value("HwAddress").toString(); + return QString(); } quint32 QNetworkManagerInterfaceDeviceWired::speed() const { - return d->connectionInterface->property("Speed").toUInt(); + if (propertyMap.contains("Speed")) + return propertyMap.value("Speed").toUInt(); + return 0; } bool QNetworkManagerInterfaceDeviceWired::carrier() const { - return d->connectionInterface->property("Carrier").toBool(); + if (propertyMap.contains("Carrier")) + return propertyMap.value("Carrier").toBool(); + return false; +} + +QStringList QNetworkManagerInterfaceDeviceWired::availableConnections() +{ + QStringList list; + if (propertyMap.contains("AvailableConnections")) { + const QDBusArgument &dbusArgs = propertyMap.value("Carrier").value(); + QDBusObjectPath path; + dbusArgs.beginArray(); + while (!dbusArgs.atEnd()) { + dbusArgs >> path; + list << path.path(); + } + dbusArgs.endArray(); + } + + return list; +} + +void QNetworkManagerInterfaceDeviceWired::propertiesSwap(QMap map) +{ + QMapIterator i(map); + while (i.hasNext()) { + i.next(); + propertyMap.insert(i.key(),i.value()); + if (i.key() == QStringLiteral("Carrier")) { + Q_EMIT carrierChanged(i.value().toBool()); + } + } + Q_EMIT propertiesChanged(map); } class QNetworkManagerInterfaceDeviceWirelessPrivate @@ -472,7 +648,7 @@ public: }; QNetworkManagerInterfaceDeviceWireless::QNetworkManagerInterfaceDeviceWireless(const QString &ifaceDevicePath, QObject *parent) - : QObject(parent), nmDBusHelper(0) + : QObject(parent) { d = new QNetworkManagerInterfaceDeviceWirelessPrivate(); d->path = ifaceDevicePath; @@ -484,6 +660,43 @@ QNetworkManagerInterfaceDeviceWireless::QNetworkManagerInterfaceDeviceWireless(c d->valid = false; return; } + + + QDBusPendingReply > nmReply + = d->connectionInterface->call(QLatin1String("GetAccessPoints")); + + if (!nmReply.isError()) { + accessPointsList = nmReply.value(); + } + + QDBusInterface deviceWirelessPropertiesInterface(QLatin1String(NM_DBUS_SERVICE), + d->path, + QLatin1String("org.freedesktop.DBus.Properties"), + QDBusConnection::systemBus(),parent); + + QList argumentList; + argumentList << QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS); + QDBusPendingReply propsReply + = deviceWirelessPropertiesInterface.callWithArgumentList(QDBus::Block,QLatin1String("GetAll"), + argumentList); + if (!propsReply.isError()) { + propertyMap = propsReply.value(); + } + + QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), + d->path, + QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS), + QLatin1String("PropertiesChanged"), + this,SLOT(propertiesSwap(QMap))); + + QDBusPendingReply > reply + = d->connectionInterface->asyncCall(QLatin1String("GetAccessPoints")); + + QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(reply); + connect(callWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(accessPointsFinished(QDBusPendingCallWatcher*))); + + d->valid = true; } @@ -498,29 +711,31 @@ bool QNetworkManagerInterfaceDeviceWireless::isValid() return d->valid; } +void QNetworkManagerInterfaceDeviceWireless::slotAccessPointAdded(QDBusObjectPath path) +{ + if (path.path().length() > 2) + Q_EMIT accessPointAdded(path.path()); +} + +void QNetworkManagerInterfaceDeviceWireless::slotAccessPointRemoved(QDBusObjectPath path) +{ + if (path.path().length() > 2) + Q_EMIT accessPointRemoved(path.path()); +} + bool QNetworkManagerInterfaceDeviceWireless::setConnections() { - if(!isValid() ) + if (!isValid()) return false; QDBusConnection dbusConnection = QDBusConnection::systemBus(); bool allOk = true; - delete nmDBusHelper; - nmDBusHelper = new QNmDBusHelper(this); - connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(QString,QMap)), - this,SIGNAL(propertiesChanged(QString,QMap))); - - connect(nmDBusHelper, SIGNAL(pathForAccessPointAdded(QString)), - this,SIGNAL(accessPointAdded(QString))); - - connect(nmDBusHelper, SIGNAL(pathForAccessPointRemoved(QString)), - this,SIGNAL(accessPointRemoved(QString))); if (!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), - d->path, + d->path, QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS), QLatin1String("AccessPointAdded"), - nmDBusHelper, SLOT(slotAccessPointAdded(QDBusObjectPath)))) { + this, SLOT(slotAccessPointAdded(QDBusObjectPath)))) { allOk = false; } @@ -529,18 +744,10 @@ bool QNetworkManagerInterfaceDeviceWireless::setConnections() d->path, QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS), QLatin1String("AccessPointRemoved"), - nmDBusHelper, SLOT(slotAccessPointRemoved(QDBusObjectPath)))) { + this, SLOT(slotAccessPointRemoved(QDBusObjectPath)))) { allOk = false; } - - if (!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), - d->path, - QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS), - QLatin1String("PropertiesChanged"), - nmDBusHelper,SLOT(slotPropertiesChanged(QMap)))) { - allOk = false; - } if (!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE), d->path, QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS), @@ -551,6 +758,19 @@ bool QNetworkManagerInterfaceDeviceWireless::setConnections() return allOk; } +void QNetworkManagerInterfaceDeviceWireless::accessPointsFinished(QDBusPendingCallWatcher *watcher) +{ + QDBusPendingReply > reply(*watcher); + watcher->deleteLater(); + if (!reply.isError()) { + accessPointsList = reply.value(); + } + + for (int i = 0; i < accessPointsList.size(); i++) { + Q_EMIT accessPointAdded(accessPointsList.at(i).path()); + } +} + QDBusInterface *QNetworkManagerInterfaceDeviceWireless::connectionInterface() const { return d->connectionInterface; @@ -558,33 +778,48 @@ QDBusInterface *QNetworkManagerInterfaceDeviceWireless::connectionInterface() co QList QNetworkManagerInterfaceDeviceWireless::getAccessPoints() { - QDBusReply > reply = d->connectionInterface->call(QLatin1String("GetAccessPoints")); - return reply.value(); + if (accessPointsList.isEmpty()) { + qWarning() << "Using blocking call!"; + QDBusReply > reply + = d->connectionInterface->call(QLatin1String("GetAccessPoints")); + accessPointsList = reply.value(); + } + return accessPointsList; } QString QNetworkManagerInterfaceDeviceWireless::hwAddress() const { - return d->connectionInterface->property("HwAddress").toString(); + if (propertyMap.contains("HwAddress")) + return propertyMap.value("HwAddress").toString(); + return QString(); } quint32 QNetworkManagerInterfaceDeviceWireless::mode() const { - return d->connectionInterface->property("Mode").toUInt(); + if (propertyMap.contains("Mode")) + return propertyMap.value("Mode").toUInt(); + return 0; } quint32 QNetworkManagerInterfaceDeviceWireless::bitrate() const { - return d->connectionInterface->property("Bitrate").toUInt(); + if (propertyMap.contains("Bitrate")) + return propertyMap.value("Bitrate").toUInt(); + return 0; } QDBusObjectPath QNetworkManagerInterfaceDeviceWireless::activeAccessPoint() const { - return d->connectionInterface->property("ActiveAccessPoint").value(); + if (propertyMap.contains("ActiveAccessPoint")) + return propertyMap.value("ActiveAccessPoint").value(); + return QDBusObjectPath(); } quint32 QNetworkManagerInterfaceDeviceWireless::wirelessCapabilities() const { - return d->connectionInterface->property("WirelelessCapabilities").toUInt(); + if (propertyMap.contains("WirelelessCapabilities")) + return propertyMap.value("WirelelessCapabilities").toUInt(); + return 0; } void QNetworkManagerInterfaceDeviceWireless::scanIsDone() @@ -597,6 +832,17 @@ void QNetworkManagerInterfaceDeviceWireless::requestScan() d->connectionInterface->asyncCall(QLatin1String("RequestScan")); } +void QNetworkManagerInterfaceDeviceWireless::propertiesSwap(QMap map) +{ + QMapIterator i(map); + while (i.hasNext()) { + i.next(); + propertyMap.insert(i.key(),i.value()); + if (i.key() == QStringLiteral("ActiveAccessPoint")) { //DeviceWireless + Q_EMIT propertiesChanged(map); + } + } +} class QNetworkManagerInterfaceDeviceModemPrivate { @@ -607,7 +853,7 @@ public: }; QNetworkManagerInterfaceDeviceModem::QNetworkManagerInterfaceDeviceModem(const QString &ifaceDevicePath, QObject *parent) - : QObject(parent), nmDBusHelper(0) + : QObject(parent) { d = new QNetworkManagerInterfaceDeviceModemPrivate(); d->path = ifaceDevicePath; @@ -619,6 +865,25 @@ QNetworkManagerInterfaceDeviceModem::QNetworkManagerInterfaceDeviceModem(const Q d->valid = false; return; } + QDBusInterface deviceModemPropertiesInterface(QLatin1String(NM_DBUS_SERVICE), + d->path, + QLatin1String("org.freedesktop.DBus.Properties"), + QDBusConnection::systemBus(),parent); + + QList argumentList; + argumentList << QLatin1String(NM_DBUS_INTERFACE_DEVICE_MODEM); + QDBusPendingReply propsReply + = deviceModemPropertiesInterface.callWithArgumentList(QDBus::Block,QLatin1String("GetAll"), + argumentList); + if (!propsReply.isError()) { + propertyMap = propsReply.value(); + } + + QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), + d->path, + QLatin1String(NM_DBUS_INTERFACE_DEVICE_MODEM), + QLatin1String("PropertiesChanged"), + this,SLOT(propertiesSwap(QMap))); d->valid = true; } @@ -639,20 +904,7 @@ bool QNetworkManagerInterfaceDeviceModem::setConnections() if (!isValid() ) return false; - bool allOk = true; - - delete nmDBusHelper; - nmDBusHelper = new QNmDBusHelper(this); - connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(QString,QMap)), - this,SIGNAL(propertiesChanged(QString,QMap))); - if (!QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), - d->path, - QLatin1String(NM_DBUS_INTERFACE_DEVICE_MODEM), - QLatin1String("PropertiesChanged"), - nmDBusHelper,SLOT(slotDevicePropertiesChanged(QMap))) ) { - allOk = false; - } - return allOk; + return true; } QDBusInterface *QNetworkManagerInterfaceDeviceModem::connectionInterface() const @@ -660,14 +912,28 @@ QDBusInterface *QNetworkManagerInterfaceDeviceModem::connectionInterface() const return d->connectionInterface; } -quint32 QNetworkManagerInterfaceDeviceModem::modemCapabilities() const +QNetworkManagerInterfaceDeviceModem::ModemCapabilities QNetworkManagerInterfaceDeviceModem::modemCapabilities() const { - return d->connectionInterface->property("ModemCapabilities").toUInt(); + if (propertyMap.contains("ModemCapabilities")) + return static_cast(propertyMap.value("ModemCapabilities").toUInt()); + return QNetworkManagerInterfaceDeviceModem::None; } -quint32 QNetworkManagerInterfaceDeviceModem::currentCapabilities() const +QNetworkManagerInterfaceDeviceModem::ModemCapabilities QNetworkManagerInterfaceDeviceModem::currentCapabilities() const { - return d->connectionInterface->property("CurrentCapabilities").toUInt(); + if (propertyMap.contains("CurrentCapabilities")) + return static_cast(propertyMap.value("CurrentCapabilities").toUInt()); + return QNetworkManagerInterfaceDeviceModem::None; +} + +void QNetworkManagerInterfaceDeviceModem::propertiesSwap(QMap map) +{ + QMapIterator i(map); + while (i.hasNext()) { + i.next(); + propertyMap.insert(i.key(),i.value()); + } + Q_EMIT propertiesChanged(map); } class QNetworkManagerSettingsPrivate @@ -691,6 +957,14 @@ QNetworkManagerSettings::QNetworkManagerSettings(const QString &settingsService, d->valid = false; return; } + + QDBusPendingReply > nmReply + = d->connectionInterface->call(QLatin1String("ListConnections")); + + if (!nmReply.isError()) { + connectionsList = nmReply.value(); + } + d->valid = true; } @@ -722,10 +996,16 @@ bool QNetworkManagerSettings::setConnections() QList QNetworkManagerSettings::listConnections() { - QDBusReply > reply = d->connectionInterface->call(QLatin1String("ListConnections")); - return reply.value(); + if (connectionsList.isEmpty()) { + qWarning() << "Using blocking call!"; + QDBusReply > reply + = d->connectionInterface->call(QLatin1String("ListConnections")); + connectionsList = reply.value(); + } + return connectionsList; } + QString QNetworkManagerSettings::getConnectionByUuid(const QString &uuid) { QList argumentList; @@ -751,7 +1031,7 @@ public: }; QNetworkManagerSettingsConnection::QNetworkManagerSettingsConnection(const QString &settingsService, const QString &connectionObjectPath, QObject *parent) - : QObject(parent), nmDBusHelper(0) + : QObject(parent) { qDBusRegisterMetaType(); d = new QNetworkManagerSettingsConnectionPrivate(); @@ -766,8 +1046,12 @@ QNetworkManagerSettingsConnection::QNetworkManagerSettingsConnection(const QStri return; } d->valid = true; - QDBusReply< QNmSettingsMap > rep = d->connectionInterface->call(QLatin1String("GetSettings")); - d->settingsMap = rep.value(); + + QDBusPendingReply nmReply + = d->connectionInterface->call(QLatin1String("GetSettings")); + if (!nmReply.isError()) { + d->settingsMap = nmReply.value(); + } } QNetworkManagerSettingsConnection::~QNetworkManagerSettingsConnection() @@ -783,7 +1067,7 @@ bool QNetworkManagerSettingsConnection::isValid() bool QNetworkManagerSettingsConnection::setConnections() { - if(!isValid() ) + if (!isValid()) return false; QDBusConnection dbusConnection = QDBusConnection::systemBus(); @@ -796,21 +1080,21 @@ bool QNetworkManagerSettingsConnection::setConnections() allOk = false; } - delete nmDBusHelper; - nmDBusHelper = new QNmDBusHelper(this); - connect(nmDBusHelper, SIGNAL(pathForSettingsRemoved(QString)), - this,SIGNAL(removed(QString))); - if (!dbusConnection.connect(d->service, d->path, QLatin1String(NM_DBUS_IFACE_SETTINGS_CONNECTION), QLatin1String("Removed"), - nmDBusHelper, SIGNAL(slotSettingsRemoved()))) { + this, SIGNAL(slotSettingsRemoved()))) { allOk = false; } return allOk; } +void QNetworkManagerSettingsConnection::slotSettingsRemoved() +{ + Q_EMIT removed(d->path); +} + QDBusInterface *QNetworkManagerSettingsConnection::connectionInterface() const { return d->connectionInterface; @@ -818,8 +1102,11 @@ QDBusInterface *QNetworkManagerSettingsConnection::connectionInterface() const QNmSettingsMap QNetworkManagerSettingsConnection::getSettings() { - QDBusReply< QNmSettingsMap > rep = d->connectionInterface->call(QLatin1String("GetSettings")); - d->settingsMap = rep.value(); + if (d->settingsMap.isEmpty()) { + qWarning() << "Using blocking call!"; + QDBusReply reply = d->connectionInterface->call(QLatin1String("GetSettings")); + d->settingsMap = reply.value(); + } return d->settingsMap; } @@ -832,6 +1119,8 @@ NMDeviceType QNetworkManagerSettingsConnection::getType() return DEVICE_TYPE_ETHERNET; else if (devType == QLatin1String("802-11-wireless")) return DEVICE_TYPE_WIFI; + else if (devType == QLatin1String("gsm")) + return DEVICE_TYPE_MODEM; else return DEVICE_TYPE_UNKNOWN; } @@ -908,7 +1197,7 @@ public: }; QNetworkManagerConnectionActive::QNetworkManagerConnectionActive(const QString &activeConnectionObjectPath, QObject *parent) - : QObject(parent), nmDBusHelper(0) + : QObject(parent) { d = new QNetworkManagerConnectionActivePrivate(); d->path = activeConnectionObjectPath; @@ -920,6 +1209,29 @@ QNetworkManagerConnectionActive::QNetworkManagerConnectionActive(const QString & d->valid = false; return; } + QDBusInterface connectionActivePropertiesInterface(QLatin1String(NM_DBUS_SERVICE), + d->path, + QLatin1String("org.freedesktop.DBus.Properties"), + QDBusConnection::systemBus()); + + + QList argumentList; + argumentList << QLatin1String(NM_DBUS_INTERFACE_ACTIVE_CONNECTION); + QDBusPendingReply propsReply + = connectionActivePropertiesInterface.callWithArgumentList(QDBus::Block,QLatin1String("GetAll"), + argumentList); + + if (!propsReply.isError()) { + propertyMap = propsReply.value(); + } else { + qWarning() << propsReply.error().message(); + } + + QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), + d->path, + QLatin1String(NM_DBUS_INTERFACE_ACTIVE_CONNECTION), + QLatin1String("PropertiesChanged"), + this,SLOT(propertiesSwap(QMap))); d->valid = true; } @@ -936,24 +1248,10 @@ bool QNetworkManagerConnectionActive::isValid() bool QNetworkManagerConnectionActive::setConnections() { - if(!isValid() ) + if (!isValid()) return false; - bool allOk = true; - delete nmDBusHelper; - nmDBusHelper = new QNmDBusHelper(this); - connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(QString,QMap)), - this,SIGNAL(propertiesChanged(QString,QMap))); - - if (!QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE), - d->path, - QLatin1String(NM_DBUS_INTERFACE_ACTIVE_CONNECTION), - QLatin1String("PropertiesChanged"), - nmDBusHelper,SLOT(activeConnectionPropertiesChanged(QMap))) ) { - allOk = false; - } - - return allOk; + return true; } QDBusInterface *QNetworkManagerConnectionActive::connectionInterface() const @@ -963,30 +1261,70 @@ QDBusInterface *QNetworkManagerConnectionActive::connectionInterface() const QDBusObjectPath QNetworkManagerConnectionActive::connection() const { - QVariant prop = d->connectionInterface->property("Connection"); - return prop.value(); + if (propertyMap.contains("Connection")) + return propertyMap.value("Connection").value(); + return QDBusObjectPath(); } QDBusObjectPath QNetworkManagerConnectionActive::specificObject() const { - QVariant prop = d->connectionInterface->property("SpecificObject"); - return prop.value(); + if (propertyMap.contains("SpecificObject")) + return propertyMap.value("SpecificObject").value(); + return QDBusObjectPath(); } -QList QNetworkManagerConnectionActive::devices() const +QStringList QNetworkManagerConnectionActive::devices() const { - QVariant prop = d->connectionInterface->property("Devices"); - return prop.value >(); + QStringList list; + if (propertyMap.contains("Devices")) { + const QDBusArgument &dbusArgs = propertyMap.value("Devices").value(); + QDBusObjectPath path; + + dbusArgs.beginArray(); + while (!dbusArgs.atEnd()) { + dbusArgs >> path; + list.append(path.path()); + } + dbusArgs.endArray(); + } + return list; } quint32 QNetworkManagerConnectionActive::state() const { - return d->connectionInterface->property("State").toUInt(); + if (propertyMap.contains("State")) + return propertyMap.value("State").toUInt(); + return 0; } bool QNetworkManagerConnectionActive::defaultRoute() const { - return d->connectionInterface->property("Default").toBool(); + if (propertyMap.contains("Default")) + return propertyMap.value("Default").toBool(); + return false; +} + +bool QNetworkManagerConnectionActive::default6Route() const +{ + if (propertyMap.contains("Default6")) + return propertyMap.value("Default6").toBool(); + return false; +} + +void QNetworkManagerConnectionActive::propertiesSwap(QMap map) +{ + QMapIterator i(map); + while (i.hasNext()) { + i.next(); + propertyMap.insert(i.key(),i.value()); + if (i.key() == QStringLiteral("State")) { + quint32 state = i.value().toUInt(); + if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED + || state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) { + Q_EMIT propertiesChanged(map); + } + } + } } class QNetworkManagerIp4ConfigPrivate diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h index 11ddaf70882..e645159d718 100644 --- a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h @@ -56,7 +56,6 @@ #include #include #include -#include "qnmdbushelper.h" #ifndef QT_NO_DBUS @@ -89,7 +88,7 @@ typedef enum NM_ACTIVE_CONNECTION_STATE_UNKNOWN = 0, NM_ACTIVE_CONNECTION_STATE_ACTIVATING, NM_ACTIVE_CONNECTION_STATE_ACTIVATED, - NM_ACTIVE_CONNECTION_STATE_DEACTIVATED + NM_ACTIVE_CONNECTION_STATE_DEACTIVATED = 4 } NMActiveConnectionState; #define NM_DBUS_SERVICE "org.freedesktop.NetworkManager" @@ -135,12 +134,23 @@ class QNetworkManagerInterface : public QObject Q_OBJECT public: + typedef enum + { + NM_STATE_UNKNOWN = 0, + NM_STATE_ASLEEP = 10, + NM_STATE_DISCONNECTED = 20, + NM_STATE_DISCONNECTING = 30, + NM_STATE_CONNECTING = 40, + NM_STATE_CONNECTED_LOCAL = 50, + NM_STATE_CONNECTED_SITE = 60, + NM_STATE_CONNECTED_GLOBAL = 70 + } NMState; QNetworkManagerInterface(QObject *parent = 0); ~QNetworkManagerInterface(); - QList getDevices() const; - void activateConnection(const QString &serviceName, QDBusObjectPath connection, QDBusObjectPath device, QDBusObjectPath specificObject); + QList getDevices(); + void activateConnection(QDBusObjectPath connection,QDBusObjectPath device, QDBusObjectPath specificObject); void deactivateConnection(QDBusObjectPath connectionPath) const; QDBusObjectPath path() const; @@ -149,21 +159,28 @@ public: bool wirelessEnabled() const; bool wirelessHardwareEnabled() const; QList activeConnections() const; - quint32 state(); + NMState state(); + QString version() const; bool setConnections(); bool isValid(); Q_SIGNALS: void deviceAdded(QDBusObjectPath); void deviceRemoved(QDBusObjectPath); - void propertiesChanged( const QString &, QMap); - void stateChanged(const QString&, quint32); + void propertiesChanged(QMap); + void stateChanged(quint32); void activationFinished(QDBusPendingCallWatcher*); + void propertiesReady(); + void devicesListReady(); private Q_SLOTS: + void propertiesSwap(QMap); + private: QNetworkManagerInterfacePrivate *d; - QNmDBusHelper *nmDBusHelper; + QVariantMap propertyMap; + QList devicesPathList; + }; class QNetworkManagerInterfaceAccessPointPrivate; @@ -228,11 +245,14 @@ public: Q_SIGNALS: void propertiesChanged(QMap ); - void propertiesChanged( const QString &, QMap); + void propertiesReady(); + +private Q_SLOTS: + void propertiesSwap(QMap); + private: QNetworkManagerInterfaceAccessPointPrivate *d; - QNmDBusHelper *nmDBusHelper; - + QVariantMap propertyMap; }; class QNetworkManagerInterfaceDevicePrivate; @@ -258,11 +278,14 @@ public: Q_SIGNALS: void stateChanged(const QString &, quint32); - void propertiesChanged(const QString &, QMap); + void propertiesChanged(QMap); void connectionsChanged(QStringList); + void propertiesReady(); +private Q_SLOTS: + void propertiesSwap(QMap); private: QNetworkManagerInterfaceDevicePrivate *d; - QNmDBusHelper *nmDBusHelper; + QVariantMap propertyMap; }; class QNetworkManagerInterfaceDeviceWiredPrivate; @@ -282,12 +305,19 @@ public: bool carrier() const; bool setConnections(); bool isValid(); + QStringList availableConnections(); Q_SIGNALS: - void propertiesChanged( const QString &, QMap); + void propertiesChanged(QMap); + void propertiesReady(); + void carrierChanged(bool); + +private Q_SLOTS: + void propertiesSwap(QMap); + private: QNetworkManagerInterfaceDeviceWiredPrivate *d; - QNmDBusHelper *nmDBusHelper; + QVariantMap propertyMap; }; class QNetworkManagerInterfaceDeviceWirelessPrivate; @@ -325,15 +355,26 @@ public: void requestScan(); Q_SIGNALS: - void propertiesChanged( const QString &, QMap); + void propertiesChanged(QMap); void accessPointAdded(const QString &); void accessPointRemoved(const QString &); void scanDone(); + void propertiesReady(); + void accessPointsReady(); + private Q_SLOTS: void scanIsDone(); + void propertiesSwap(QMap); + + void slotAccessPointAdded(QDBusObjectPath); + void slotAccessPointRemoved(QDBusObjectPath); + + void accessPointsFinished(QDBusPendingCallWatcher *watcher); + private: QNetworkManagerInterfaceDeviceWirelessPrivate *d; - QNmDBusHelper *nmDBusHelper; + QVariantMap propertyMap; + QList accessPointsList; }; class QNetworkManagerInterfaceDeviceModemPrivate; @@ -350,6 +391,7 @@ public: Gsm_Umts = 0x4, Lte = 0x08 }; + Q_DECLARE_FLAGS(ModemCapabilities, ModemCapability) explicit QNetworkManagerInterfaceDeviceModem(const QString &ifaceDevicePath, QObject *parent = 0); @@ -361,16 +403,22 @@ public: bool setConnections(); bool isValid(); - quint32 modemCapabilities() const; - quint32 currentCapabilities() const; + ModemCapabilities modemCapabilities() const; + ModemCapabilities currentCapabilities() const; Q_SIGNALS: - void propertiesChanged( const QString &, QMap); + void propertiesChanged(QMap); + void propertiesReady(); + +private Q_SLOTS: + void propertiesSwap(QMap); + private: QNetworkManagerInterfaceDeviceModemPrivate *d; - QNmDBusHelper *nmDBusHelper; + QVariantMap propertyMap; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QNetworkManagerInterfaceDeviceModem::ModemCapabilities) class QNetworkManagerSettingsPrivate; class QNetworkManagerSettings : public QObject @@ -390,8 +438,10 @@ public: Q_SIGNALS: void newConnection(QDBusObjectPath); + void connectionsListReady(); private: QNetworkManagerSettingsPrivate *d; + QList connectionsList; }; class QNetworkManagerSettingsConnectionPrivate; @@ -418,12 +468,14 @@ public: bool isValid(); Q_SIGNALS: - void updated(); void removed(const QString &path); + void settingsReady(); + +private Q_SLOTS: + void slotSettingsRemoved(); private: - QNmDBusHelper *nmDBusHelper; QNetworkManagerSettingsConnectionPrivate *d; }; @@ -444,22 +496,26 @@ public: ~ QNetworkManagerConnectionActive(); QDBusInterface *connectionInterface() const; - QString serviceName() const; QDBusObjectPath connection() const; QDBusObjectPath specificObject() const; - QList devices() const; + QStringList devices() const; quint32 state() const; bool defaultRoute() const; + bool default6Route() const; bool setConnections(); bool isValid(); Q_SIGNALS: - void propertiesChanged(QList); - void propertiesChanged( const QString &, QMap); + void propertiesChanged(QMap); + void propertiesReady(); + +private Q_SLOTS: + void propertiesSwap(QMap); + private: QNetworkManagerConnectionActivePrivate *d; - QNmDBusHelper *nmDBusHelper; + QVariantMap propertyMap; }; class QNetworkManagerIp4ConfigPrivate; diff --git a/src/plugins/bearer/networkmanager/qnmdbushelper.cpp b/src/plugins/bearer/networkmanager/qnmdbushelper.cpp deleted file mode 100644 index 0decfd78b9e..00000000000 --- a/src/plugins/bearer/networkmanager/qnmdbushelper.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** 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. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// this class is for helping qdbus get stuff - -#include "qnmdbushelper.h" - -#include "qnetworkmanagerservice.h" - -#include -#include -#include -#include - -#include - -#ifndef QT_NO_DBUS - -QT_BEGIN_NAMESPACE - -QNmDBusHelper::QNmDBusHelper(QObject * parent) - : QObject(parent) -{ -} - -QNmDBusHelper::~QNmDBusHelper() -{ -} - -void QNmDBusHelper::deviceStateChanged(quint32 state) - { - QDBusMessage msg = this->message(); - if (state == NM_DEVICE_STATE_ACTIVATED - || state == NM_DEVICE_STATE_DISCONNECTED - || state == NM_DEVICE_STATE_UNAVAILABLE - || state == NM_DEVICE_STATE_FAILED) { - emit pathForStateChanged(msg.path(), state); - } - } - -void QNmDBusHelper::slotAccessPointAdded(QDBusObjectPath path) -{ - if (path.path().length() > 2) - emit pathForAccessPointAdded(path.path()); -} - -void QNmDBusHelper::slotAccessPointRemoved(QDBusObjectPath path) -{ - if (path.path().length() > 2) - emit pathForAccessPointRemoved(path.path()); -} - -void QNmDBusHelper::slotPropertiesChanged(QMap map) -{ - QDBusMessage msg = this->message(); - QMapIterator i(map); - while (i.hasNext()) { - i.next(); - if (i.key() == QStringLiteral("State")) { - quint32 state = i.value().toUInt(); - if (state == NM_DEVICE_STATE_ACTIVATED - || state == NM_DEVICE_STATE_DISCONNECTED - || state == NM_DEVICE_STATE_UNAVAILABLE - || state == NM_DEVICE_STATE_FAILED) { - emit pathForPropertiesChanged(msg.path(), map); - } - } else if (i.key() == QStringLiteral("ActiveAccessPoint")) { - emit pathForPropertiesChanged(msg.path(), map); - } else if (i.key() == QStringLiteral("ActiveConnections")) { - emit pathForPropertiesChanged(msg.path(), map); - } else if (i.key() == QStringLiteral("AvailableConnections")) { - const QDBusArgument &dbusArgs = i.value().value(); - QDBusObjectPath path; - QStringList paths; - dbusArgs.beginArray(); - while (!dbusArgs.atEnd()) { - dbusArgs >> path; - paths << path.path(); - } - dbusArgs.endArray(); - emit pathForConnectionsChanged(paths); - } - } -} - -void QNmDBusHelper::slotSettingsRemoved() -{ - QDBusMessage msg = this->message(); - emit pathForSettingsRemoved(msg.path()); -} - -void QNmDBusHelper::activeConnectionPropertiesChanged(QMap map) -{ - QDBusMessage msg = this->message(); - QMapIterator i(map); - while (i.hasNext()) { - i.next(); - if (i.key() == QStringLiteral("State")) { - quint32 state = i.value().toUInt(); - if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED - || state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) { - emit pathForPropertiesChanged(msg.path(), map); - } - } - } -} - -QT_END_NAMESPACE - -#endif // QT_NO_DBUS diff --git a/src/plugins/bearer/qnetworksession_impl.cpp b/src/plugins/bearer/qnetworksession_impl.cpp index 1db59fec94a..c5adc98af7b 100644 --- a/src/plugins/bearer/qnetworksession_impl.cpp +++ b/src/plugins/bearer/qnetworksession_impl.cpp @@ -366,7 +366,8 @@ void QNetworkSessionPrivateImpl::networkConfigurationsChanged() else updateStateFromActiveConfig(); - startTime = engine->startTime(activeConfig.identifier()); + if (engine) + startTime = engine->startTime(activeConfig.identifier()); } void QNetworkSessionPrivateImpl::configurationChanged(QNetworkConfigurationPrivatePointer config) diff --git a/src/plugins/platforminputcontexts/ibus/qibustypes.cpp b/src/plugins/platforminputcontexts/ibus/qibustypes.cpp index 9bc53ed5c00..ec8c746b2d4 100644 --- a/src/plugins/platforminputcontexts/ibus/qibustypes.cpp +++ b/src/plugins/platforminputcontexts/ibus/qibustypes.cpp @@ -32,7 +32,6 @@ ****************************************************************************/ #include "qibustypes.h" -#include #include #include @@ -134,7 +133,7 @@ const QDBusArgument &operator>>(const QDBusArgument &argument, QIBusAttribute &a return argument; } -QTextFormat QIBusAttribute::format() const +QTextCharFormat QIBusAttribute::format() const { QTextCharFormat fmt; switch (type) { @@ -225,11 +224,32 @@ const QDBusArgument &operator>>(const QDBusArgument &arg, QIBusAttributeList &at QList QIBusAttributeList::imAttributes() const { - QList imAttrs; + QHash, QTextCharFormat> rangeAttrs; + + // Merge text fomats for identical ranges into a single QTextFormat. for (int i = 0; i < attributes.size(); ++i) { const QIBusAttribute &attr = attributes.at(i); - imAttrs += QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, attr.start, attr.end - attr.start, attr.format()); + const QTextCharFormat &format = attr.format(); + + if (format.isValid()) { + const QPair range(attr.start, attr.end); + rangeAttrs[range].merge(format); + } } + + // Assemble list in original attribute order. + QList imAttrs; + + for (int i = 0; i < attributes.size(); ++i) { + const QIBusAttribute &attr = attributes.at(i); + const QTextFormat &format = attr.format(); + + imAttrs += QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, + attr.start, + attr.end - attr.start, + format.isValid() ? rangeAttrs[QPair(attr.start, attr.end)] : format); + } + return imAttrs; } diff --git a/src/plugins/platforminputcontexts/ibus/qibustypes.h b/src/plugins/platforminputcontexts/ibus/qibustypes.h index 2ec3b019ff2..96791b17a18 100644 --- a/src/plugins/platforminputcontexts/ibus/qibustypes.h +++ b/src/plugins/platforminputcontexts/ibus/qibustypes.h @@ -36,6 +36,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -70,7 +71,7 @@ public: QIBusAttribute(); ~QIBusAttribute(); - QTextFormat format() const; + QTextCharFormat format() const; Type type; quint32 value; diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp index 536415339f6..62da60ab925 100644 --- a/src/plugins/platforms/android/androidjniinput.cpp +++ b/src/plugins/platforms/android/androidjniinput.cpp @@ -48,10 +48,6 @@ using namespace QtAndroid; namespace QtAndroidInput { - static jmethodID m_showSoftwareKeyboardMethodID = 0; - static jmethodID m_resetSoftwareKeyboardMethodID = 0; - static jmethodID m_hideSoftwareKeyboardMethodID = 0; - static jmethodID m_updateSelectionMethodID = 0; static bool m_ignoreMouseEvents = false; static bool m_softwareKeyboardVisible = false; @@ -62,30 +58,28 @@ namespace QtAndroidInput void updateSelection(int selStart, int selEnd, int candidatesStart, int candidatesEnd) { - AttachedJNIEnv env; - if (!env.jniEnv) - return; - #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << ">>> UPDATESELECTION" << selStart << selEnd << candidatesStart << candidatesEnd; #endif - env.jniEnv->CallStaticVoidMethod(applicationClass(), m_updateSelectionMethodID, - selStart, selEnd, candidatesStart, candidatesEnd); + QJNIObjectPrivate::callStaticMethod(applicationClass(), + "updateSelection", + "(IIII)V", + selStart, + selEnd, + candidatesStart, + candidatesEnd); } void showSoftwareKeyboard(int left, int top, int width, int height, int inputHints) { - AttachedJNIEnv env; - if (!env.jniEnv) - return; - - env.jniEnv->CallStaticVoidMethod(applicationClass(), - m_showSoftwareKeyboardMethodID, - left, - top, - width, - height, - inputHints); + QJNIObjectPrivate::callStaticMethod(applicationClass(), + "showSoftwareKeyboard", + "(IIIII)V", + left, + top, + width, + height, + inputHints); #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << "@@@ SHOWSOFTWAREKEYBOARD" << left << top << width << height << inputHints; #endif @@ -93,11 +87,7 @@ namespace QtAndroidInput void resetSoftwareKeyboard() { - AttachedJNIEnv env; - if (!env.jniEnv) - return; - - env.jniEnv->CallStaticVoidMethod(applicationClass(), m_resetSoftwareKeyboardMethodID); + QJNIObjectPrivate::callStaticMethod(applicationClass(), "resetSoftwareKeyboard"); #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << "@@@ RESETSOFTWAREKEYBOARD"; #endif @@ -105,11 +95,7 @@ namespace QtAndroidInput void hideSoftwareKeyboard() { - AttachedJNIEnv env; - if (!env.jniEnv) - return; - - env.jniEnv->CallStaticVoidMethod(applicationClass(), m_hideSoftwareKeyboardMethodID); + QJNIObjectPrivate::callStaticMethod(applicationClass(), "hideSoftwareKeyboard"); #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << "@@@ HIDESOFTWAREKEYBOARD"; #endif @@ -722,13 +708,6 @@ namespace QtAndroidInput {"keyboardVisibilityChanged", "(Z)V", (void *)keyboardVisibilityChanged} }; -#define GET_AND_CHECK_STATIC_METHOD(VAR, CLASS, METHOD_NAME, METHOD_SIGNATURE) \ - VAR = env->GetStaticMethodID(CLASS, METHOD_NAME, METHOD_SIGNATURE); \ - if (!VAR) { \ - __android_log_print(ANDROID_LOG_FATAL, qtTagText(), methodErrorMsgFmt(), METHOD_NAME, METHOD_SIGNATURE); \ - return false; \ - } - bool registerNatives(JNIEnv *env) { jclass appClass = QtAndroid::applicationClass(); @@ -738,10 +717,6 @@ namespace QtAndroidInput return false; } - GET_AND_CHECK_STATIC_METHOD(m_showSoftwareKeyboardMethodID, appClass, "showSoftwareKeyboard", "(IIIII)V"); - GET_AND_CHECK_STATIC_METHOD(m_resetSoftwareKeyboardMethodID, appClass, "resetSoftwareKeyboard", "()V"); - GET_AND_CHECK_STATIC_METHOD(m_hideSoftwareKeyboardMethodID, appClass, "hideSoftwareKeyboard", "()V"); - GET_AND_CHECK_STATIC_METHOD(m_updateSelectionMethodID, appClass, "updateSelection", "(IIII)V"); return true; } } diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index 235e0049049..df0a8c56cbe 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -80,7 +80,6 @@ static jmethodID m_createBitmapMethodID = Q_NULLPTR; static jobject m_ARGB_8888_BitmapConfigValue = Q_NULLPTR; static jobject m_RGB_565_BitmapConfigValue = Q_NULLPTR; -jmethodID m_setFullScreenMethodID = Q_NULLPTR; static bool m_statusBarShowing = true; static jclass m_bitmapDrawableClass = Q_NULLPTR; @@ -182,13 +181,7 @@ namespace QtAndroid if (m_statusBarShowing) return; - QtAndroid::AttachedJNIEnv env; - if (!env.jniEnv) { - qWarning("Failed to get JNI Environment."); - return; - } - - env.jniEnv->CallStaticVoidMethod(m_applicationClass, m_setFullScreenMethodID, false); + QJNIObjectPrivate::callStaticMethod(m_applicationClass, "setFullScreen", "(Z)V", false); m_statusBarShowing = true; } @@ -197,13 +190,7 @@ namespace QtAndroid if (!m_statusBarShowing) return; - QtAndroid::AttachedJNIEnv env; - if (!env.jniEnv) { - qWarning("Failed to get JNI Environment."); - return; - } - - env.jniEnv->CallStaticVoidMethod(m_applicationClass, m_setFullScreenMethodID, true); + QJNIObjectPrivate::callStaticMethod(m_applicationClass, "setFullScreen", "(Z)V", true); m_statusBarShowing = false; } @@ -453,16 +440,9 @@ static void *startMainMethod(void */*data*/) if (res < 0) qWarning() << "dlclose failed:" << dlerror(); } - m_mainLibraryHnd = Q_NULLPTR; - m_main = Q_NULLPTR; - QtAndroid::AttachedJNIEnv env; - if (!env.jniEnv) - return 0; - if (m_applicationClass) { - jmethodID quitApp = env.jniEnv->GetStaticMethodID(m_applicationClass, "quitApp", "()V"); - env.jniEnv->CallStaticVoidMethod(m_applicationClass, quitApp); - } + if (m_applicationClass) + QJNIObjectPrivate::callStaticMethod(m_applicationClass, "quitApp", "()V"); return 0; } @@ -723,7 +703,6 @@ static int registerNatives(JNIEnv *env) jclass clazz; FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/QtNative"); m_applicationClass = static_cast(env->NewGlobalRef(clazz)); - GET_AND_CHECK_STATIC_METHOD(m_setFullScreenMethodID, m_applicationClass, "setFullScreen", "(Z)V"); if (env->RegisterNatives(m_applicationClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) { __android_log_print(ANDROID_LOG_FATAL,"Qt", "RegisterNatives failed"); diff --git a/src/plugins/platforms/android/androidjnimain.h b/src/plugins/platforms/android/androidjnimain.h index 01330ce283a..8cf92748579 100644 --- a/src/plugins/platforms/android/androidjnimain.h +++ b/src/plugins/platforms/android/androidjnimain.h @@ -85,29 +85,6 @@ namespace QtAndroid jobject createBitmap(int width, int height, QImage::Format format, JNIEnv *env); jobject createBitmapDrawable(jobject bitmap, JNIEnv *env = 0); - struct AttachedJNIEnv - { - AttachedJNIEnv() - { - attached = false; - if (QtAndroid::javaVM()->GetEnv((void**)&jniEnv, JNI_VERSION_1_6) < 0) { - if (QtAndroid::javaVM()->AttachCurrentThread(&jniEnv, NULL) < 0) { - __android_log_print(ANDROID_LOG_ERROR, "Qt", "AttachCurrentThread failed"); - jniEnv = Q_NULLPTR; - return; - } - attached = true; - } - } - - ~AttachedJNIEnv() - { - if (attached) - QtAndroid::javaVM()->DetachCurrentThread(); - } - bool attached; - JNIEnv *jniEnv; - }; const char *classErrorMsgFmt(); const char *methodErrorMsgFmt(); const char *qtTagText(); diff --git a/src/plugins/platforms/android/androidjnimenu.cpp b/src/plugins/platforms/android/androidjnimenu.cpp index 1251bbf193e..36c349f6b49 100644 --- a/src/plugins/platforms/android/androidjnimenu.cpp +++ b/src/plugins/platforms/android/androidjnimenu.cpp @@ -44,6 +44,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -61,9 +62,6 @@ namespace QtAndroidMenu static QMutex menuBarMutex(QMutex::Recursive); static jmethodID openContextMenuMethodID = 0; - static jmethodID closeContextMenuMethodID = 0; - static jmethodID resetOptionsMenuMethodID = 0; - static jmethodID openOptionsMenuMethodID = 0; static jmethodID clearMenuMethodID = 0; static jmethodID addMenuItemMethodID = 0; @@ -78,16 +76,12 @@ namespace QtAndroidMenu void resetMenuBar() { - AttachedJNIEnv env; - if (env.jniEnv) - env.jniEnv->CallStaticVoidMethod(applicationClass(), resetOptionsMenuMethodID); + QJNIObjectPrivate::callStaticMethod(applicationClass(), "resetOptionsMenu"); } void openOptionsMenu() { - AttachedJNIEnv env; - if (env.jniEnv) - env.jniEnv->CallStaticVoidMethod(applicationClass(), openOptionsMenuMethodID); + QJNIObjectPrivate::callStaticMethod(applicationClass(), "openOptionsMenu"); } void showContextMenu(QAndroidPlatformMenu *menu, const QRect &anchorRect, JNIEnv *env) @@ -103,22 +97,14 @@ namespace QtAndroidMenu visibleMenu = menu; menu->aboutToShow(); - if (env) { - env->CallStaticVoidMethod(applicationClass(), openContextMenuMethodID, anchorRect.x(), anchorRect.y(), anchorRect.width(), anchorRect.height()); - } else { - AttachedJNIEnv aenv; - if (aenv.jniEnv) - aenv.jniEnv->CallStaticVoidMethod(applicationClass(), openContextMenuMethodID, anchorRect.x(), anchorRect.y(), anchorRect.width(), anchorRect.height()); - } + env->CallStaticVoidMethod(applicationClass(), openContextMenuMethodID, anchorRect.x(), anchorRect.y(), anchorRect.width(), anchorRect.height()); } void hideContextMenu(QAndroidPlatformMenu *menu) { QMutexLocker lock(&visibleMenuMutex); if (visibleMenu == menu) { - AttachedJNIEnv env; - if (env.jniEnv) - env.jniEnv->CallStaticVoidMethod(applicationClass(), closeContextMenuMethodID); + QJNIObjectPrivate::callStaticMethod(applicationClass(), "closeContextMenu"); pendingContextMenus.clear(); } else { pendingContextMenus.removeOne(menu); @@ -430,9 +416,6 @@ namespace QtAndroidMenu } GET_AND_CHECK_STATIC_METHOD(openContextMenuMethodID, appClass, "openContextMenu", "(IIII)V"); - GET_AND_CHECK_STATIC_METHOD(closeContextMenuMethodID, appClass, "closeContextMenu", "()V"); - GET_AND_CHECK_STATIC_METHOD(resetOptionsMenuMethodID, appClass, "resetOptionsMenu", "()V"); - GET_AND_CHECK_STATIC_METHOD(openOptionsMenuMethodID, appClass, "openOptionsMenu", "()V"); jclass clazz; FIND_AND_CHECK_CLASS("android/view/Menu"); diff --git a/src/plugins/platforms/android/androidjnimenu.h b/src/plugins/platforms/android/androidjnimenu.h index c54eb37f379..f85db9ff863 100644 --- a/src/plugins/platforms/android/androidjnimenu.h +++ b/src/plugins/platforms/android/androidjnimenu.h @@ -50,7 +50,7 @@ namespace QtAndroidMenu { // Menu support void openOptionsMenu(); - void showContextMenu(QAndroidPlatformMenu *menu, const QRect &anchorRect, JNIEnv *env = 0); + void showContextMenu(QAndroidPlatformMenu *menu, const QRect &anchorRect, JNIEnv *env); void hideContextMenu(QAndroidPlatformMenu *menu); void syncMenu(QAndroidPlatformMenu *menu); void androidPlatformMenuDestroyed(QAndroidPlatformMenu *menu); diff --git a/src/plugins/platforms/android/qandroidplatformclipboard.cpp b/src/plugins/platforms/android/qandroidplatformclipboard.cpp index fb73db84554..2605ec9901f 100644 --- a/src/plugins/platforms/android/qandroidplatformclipboard.cpp +++ b/src/plugins/platforms/android/qandroidplatformclipboard.cpp @@ -44,6 +44,7 @@ QAndroidPlatformClipboard::QAndroidPlatformClipboard() QMimeData *QAndroidPlatformClipboard::mimeData(QClipboard::Mode mode) { + Q_UNUSED(mode); Q_ASSERT(supportsMode(mode)); m_mimeData.setText(QtAndroidClipboard::hasClipboardText() ? QtAndroidClipboard::clipboardText() @@ -53,8 +54,8 @@ QMimeData *QAndroidPlatformClipboard::mimeData(QClipboard::Mode mode) void QAndroidPlatformClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) { - Q_ASSERT(supportsMode(mode)); - QtAndroidClipboard::setClipboardText(data != 0 && data->hasText() ? data->text() : QString()); + if (supportsMode(mode)) + QtAndroidClipboard::setClipboardText(data != 0 && data->hasText() ? data->text() : QString()); if (data != 0) data->deleteLater(); } diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp index 8a3a958d3b1..07bdf95bf49 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp @@ -78,10 +78,24 @@ void *QAndroidPlatformNativeInterface::nativeResourceForIntegration(const QByteA return QtAndroid::javaVM(); if (resource == "QtActivity") return QtAndroid::activity(); - if (resource == "AndroidStylePalettes") - return &m_palettes; - if (resource == "AndroidStyleFonts") - return &m_fonts; + if (resource == "AndroidStyleData") { + if (m_androidStyle) + return &m_androidStyle->m_styleData; + else + return Q_NULLPTR; + } + if (resource == "AndroidStandardPalette") { + if (m_androidStyle) + return &m_androidStyle->m_standardPalette; + else + return Q_NULLPTR; + } + if (resource == "AndroidQWidgetFonts") { + if (m_androidStyle) + return &m_androidStyle->m_QWidgetsFonts; + else + return Q_NULLPTR; + } if (resource == "AndroidDeviceName") { static QString deviceName = QtAndroid::deviceName(); return &deviceName; diff --git a/src/plugins/platforms/android/qandroidplatformintegration.h b/src/plugins/platforms/android/qandroidplatformintegration.h index 13c98442e92..7b4ab08847d 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.h +++ b/src/plugins/platforms/android/qandroidplatformintegration.h @@ -44,6 +44,8 @@ #include "qandroidplatformscreen.h" +#include + QT_BEGIN_NAMESPACE class QDesktopWidget; @@ -51,12 +53,12 @@ class QAndroidPlatformServices; class QAndroidSystemLocale; class QPlatformAccessibility; +struct AndroidStyle; class QAndroidPlatformNativeInterface: public QPlatformNativeInterface { public: void *nativeResourceForIntegration(const QByteArray &resource); - QHash m_palettes; - QHash m_fonts; + std::shared_ptr m_androidStyle; }; class QAndroidPlatformIntegration : public QPlatformIntegration diff --git a/src/plugins/platforms/android/qandroidplatformmenu.cpp b/src/plugins/platforms/android/qandroidplatformmenu.cpp index f3505fac3c4..8f992f6beaf 100644 --- a/src/plugins/platforms/android/qandroidplatformmenu.cpp +++ b/src/plugins/platforms/android/qandroidplatformmenu.cpp @@ -34,6 +34,7 @@ #include "qandroidplatformmenu.h" #include "qandroidplatformmenuitem.h" #include "androidjnimenu.h" +#include QT_BEGIN_NAMESPACE @@ -140,7 +141,7 @@ void QAndroidPlatformMenu::showPopup(const QWindow *parentWindow, const QRect &t Q_UNUSED(parentWindow); Q_UNUSED(item); setVisible(true); - QtAndroidMenu::showContextMenu(this, targetRect); + QtAndroidMenu::showContextMenu(this, targetRect, QJNIEnvironmentPrivate()); } QPlatformMenuItem *QAndroidPlatformMenu::menuItemAt(int position) const diff --git a/src/plugins/platforms/android/qandroidplatformtheme.cpp b/src/plugins/platforms/android/qandroidplatformtheme.cpp index 914de9d2702..b955cff44db 100644 --- a/src/plugins/platforms/android/qandroidplatformtheme.cpp +++ b/src/plugins/platforms/android/qandroidplatformtheme.cpp @@ -37,17 +37,281 @@ #include "qandroidplatformmenu.h" #include "qandroidplatformmenuitem.h" #include "qandroidplatformdialoghelpers.h" -#include -#include + #include +#include +#include +#include +#include + #include #include QT_BEGIN_NAMESPACE +namespace { + const int textStyle_bold = 1; + const int textStyle_italic = 2; + + const int typeface_sans = 1; + const int typeface_serif = 2; + const int typeface_monospace = 3; +} + +static int fontType(const QString &androidControl) +{ + if (androidControl == QLatin1String("defaultStyle")) + return QPlatformTheme::SystemFont; + if (androidControl == QLatin1String("textViewStyle")) + return QPlatformTheme::LabelFont; + else if (androidControl == QLatin1String("buttonStyle")) + return QPlatformTheme::PushButtonFont; + else if (androidControl == QLatin1String("checkboxStyle")) + return QPlatformTheme::CheckBoxFont; + else if (androidControl == QLatin1String("radioButtonStyle")) + return QPlatformTheme::RadioButtonFont; + else if (androidControl == QLatin1String("simple_list_item_single_choice")) + return QPlatformTheme::ItemViewFont; + else if (androidControl == QLatin1String("simple_spinner_dropdown_item")) + return QPlatformTheme::ComboMenuItemFont; + else if (androidControl == QLatin1String("spinnerStyle")) + return QPlatformTheme::ComboLineEditFont; + else if (androidControl == QLatin1String("simple_list_item")) + return QPlatformTheme::ListViewFont; + return -1; +} + +static int paletteType(const QString &androidControl) +{ + if (androidControl == QLatin1String("defaultStyle")) + return QPlatformTheme::SystemPalette; + if (androidControl == QLatin1String("textViewStyle")) + return QPlatformTheme::LabelPalette; + else if (androidControl == QLatin1String("buttonStyle")) + return QPlatformTheme::ButtonPalette; + else if (androidControl == QLatin1String("checkboxStyle")) + return QPlatformTheme::CheckBoxPalette; + else if (androidControl == QLatin1String("radioButtonStyle")) + return QPlatformTheme::RadioButtonPalette; + else if (androidControl == QLatin1String("simple_list_item_single_choice")) + return QPlatformTheme::ItemViewPalette; + else if (androidControl == QLatin1String("editTextStyle")) + return QPlatformTheme::TextLineEditPalette; + else if (androidControl == QLatin1String("spinnerStyle")) + return QPlatformTheme::ComboBoxPalette; + return -1; +} + +static void setPaletteColor(const QVariantMap &object, + QPalette &palette, + QPalette::ColorRole role) +{ + // QPalette::Active -> ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET + palette.setColor(QPalette::Active, + role, + QRgb(object.value(QLatin1String("ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET")).toInt())); + + // QPalette::Inactive -> ENABLED_STATE_SET + palette.setColor(QPalette::Inactive, + role, + QRgb(object.value(QLatin1String("ENABLED_STATE_SET")).toInt())); + + // QPalette::Disabled -> EMPTY_STATE_SET + palette.setColor(QPalette::Disabled, + role, + QRgb(object.value(QLatin1String("EMPTY_STATE_SET")).toInt())); + + palette.setColor(QPalette::Current, role, palette.color(QPalette::Active, role)); + + if (role == QPalette::WindowText) { + // QPalette::BrightText -> PRESSED + // QPalette::Active -> PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET + palette.setColor(QPalette::Active, + QPalette::BrightText, + QRgb(object.value(QLatin1String("PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET")).toInt())); + + // QPalette::Inactive -> PRESSED_ENABLED_STATE_SET + palette.setColor(QPalette::Inactive, + QPalette::BrightText, + QRgb(object.value(QLatin1String("PRESSED_ENABLED_STATE_SET")).toInt())); + + // QPalette::Disabled -> PRESSED_STATE_SET + palette.setColor(QPalette::Disabled, + QPalette::BrightText, + QRgb(object.value(QLatin1String("PRESSED_STATE_SET")).toInt())); + + palette.setColor(QPalette::Current, QPalette::BrightText, palette.color(QPalette::Active, QPalette::BrightText)); + + // QPalette::HighlightedText -> SELECTED + // QPalette::Active -> ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET + palette.setColor(QPalette::Active, + QPalette::HighlightedText, + QRgb(object.value(QLatin1String("ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET")).toInt())); + + // QPalette::Inactive -> ENABLED_SELECTED_STATE_SET + palette.setColor(QPalette::Inactive, + QPalette::HighlightedText, + QRgb(object.value(QLatin1String("ENABLED_SELECTED_STATE_SET")).toInt())); + + // QPalette::Disabled -> SELECTED_STATE_SET + palette.setColor(QPalette::Disabled, + QPalette::HighlightedText, + QRgb(object.value(QLatin1String("SELECTED_STATE_SET")).toInt())); + + palette.setColor(QPalette::Current, + QPalette::HighlightedText, + palette.color(QPalette::Active, QPalette::HighlightedText)); + + // Same colors for Text + palette.setColor(QPalette::Active, QPalette::Text, palette.color(QPalette::Active, role)); + palette.setColor(QPalette::Inactive, QPalette::Text, palette.color(QPalette::Inactive, role)); + palette.setColor(QPalette::Disabled, QPalette::Text, palette.color(QPalette::Disabled, role)); + palette.setColor(QPalette::Current, QPalette::Text, palette.color(QPalette::Current, role)); + + // And for ButtonText + palette.setColor(QPalette::Active, QPalette::ButtonText, palette.color(QPalette::Active, role)); + palette.setColor(QPalette::Inactive, QPalette::ButtonText, palette.color(QPalette::Inactive, role)); + palette.setColor(QPalette::Disabled, QPalette::ButtonText, palette.color(QPalette::Disabled, role)); + palette.setColor(QPalette::Current, QPalette::ButtonText, palette.color(QPalette::Current, role)); + } +} + +static std::shared_ptr loadAndroidStyle(QPalette *defaultPalette) +{ + QString stylePath(QLatin1String(qgetenv("MINISTRO_ANDROID_STYLE_PATH"))); + const QLatin1Char slashChar('/'); + if (!stylePath.isEmpty() && !stylePath.endsWith(slashChar)) + stylePath += slashChar; + + QString androidTheme = QLatin1String(qgetenv("QT_ANDROID_THEME")); + if (!androidTheme.isEmpty() && !androidTheme.endsWith(slashChar)) + androidTheme += slashChar; + + if (stylePath.isEmpty()) { + stylePath = QLatin1String("/data/data/org.kde.necessitas.ministro/files/dl/style/") + + QLatin1String(qgetenv("QT_ANDROID_THEME_DISPLAY_DPI")) + slashChar; + } + Q_ASSERT(!stylePath.isEmpty()); + + if (!androidTheme.isEmpty() && QFileInfo(stylePath + androidTheme + QLatin1String("style.json")).exists()) + stylePath += androidTheme; + + QFile f(stylePath + QLatin1String("style.json")); + if (!f.open(QIODevice::ReadOnly)) + return std::shared_ptr(); + + QJsonParseError error; + QJsonDocument document = QJsonDocument::fromJson(f.readAll(), &error); + if (document.isNull()) { + qCritical() << error.errorString(); + return std::shared_ptr(); + } + + if (!document.isObject()) { + qCritical() << "Style.json does not contain a valid style."; + return std::shared_ptr(); + } + std::shared_ptr style(new AndroidStyle); + style->m_styleData = document.object(); + for (QJsonObject::const_iterator objectIterator = style->m_styleData.constBegin(); + objectIterator != style->m_styleData.constEnd(); + ++objectIterator) { + QString key = objectIterator.key(); + QJsonValue value = objectIterator.value(); + if (!value.isObject()) { + qWarning("Style.json structure is unrecognized."); + continue; + } + QJsonObject item = value.toObject(); + QJsonObject::const_iterator attributeIterator = item.find(QLatin1String("qtClass")); + QByteArray qtClassName; + if (attributeIterator != item.constEnd()) { + // The item has palette and font information for a specific Qt Class (e.g. QWidget, QPushButton, etc.) + qtClassName = attributeIterator.value().toString().toLatin1(); + } + const int ft = fontType(key); + if (ft > -1 || !qtClassName.isEmpty()) { + // Extract font information + QFont font; + + // Font size (in pixels) + attributeIterator = item.find(QLatin1String("TextAppearance_textSize")); + if (attributeIterator != item.constEnd()) + font.setPixelSize(int(attributeIterator.value().toDouble())); + + // Font style + attributeIterator = item.find(QLatin1String("TextAppearance_textStyle")); + if (attributeIterator != item.constEnd()) { + const int style = int(attributeIterator.value().toDouble()); + font.setBold(style & textStyle_bold); + font.setItalic(style & textStyle_italic); + } + + // Font typeface + attributeIterator = item.find(QLatin1String("TextAppearance_typeface")); + if (attributeIterator != item.constEnd()) { + QFont::StyleHint styleHint = QFont::AnyStyle; + switch (int(attributeIterator.value().toDouble())) { + case typeface_sans: + styleHint = QFont::SansSerif; + break; + case typeface_serif: + styleHint = QFont::Serif; + break; + case typeface_monospace: + styleHint = QFont::Monospace; + break; + } + font.setStyleHint(styleHint, QFont::PreferMatch); + } + if (!qtClassName.isEmpty()) + style->m_QWidgetsFonts.insert(qtClassName, font); + + if (ft > -1) { + style->m_fonts.insert(ft, font); + if (ft == QPlatformTheme::SystemFont) + QGuiApplication::setFont(font); + } + // Extract font information + } + + const int pt = paletteType(key); + if (pt > -1 || !qtClassName.isEmpty()) { + // Extract palette information + QPalette palette; + attributeIterator = item.find(QLatin1String("defaultTextColorPrimary")); + if (attributeIterator != item.constEnd()) + palette.setColor(QPalette::WindowText, QRgb(int(attributeIterator.value().toDouble()))); + + attributeIterator = item.find(QLatin1String("defaultBackgroundColor")); + if (attributeIterator != item.constEnd()) + palette.setColor(QPalette::Background, QRgb(int(attributeIterator.value().toDouble()))); + + attributeIterator = item.find(QLatin1String("TextAppearance_textColor")); + if (attributeIterator != item.constEnd()) + setPaletteColor(attributeIterator.value().toObject().toVariantMap(), palette, QPalette::WindowText); + + attributeIterator = item.find(QLatin1String("TextAppearance_textColorLink")); + if (attributeIterator != item.constEnd()) + setPaletteColor(attributeIterator.value().toObject().toVariantMap(), palette, QPalette::Link); + + attributeIterator = item.find(QLatin1String("TextAppearance_textColorHighlight")); + if (attributeIterator != item.constEnd()) + palette.setColor(QPalette::Highlight, QRgb(int(attributeIterator.value().toDouble()))); + + if (pt == QPlatformTheme::SystemPalette) + *defaultPalette = style->m_standardPalette = palette; + + if (pt > -1) + style->m_palettes.insert(pt, palette); + // Extract palette information + } + } + return style; +} + QAndroidPlatformTheme::QAndroidPlatformTheme(QAndroidPlatformNativeInterface *androidPlatformNativeInterface) { - m_androidPlatformNativeInterface = androidPlatformNativeInterface; QColor background(229, 229, 229); QColor light = background.lighter(150); QColor mid(background.darker(130)); @@ -80,6 +344,9 @@ QAndroidPlatformTheme::QAndroidPlatformTheme(QAndroidPlatformNativeInterface *an m_defaultPalette.setBrush(QPalette::Active, QPalette::Highlight, highlight); m_defaultPalette.setBrush(QPalette::Inactive, QPalette::Highlight, highlight); m_defaultPalette.setBrush(QPalette::Disabled, QPalette::Highlight, highlight.lighter(150)); + m_androidStyleData = loadAndroidStyle(&m_defaultPalette); + QGuiApplication::setPalette(m_defaultPalette); + androidPlatformNativeInterface->m_androidStyle = m_androidStyleData; } QPlatformMenuBar *QAndroidPlatformTheme::createPlatformMenuBar() const @@ -132,9 +399,11 @@ static inline int paletteType(QPlatformTheme::Palette type) const QPalette *QAndroidPlatformTheme::palette(Palette type) const { - QHash::const_iterator it = m_androidPlatformNativeInterface->m_palettes.find(paletteType(type)); - if (it != m_androidPlatformNativeInterface->m_palettes.end()) - return &(it.value()); + if (m_androidStyleData) { + auto it = m_androidStyleData->m_palettes.find(paletteType(type)); + if (it != m_androidStyleData->m_palettes.end()) + return &(it.value()); + } return &m_defaultPalette; } @@ -154,9 +423,11 @@ static inline int fontType(QPlatformTheme::Font type) const QFont *QAndroidPlatformTheme::font(Font type) const { - QHash::const_iterator it = m_androidPlatformNativeInterface->m_fonts.find(fontType(type)); - if (it != m_androidPlatformNativeInterface->m_fonts.end()) - return &(it.value()); + if (m_androidStyleData) { + auto it = m_androidStyleData->m_fonts.find(fontType(type)); + if (it != m_androidStyleData->m_fonts.end()) + return &(it.value()); + } // default in case the style has not set a font static QFont systemFont("Roboto", 14.0 * 100 / 72); // keep default size the same after changing from 100 dpi to 72 dpi @@ -165,18 +436,12 @@ const QFont *QAndroidPlatformTheme::font(Font type) const return 0; } -static const QLatin1String STYLES_PATH("/data/data/org.kde.necessitas.ministro/files/dl/style/"); -static const QLatin1String STYLE_FILE("/style.json"); - QVariant QAndroidPlatformTheme::themeHint(ThemeHint hint) const { switch (hint) { case StyleNames: if (qEnvironmentVariableIntValue("QT_USE_ANDROID_NATIVE_STYLE") - && (!qgetenv("MINISTRO_ANDROID_STYLE_PATH").isEmpty() - || QFileInfo(STYLES_PATH - + QLatin1String(qgetenv("QT_ANDROID_THEME_DISPLAY_DPI")) - + STYLE_FILE).exists())) { + && m_androidStyleData) { return QStringList("android"); } return QStringList("fusion"); diff --git a/src/plugins/platforms/android/qandroidplatformtheme.h b/src/plugins/platforms/android/qandroidplatformtheme.h index 01611bf9d41..334e86ad7a5 100644 --- a/src/plugins/platforms/android/qandroidplatformtheme.h +++ b/src/plugins/platforms/android/qandroidplatformtheme.h @@ -37,8 +37,22 @@ #include #include +#include + +#include + QT_BEGIN_NAMESPACE +struct AndroidStyle +{ + QJsonObject m_styleData; + QPalette m_standardPalette; + QHash m_palettes; + QHash m_fonts; + QHash m_QWidgetsFonts; + QHash m_QWidgetsPalettes; +}; + class QAndroidPlatformNativeInterface; class QAndroidPlatformTheme: public QPlatformTheme { @@ -57,7 +71,7 @@ public: private: - QAndroidPlatformNativeInterface * m_androidPlatformNativeInterface; + std::shared_ptr m_androidStyleData; QPalette m_defaultPalette; }; diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h index bfff5c3266f..917f020132d 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.h +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h @@ -51,12 +51,9 @@ public: QPaintDevice *paintDevice(); void flush(QWindow *widget, const QRegion ®ion, const QPoint &offset); -#ifndef QT_NO_OPENGL - QImage toImage() const Q_DECL_OVERRIDE; -#endif + QImage toImage() const; void resize (const QSize &size, const QRegion &); bool scroll(const QRegion &area, int dx, int dy); - CGImageRef getBackingStoreCGImage(); qreal getBackingStoreDevicePixelRatio(); private: diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index e13e295511e..ba1198c19cd 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -96,12 +96,10 @@ void QCocoaBackingStore::flush(QWindow *win, const QRegion ®ion, const QPoint } } -#ifndef QT_NO_OPENGL QImage QCocoaBackingStore::toImage() const { return m_qImage; } -#endif void QCocoaBackingStore::resize(const QSize &size, const QRegion &) { @@ -121,17 +119,6 @@ bool QCocoaBackingStore::scroll(const QRegion &area, int dx, int dy) return true; } -CGImageRef QCocoaBackingStore::getBackingStoreCGImage() -{ - if (!m_cgImage) - 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 - // needs special memory considerations. - return m_cgImage; -} - qreal QCocoaBackingStore::getBackingStoreDevicePixelRatio() { return m_qImage.devicePixelRatio(); diff --git a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm index 8158c244aba..7d99f566bfa 100644 --- a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -106,10 +106,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate); mResultSet = false; mClosingDueToKnownButton = false; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) - [mColorPanel setRestorable:NO]; -#endif + [mColorPanel setRestorable:NO]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(colorChanged:) diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm index c37bb63916d..f5e22d1125b 100644 --- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm @@ -149,11 +149,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate); mDialogIsExecuting = false; mResultSet = false; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) - [mFontPanel setRestorable:NO]; -#endif - + [mFontPanel setRestorable:NO]; [mFontPanel setDelegate:self]; [[NSFontManager sharedFontManager] setDelegate:self]; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index e0838cb3424..72bd09625a4 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -144,15 +144,8 @@ void QCocoaScreen::updateGeometry() qreal QCocoaScreen::devicePixelRatio() const { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) { - NSScreen * screen = osScreen(); - return qreal(screen ? [screen backingScaleFactor] : 1.0); - } else -#endif - { - return 1.0; - } + NSScreen * screen = osScreen(); + return qreal(screen ? [screen backingScaleFactor] : 1.0); } QWindow *QCocoaScreen::topLevelAt(const QPoint &point) const diff --git a/src/plugins/platforms/cocoa/qcocoaintrospection.mm b/src/plugins/platforms/cocoa/qcocoaintrospection.mm index 806effc9299..84b16813dc6 100644 --- a/src/plugins/platforms/cocoa/qcocoaintrospection.mm +++ b/src/plugins/platforms/cocoa/qcocoaintrospection.mm @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -79,43 +79,33 @@ QT_BEGIN_NAMESPACE void qt_cocoa_change_implementation(Class baseClass, SEL originalSel, Class proxyClass, SEL replacementSel, SEL backupSel) { -#ifndef QT_MAC_USE_COCOA - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) -#endif - { - // The following code replaces the _implementation_ for the selector we want to hack - // (originalSel) with the implementation found in proxyClass. Then it creates - // a new 'backup' method inside baseClass containing the old, original, - // implementation (fakeSel). You can let the proxy implementation of originalSel - // call fakeSel if needed (similar approach to calling a super class implementation). - // fakeSel must also be implemented in proxyClass, as the signature is used - // as template for the method one we add into baseClass. - // NB: You will typically never create any instances of proxyClass; we use it - // only for stealing its contents and put it into baseClass. - if (!replacementSel) - replacementSel = originalSel; + // The following code replaces the _implementation_ for the selector we want to hack + // (originalSel) with the implementation found in proxyClass. Then it creates + // a new 'backup' method inside baseClass containing the old, original, + // implementation (fakeSel). You can let the proxy implementation of originalSel + // call fakeSel if needed (similar approach to calling a super class implementation). + // fakeSel must also be implemented in proxyClass, as the signature is used + // as template for the method one we add into baseClass. + // NB: You will typically never create any instances of proxyClass; we use it + // only for stealing its contents and put it into baseClass. + if (!replacementSel) + replacementSel = originalSel; - Method originalMethod = class_getInstanceMethod(baseClass, originalSel); - Method replacementMethod = class_getInstanceMethod(proxyClass, replacementSel); - IMP originalImp = method_setImplementation(originalMethod, method_getImplementation(replacementMethod)); + Method originalMethod = class_getInstanceMethod(baseClass, originalSel); + Method replacementMethod = class_getInstanceMethod(proxyClass, replacementSel); + IMP originalImp = method_setImplementation(originalMethod, method_getImplementation(replacementMethod)); - if (backupSel) { - Method backupMethod = class_getInstanceMethod(proxyClass, backupSel); - class_addMethod(baseClass, backupSel, originalImp, method_getTypeEncoding(backupMethod)); - } + if (backupSel) { + Method backupMethod = class_getInstanceMethod(proxyClass, backupSel); + class_addMethod(baseClass, backupSel, originalImp, method_getTypeEncoding(backupMethod)); } } void qt_cocoa_change_back_implementation(Class baseClass, SEL originalSel, SEL backupSel) { -#ifndef QT_MAC_USE_COCOA - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) -#endif - { - Method originalMethod = class_getInstanceMethod(baseClass, originalSel); - Method backupMethodInBaseClass = class_getInstanceMethod(baseClass, backupSel); - method_setImplementation(originalMethod, method_getImplementation(backupMethodInBaseClass)); - } + Method originalMethod = class_getInstanceMethod(baseClass, originalSel); + Method backupMethodInBaseClass = class_getInstanceMethod(baseClass, backupSel); + method_setImplementation(originalMethod, method_getImplementation(backupMethodInBaseClass)); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm index 791b0805d0a..251fe9485c8 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm @@ -323,17 +323,22 @@ NSMenuItem *QCocoaMenuItem::sync() text += QLatin1String(" (") + accel.toString(QKeySequence::NativeText) + QLatin1String(")"); QString finalString = qt_mac_removeMnemonics(text); + bool useAttributedTitle = false; // Cocoa Font and title if (m_font.resolve()) { NSFont *customMenuFont = [NSFont fontWithName:QCFString::toNSString(m_font.family()) size:m_font.pointSize()]; - NSArray *keys = [NSArray arrayWithObjects:NSFontAttributeName, nil]; - NSArray *objects = [NSArray arrayWithObjects:customMenuFont, nil]; - NSDictionary *attributes = [NSDictionary dictionaryWithObjects:objects forKeys:keys]; - NSAttributedString *str = [[[NSAttributedString alloc] initWithString:QCFString::toNSString(finalString) - attributes:attributes] autorelease]; - [m_native setAttributedTitle: str]; - } else { + if (customMenuFont) { + NSArray *keys = [NSArray arrayWithObjects:NSFontAttributeName, nil]; + NSArray *objects = [NSArray arrayWithObjects:customMenuFont, nil]; + NSDictionary *attributes = [NSDictionary dictionaryWithObjects:objects forKeys:keys]; + NSAttributedString *str = [[[NSAttributedString alloc] initWithString:QCFString::toNSString(finalString) + attributes:attributes] autorelease]; + [m_native setAttributedTitle: str]; + useAttributedTitle = true; + } + } + if (!useAttributedTitle) { [m_native setTitle: QCFString::toNSString(finalString)]; } diff --git a/src/plugins/platforms/cocoa/qcocoamimetypes.mm b/src/plugins/platforms/cocoa/qcocoamimetypes.mm index 421d934fa78..b657ef9a82e 100644 --- a/src/plugins/platforms/cocoa/qcocoamimetypes.mm +++ b/src/plugins/platforms/cocoa/qcocoamimetypes.mm @@ -88,9 +88,9 @@ QVariant QMacPasteboardMimeTraditionalMacPlainText::convertToMime(const QString const QByteArray &firstData = data.first(); QVariant ret; if (flavor == QLatin1String("com.apple.traditional-mac-plain-text")) { - return QString::fromCFString(CFStringCreateWithBytes(kCFAllocatorDefault, + return QString(QCFString(CFStringCreateWithBytes(kCFAllocatorDefault, reinterpret_cast(firstData.constData()), - firstData.size(), CFStringGetSystemEncoding(), false)); + firstData.size(), CFStringGetSystemEncoding(), false))); } else { qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype)); } diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm index 2101b687695..c26a2b22fdc 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm +++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm @@ -466,17 +466,13 @@ bool QCocoaPrintDevice::openPpdFile() ppdClose(m_ppd); m_ppd = 0; CFURLRef ppdURL = NULL; -#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 - char ppdPath[PATH_MAX]; -#else char ppdPath[MAXPATHLEN]; -#endif if (PMPrinterCopyDescriptionURL(m_printer, kPMPPDDescriptionType, &ppdURL) == noErr - && ppdURL != NULL - && CFURLGetFileSystemRepresentation(ppdURL, true, (UInt8*)ppdPath, sizeof(ppdPath))) { - m_ppd = ppdOpenFile(ppdPath); + && ppdURL != NULL) { + if (CFURLGetFileSystemRepresentation(ppdURL, true, (UInt8*)ppdPath, sizeof(ppdPath))) + m_ppd = ppdOpenFile(ppdPath); + CFRelease(ppdURL); } - CFRelease(ppdURL); return m_ppd ? true : false; } diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index a43cf73d348..b232c7a4d34 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -268,6 +268,7 @@ public: // for QNSView bool m_inConstructor; bool m_inSetVisible; + bool m_inSetGeometry; #ifndef QT_NO_OPENGL QCocoaGLContext *m_glContext; #endif diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 3366e5bc3cc..6656212457c 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -107,26 +107,6 @@ static void selectNextKeyWindow(NSWindow *currentKeyWindow) } } - -@interface NSWindow (CocoaWindowCategory) -- (NSRect) legacyConvertRectFromScreen:(NSRect) rect; -@end - -@implementation NSWindow (CocoaWindowCategory) -- (NSRect) legacyConvertRectFromScreen:(NSRect) rect -{ -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) { - return [self convertRectFromScreen: rect]; - } -#endif - NSRect r = rect; - r.origin = [self convertScreenToBase:rect.origin]; - return r; -} -@end - - @implementation QNSWindowHelper @synthesize window = _window; @@ -197,7 +177,7 @@ static void selectNextKeyWindow(NSWindow *currentKeyWindow) if (pw && pw->frameStrutEventsEnabled() && isMouseEvent(theEvent)) { NSPoint loc = [theEvent locationInWindow]; - NSRect windowFrame = [self.window legacyConvertRectFromScreen:[self.window frame]]; + NSRect windowFrame = [self.window convertRectFromScreen:[self.window frame]]; NSRect contentFrame = [[self.window contentView] frame]; if (NSMouseInRect(loc, windowFrame, NO) && !NSMouseInRect(loc, contentFrame, NO)) @@ -401,6 +381,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw) , m_windowUnderMouse(false) , m_inConstructor(true) , m_inSetVisible(false) + , m_inSetGeometry(false) #ifndef QT_NO_OPENGL , m_glContext(0) #endif @@ -432,19 +413,16 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw) } else { m_qtView = [[QNSView alloc] initWithQWindow:tlw platformWindow:this]; m_contentView = m_qtView; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 // Enable high-dpi OpenGL for retina displays. Enabling has the side // effect that Cocoa will start calling glViewport(0, 0, width, height), // overriding any glViewport calls in application code. This is usually not a // problem, except if the appilcation wants to have a "custom" viewport. // (like the hellogl example) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7 - && tlw->supportsOpenGL()) { + if (tlw->supportsOpenGL()) { BOOL enable = qt_mac_resolveOption(YES, tlw, "_q_mac_wantsBestResolutionOpenGLSurface", "QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE"); [m_contentView setWantsBestResolutionOpenGLSurface:enable]; } -#endif BOOL enable = qt_mac_resolveOption(NO, tlw, "_q_mac_wantsLayer", "QT_MAC_WANTS_LAYER"); [m_contentView setWantsLayer:enable]; @@ -493,6 +471,8 @@ QSurfaceFormat QCocoaWindow::format() const void QCocoaWindow::setGeometry(const QRect &rectIn) { + QBoolBlocker inSetGeometry(m_inSetGeometry, true); + QRect rect = rectIn; // This means it is a call from QWindow::setFramePosition() and // the coordinates include the frame (size is still the contents rectangle). @@ -516,7 +496,8 @@ QRect QCocoaWindow::geometry() const // of view. Embedded QWindows get global (screen) geometry. if (m_contentViewIsEmbedded) { NSPoint windowPoint = [m_contentView convertPoint:NSMakePoint(0, 0) toView:nil]; - NSPoint screenPoint = [[m_contentView window] convertBaseToScreen:windowPoint]; // ### use convertRectToScreen after 10.6 removal + NSRect screenRect = [[m_contentView window] convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)]; + NSPoint screenPoint = screenRect.origin; QPoint position = qt_mac_flipPoint(screenPoint).toPoint(); QSize size = qt_mac_toQRect([m_contentView bounds]).size(); return QRect(position, size); @@ -681,11 +662,7 @@ void QCocoaWindow::setVisible(bool visible) // Since this isn't a native popup, the window manager doesn't close the popup when you click outside NSUInteger parentStyleMask = [parentCocoaWindow->m_nsWindow styleMask]; if ((m_resizableTransientParent = (parentStyleMask & NSResizableWindowMask)) -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - && QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7 - && !([parentCocoaWindow->m_nsWindow styleMask] & NSFullScreenWindowMask) -#endif - ) + && !([parentCocoaWindow->m_nsWindow styleMask] & NSFullScreenWindowMask)) [parentCocoaWindow->m_nsWindow setStyleMask:parentStyleMask & ~NSResizableWindowMask]; } @@ -784,11 +761,7 @@ void QCocoaWindow::setVisible(bool visible) if (parentCocoaWindow && window()->type() == Qt::Popup) { parentCocoaWindow->m_activePopupWindow = 0; if (m_resizableTransientParent -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - && QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7 - && !([parentCocoaWindow->m_nsWindow styleMask] & NSFullScreenWindowMask) -#endif - ) + && !([parentCocoaWindow->m_nsWindow styleMask] & NSFullScreenWindowMask)) // QTBUG-30266: a window should not be resizable while a transient popup is open [parentCocoaWindow->m_nsWindow setStyleMask:[parentCocoaWindow->m_nsWindow styleMask] | NSResizableWindowMask]; } @@ -903,19 +876,15 @@ void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags) setWindowTitle(window()->title()); } -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) { - Qt::WindowType type = window()->type(); - if ((type & Qt::Popup) != Qt::Popup && (type & Qt::Dialog) != Qt::Dialog) { - NSWindowCollectionBehavior behavior = [m_nsWindow collectionBehavior]; - if (flags & Qt::WindowFullscreenButtonHint) - behavior |= NSWindowCollectionBehaviorFullScreenPrimary; - else - behavior &= ~NSWindowCollectionBehaviorFullScreenPrimary; - [m_nsWindow setCollectionBehavior:behavior]; - } + Qt::WindowType type = window()->type(); + if ((type & Qt::Popup) != Qt::Popup && (type & Qt::Dialog) != Qt::Dialog) { + NSWindowCollectionBehavior behavior = [m_nsWindow collectionBehavior]; + if (flags & Qt::WindowFullscreenButtonHint) + behavior |= NSWindowCollectionBehaviorFullScreenPrimary; + else + behavior &= ~NSWindowCollectionBehaviorFullScreenPrimary; + [m_nsWindow setCollectionBehavior:behavior]; } -#endif setWindowZoomButton(flags); } @@ -1340,13 +1309,9 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow) m_nsWindow.hasShadow = NO; m_nsWindow.level = NSNormalWindowLevel; NSWindowCollectionBehavior collectionBehavior = - NSWindowCollectionBehaviorManaged | NSWindowCollectionBehaviorIgnoresCycle; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) { - collectionBehavior |= NSWindowCollectionBehaviorFullScreenAuxiliary; - m_nsWindow.animationBehavior = NSWindowAnimationBehaviorNone; - } -#endif + NSWindowCollectionBehaviorManaged | NSWindowCollectionBehaviorIgnoresCycle + | NSWindowCollectionBehaviorFullScreenAuxiliary; + m_nsWindow.animationBehavior = NSWindowAnimationBehaviorNone; m_nsWindow.collectionBehavior = collectionBehavior; setCocoaGeometry(window()->geometry()); @@ -1438,17 +1403,17 @@ QCocoaNSWindow * QCocoaWindow::createNSWindow() if ((type & Qt::Popup) == Qt::Popup) [window setHasShadow:YES]; - [window setHidesOnDeactivate:(type & Qt::Tool) == Qt::Tool]; + // Qt::Tool windows hide on app deactivation, unless Qt::WA_MacAlwaysShowToolWindow is set. + QVariant showWithoutActivating = QPlatformWindow::window()->property("_q_macAlwaysShowToolWindow"); + bool shouldHideOnDeactivate = ((type & Qt::Tool) == Qt::Tool) && + !(showWithoutActivating.isValid() && showWithoutActivating.toBool()); + [window setHidesOnDeactivate: shouldHideOnDeactivate]; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) { - // Make popup winows show on the same desktop as the parent full-screen window. - [window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary]; + // Make popup windows show on the same desktop as the parent full-screen window. + [window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary]; + if ((type & Qt::Popup) == Qt::Popup) + [window setAnimationBehavior:NSWindowAnimationBehaviorUtilityWindow]; - if ((type & Qt::Popup) == Qt::Popup) - [window setAnimationBehavior:NSWindowAnimationBehaviorUtilityWindow]; - } -#endif createdWindow = window; } else { QNSWindow *window; @@ -1458,10 +1423,8 @@ QCocoaNSWindow * QCocoaWindow::createNSWindow() createdWindow = window; } -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 if ([createdWindow respondsToSelector:@selector(setRestorable:)]) [createdWindow setRestorable: NO]; -#endif NSInteger level = windowLevel(flags); [createdWindow setLevel:level]; @@ -1562,18 +1525,11 @@ void QCocoaWindow::syncWindowState(Qt::WindowState newState) } if ((m_synchedWindowState & Qt::WindowFullScreen) != (newState & Qt::WindowFullScreen)) { - bool fakeFullScreen = true; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) { - if (window()->flags() & Qt::WindowFullscreenButtonHint) { - fakeFullScreen = false; - if (m_effectivelyMaximized && m_synchedWindowState == Qt::WindowFullScreen) - predictedState = Qt::WindowMaximized; - [m_nsWindow toggleFullScreen : m_nsWindow]; - } - } -#endif - if (fakeFullScreen) { + if (window()->flags() & Qt::WindowFullscreenButtonHint) { + if (m_effectivelyMaximized && m_synchedWindowState == Qt::WindowFullScreen) + predictedState = Qt::WindowMaximized; + [m_nsWindow toggleFullScreen : m_nsWindow]; + } else { if (newState & Qt::WindowFullScreen) { QScreen *screen = window()->screen(); if (screen) { @@ -1747,20 +1703,13 @@ bool QCocoaWindow::testContentBorderAreaPosition(int position) const qreal QCocoaWindow::devicePixelRatio() const { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) { - // The documented way to observe the relationship between device-independent - // and device pixels is to use one for the convertToBacking functions. Other - // methods such as [NSWindow backingScaleFacor] might not give the correct - // result, for example if setWantsBestResolutionOpenGLSurface is not set or - // or ignored by the OpenGL driver. - NSSize backingSize = [m_contentView convertSizeToBacking:NSMakeSize(1.0, 1.0)]; - return backingSize.height; - } else -#endif - { - return 1.0; - } + // The documented way to observe the relationship between device-independent + // and device pixels is to use one for the convertToBacking functions. Other + // methods such as [NSWindow backingScaleFacor] might not give the correct + // result, for example if setWantsBestResolutionOpenGLSurface is not set or + // or ignored by the OpenGL driver. + NSSize backingSize = [m_contentView convertSizeToBacking:NSMakeSize(1.0, 1.0)]; + return backingSize.height; } // Returns whether the window can be expose, which it can @@ -1808,10 +1757,15 @@ void QCocoaWindow::updateExposedGeometry() if (!m_geometryUpdateExposeAllowed) return; + // Do not send incorrect exposes in case the window is not even visible yet. + // We might get here as a result of a resize() from QWidget's show(), for instance. + if (!window()->isVisible()) + return; + if (!isWindowExposable()) return; - if (m_exposedGeometry == geometry() && m_exposedDevicePixelRatio == devicePixelRatio()) + if (m_exposedGeometry.size() == geometry().size() && m_exposedDevicePixelRatio == devicePixelRatio()) return; m_isExposed = true; diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index 8b23f84a25d..8d8df13dc38 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -51,7 +51,8 @@ QT_END_NAMESPACE Q_FORWARD_DECLARE_OBJC_CLASS(QNSViewMouseMoveHelper); @interface QT_MANGLE_NAMESPACE(QNSView) : NSView { - QCocoaBackingStore* m_backingStore; + QImage m_backingStore; + qreal m_pixelRatio; QPoint m_backingStoreOffset; CGImageRef m_maskImage; uchar *m_maskData; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 1f58a0457fc..0ce5b3b3327 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -143,7 +143,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; { self = [super initWithFrame : NSMakeRect(0,0, 300,300)]; if (self) { - m_backingStore = 0; + m_pixelRatio = 1.; m_maskImage = 0; m_shouldInvalidateWindowShadow = false; m_window = 0; @@ -361,12 +361,11 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; // Send a geometry change event to Qt, if it's ready to handle events if (!m_platformWindow->m_inConstructor) { QWindowSystemInterface::handleGeometryChange(m_window, geometry); - // Do not send incorrect exposes in case the window is not even visible yet. - // We might get here as a result of a resize() from QWidget's show(), for instance. - if (m_platformWindow->window()->isVisible()) { - m_platformWindow->updateExposedGeometry(); + m_platformWindow->updateExposedGeometry(); + // Guard against processing window system events during QWindow::setGeometry + // calles, which Qt and Qt applications do not excpect. + if (!m_platformWindow->m_inSetGeometry) QWindowSystemInterface::flushWindowSystemEvents(); - } } } @@ -408,10 +407,6 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; Qt::WindowState newState = notificationName == NSWindowDidMiniaturizeNotification ? Qt::WindowMinimized : Qt::WindowNoState; [self notifyWindowStateChanged:newState]; - // NSWindowDidOrderOnScreenAndFinishAnimatingNotification is private API, and not - // emitted in 10.6, so we bring back the old behavior for that case alone. - if (newState == Qt::WindowNoState && QSysInfo::QSysInfo::MacintoshVersion == QSysInfo::MV_10_6) - m_platformWindow->exposeWindow(); } else if ([notificationName isEqualToString: @"NSWindowDidOrderOffScreenNotification"]) { m_platformWindow->obscureWindow(); } else if ([notificationName isEqualToString: @"NSWindowDidOrderOnScreenAndFinishAnimatingNotification"]) { @@ -424,12 +419,17 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; #pragma clang diagnostic ignored "-Wobjc-method-access" enum { NSWindowOcclusionStateVisible = 1UL << 1 }; #endif - // Older versions managed in -[QNSView viewDidMoveToWindow]. - // Support QWidgetAction in NSMenu. Mavericks only sends this notification. - // Ideally we should support this in Qt as well, in order to disable animations - // when the window is occluded. - if ((NSUInteger)[self.window occlusionState] & NSWindowOcclusionStateVisible) + if ((NSUInteger)[self.window occlusionState] & NSWindowOcclusionStateVisible) { m_platformWindow->exposeWindow(); + } else { + // Send Obscure events on window occlusion to stop animations. Several + // unit tests expect paint and/or expose events for windows that are + // sometimes (unpredictably) occlouded: Don't send Obscure events when + // running under QTestLib. + static bool onTestLib = qt_mac_resolveOption(false, "QT_QTESTLIB_RUNNING"); + if (!onTestLib) + m_platformWindow->obscureWindow(); + } #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9 #pragma clang diagnostic pop #endif @@ -437,24 +437,16 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; if (m_window) { NSUInteger screenIndex = [[NSScreen screens] indexOfObject:self.window.screen]; if (screenIndex != NSNotFound) { - m_platformWindow->updateExposedGeometry(); QCocoaScreen *cocoaScreen = QCocoaIntegration::instance()->screenAtIndex(screenIndex); QWindowSystemInterface::handleWindowScreenChanged(m_window, cocoaScreen->screen()); + m_platformWindow->updateExposedGeometry(); } } - } else { - -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) { - if (notificationName == NSWindowDidEnterFullScreenNotification - || notificationName == NSWindowDidExitFullScreenNotification) { - Qt::WindowState newState = notificationName == NSWindowDidEnterFullScreenNotification ? - Qt::WindowFullScreen : Qt::WindowNoState; - [self notifyWindowStateChanged:newState]; - } - } -#endif - + } else if (notificationName == NSWindowDidEnterFullScreenNotification + || notificationName == NSWindowDidExitFullScreenNotification) { + Qt::WindowState newState = notificationName == NSWindowDidEnterFullScreenNotification ? + Qt::WindowFullScreen : Qt::WindowNoState; + [self notifyWindowStateChanged:newState]; } } @@ -478,8 +470,9 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; - (void) flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset { - m_backingStore = backingStore; - m_backingStoreOffset = offset * m_backingStore->getBackingStoreDevicePixelRatio(); + m_backingStore = backingStore->toImage(); + m_pixelRatio = backingStore->getBackingStoreDevicePixelRatio(); + m_backingStoreOffset = offset * m_pixelRatio; foreach (QRect rect, region.rects()) { [self setNeedsDisplayInRect:NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())]; } @@ -543,7 +536,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; if (m_platformWindow->m_drawContentBorderGradient) NSDrawWindowBackground(dirtyRect); - if (!m_backingStore) + if (m_backingStore.isNull()) return; // Calculate source and target rects. The target rect is the dirtyRect: @@ -551,11 +544,10 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; // The backing store source rect will be larger on retina displays. // Scale dirtyRect by the device pixel ratio: - const qreal devicePixelRatio = m_backingStore->getBackingStoreDevicePixelRatio(); - CGRect dirtyBackingRect = CGRectMake(dirtyRect.origin.x * devicePixelRatio, - dirtyRect.origin.y * devicePixelRatio, - dirtyRect.size.width * devicePixelRatio, - dirtyRect.size.height * devicePixelRatio); + CGRect dirtyBackingRect = CGRectMake(dirtyRect.origin.x * m_pixelRatio, + dirtyRect.origin.y * m_pixelRatio, + dirtyRect.size.width * m_pixelRatio, + dirtyRect.size.height * m_pixelRatio); NSGraphicsContext *nsGraphicsContext = [NSGraphicsContext currentContext]; CGContextRef cgContext = (CGContextRef) [nsGraphicsContext graphicsPort]; @@ -581,7 +573,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; dirtyBackingRect.size.width, dirtyBackingRect.size.height ); - CGImageRef bsCGImage = m_backingStore->getBackingStoreCGImage(); + CGImageRef bsCGImage = qt_mac_toCGImage(m_backingStore); CGImageRef cleanImg = CGImageCreateWithImageInRect(bsCGImage, backingStoreRect); // Optimization: Copy frame buffer content instead of blending for @@ -596,10 +588,9 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; CGContextRestoreGState(cgContext); CGImageRelease(cleanImg); CGImageRelease(subMask); + CGImageRelease(bsCGImage); [self invalidateWindowShadowIfNeeded]; - - m_backingStore = 0; } - (BOOL) isFlipped @@ -611,7 +602,8 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; { if (m_window->flags() & Qt::WindowTransparentForInput) return NO; - QWindowSystemInterface::handleWindowActivated([self topLevelWindow]); + if (!m_platformWindow->windowIsPopupType()) + QWindowSystemInterface::handleWindowActivated([self topLevelWindow]); return YES; } @@ -656,16 +648,8 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; NSWindow *window = [self window]; NSPoint nsWindowPoint; - // Use convertRectToScreen if available (added in 10.7). -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - if ([window respondsToSelector:@selector(convertRectFromScreen:)]) { - NSRect windowRect = [window convertRectFromScreen:NSMakeRect(mouseLocation.x, mouseLocation.y, 1, 1)]; - nsWindowPoint = windowRect.origin; // NSWindow coordinates - } else -#endif - { - nsWindowPoint = [window convertScreenToBase:mouseLocation]; // NSWindow coordinates - } + NSRect windowRect = [window convertRectFromScreen:NSMakeRect(mouseLocation.x, mouseLocation.y, 1, 1)]; + nsWindowPoint = windowRect.origin; // NSWindow coordinates NSPoint nsViewPoint = [self convertPoint: nsWindowPoint fromView: nil]; // NSView/QWindow coordinates *qtWindowPoint = QPointF(nsViewPoint.x, nsViewPoint.y); // NSView/QWindow coordinates @@ -678,6 +662,19 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; m_frameStrutButtons = Qt::NoButton; } +- (NSPoint) screenMousePoint:(NSEvent *)theEvent +{ + NSPoint screenPoint; + if (theEvent) { + NSPoint windowPoint = [theEvent locationInWindow]; + NSRect screenRect = [[theEvent window] convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)]; + screenPoint = screenRect.origin; + } else { + screenPoint = [NSEvent mouseLocation]; + } + return screenPoint; +} + - (void)handleMouseEvent:(NSEvent *)theEvent { [self handleTabletEvent: theEvent]; @@ -692,23 +689,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; m_platformWindow->m_forwardWindow = 0; } - NSPoint globalPos = [NSEvent mouseLocation]; - - if ([self.window parentWindow] - && (theEvent.type == NSLeftMouseDragged || theEvent.type == NSLeftMouseUp)) { - // QToolBar can be implemented as a child window on top of its main window - // (with a borderless NSWindow). If an option "unified toolbar" set on the main window, - // it's possible to drag such a window using this toolbar. - // While handling mouse drag events, QToolBar moves the window (QWidget::move). - // In such a combination [NSEvent mouseLocation] is very different from the - // real event location and as a result a window will move chaotically. - NSPoint winPoint = [theEvent locationInWindow]; - NSRect tmpRect = NSMakeRect(winPoint.x, winPoint.y, 1., 1.); - tmpRect = [[theEvent window] convertRectToScreen:tmpRect]; - globalPos = tmpRect.origin; - } - - [targetView convertFromScreen:globalPos toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint]; + [targetView convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint]; ulong timestamp = [theEvent timestamp] * 1000; QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag(); @@ -881,7 +862,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; QPointF windowPoint; QPointF screenPoint; - [self convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; + [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; QWindow *childWindow = m_platformWindow->childWindowAt(windowPoint.toPoint()); // Top-level windows generate enter-leave events for sub-windows. @@ -1296,18 +1277,8 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) // It looks like 1/4 degrees per pixel behaves most native. // (NB: Qt expects the unit for delta to be 8 per degree): const int pixelsToDegrees = 2; // 8 * 1/4 - -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - if ([theEvent respondsToSelector:@selector(scrollingDeltaX)]) { - angleDelta.setX([theEvent scrollingDeltaX] * pixelsToDegrees); - angleDelta.setY([theEvent scrollingDeltaY] * pixelsToDegrees); - } else -#endif - { - angleDelta.setX([theEvent deviceDeltaX] * pixelsToDegrees); - angleDelta.setY([theEvent deviceDeltaY] * pixelsToDegrees); - } - + angleDelta.setX([theEvent scrollingDeltaX] * pixelsToDegrees); + angleDelta.setY([theEvent scrollingDeltaY] * pixelsToDegrees); } else { // carbonEventKind == kEventMouseWheelMoved // Remove acceleration, and use either -120 or 120 as delta: @@ -1316,20 +1287,16 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) } QPoint pixelDelta; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - if ([theEvent respondsToSelector:@selector(scrollingDeltaX)]) { - if ([theEvent hasPreciseScrollingDeltas]) { - pixelDelta.setX([theEvent scrollingDeltaX]); - pixelDelta.setY([theEvent scrollingDeltaY]); - } else { - // docs: "In the case of !hasPreciseScrollingDeltas, multiply the delta with the line width." - // scrollingDeltaX seems to return a minimum value of 0.1 in this case, map that to two pixels. - const CGFloat lineWithEstimate = 20.0; - pixelDelta.setX([theEvent scrollingDeltaX] * lineWithEstimate); - pixelDelta.setY([theEvent scrollingDeltaY] * lineWithEstimate); - } + if ([theEvent hasPreciseScrollingDeltas]) { + pixelDelta.setX([theEvent scrollingDeltaX]); + pixelDelta.setY([theEvent scrollingDeltaY]); + } else { + // docs: "In the case of !hasPreciseScrollingDeltas, multiply the delta with the line width." + // scrollingDeltaX seems to return a minimum value of 0.1 in this case, map that to two pixels. + const CGFloat lineWithEstimate = 20.0; + pixelDelta.setX([theEvent scrollingDeltaX] * lineWithEstimate); + pixelDelta.setY([theEvent scrollingDeltaY] * lineWithEstimate); } -#endif QPointF qt_windowPoint; QPointF qt_screenPoint; @@ -1337,44 +1304,36 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) NSTimeInterval timestamp = [theEvent timestamp]; ulong qt_timestamp = timestamp * 1000; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - if ([theEvent respondsToSelector:@selector(scrollingDeltaX)]) { - // Prevent keyboard modifier state from changing during scroll event streams. - // A two-finger trackpad flick generates a stream of scroll events. We want - // the keyboard modifier state to be the state at the beginning of the - // flick in order to avoid changing the interpretation of the events - // mid-stream. One example of this happening would be when pressing cmd - // after scrolling in Qt Creator: not taking the phase into account causes - // the end of the event stream to be interpreted as font size changes. - NSEventPhase momentumPhase = [theEvent momentumPhase]; - if (momentumPhase == NSEventPhaseNone) { - currentWheelModifiers = [QNSView convertKeyModifiers:[theEvent modifierFlags]]; - } + // Prevent keyboard modifier state from changing during scroll event streams. + // A two-finger trackpad flick generates a stream of scroll events. We want + // the keyboard modifier state to be the state at the beginning of the + // flick in order to avoid changing the interpretation of the events + // mid-stream. One example of this happening would be when pressing cmd + // after scrolling in Qt Creator: not taking the phase into account causes + // the end of the event stream to be interpreted as font size changes. + NSEventPhase momentumPhase = [theEvent momentumPhase]; + if (momentumPhase == NSEventPhaseNone) { + currentWheelModifiers = [QNSView convertKeyModifiers:[theEvent modifierFlags]]; + } - NSEventPhase phase = [theEvent phase]; - Qt::ScrollPhase ph = Qt::ScrollUpdate; + NSEventPhase phase = [theEvent phase]; + Qt::ScrollPhase ph = Qt::ScrollUpdate; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 - if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) { - // On 10.8 and above, MayBegin is likely to happen. We treat it the same as an actual begin. - if (phase == NSEventPhaseMayBegin) - ph = Qt::ScrollBegin; - } else + if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) { + // On 10.8 and above, MayBegin is likely to happen. We treat it the same as an actual begin. + if (phase == NSEventPhaseMayBegin) + ph = Qt::ScrollBegin; + } else #endif if (phase == NSEventPhaseBegan) { // On 10.7, MayBegin will not happen, so Began is the actual beginning. ph = Qt::ScrollBegin; } - if (phase == NSEventPhaseEnded || phase == NSEventPhaseCancelled) { - ph = Qt::ScrollEnd; - } - - QWindowSystemInterface::handleWheelEvent(m_window, qt_timestamp, qt_windowPoint, qt_screenPoint, pixelDelta, angleDelta, currentWheelModifiers, ph); - } else -#endif - { - QWindowSystemInterface::handleWheelEvent(m_window, qt_timestamp, qt_windowPoint, qt_screenPoint, pixelDelta, angleDelta, - [QNSView convertKeyModifiers:[theEvent modifierFlags]]); + if (phase == NSEventPhaseEnded || phase == NSEventPhaseCancelled) { + ph = Qt::ScrollEnd; } + + QWindowSystemInterface::handleWheelEvent(m_window, qt_timestamp, qt_windowPoint, qt_screenPoint, pixelDelta, angleDelta, currentWheelModifiers, ph); } #endif //QT_NO_WHEELEVENT @@ -1432,7 +1391,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) QString text; // ignore text for the U+F700-U+F8FF range. This is used by Cocoa when // delivering function keys (e.g. arrow keys, backspace, F1-F35, etc.) - if (ch.unicode() < 0xf700 || ch.unicode() > 0xf8ff) + if (!(modifiers & (Qt::ControlModifier | Qt::MetaModifier)) && (ch.unicode() < 0xf700 || ch.unicode() > 0xf8ff)) text = QCFString::toQString(characters); QWindow *focusWindow = [self topLevelWindow]; diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm index d48cbdfac8c..7b77c9f1a81 100644 --- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -90,20 +90,13 @@ static void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransfor if (rgn.isEmpty()) { CGContextAddRect(hd, CGRectMake(0, 0, 0, 0)); } else { - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { - QCFType shape = qt_mac_QRegionToHIMutableShape(rgn); - Q_ASSERT(!HIShapeIsEmpty(shape)); - HIShapeReplacePathInCGContext(shape, hd); - } else { - QVector rects = rgn.rects(); - const int count = rects.size(); - for (int i = 0; i < count; i++) { - const QRect &r = rects[i]; - CGRect mac_r = CGRectMake(r.x(), r.y(), r.width(), r.height()); - CGContextAddRect(hd, mac_r); - } + QVector rects = rgn.rects(); + const int count = rects.size(); + for (int i = 0; i < count; i++) { + const QRect &r = rects[i]; + CGRect mac_r = CGRectMake(r.x(), r.y(), r.width(), r.height()); + CGContextAddRect(hd, mac_r); } - } CGContextClip(hd); @@ -1137,184 +1130,85 @@ extern "C" { void QCoreGraphicsPaintEngine::updateCompositionMode(QPainter::CompositionMode mode) { - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { - int cg_mode = kCGBlendModeNormal; - switch (mode) { - case QPainter::CompositionMode_Multiply: - cg_mode = kCGBlendModeMultiply; - break; - case QPainter::CompositionMode_Screen: - cg_mode = kCGBlendModeScreen; - break; - case QPainter::CompositionMode_Overlay: - cg_mode = kCGBlendModeOverlay; - break; - case QPainter::CompositionMode_Darken: - cg_mode = kCGBlendModeDarken; - break; - case QPainter::CompositionMode_Lighten: - cg_mode = kCGBlendModeLighten; - break; - case QPainter::CompositionMode_ColorDodge: - cg_mode = kCGBlendModeColorDodge; - break; - case QPainter::CompositionMode_ColorBurn: - cg_mode = kCGBlendModeColorBurn; - break; - case QPainter::CompositionMode_HardLight: - cg_mode = kCGBlendModeHardLight; - break; - case QPainter::CompositionMode_SoftLight: - cg_mode = kCGBlendModeSoftLight; - break; - case QPainter::CompositionMode_Difference: - cg_mode = kCGBlendModeDifference; - break; - case QPainter::CompositionMode_Exclusion: - cg_mode = kCGBlendModeExclusion; - break; - case QPainter::CompositionMode_Plus: - cg_mode = kCGBlendModePlusLighter; - break; - case QPainter::CompositionMode_SourceOver: - cg_mode = kCGBlendModeNormal; - break; - case QPainter::CompositionMode_DestinationOver: - cg_mode = kCGBlendModeDestinationOver; - break; - case QPainter::CompositionMode_Clear: - cg_mode = kCGBlendModeClear; - break; - case QPainter::CompositionMode_Source: - cg_mode = kCGBlendModeCopy; - break; - case QPainter::CompositionMode_Destination: - cg_mode = -1; - break; - case QPainter::CompositionMode_SourceIn: - cg_mode = kCGBlendModeSourceIn; - break; - case QPainter::CompositionMode_DestinationIn: - cg_mode = kCGCompositeModeDestinationIn; - break; - case QPainter::CompositionMode_SourceOut: - cg_mode = kCGBlendModeSourceOut; - break; - case QPainter::CompositionMode_DestinationOut: - cg_mode = kCGBlendModeDestinationOver; - break; - case QPainter::CompositionMode_SourceAtop: - cg_mode = kCGBlendModeSourceAtop; - break; - case QPainter::CompositionMode_DestinationAtop: - cg_mode = kCGBlendModeDestinationAtop; - break; - case QPainter::CompositionMode_Xor: - cg_mode = kCGBlendModeXOR; - break; - default: - break; - } - if (cg_mode > -1) { - CGContextSetBlendMode(d_func()->hd, CGBlendMode(cg_mode)); - } - } else if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_3 - && mode <= QPainter::CompositionMode_Xor) { - // The standard porter duff ops. - int cg_mode = kCGCompositeModeCopy; - switch (mode) { - case QPainter::CompositionMode_SourceOver: - cg_mode = kCGCompositeModeSourceOver; - break; - case QPainter::CompositionMode_DestinationOver: - cg_mode = kCGCompositeModeDestinationOver; - break; - case QPainter::CompositionMode_Clear: - cg_mode = kCGCompositeModeClear; - break; - default: - qWarning("QCoreGraphicsPaintEngine: Unhandled composition mode %d", (int)mode); - break; - case QPainter::CompositionMode_Source: - cg_mode = kCGCompositeModeCopy; - break; - case QPainter::CompositionMode_Destination: - cg_mode = CGCompositeMode(-1); - break; - case QPainter::CompositionMode_SourceIn: - cg_mode = kCGCompositeModeSourceIn; - break; - case QPainter::CompositionMode_DestinationIn: - cg_mode = kCGCompositeModeDestinationIn; - break; - case QPainter::CompositionMode_SourceOut: - cg_mode = kCGCompositeModeSourceOut; - break; - case QPainter::CompositionMode_DestinationOut: - cg_mode = kCGCompositeModeDestinationOut; - break; - case QPainter::CompositionMode_SourceAtop: - cg_mode = kCGCompositeModeSourceAtop; - break; - case QPainter::CompositionMode_DestinationAtop: - cg_mode = kCGCompositeModeDestinationAtop; - break; - case QPainter::CompositionMode_Xor: - cg_mode = kCGCompositeModeXOR; - break; - } - if (cg_mode > -1) - CGContextSetCompositeOperation(d_func()->hd, CGCompositeMode(cg_mode)); - } else { - bool needPrivateAPI = false; - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - int cg_mode = kCGBlendModeNormal; - switch (mode) { - case QPainter::CompositionMode_Multiply: - cg_mode = kCGBlendModeMultiply; - break; - case QPainter::CompositionMode_Screen: - cg_mode = kCGBlendModeScreen; - break; - case QPainter::CompositionMode_Overlay: - cg_mode = kCGBlendModeOverlay; - break; - case QPainter::CompositionMode_Darken: - cg_mode = kCGBlendModeDarken; - break; - case QPainter::CompositionMode_Lighten: - cg_mode = kCGBlendModeLighten; - break; - case QPainter::CompositionMode_ColorDodge: - cg_mode = kCGBlendModeColorDodge; - break; - case QPainter::CompositionMode_ColorBurn: - cg_mode = kCGBlendModeColorBurn; - break; - case QPainter::CompositionMode_HardLight: - cg_mode = kCGBlendModeHardLight; - break; - case QPainter::CompositionMode_SoftLight: - cg_mode = kCGBlendModeSoftLight; - break; - case QPainter::CompositionMode_Difference: - cg_mode = kCGBlendModeDifference; - break; - case QPainter::CompositionMode_Exclusion: - cg_mode = kCGBlendModeExclusion; - break; - case QPainter::CompositionMode_Plus: - needPrivateAPI = true; - cg_mode = kCGCompositeModePlusLighter; - break; - default: - break; - } - if (!needPrivateAPI) - CGContextSetBlendMode(d_func()->hd, CGBlendMode(cg_mode)); - else - CGContextSetCompositeOperation(d_func()->hd, CGCompositeMode(cg_mode)); - } + int cg_mode = kCGBlendModeNormal; + switch (mode) { + case QPainter::CompositionMode_Multiply: + cg_mode = kCGBlendModeMultiply; + break; + case QPainter::CompositionMode_Screen: + cg_mode = kCGBlendModeScreen; + break; + case QPainter::CompositionMode_Overlay: + cg_mode = kCGBlendModeOverlay; + break; + case QPainter::CompositionMode_Darken: + cg_mode = kCGBlendModeDarken; + break; + case QPainter::CompositionMode_Lighten: + cg_mode = kCGBlendModeLighten; + break; + case QPainter::CompositionMode_ColorDodge: + cg_mode = kCGBlendModeColorDodge; + break; + case QPainter::CompositionMode_ColorBurn: + cg_mode = kCGBlendModeColorBurn; + break; + case QPainter::CompositionMode_HardLight: + cg_mode = kCGBlendModeHardLight; + break; + case QPainter::CompositionMode_SoftLight: + cg_mode = kCGBlendModeSoftLight; + break; + case QPainter::CompositionMode_Difference: + cg_mode = kCGBlendModeDifference; + break; + case QPainter::CompositionMode_Exclusion: + cg_mode = kCGBlendModeExclusion; + break; + case QPainter::CompositionMode_Plus: + cg_mode = kCGBlendModePlusLighter; + break; + case QPainter::CompositionMode_SourceOver: + cg_mode = kCGBlendModeNormal; + break; + case QPainter::CompositionMode_DestinationOver: + cg_mode = kCGBlendModeDestinationOver; + break; + case QPainter::CompositionMode_Clear: + cg_mode = kCGBlendModeClear; + break; + case QPainter::CompositionMode_Source: + cg_mode = kCGBlendModeCopy; + break; + case QPainter::CompositionMode_Destination: + cg_mode = -1; + break; + case QPainter::CompositionMode_SourceIn: + cg_mode = kCGBlendModeSourceIn; + break; + case QPainter::CompositionMode_DestinationIn: + cg_mode = kCGCompositeModeDestinationIn; + break; + case QPainter::CompositionMode_SourceOut: + cg_mode = kCGBlendModeSourceOut; + break; + case QPainter::CompositionMode_DestinationOut: + cg_mode = kCGBlendModeDestinationOver; + break; + case QPainter::CompositionMode_SourceAtop: + cg_mode = kCGBlendModeSourceAtop; + break; + case QPainter::CompositionMode_DestinationAtop: + cg_mode = kCGBlendModeDestinationAtop; + break; + case QPainter::CompositionMode_Xor: + cg_mode = kCGBlendModeXOR; + break; + default: + break; + } + if (cg_mode > -1) { + CGContextSetBlendMode(d_func()->hd, CGBlendMode(cg_mode)); } } @@ -1645,8 +1539,6 @@ void QCoreGraphicsPaintEnginePrivate::drawPath(uchar ops, CGMutablePathRef path) if (!(q->state->renderHints() & QPainter::Antialiasing)) { if (current.pen.style() == Qt::SolidLine || current.pen.width() >= 3) CGContextTranslateCTM(hd, double(pixelSize.x()) * 0.25, double(pixelSize.y()) * 0.25); - else if (current.pen.style() == Qt::DotLine && QSysInfo::MacintoshVersion == QSysInfo::MV_10_3) - ; // Do nothing. else CGContextTranslateCTM(hd, 0, double(pixelSize.y()) * 0.1); } diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index f684fef233f..a58514614b1 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -412,7 +412,10 @@ void QMacPrintEngine::drawTextItem(const QPointF &p, const QTextItem &ti) { Q_D(QMacPrintEngine); Q_ASSERT(d->state == QPrinter::Active); - d->paintEngine->drawTextItem(p, ti); + if (!d->embedFonts) + QPaintEngine::drawTextItem(p, ti); + else + d->paintEngine->drawTextItem(p, ti); } void QMacPrintEngine::drawTiledPixmap(const QRectF &dr, const QPixmap &pixmap, const QPointF &sr) @@ -457,8 +460,6 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va break; case PPK_CustomBase: break; - case PPK_FontEmbedding: - break; case PPK_PageOrder: // TODO Check if can be supported via Cups Options break; @@ -471,6 +472,9 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va break; // The following keys are properties and settings that are supported by the Mac PrintEngine + case PPK_FontEmbedding: + d->embedFonts = value.toBool(); + break; case PPK_Resolution: { // TODO It appears the old code didn't actually set the resolution??? Can we delete all this??? int bestResolution = 0; @@ -622,9 +626,6 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const case PPK_CustomBase: // Special case, leave null break; - case PPK_FontEmbedding: - ret = false; - break; case PPK_PageOrder: // TODO Check if can be supported via Cups Options ret = QPrinter::FirstPageFirst; @@ -648,6 +649,9 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const break; // The following keys are properties and settings that are supported by the Mac PrintEngine + case PPK_FontEmbedding: + ret = d->embedFonts; + break; case PPK_CollateCopies: { Boolean status; PMGetCollate(d->settings(), &status); diff --git a/src/plugins/platforms/cocoa/qprintengine_mac_p.h b/src/plugins/platforms/cocoa/qprintengine_mac_p.h index c7307688aef..c99069b7f71 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac_p.h +++ b/src/plugins/platforms/cocoa/qprintengine_mac_p.h @@ -124,10 +124,11 @@ public: QString m_creator; QPaintEngine *paintEngine; QHash valueCache; + uint embedFonts; QMacPrintEnginePrivate() : mode(QPrinter::ScreenResolution), state(QPrinter::Idle), m_pageLayout(QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0, 0, 0, 0))), - printInfo(0), paintEngine(0) {} + printInfo(0), paintEngine(0), embedFonts(true) {} ~QMacPrintEnginePrivate(); void initialize(); diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp index 142362a0653..351f94be2bf 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp @@ -39,6 +39,7 @@ #include "qwindowsdirect2dwindow.h" #include "qwindowscontext.h" +#include "qwindowsguieventdispatcher.h" #include #include @@ -47,6 +48,16 @@ QT_BEGIN_NAMESPACE +class QWindowsDirect2DEventDispatcher : public QWindowsGuiEventDispatcher +{ +public: + QWindowsDirect2DEventDispatcher(QObject *parent = 0) + : QWindowsGuiEventDispatcher(parent) + { + uninstallMessageHook(); // ### Workaround for QTBUG-42428 + } +}; + class QWindowsDirect2DIntegrationPrivate { public: @@ -237,6 +248,11 @@ QPlatformBackingStore *QWindowsDirect2DIntegration::createPlatformBackingStore(Q return new QWindowsDirect2DBackingStore(window); } +QAbstractEventDispatcher *QWindowsDirect2DIntegration::createEventDispatcher() const +{ + return new QWindowsDirect2DEventDispatcher; +} + QWindowsDirect2DContext *QWindowsDirect2DIntegration::direct2DContext() const { return &d->m_d2dContext; diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h index b4104643721..c72b22a6e82 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h @@ -56,6 +56,7 @@ public: QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE; QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const Q_DECL_OVERRIDE; QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE; + QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE; QWindowsDirect2DContext *direct2DContext() const; diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp index c13f0f333a2..a86bb0ee045 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp @@ -1471,7 +1471,8 @@ void QWindowsDirect2DPaintEngine::drawPixmap(const QRectF &r, r.x(), r.y() + r.height() }; const QVectorPath vp(points, 4, 0, QVectorPath::RectangleHint); - const QBrush brush(sr.isValid() ? pm.copy(sr.toRect()) : pm); + QBrush brush(sr.isValid() ? pm.copy(sr.toRect()) : pm); + brush.setTransform(QTransform::fromTranslate(r.x(), r.y())); rasterFill(vp, brush); return; } diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp index ef02d773753..c89d293d1d9 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp @@ -199,12 +199,13 @@ void QWindowsDirect2DWindow::setupSwapChain() void QWindowsDirect2DWindow::resizeSwapChain(const QSize &size) { - if (!m_swapChain) - return; - m_pixmap.reset(); m_bitmap.reset(); m_deviceContext->SetTarget(Q_NULLPTR); + m_needsFullFlush = true; + + if (!m_swapChain) + return; HRESULT hr = m_swapChain->ResizeBuffers(0, size.width(), size.height(), @@ -212,8 +213,6 @@ void QWindowsDirect2DWindow::resizeSwapChain(const QSize &size) 0); if (FAILED(hr)) qWarning("%s: Could not resize swap chain: %#x", __FUNCTION__, hr); - - m_needsFullFlush = true; } QSharedPointer QWindowsDirect2DWindow::copyBackBuffer() const diff --git a/src/plugins/platforms/directfb/directfb.pro b/src/plugins/platforms/directfb/directfb.pro index 89d8d42ceae..13481f61987 100644 --- a/src/plugins/platforms/directfb/directfb.pro +++ b/src/plugins/platforms/directfb/directfb.pro @@ -29,6 +29,8 @@ HEADERS = qdirectfbintegration.h \ qdirectfbscreen.h \ qdirectfbeglhooks.h +contains(QT_CONFIG, libudev): DEFINES += QDEVICEDISCOVERY_UDEV + # ### port the GL context contains(QT_CONFIG, directfb_egl) { HEADERS += qdirectfb_egl.h diff --git a/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp b/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp index ddf19face63..1b042a07432 100644 --- a/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp +++ b/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp @@ -67,11 +67,13 @@ QByteArray QEglFSHooks::fbDeviceName() const int QEglFSHooks::framebufferIndex() const { int fbIndex = 0; +#ifndef QT_NO_REGULAREXPRESSION QRegularExpression fbIndexRx(QLatin1String("fb(\\d+)")); QRegularExpressionMatch match = fbIndexRx.match(fbDeviceName()); if (match.hasMatch()) fbIndex = match.captured(1).toInt(); +#endif return fbIndex; } diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.h b/src/plugins/platforms/eglfs/qeglfsscreen.h index c7d8b55b190..c5ab3b52f5f 100644 --- a/src/plugins/platforms/eglfs/qeglfsscreen.h +++ b/src/plugins/platforms/eglfs/qeglfsscreen.h @@ -76,7 +76,6 @@ protected: private: friend class QEglFSWindow; - EGLDisplay m_dpy; EGLSurface m_surface; QPlatformCursor *m_cursor; QEGLPlatformWindow *m_rootWindow; diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp index ef1f496b290..59c2014d661 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp @@ -103,7 +103,7 @@ void QEglFSWindow::create() if (isRaster()) { QOpenGLContext *context = new QOpenGLContext(QGuiApplication::instance()); - context->setFormat(window()->requestedFormat()); + context->setFormat(m_format); context->setScreen(window()->screen()); if (!context->create()) qFatal("EGLFS: Failed to create compositing context"); diff --git a/src/plugins/platforms/ios/qioseventdispatcher.mm b/src/plugins/platforms/ios/qioseventdispatcher.mm index ce7dfe26064..ffffc4cbc44 100644 --- a/src/plugins/platforms/ios/qioseventdispatcher.mm +++ b/src/plugins/platforms/ios/qioseventdispatcher.mm @@ -241,11 +241,11 @@ enum SetJumpResult kJumpedFromUserMainTrampoline, }; -// We define qt_main so that user_main_trampoline() will not cause +// We define qtmn so that user_main_trampoline() will not cause // missing symbols in the case of hybrid applications that don't -// user our main wrapper. Since the symbol is weak, it will not +// use our main wrapper. Since the symbol is weak, it will not // get used or cause a clash in the normal Qt application usecase, -// where we rename main to qt_main. +// where we rename main to qtmn before linking. extern "C" int __attribute__((weak)) qtmn(int argc, char *argv[]) { Q_UNUSED(argc); @@ -317,11 +317,16 @@ static bool rootLevelRunLoopIntegration() } #if defined(Q_PROCESSOR_X86) -# define SET_STACK_POINTER "mov %0, %%esp" # define FUNCTION_CALL_ALIGNMENT 16 +# if defined(Q_PROCESSOR_X86_32) +# define SET_STACK_POINTER "mov %0, %%esp" +# elif defined(Q_PROCESSOR_X86_64) +# define SET_STACK_POINTER "movq %0, %%rsp" +# endif #elif defined(Q_PROCESSOR_ARM) -# define SET_STACK_POINTER "mov sp, %0" +# // Valid for both 32 and 64-bit ARM # define FUNCTION_CALL_ALIGNMENT 4 +# define SET_STACK_POINTER "mov sp, %0" #else # error "Unknown processor family" #endif diff --git a/src/plugins/platforms/ios/qiosglobal.h b/src/plugins/platforms/ios/qiosglobal.h index c09987f9dcd..f7b9cd70157 100644 --- a/src/plugins/platforms/ios/qiosglobal.h +++ b/src/plugins/platforms/ios/qiosglobal.h @@ -41,6 +41,16 @@ QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcQpaInputMethods); + +#if !defined(QT_NO_DEBUG) +#define qImDebug(...) \ + for (bool qt_category_enabled = lcQpaInputMethods().isDebugEnabled(); qt_category_enabled; qt_category_enabled = false) \ + QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC, lcQpaInputMethods().categoryName()).debug(__VA_ARGS__) +#else +#define qImDebug() QT_NO_QDEBUG_MACRO() +#endif + class QPlatformScreen; bool isQtApplication(); @@ -52,7 +62,7 @@ QPointF fromCGPoint(const CGPoint &point); Qt::ScreenOrientation toQtScreenOrientation(UIDeviceOrientation uiDeviceOrientation); UIDeviceOrientation fromQtScreenOrientation(Qt::ScreenOrientation qtOrientation); -QRect fromPortraitToPrimary(const QRect &rect, QPlatformScreen *screen); + int infoPlistValue(NSString* key, int defaultValue); QT_END_NAMESPACE @@ -61,4 +71,14 @@ QT_END_NAMESPACE +(id)currentFirstResponder; @end +class FirstResponderCandidate : public QScopedValueRollback +{ +public: + FirstResponderCandidate(UIResponder *); + static UIResponder *currentCandidate() { return s_firstResponderCandidate; } + +private: + static UIResponder *s_firstResponderCandidate; +}; + #endif // QIOSGLOBAL_H diff --git a/src/plugins/platforms/ios/qiosglobal.mm b/src/plugins/platforms/ios/qiosglobal.mm index 7ff4950599b..3ecd0ca61fc 100644 --- a/src/plugins/platforms/ios/qiosglobal.mm +++ b/src/plugins/platforms/ios/qiosglobal.mm @@ -46,6 +46,8 @@ QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcQpaInputMethods, "qt.qpa.input.methods"); + bool isQtApplication() { // Returns \c true if the plugin is in full control of the whole application. This means @@ -125,15 +127,6 @@ UIDeviceOrientation fromQtScreenOrientation(Qt::ScreenOrientation qtOrientation) return uiOrientation; } -QRect fromPortraitToPrimary(const QRect &rect, QPlatformScreen *screen) -{ - // UIScreen is always in portrait. Use this function to convert CGRects - // aligned with UIScreen into whatever is the current orientation of QScreen. - QRect geometry = screen->geometry(); - return geometry.width() < geometry.height() ? rect - : QRect(rect.y(), geometry.height() - rect.width() - rect.x(), rect.height(), rect.width()); -} - int infoPlistValue(NSString* key, int defaultValue) { static NSBundle *bundle = [NSBundle mainBundle]; @@ -148,6 +141,27 @@ int infoPlistValue(NSString* key, int defaultValue) @end @implementation QtFirstResponderEvent +- (void) dealloc +{ + self.firstResponder = 0; + [super dealloc]; +} +@end + + +@implementation UIView (QtFirstResponder) +- (UIView*)qt_findFirstResponder +{ + if ([self isFirstResponder]) + return self; + + for (UIView *subview in self.subviews) { + if (UIView *firstResponder = [subview qt_findFirstResponder]) + return firstResponder; + } + + return nil; +} @end @implementation UIResponder (QtFirstResponder) @@ -162,9 +176,20 @@ int infoPlistValue(NSString* key, int defaultValue) - (void)qt_findFirstResponder:(id)sender event:(QtFirstResponderEvent *)event { Q_UNUSED(sender); - event.firstResponder = self; + + if ([self isKindOfClass:[UIView class]]) + event.firstResponder = [static_cast(self) qt_findFirstResponder]; + else + event.firstResponder = [self isFirstResponder] ? self : nil; } @end +FirstResponderCandidate::FirstResponderCandidate(UIResponder *responder) + : QScopedValueRollback(s_firstResponderCandidate, responder) +{ +} + +UIResponder *FirstResponderCandidate::s_firstResponderCandidate = 0; + QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qiosinputcontext.h b/src/plugins/platforms/ios/qiosinputcontext.h index 8850bbf80e6..d2a9c261ba6 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.h +++ b/src/plugins/platforms/ios/qiosinputcontext.h @@ -42,6 +42,7 @@ const char kImePlatformDataInputView[] = "inputView"; const char kImePlatformDataInputAccessoryView[] = "inputAccessoryView"; +const char kImePlatformDataReturnKeyType[] = "returnKeyType"; QT_BEGIN_NAMESPACE @@ -50,9 +51,10 @@ QT_BEGIN_NAMESPACE struct ImeState { - ImeState() : currentState(0) {} + ImeState() : currentState(0), focusObject(0) {} Qt::InputMethodQueries update(Qt::InputMethodQueries properties); QInputMethodQueryEvent currentState; + QObject *focusObject; }; class QIOSInputContext : public QPlatformInputContext @@ -65,7 +67,8 @@ public: void showInputPanel(); void hideInputPanel(); - void hideVirtualKeyboard(); + + void clearCurrentFocusObject(); bool isInputPanelVisible() const; void setFocusObject(QObject *object); @@ -80,6 +83,9 @@ public: void commit(); const ImeState &imeState() { return m_imeState; }; + bool inputMethodAccepted() const; + + static QIOSInputContext *instance(); private: QIOSKeyboardListener *m_keyboardListener; diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm index b4031543211..e417e9a1fba 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.mm +++ b/src/plugins/platforms/ios/qiosinputcontext.mm @@ -44,26 +44,30 @@ #import #include "qiosglobal.h" +#include "qiosintegration.h" #include "qiostextresponder.h" +#include "qiosviewcontroller.h" #include "qioswindow.h" #include "quiview.h" #include #include +// ------------------------------------------------------------------------- + static QUIView *focusView() { return qApp->focusWindow() ? reinterpret_cast(qApp->focusWindow()->winId()) : 0; } -@interface QIOSKeyboardListener : UIGestureRecognizer { +// ------------------------------------------------------------------------- + +@interface QIOSKeyboardListener : UIGestureRecognizer { @public QIOSInputContext *m_context; BOOL m_keyboardVisible; BOOL m_keyboardVisibleAndDocked; - BOOL m_touchPressWhileKeyboardVisible; - BOOL m_keyboardHiddenByGesture; QRectF m_keyboardRect; CGRect m_keyboardEndRect; NSTimeInterval m_duration; @@ -76,13 +80,11 @@ static QUIView *focusView() - (id)initWithQIOSInputContext:(QIOSInputContext *)context { - self = [super initWithTarget:self action:@selector(gestureTriggered)]; + self = [super initWithTarget:self action:@selector(gestureStateChanged:)]; if (self) { m_context = context; m_keyboardVisible = NO; m_keyboardVisibleAndDocked = NO; - m_touchPressWhileKeyboardVisible = NO; - m_keyboardHiddenByGesture = NO; m_duration = 0; m_curve = UIViewAnimationCurveEaseOut; m_viewController = 0; @@ -98,10 +100,9 @@ static QUIView *focusView() Q_ASSERT(m_viewController); // Attach 'hide keyboard' gesture to the window, but keep it disabled when the - // keyboard is not visible. Note that we never trigger the gesture the way it is intended - // since we don't want to cancel touch events and interrupt flicking etc. Instead we use - // the gesture framework more as an event filter and hide the keyboard silently. + // keyboard is not visible. self.enabled = NO; + self.cancelsTouchesInView = NO; self.delaysTouchesEnded = NO; [m_viewController.view.window addGestureRecognizer:self]; } @@ -155,11 +156,19 @@ static QUIView *focusView() // Note that UIKeyboardWillShowNotification is only sendt when the keyboard is docked. m_keyboardVisibleAndDocked = YES; m_keyboardEndRect = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; - self.enabled = YES; + if (!m_duration) { m_duration = [[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; m_curve = UIViewAnimationCurve([[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue]); } + + UIResponder *firstResponder = [UIResponder currentFirstResponder]; + if (![firstResponder isKindOfClass:[QIOSTextInputResponder class]]) + return; + + // Enable hide-keyboard gesture + self.enabled = YES; + m_context->scrollToCursor(); } @@ -168,7 +177,7 @@ static QUIView *focusView() // Note that UIKeyboardWillHideNotification is also sendt when the keyboard is undocked. m_keyboardVisibleAndDocked = NO; m_keyboardEndRect = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; - if (!m_keyboardHiddenByGesture) { + if (self.state != UIGestureRecognizerStateBegan) { // Only disable the gesture if the hiding of the keyboard was not caused by it. // Otherwise we need to await the final touchEnd callback for doing some clean-up. self.enabled = NO; @@ -201,51 +210,81 @@ static QUIView *focusView() } } -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event -{ - CGPoint p = [[touches anyObject] locationInView:m_viewController.view.window]; - if (CGRectContainsPoint(m_keyboardEndRect, p)) { - m_keyboardHiddenByGesture = YES; - m_context->hideVirtualKeyboard(); - } - - [super touchesMoved:touches withEvent:event]; -} +// ------------------------------------------------------------------------- - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { - Q_ASSERT(m_keyboardVisibleAndDocked); - m_touchPressWhileKeyboardVisible = YES; [super touchesBegan:touches withEvent:event]; + + Q_ASSERT(m_keyboardVisibleAndDocked); + + if ([touches count] != 1) + self.state = UIGestureRecognizerStateFailed; +} + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +{ + [super touchesMoved:touches withEvent:event]; + + if (self.state != UIGestureRecognizerStatePossible) + return; + + CGPoint touchPoint = [[touches anyObject] locationInView:m_viewController.view.window]; + if (CGRectContainsPoint(m_keyboardEndRect, touchPoint)) + self.state = UIGestureRecognizerStateBegan; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { - m_touchPressWhileKeyboardVisible = NO; - [self performSelectorOnMainThread:@selector(touchesEndedPostDelivery) withObject:nil waitUntilDone:NO]; [super touchesEnded:touches withEvent:event]; + + [self touchesEndedOrCancelled]; } - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { - m_touchPressWhileKeyboardVisible = NO; - [self performSelectorOnMainThread:@selector(touchesEndedPostDelivery) withObject:nil waitUntilDone:NO]; [super touchesCancelled:touches withEvent:event]; + + [self touchesEndedOrCancelled]; } -- (void)touchesEndedPostDelivery +- (void)touchesEndedOrCancelled { - // Do some clean-up _after_ touchEnd has been delivered to QUIView - m_keyboardHiddenByGesture = NO; + // Defer final state change until next runloop iteration, so that Qt + // has a chance to process the final touch events first, before we eg. + // scroll the view. + dispatch_async(dispatch_get_main_queue (), ^{ + // iOS will transition from began to changed by itself + Q_ASSERT(self.state != UIGestureRecognizerStateBegan); + + if (self.state == UIGestureRecognizerStateChanged) + self.state = UIGestureRecognizerStateEnded; + else + self.state = UIGestureRecognizerStateFailed; + }); +} + +- (void)gestureStateChanged:(id)sender +{ + Q_UNUSED(sender); + + if (self.state == UIGestureRecognizerStateBegan) { + qImDebug() << "hide keyboard gesture was triggered"; + UIResponder *firstResponder = [UIResponder currentFirstResponder]; + Q_ASSERT([firstResponder isKindOfClass:[QIOSTextInputResponder class]]); + [firstResponder resignFirstResponder]; + } +} + +- (void)reset +{ + [super reset]; + if (!m_keyboardVisibleAndDocked) { + qImDebug() << "keyboard was hidden, disabling hide-keyboard gesture"; self.enabled = NO; - if (qApp->focusObject()) { - // UI Controls are told to gain focus on touch release. So when the 'hide keyboard' gesture - // finishes, the final touch end can trigger a control to gain focus. This is in conflict with - // the gesture, so we clear focus once more as a work-around. - static_cast(QObjectPrivate::get(qApp->focusWindow()))->clearFocusObject(); - } } else { + qImDebug() << "gesture completed without triggering, scrolling view to cursor"; m_context->scrollToCursor(); } } @@ -261,8 +300,11 @@ Qt::InputMethodQueries ImeState::update(Qt::InputMethodQueries properties) QInputMethodQueryEvent newState(properties); - if (qApp && qApp->focusObject()) - QCoreApplication::sendEvent(qApp->focusObject(), &newState); + // Update the focus object that the new state is based on + focusObject = qApp ? qApp->focusObject() : 0; + + if (focusObject) + QCoreApplication::sendEvent(focusObject, &newState); Qt::InputMethodQueries updatedProperties; for (uint i = 0; i < (sizeof(Qt::ImQueryAll) * CHAR_BIT); ++i) { @@ -279,6 +321,11 @@ Qt::InputMethodQueries ImeState::update(Qt::InputMethodQueries properties) // ------------------------------------------------------------------------- +QIOSInputContext *QIOSInputContext::instance() +{ + return static_cast(QIOSIntegration::instance()->inputContext()); +} + QIOSInputContext::QIOSInputContext() : QPlatformInputContext() , m_keyboardListener([[QIOSKeyboardListener alloc] initWithQIOSInputContext:this]) @@ -303,16 +350,29 @@ QRectF QIOSInputContext::keyboardRect() const void QIOSInputContext::showInputPanel() { // No-op, keyboard controlled fully by platform based on focus + qImDebug() << "can't show virtual keyboard without a focus object, ignoring"; } void QIOSInputContext::hideInputPanel() { - // No-op, keyboard controlled fully by platform based on focus + if (![m_textResponder isFirstResponder]) { + qImDebug() << "QIOSTextInputResponder is not first responder, ignoring"; + return; + } + + if (qGuiApp->focusObject() != m_imeState.focusObject) { + qImDebug() << "current focus object does not match IM state, likely hiding from focusOut event, so ignoring"; + return; + } + + qImDebug() << "hiding VKB as requested by QInputMethod::hide()"; + [m_textResponder resignFirstResponder]; } -void QIOSInputContext::hideVirtualKeyboard() +void QIOSInputContext::clearCurrentFocusObject() { - static_cast(QObjectPrivate::get(qApp->focusWindow()))->clearFocusObject(); + if (QWindow *focusWindow = qApp->focusWindow()) + static_cast(QObjectPrivate::get(focusWindow))->clearFocusObject(); } bool QIOSInputContext::isInputPanelVisible() const @@ -342,10 +402,10 @@ void QIOSInputContext::scrollToCursor() if (!isQtApplication()) return; - if (m_keyboardListener->m_touchPressWhileKeyboardVisible) { - // Don't scroll to the cursor if the user is touching the screen. This - // interferes with selection and the 'hide keyboard' gesture. Instead - // we update scrolling upon touchEnd. + if (m_keyboardListener.state == UIGestureRecognizerStatePossible && m_keyboardListener.numberOfTouches == 1) { + // Don't scroll to the cursor if the user is touching the screen and possibly + // trying to trigger the hide-keyboard gesture. + qImDebug() << "preventing scrolling to cursor as we're still waiting for a possible gesture"; return; } @@ -415,6 +475,18 @@ void QIOSInputContext::setFocusObject(QObject *focusObject) { Q_UNUSED(focusObject); + qImDebug() << "new focus object =" << focusObject; + + if (m_keyboardListener.state == UIGestureRecognizerStateChanged) { + // A new focus object may be set as part of delivering touch events to + // application during the hide-keyboard gesture, but we don't want that + // to result in a new object getting focus and bringing the keyboard up + // again. + qImDebug() << "clearing focus object" << focusObject << "as hide-keyboard gesture is active"; + clearCurrentFocusObject(); + return; + } + reset(); if (m_keyboardListener->m_keyboardVisibleAndDocked) @@ -425,6 +497,8 @@ void QIOSInputContext::focusWindowChanged(QWindow *focusWindow) { Q_UNUSED(focusWindow); + qImDebug() << "new focus window =" << focusWindow; + reset(); [m_keyboardListener handleKeyboardRectChanged]; @@ -443,17 +517,59 @@ void QIOSInputContext::update(Qt::InputMethodQueries updatedProperties) // Mask for properties that we are interested in and see if any of them changed updatedProperties &= (Qt::ImEnabled | Qt::ImHints | Qt::ImQueryInput | Qt::ImPlatformData); + if (updatedProperties & Qt::ImEnabled) { + // Switching on and off input-methods needs a re-fresh of hints and platform + // data when we turn them on again, as the IM state we have may have been + // invalidated when IM was switched off. We could defer this until we know + // if IM was turned on, to limit the extra query parameters, but for simplicity + // we always do the update. + updatedProperties |= (Qt::ImHints | Qt::ImPlatformData); + } + + qImDebug() << "fw =" << qApp->focusWindow() << "fo =" << qApp->focusObject(); + Qt::InputMethodQueries changedProperties = m_imeState.update(updatedProperties); if (changedProperties & (Qt::ImEnabled | Qt::ImHints | Qt::ImPlatformData)) { // Changes to enablement or hints require virtual keyboard reconfigure - [m_textResponder release]; - m_textResponder = [[QIOSTextInputResponder alloc] initWithInputContext:this]; - [m_textResponder reloadInputViews]; + + qImDebug() << "changed IM properties" << changedProperties << "require keyboard reconfigure"; + + if (inputMethodAccepted()) { + qImDebug() << "replacing text responder with new text responder"; + [m_textResponder autorelease]; + m_textResponder = [[QIOSTextInputResponder alloc] initWithInputContext:this]; + [m_textResponder becomeFirstResponder]; + } else if ([UIResponder currentFirstResponder] == m_textResponder) { + qImDebug() << "IM not enabled, resigning text responder as first responder"; + [m_textResponder resignFirstResponder]; + } else { + qImDebug() << "IM not enabled. Text responder not first responder. Nothing to do"; + } } else { [m_textResponder notifyInputDelegate:changedProperties]; } } +bool QIOSInputContext::inputMethodAccepted() const +{ + // The IM enablement state is based on the last call to update() + bool lastKnownImEnablementState = m_imeState.currentState.value(Qt::ImEnabled).toBool(); + +#if !defined(QT_NO_DEBUG) + // QPlatformInputContext keeps a cached value of the current IM enablement state that is + // updated by QGuiApplication when the current focus object changes, or by QInputMethod's + // update() function. If the focus object changes, but the change is not propagated as + // a signal to QGuiApplication due to bugs in the widget/graphicsview/qml stack, we'll + // end up with a stale value for QPlatformInputContext::inputMethodAccepted(). To be on + // the safe side we always use our own cached value to decide if IM is enabled, and try + // to detect the case where the two values are out of sync. + if (lastKnownImEnablementState != QPlatformInputContext::inputMethodAccepted()) + qWarning("QPlatformInputContext::inputMethodAccepted() does not match actual focus object IM enablement!"); +#endif + + return lastKnownImEnablementState; +} + /*! Called by the input item to reset the input method state. */ @@ -478,16 +594,3 @@ void QIOSInputContext::commit() [m_textResponder unmarkText]; [m_textResponder notifyInputDelegate:Qt::ImSurroundingText]; } - -// ------------------------------------------------------------------------- - -@interface QUIView (InputMethods) -- (void)reloadInputViews; -@end - -@implementation QUIView (InputMethods) -- (void)reloadInputViews -{ - qApp->inputMethod()->reset(); -} -@end diff --git a/src/plugins/platforms/ios/qiosmenu.mm b/src/plugins/platforms/ios/qiosmenu.mm index 005b06547e6..0f351f785b8 100644 --- a/src/plugins/platforms/ios/qiosmenu.mm +++ b/src/plugins/platforms/ios/qiosmenu.mm @@ -153,13 +153,29 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_"; [self setDelegate:self]; [self setDataSource:self]; [self selectRow:m_selectedRow inComponent:0 animated:false]; + [self listenForKeyboardWillHideNotification:YES]; } return self; } +-(void)listenForKeyboardWillHideNotification:(BOOL)listen +{ + if (listen) { + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(cancelMenu) + name:@"UIKeyboardWillHideNotification" object:nil]; + } else { + [[NSNotificationCenter defaultCenter] + removeObserver:self + name:@"UIKeyboardWillHideNotification" object:nil]; + } +} + -(void)dealloc { + [self listenForKeyboardWillHideNotification:NO]; self.toolbar = 0; [super dealloc]; } @@ -193,6 +209,7 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_"; - (void)closeMenu { + [self listenForKeyboardWillHideNotification:NO]; if (!m_visibleMenuItems.isEmpty()) QIOSMenu::currentMenu()->handleItemSelected(m_visibleMenuItems.at(m_selectedRow)); else @@ -201,6 +218,7 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_"; - (void)cancelMenu { + [self listenForKeyboardWillHideNotification:NO]; QIOSMenu::currentMenu()->dismiss(); } @@ -452,11 +470,11 @@ void QIOSMenu::toggleShowUsingUIPickerView(bool show) Q_ASSERT(!focusObjectWithPickerView); focusObjectWithPickerView = qApp->focusWindow()->focusObject(); focusObjectWithPickerView->installEventFilter(this); - qApp->inputMethod()->update(Qt::ImPlatformData); + qApp->inputMethod()->update(Qt::ImEnabled | Qt::ImPlatformData); } else { Q_ASSERT(focusObjectWithPickerView); focusObjectWithPickerView->removeEventFilter(this); - qApp->inputMethod()->update(Qt::ImPlatformData); + qApp->inputMethod()->update(Qt::ImEnabled | Qt::ImPlatformData); focusObjectWithPickerView = 0; Q_ASSERT(m_pickerView); @@ -477,6 +495,7 @@ bool QIOSMenu::eventFilter(QObject *obj, QEvent *event) imPlatformData.insert(kImePlatformDataInputView, QVariant::fromValue(static_cast(m_pickerView))); imPlatformData.insert(kImePlatformDataInputAccessoryView, QVariant::fromValue(static_cast(m_pickerView.toolbar))); queryEvent->setValue(Qt::ImPlatformData, imPlatformData); + queryEvent->setValue(Qt::ImEnabled, true); return true; } diff --git a/src/plugins/platforms/ios/qiosplatformaccessibility.mm b/src/plugins/platforms/ios/qiosplatformaccessibility.mm index ad8bd9bdf4f..705c626272c 100644 --- a/src/plugins/platforms/ios/qiosplatformaccessibility.mm +++ b/src/plugins/platforms/ios/qiosplatformaccessibility.mm @@ -58,16 +58,16 @@ void invalidateCache(QAccessibleInterface *iface) return; } - QWindow *win = 0; - QAccessibleInterface *parent = iface; - do { - win = parent->window(); - parent = parent->parent(); - } while (!win && parent); - - if (win && win->handle()) { - QIOSWindow *window = static_cast(win->handle()); - window->clearAccessibleCache(); + // This will invalidate everything regardless of what window the + // interface belonged to. We might want to revisit this strategy later. + // (Therefore this function still takes the interface as argument) + // It is also responsible for the bug that focus gets temporary lost + // when items get added or removed from the screen + foreach (QWindow *win, QGuiApplication::topLevelWindows()) { + if (win && win->handle()) { + QIOSWindow *window = static_cast(win->handle()); + window->clearAccessibleCache(); + } } } diff --git a/src/plugins/platforms/ios/qiostextresponder.h b/src/plugins/platforms/ios/qiostextresponder.h index 2923feba3b6..118ab8958a1 100644 --- a/src/plugins/platforms/ios/qiostextresponder.h +++ b/src/plugins/platforms/ios/qiostextresponder.h @@ -47,12 +47,10 @@ class QIOSInputContext; @interface QIOSTextInputResponder : UIResponder { - @public - QString m_markedText; - BOOL m_inSendEventToFocusObject; - @private QIOSInputContext *m_inputContext; + QString m_markedText; + BOOL m_inSendEventToFocusObject; } - (id)initWithInputContext:(QIOSInputContext *)context; diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index 54362cde7a3..2fcc7258f71 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -173,9 +173,13 @@ m_inSendEventToFocusObject = NO; m_inputContext = inputContext; + QVariantMap platformData = [self imValue:Qt::ImPlatformData].toMap(); Qt::InputMethodHints hints = Qt::InputMethodHints([self imValue:Qt::ImHints].toUInt()); - self.returnKeyType = (hints & Qt::ImhMultiLine) ? UIReturnKeyDefault : UIReturnKeyDone; + self.returnKeyType = platformData.value(kImePlatformDataReturnKeyType).isValid() ? + UIReturnKeyType(platformData.value(kImePlatformDataReturnKeyType).toInt()) : + (hints & Qt::ImhMultiLine) ? UIReturnKeyDefault : UIReturnKeyDone; + self.secureTextEntry = BOOL(hints & Qt::ImhHiddenText); self.autocorrectionType = (hints & Qt::ImhNoPredictiveText) ? UITextAutocorrectionTypeNo : UITextAutocorrectionTypeDefault; @@ -202,7 +206,6 @@ else self.keyboardType = UIKeyboardTypeDefault; - QVariantMap platformData = [self imValue:Qt::ImPlatformData].toMap(); if (UIView *inputView = static_cast(platformData.value(kImePlatformDataInputView).value())) self.inputView = [[[WrapperView alloc] initWithView:inputView] autorelease]; if (UIView *accessoryView = static_cast(platformData.value(kImePlatformDataInputAccessoryView).value())) @@ -218,32 +221,70 @@ [super dealloc]; } -- (BOOL)isFirstResponder +- (BOOL)canBecomeFirstResponder { return YES; } +- (BOOL)becomeFirstResponder +{ + FirstResponderCandidate firstResponderCandidate(self); + + qImDebug() << "self:" << self << "first:" << [UIResponder currentFirstResponder]; + + if (![super becomeFirstResponder]) { + qImDebug() << self << "was not allowed to become first responder"; + return NO; + } + + qImDebug() << self << "became first responder"; + + return YES; +} + +- (BOOL)resignFirstResponder +{ + qImDebug() << "self:" << self << "first:" << [UIResponder currentFirstResponder]; + + // Don't allow activation events of the window that we're doing text on behalf on + // to steal responder. + if (FirstResponderCandidate::currentCandidate() == [self nextResponder]) { + qImDebug() << "not allowing parent window to steal responder"; + return NO; + } + + if (![super resignFirstResponder]) + return NO; + + qImDebug() << self << "resigned first responder"; + + // Dismissing the keyboard will trigger resignFirstResponder, but so will + // a regular responder transfer to another window. In the former case, iOS + // will set the new first-responder to our next-responder, and in the latter + // case we'll have an active responder candidate. + if ([UIResponder currentFirstResponder] == [self nextResponder]) { + // We have resigned the keyboard, and transferred back to the parent view, so unset focus object + Q_ASSERT(!FirstResponderCandidate::currentCandidate()); + qImDebug() << "keyboard was closed, clearing focus object"; + m_inputContext->clearCurrentFocusObject(); + } else { + // We've lost responder status because another Qt window was made active, + // another QIOSTextResponder was made first-responder, another UIView was + // made first-responder, or the first-responder was cleared globally. In + // either of these cases we don't have to do anything. + qImDebug() << "lost first responder, but not clearing focus object"; + } + + return YES; +} + + - (UIResponder*)nextResponder { return qApp->focusWindow() ? reinterpret_cast(qApp->focusWindow()->handle()->winId()) : 0; } -/*! - iOS uses [UIResponder(Internal) _requiresKeyboardWhenFirstResponder] to check if the - current responder should bring up the keyboard, which in turn checks if the responder - supports the UIKeyInput protocol. By dynamically reporting our protocol conformance - we can control the keyboard visibility depending on whether or not we have a focus - object with IME enabled. -*/ -- (BOOL)conformsToProtocol:(Protocol *)protocol -{ - if (protocol == @protocol(UIKeyInput)) - return m_inputContext->inputMethodAccepted(); - - return [super conformsToProtocol:protocol]; -} - // ------------------------------------------------------------------------- - (void)notifyInputDelegate:(Qt::InputMethodQueries)updatedProperties @@ -575,9 +616,8 @@ [self sendEventToFocusObject:press]; [self sendEventToFocusObject:release]; - Qt::InputMethodHints imeHints = static_cast([self imValue:Qt::ImHints].toUInt()); - if (!(imeHints & Qt::ImhMultiLine)) - m_inputContext->hideVirtualKeyboard(); + if (self.returnKeyType == UIReturnKeyDone) + [self resignFirstResponder]; return; } diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index c46ed4c0b1c..c4b92618b1e 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -44,6 +44,7 @@ #include "qiosglobal.h" #include "qiosintegration.h" #include "qiosviewcontroller.h" +#include "qiostextresponder.h" #include "qioswindow.h" #include "qiosmenu.h" @@ -191,33 +192,66 @@ - (BOOL)becomeFirstResponder { - if ([super becomeFirstResponder]) { - QWindowSystemInterface::handleWindowActivated(m_qioswindow->window()); - QWindowSystemInterface::flushWindowSystemEvents(); + FirstResponderCandidate firstResponderCandidate(self); - return YES; + qImDebug() << "win:" << m_qioswindow->window() << "self:" << self + << "first:" << [UIResponder currentFirstResponder]; + + if (![super becomeFirstResponder]) { + qImDebug() << m_qioswindow->window() + << "was not allowed to become first responder"; + return NO; } - return NO; + qImDebug() << m_qioswindow->window() << "became first responder"; + + if (qGuiApp->focusWindow() != m_qioswindow->window()) { + QWindowSystemInterface::handleWindowActivated(m_qioswindow->window()); + QWindowSystemInterface::flushWindowSystemEvents(); + } else { + qImDebug() << m_qioswindow->window() + << "already active, not sending window activation"; + } + + return YES; +} + +- (BOOL)responderShouldTriggerWindowDeactivation:(UIResponder *)responder +{ + // We don't want to send window deactivation in case the resign + // was a result of another Qt window becoming first responder. + if ([responder isKindOfClass:[QUIView class]]) + return NO; + + // Nor do we want to deactivate the Qt window if the new responder + // is temporarily handling text input on behalf of a Qt window. + if ([responder isKindOfClass:[QIOSTextInputResponder class]]) { + while ((responder = [responder nextResponder])) { + if ([responder isKindOfClass:[QUIView class]]) + return NO; + } + } + + return YES; } - (BOOL)resignFirstResponder { - if ([super resignFirstResponder]) { - // We don't want to send window deactivation in case we're in the process - // of activating another window. The handleWindowActivated of the activation - // will take care of both. - dispatch_async(dispatch_get_main_queue (), ^{ - if (![[UIResponder currentFirstResponder] isKindOfClass:[QUIView class]]) { - QWindowSystemInterface::handleWindowActivated(0); - QWindowSystemInterface::flushWindowSystemEvents(); - } - }); + qImDebug() << "win:" << m_qioswindow->window() << "self:" << self + << "first:" << [UIResponder currentFirstResponder]; - return YES; + if (![super resignFirstResponder]) + return NO; + + qImDebug() << m_qioswindow->window() << "resigned first responder"; + + UIResponder *newResponder = FirstResponderCandidate::currentCandidate(); + if ([self responderShouldTriggerWindowDeactivation:newResponder]) { + QWindowSystemInterface::handleWindowActivated(0); + QWindowSystemInterface::flushWindowSystemEvents(); } - return NO; + return YES; } // ------------------------------------------------------------------------- diff --git a/src/plugins/platforms/ios/quiview_accessibility.mm b/src/plugins/platforms/ios/quiview_accessibility.mm index 6565e083021..7e1cb9a4fd9 100644 --- a/src/plugins/platforms/ios/quiview_accessibility.mm +++ b/src/plugins/platforms/ios/quiview_accessibility.mm @@ -48,7 +48,7 @@ - (void)createAccessibleElement:(QAccessibleInterface *)iface { - if (!iface || iface->state().invisible) + if (!iface || iface->state().invisible || (iface->text(QAccessible::Name).isEmpty() && iface->text(QAccessible::Value).isEmpty() && iface->text(QAccessible::Description).isEmpty())) return; QAccessible::Id accessibleId = QAccessible::uniqueId(iface); UIAccessibilityElement *elem = [[QMacAccessibilityElement alloc] initWithId: accessibleId withAccessibilityContainer: self]; @@ -60,12 +60,9 @@ if (!iface) return; - if (iface->childCount() == 0) { - [self createAccessibleElement: iface]; - } else { - for (int i = 0; i < iface->childCount(); ++i) - [self createAccessibleContainer: iface->child(i)]; - } + [self createAccessibleElement: iface]; + for (int i = 0; i < iface->childCount(); ++i) + [self createAccessibleContainer: iface->child(i)]; } - (void)initAccessibility diff --git a/src/plugins/platforms/kms/kms.pro b/src/plugins/platforms/kms/kms.pro index baa87781536..948d986fc5a 100644 --- a/src/plugins/platforms/kms/kms.pro +++ b/src/plugins/platforms/kms/kms.pro @@ -9,6 +9,7 @@ QT += core-private gui-private platformsupport-private qtHaveModule(opengl):QT += opengl-private DEFINES += MESA_EGL_NO_X11_HEADERS __GBM__ +contains(QT_CONFIG, libudev): DEFINES += QDEVICEDISCOVERY_UDEV CONFIG += link_pkgconfig egl qpa/genericunixfontdatabase diff --git a/src/plugins/platforms/linuxfb/linuxfb.pro b/src/plugins/platforms/linuxfb/linuxfb.pro index 389d45c29c4..5e185e357fe 100644 --- a/src/plugins/platforms/linuxfb/linuxfb.pro +++ b/src/plugins/platforms/linuxfb/linuxfb.pro @@ -9,6 +9,7 @@ QT += core-private gui-private platformsupport-private SOURCES = main.cpp qlinuxfbintegration.cpp qlinuxfbscreen.cpp HEADERS = qlinuxfbintegration.h qlinuxfbscreen.h +contains(QT_CONFIG, libudev): DEFINES += QDEVICEDISCOVERY_UDEV CONFIG += qpa/genericunixfontdatabase diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index db48e0ed938..22a4dbb09f3 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -102,15 +102,6 @@ static inline int componentVerbose(const char *v, const char *keyWord) return 0; } -static inline bool hasTouchSupport(QSysInfo::WinVersion wv) -{ - enum { QT_SM_DIGITIZER = 94, QT_NID_INTEGRATED_TOUCH = 0x1, - QT_NID_EXTERNAL_TOUCH = 0x02, QT_NID_MULTI_INPUT = 0x40 }; - - return wv < QSysInfo::WV_WINDOWS7 ? false : - (GetSystemMetrics(QT_SM_DIGITIZER) & (QT_NID_INTEGRATED_TOUCH | QT_NID_EXTERNAL_TOUCH | QT_NID_MULTI_INPUT)) != 0; -} - #if !defined(LANG_SYRIAC) # define LANG_SYRIAC 0x5a #endif @@ -318,7 +309,7 @@ QWindowsContextPrivate::QWindowsContextPrivate() QWindowsContext::shell32dll.init(); QWindowsContext::shcoredll.init(); - if (hasTouchSupport(ver) && QWindowsContext::user32dll.initTouch()) + if (m_mouseHandler.touchDevice() && QWindowsContext::user32dll.initTouch()) m_systemInfo |= QWindowsContext::SI_SupportsTouch; #endif // !Q_OS_WINCE m_displayContext = GetDC(0); diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index 4cbead44c51..f1f472b3e26 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -1224,16 +1224,21 @@ void QWindowsNativeFileDialogBase::setNameFilters(const QStringList &filters) QScopedArrayPointer buffer(new WCHAR[totalStringLength + 2 * size]); QScopedArrayPointer comFilterSpec(new COMDLG_FILTERSPEC[size]); - const QString matchesAll = QStringLiteral(" (*)"); WCHAR *ptr = buffer.data(); // Split filter specification as 'Texts (*.txt[;] *.doc)' // into description and filters specification as '*.txt;*.doc' for (int i = 0; i < size; ++i) { - // Display glitch (CLSID only): 'All files (*)' shows up as 'All files (*) (*)' + // Display glitch (CLSID only): Any filter not filtering on suffix (such as + // '*', 'a.*') will be duplicated in combo: 'All files (*) (*)', + // 'AAA files (a.*) (a.*)' QString description = specs[i].description; - if (!m_hideFiltersDetails && description.endsWith(matchesAll)) - description.truncate(description.size() - matchesAll.size()); + const QString &filter = specs[i].filter; + if (!m_hideFiltersDetails && !filter.startsWith(QLatin1String("*."))) { + const int pos = description.lastIndexOf(QLatin1Char('(')); + if (pos > 0) + description.truncate(pos); + } // Add to buffer. comFilterSpec[i].pszName = ptr; ptr += description.toWCharArray(ptr); diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index 3b277c0b5ab..c0d0c1f77cc 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -360,10 +360,10 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create() EGLDisplay display = EGL_NO_DISPLAY; #ifdef EGL_ANGLE_platform_angle_opengl if (libEGL.eglGetPlatformDisplayEXT && qEnvironmentVariableIsSet("QT_ANGLE_PLATFORM")) { - const EGLint anglePlatformAttributes[][3] = { + const EGLint anglePlatformAttributes[][5] = { { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_NONE }, { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, EGL_NONE }, - { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE, EGL_NONE } + { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_PLATFORM_ANGLE_USE_WARP_ANGLE, EGL_TRUE, EGL_NONE } }; const EGLint *attributes = 0; const QByteArray anglePlatform = qgetenv("QT_ANGLE_PLATFORM"); diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.h b/src/plugins/platforms/windows/qwindowsfontdatabase.h index efef6f4dedf..4abf2d703e8 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.h +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.h @@ -38,13 +38,13 @@ #include #include "qtwindows_additional.h" -QT_BEGIN_NAMESPACE - #if !defined(QT_NO_DIRECTWRITE) struct IDWriteFactory; struct IDWriteGdiInterop; #endif +QT_BEGIN_NAMESPACE + class QWindowsFontEngineData { Q_DISABLE_COPY(QWindowsFontEngineData) diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp index fd585ee6839..e6f30f2c356 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.cpp +++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp @@ -804,10 +804,8 @@ static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc, uint format = GGO_METRICS; if (ttf) format |= GGO_GLYPH_INDEX; - int res = GetGlyphOutline(hdc, glyph, format, &gMetric, 0, 0, &mat); - if (res == GDI_ERROR) { + if (GetGlyphOutline(hdc, glyph, format, &gMetric, 0, 0, &mat) == GDI_ERROR) return false; - } // #### obey scale *metric = glyph_metrics_t(gMetric.gmptGlyphOrigin.x, -gMetric.gmptGlyphOrigin.y, (int)gMetric.gmBlackBoxX, (int)gMetric.gmBlackBoxY, diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h index 76c57905548..2addb90de32 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h @@ -41,16 +41,16 @@ #include #include -class QWindowsFontEngineData; - -struct IDWriteFont ; -struct IDWriteFontFace ; -struct IDWriteFactory ; -struct IDWriteBitmapRenderTarget ; -struct IDWriteGdiInterop ; +struct IDWriteFont; +struct IDWriteFontFace; +struct IDWriteFactory; +struct IDWriteBitmapRenderTarget; +struct IDWriteGdiInterop; QT_BEGIN_NAMESPACE +class QWindowsFontEngineData; + class QWindowsFontEngineDirectWrite : public QFontEngine { public: diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index 990dbaeba26..ff9ad1874aa 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -39,6 +39,7 @@ #include #include +#include #include QT_BEGIN_NAMESPACE @@ -1104,9 +1105,17 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms else { const QString text = uch.isNull() ? QString() : QString(uch); const char a = uch.row() ? 0 : uch.cell(); + const Qt::KeyboardModifiers modifiers(state); +#ifndef QT_NO_SHORTCUT + // Is Qt interested in the context menu key? + if (modifiers == Qt::SHIFT && code == Qt::Key_F10 + && !QGuiApplicationPrivate::instance()->shortcutMap.hasShortcutForKeySequence(QKeySequence(Qt::SHIFT + Qt::Key_F10))) { + return false; + } +#endif // !QT_NO_SHORTCUT key_recorder.storeKey(msg.wParam, a, state, text); QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyPress, code, - Qt::KeyboardModifier(state), scancode, msg.wParam, nModifiers, text, false); + modifiers, scancode, msg.wParam, nModifiers, text, false); result =true; bool store = true; #ifndef Q_OS_WINCE diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index 39321c34607..acb692579bc 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -109,6 +109,30 @@ static inline void compressMouseMove(MSG *msg) } } +static inline QTouchDevice *createTouchDevice() +{ + enum { QT_SM_TABLETPC = 86, QT_SM_DIGITIZER = 94, QT_SM_MAXIMUMTOUCHES = 95, + QT_NID_INTEGRATED_TOUCH = 0x1, QT_NID_EXTERNAL_TOUCH = 0x02, + QT_NID_MULTI_INPUT = 0x40, QT_NID_READY = 0x80 }; + + if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS7) + return 0; + const int digitizers = GetSystemMetrics(QT_SM_DIGITIZER); + if (!(digitizers & (QT_NID_INTEGRATED_TOUCH | QT_NID_EXTERNAL_TOUCH))) + return 0; + const int tabletPc = GetSystemMetrics(QT_SM_TABLETPC); + const int maxTouchPoints = GetSystemMetrics(QT_SM_MAXIMUMTOUCHES); + qCDebug(lcQpaEvents) << "Digitizers:" << hex << showbase << (digitizers & ~QT_NID_READY) + << "Ready:" << (digitizers & QT_NID_READY) << dec << noshowbase + << "Tablet PC:" << tabletPc << "Max touch points:" << maxTouchPoints; + QTouchDevice *result = new QTouchDevice; + result->setType(digitizers & QT_NID_INTEGRATED_TOUCH + ? QTouchDevice::TouchScreen : QTouchDevice::TouchPad); + result->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::NormalizedPosition); + result->setMaximumTouchPoints(maxTouchPoints); + return result; +} + /*! \class QWindowsMouseHandler \brief Windows mouse handler @@ -122,10 +146,12 @@ static inline void compressMouseMove(MSG *msg) QWindowsMouseHandler::QWindowsMouseHandler() : m_windowUnderMouse(0), m_trackedWindow(0), - m_touchDevice(0), + m_touchDevice(createTouchDevice()), m_leftButtonDown(false), m_previousCaptureWindow(0) { + if (m_touchDevice) + QWindowSystemInterface::registerTouchDevice(m_touchDevice); } Qt::MouseButtons QWindowsMouseHandler::queryMouseButtons() @@ -404,6 +430,7 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND, typedef QWindowSystemInterface::TouchPoint QTouchPoint; typedef QList QTouchPointList; + Q_ASSERT(m_touchDevice); const QRect screenGeometry = window->screen()->geometry(); const int winTouchPointCount = msg.wParam; @@ -464,14 +491,6 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND, if (allStates == Qt::TouchPointReleased) m_touchInputIDToTouchPointID.clear(); - if (!m_touchDevice) { - m_touchDevice = new QTouchDevice; - // TODO: Device used to be hardcoded to screen in previous code. - m_touchDevice->setType(QTouchDevice::TouchScreen); - m_touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::NormalizedPosition); - QWindowSystemInterface::registerTouchDevice(m_touchDevice); - } - QWindowSystemInterface::handleTouchEvent(window, m_touchDevice, touchPoints); diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.h b/src/plugins/platforms/windows/qwindowsmousehandler.h index 967c64e597c..6491de93b51 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.h +++ b/src/plugins/platforms/windows/qwindowsmousehandler.h @@ -51,6 +51,8 @@ class QWindowsMouseHandler public: QWindowsMouseHandler(); + QTouchDevice *touchDevice() const { return m_touchDevice; } + bool translateMouseEvent(QWindow *widget, HWND hwnd, QtWindows::WindowsEventType t, MSG msg, LRESULT *result); diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.cpp b/src/plugins/platforms/winrt/qwinrteglcontext.cpp index 5daeee69c08..64aedb1b33c 100644 --- a/src/plugins/platforms/winrt/qwinrteglcontext.cpp +++ b/src/plugins/platforms/winrt/qwinrteglcontext.cpp @@ -35,8 +35,8 @@ QT_BEGIN_NAMESPACE -QWinRTEGLContext::QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLSurface surface) - : QEGLPlatformContext(format, share, display), m_eglSurface(surface) +QWinRTEGLContext::QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLSurface surface, EGLConfig config) + : QEGLPlatformContext(format, share, display, &config), m_eglSurface(surface) { } diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.h b/src/plugins/platforms/winrt/qwinrteglcontext.h index fb1199a79ea..142e204fc84 100644 --- a/src/plugins/platforms/winrt/qwinrteglcontext.h +++ b/src/plugins/platforms/winrt/qwinrteglcontext.h @@ -41,7 +41,7 @@ QT_BEGIN_NAMESPACE class QWinRTEGLContext : public QEGLPlatformContext { public: - explicit QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLSurface surface); + explicit QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLSurface surface, EGLConfig config); QFunctionPointer getProcAddress(const QByteArray &procName) Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp index b8ca9fdc666..4fa90b4b68a 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.cpp +++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp @@ -110,7 +110,7 @@ QPlatformBackingStore *QWinRTIntegration::createPlatformBackingStore(QWindow *wi QPlatformOpenGLContext *QWinRTIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const { QWinRTScreen *screen = static_cast(context->screen()->handle()); - return new QWinRTEGLContext(context->format(), context->handle(), screen->eglDisplay(), screen->eglSurface()); + return new QWinRTEGLContext(context->format(), context->handle(), screen->eglDisplay(), screen->eglSurface(), screen->eglConfig()); } QPlatformFontDatabase *QWinRTIntegration::fontDatabase() const diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 3933902ae3f..fadcd01b066 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -33,6 +33,11 @@ #include "qwinrtscreen.h" +#define EGL_EGLEXT_PROTOTYPES +#include +#include +#include + #include "qwinrtbackingstore.h" #include "qwinrtinputcontext.h" #include "qwinrtcursor.h" @@ -452,6 +457,7 @@ public: EGLDisplay eglDisplay; EGLSurface eglSurface; + EGLConfig eglConfig; QHash applicationTokens; QHash windowTokens; @@ -467,6 +473,7 @@ QWinRTScreen::QWinRTScreen() Q_D(QWinRTScreen); d->orientation = Qt::PrimaryOrientation; d->touchDevice = Q_NULLPTR; + d->eglDisplay = EGL_NO_DISPLAY; // Obtain the WinRT Application, view, and window HRESULT hr; @@ -525,8 +532,10 @@ QWinRTScreen::QWinRTScreen() Q_ASSERT_SUCCEEDED(hr); hr = d->coreWindow->add_PointerWheelChanged(Callback(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerWheelChanged]); Q_ASSERT_SUCCEEDED(hr); +#ifndef Q_OS_WINPHONE hr = d->coreWindow->add_SizeChanged(Callback(this, &QWinRTScreen::onSizeChanged).Get(), &d->windowTokens[&ICoreWindow::remove_SizeChanged]); Q_ASSERT_SUCCEEDED(hr); +#endif hr = d->coreWindow->add_Activated(Callback(this, &QWinRTScreen::onActivated).Get(), &d->windowTokens[&ICoreWindow::remove_Activated]); Q_ASSERT_SUCCEEDED(hr); hr = d->coreWindow->add_Closed(Callback(this, &QWinRTScreen::onClosed).Get(), &d->windowTokens[&ICoreWindow::remove_Closed]); @@ -575,7 +584,43 @@ QWinRTScreen::QWinRTScreen() if (!eglInitialize(d->eglDisplay, NULL, NULL)) qCritical("Failed to initialize EGL: 0x%x", eglGetError()); - d->eglSurface = eglCreateWindowSurface(d->eglDisplay, q_configFromGLFormat(d->eglDisplay, d->surfaceFormat), d->coreWindow.Get(), NULL); + // Check that the device properly supports depth/stencil rendering, and disable them if not + ComPtr d3dDevice; + const EGLBoolean ok = eglQuerySurfacePointerANGLE(d->eglDisplay, EGL_NO_SURFACE, EGL_DEVICE_EXT, (void **)d3dDevice.GetAddressOf()); + if (ok && d3dDevice) { + ComPtr dxgiDevice; + hr = d3dDevice.As(&dxgiDevice); + if (SUCCEEDED(hr)) { + ComPtr dxgiAdapter; + hr = dxgiDevice->GetAdapter(&dxgiAdapter); + if (SUCCEEDED(hr)) { + ComPtr dxgiAdapter2; + hr = dxgiAdapter.As(&dxgiAdapter2); + if (SUCCEEDED(hr)) { + DXGI_ADAPTER_DESC2 desc; + hr = dxgiAdapter2->GetDesc2(&desc); + if (SUCCEEDED(hr)) { + // The following GPUs do not render properly with depth/stencil + if ((desc.VendorId == 0x4d4f4351 && desc.DeviceId == 0x32303032)) { // Qualcomm Adreno 225 + d->surfaceFormat.setDepthBufferSize(-1); + d->surfaceFormat.setStencilBufferSize(-1); + } + } + } + } + } + } + + d->eglConfig = q_configFromGLFormat(d->eglDisplay, d->surfaceFormat); + d->surfaceFormat = q_glFormatFromConfig(d->eglDisplay, d->eglConfig, d->surfaceFormat); + const QRect bounds = geometry(); + EGLint windowAttributes[] = { + EGL_FIXED_SIZE_ANGLE, EGL_TRUE, + EGL_WIDTH, bounds.width(), + EGL_HEIGHT, bounds.height(), + EGL_NONE + }; + d->eglSurface = eglCreateWindowSurface(d->eglDisplay, d->eglConfig, d->coreWindow.Get(), windowAttributes); if (d->eglSurface == EGL_NO_SURFACE) qCritical("Failed to create EGL window surface: 0x%x", eglGetError()); } @@ -706,6 +751,12 @@ EGLSurface QWinRTScreen::eglSurface() const return d->eglSurface; } +EGLConfig QWinRTScreen::eglConfig() const +{ + Q_D(const QWinRTScreen); + return d->eglConfig; +} + QWindow *QWinRTScreen::topWindow() const { Q_D(const QWinRTScreen); @@ -1010,26 +1061,33 @@ HRESULT QWinRTScreen::onAutomationProviderRequested(ICoreWindow *, IAutomationPr return S_OK; } -HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *args) +HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *) { Q_D(QWinRTScreen); - Size size; - HRESULT hr = args->get_Size(&size); - RETURN_OK_IF_FAILED("Failed to get window size."); - + Rect size; + HRESULT hr; + hr = d->coreWindow->get_Bounds(&size); + RETURN_OK_IF_FAILED("Failed to get window bounds"); QSizeF logicalSize = QSizeF(size.Width, size.Height); +#ifndef Q_OS_WINPHONE // This handler is called from orientation changed, in which case we should always update the size if (d->logicalSize == logicalSize) return S_OK; +#endif - // Regardless of state, all top-level windows are viewport-sized - this might change if - // a more advanced compositor is written. d->logicalSize = logicalSize; - const QRect newGeometry = geometry(); - QWindowSystemInterface::handleScreenGeometryChange(screen(), newGeometry, newGeometry); - QPlatformScreen::resizeMaximizedWindows(); - handleExpose(); - + if (d->eglDisplay) { + const QRect newGeometry = geometry(); +#ifdef Q_OS_WINPHONE // Resize the EGL window + const int width = newGeometry.width() * (d->orientation == Qt::InvertedPortraitOrientation || d->orientation == Qt::LandscapeOrientation ? -1 : 1); + const int height = newGeometry.height() * (d->orientation == Qt::InvertedPortraitOrientation || d->orientation == Qt::InvertedLandscapeOrientation ? -1 : 1); + eglSurfaceAttrib(d->eglDisplay, d->eglSurface, EGL_WIDTH, width); + eglSurfaceAttrib(d->eglDisplay, d->eglSurface, EGL_HEIGHT, height); +#endif + QWindowSystemInterface::handleScreenGeometryChange(screen(), newGeometry, newGeometry); + QPlatformScreen::resizeMaximizedWindows(); + handleExpose(); + } return S_OK; } @@ -1099,6 +1157,9 @@ HRESULT QWinRTScreen::onOrientationChanged(IDisplayInformation *, IInspectable * QWindowSystemInterface::handleScreenOrientationChange(screen(), d->orientation); } +#ifdef Q_OS_WINPHONE // The size changed handler is ignored in favor of this callback + onSizeChanged(Q_NULLPTR, Q_NULLPTR); +#endif return S_OK; } diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h index e70a9982166..c95a2073ed2 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.h +++ b/src/plugins/platforms/winrt/qwinrtscreen.h @@ -109,6 +109,7 @@ public: ABI::Windows::UI::Core::ICoreWindow *coreWindow() const; EGLDisplay eglDisplay() const; // To opengl context EGLSurface eglSurface() const; // To window + EGLConfig eglConfig() const; private: void handleExpose(); diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp index 35d6b640089..8800db60d3c 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.cpp +++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp @@ -40,6 +40,14 @@ #include #include +#include +#include +#include + +using namespace ABI::Windows::UI::ViewManagement; +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; + QT_BEGIN_NAMESPACE QWinRTWindow::QWinRTWindow(QWindow *window) @@ -48,6 +56,7 @@ QWinRTWindow::QWinRTWindow(QWindow *window) { setWindowFlags(window->flags()); setWindowState(window->windowState()); + setWindowTitle(window->title()); handleContentOrientationChange(window->contentOrientation()); setGeometry(window->geometry()); } @@ -94,6 +103,24 @@ void QWinRTWindow::setVisible(bool visible) m_screen->removeWindow(window()); } +void QWinRTWindow::setWindowTitle(const QString &title) +{ + ComPtr statics; + HRESULT hr; + + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_ApplicationView).Get(), + IID_PPV_ARGS(&statics)); + RETURN_VOID_IF_FAILED("Could not get ApplicationViewStatics"); + + ComPtr view; + hr = statics->GetForCurrentView(&view); + RETURN_VOID_IF_FAILED("Could not access currentView"); + + HStringReference str(reinterpret_cast(title.utf16()), title.length()); + hr = view->put_Title(str.Get()); + RETURN_VOID_IF_FAILED("Unable to set window title"); +} + void QWinRTWindow::raise() { if (!window()->isTopLevel()) diff --git a/src/plugins/platforms/winrt/qwinrtwindow.h b/src/plugins/platforms/winrt/qwinrtwindow.h index 85f3efab5d6..7e01efa818d 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.h +++ b/src/plugins/platforms/winrt/qwinrtwindow.h @@ -52,6 +52,7 @@ public: bool isExposed() const; void setGeometry(const QRect &rect); void setVisible(bool visible); + void setWindowTitle(const QString &title); void raise(); void lower(); diff --git a/src/plugins/platforms/xcb/qglxintegration.h b/src/plugins/platforms/xcb/qglxintegration.h index 84910c41724..57779800937 100644 --- a/src/plugins/platforms/xcb/qglxintegration.h +++ b/src/plugins/platforms/xcb/qglxintegration.h @@ -75,7 +75,6 @@ private: void init(QXcbScreen *screen, QPlatformOpenGLContext *share); void init(QXcbScreen *screen, QPlatformOpenGLContext *share, const QVariant &nativeHandle); - QXcbScreen *m_screen; Display *m_display; GLXFBConfig m_config; GLXContext m_context; diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index 45856f3e6ce..8b3893ec2f5 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -276,7 +276,7 @@ QXcbClipboard::QXcbClipboard(QXcbConnection *c) m_timestamp[QClipboard::Clipboard] = XCB_CURRENT_TIME; m_timestamp[QClipboard::Selection] = XCB_CURRENT_TIME; - m_screen = connection()->screens().at(connection()->primaryScreen()); + m_screen = connection()->primaryScreen(); int x = 0, y = 0, w = 3, h = 3; diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 835c414d85a..5510c3b1b4d 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -244,7 +244,7 @@ void QXcbConnection::updateScreens() // the first or an exact match. An exact match isn't // always available if primary->output is XCB_NONE // or currently disconnected output. - if (m_primaryScreen == xcbScreenNumber) { + if (m_primaryScreenNumber == xcbScreenNumber) { if (!primaryScreen || (primary && outputs[i] == primary->output)) { primaryScreen = screen; siblings.prepend(siblings.takeLast()); @@ -306,7 +306,7 @@ void QXcbConnection::updateScreens() QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, const char *displayName) : m_connection(0) , m_canGrabServer(canGrabServer) - , m_primaryScreen(0) + , m_primaryScreenNumber(0) , m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY")) , m_nativeInterface(nativeInterface) , xfixes_first_event(0) @@ -331,7 +331,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra #ifdef XCB_USE_XLIB dpy = XOpenDisplay(m_displayName.constData()); if (dpy) { - m_primaryScreen = DefaultScreen(dpy); + m_primaryScreenNumber = DefaultScreen(dpy); m_connection = XGetXCBConnection(dpy); XSetEventQueueOwner(dpy, XCBOwnsEventQueue); XSetErrorHandler(nullErrorHandler); @@ -339,7 +339,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra m_xlib_display = dpy; } #else - m_connection = xcb_connect(m_displayName.constData(), &m_primaryScreen); + m_connection = xcb_connect(m_displayName.constData(), &m_primaryScreenNumber); #endif //XCB_USE_XLIB if (!m_connection || xcb_connection_has_error(m_connection)) @@ -449,6 +449,16 @@ QXcbConnection::~QXcbConnection() delete m_keyboard; } +QXcbScreen *QXcbConnection::primaryScreen() const +{ + if (!m_screens.isEmpty()) { + Q_ASSERT(m_screens.first()->screenNumber() == primaryScreenNumber()); + return m_screens.first(); + } + + return Q_NULLPTR; +} + void QXcbConnection::addWindowEventListener(xcb_window_t id, QXcbWindowEventListener *eventListener) { m_mapper.insert(id, eventListener); @@ -1219,7 +1229,7 @@ xcb_timestamp_t QXcbConnection::getTimestamp() xcb_window_t QXcbConnection::rootWindow() { - return screens().at(primaryScreen())->root(); + return primaryScreen()->root(); } void QXcbConnection::processXcbEvents() diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 4a16e116c6e..7286b6b89b3 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -324,6 +324,7 @@ private: class QXcbWindowEventListener { public: + virtual ~QXcbWindowEventListener() {} virtual bool handleGenericEvent(xcb_generic_event_t *, long *) { return false; } virtual void handleExposeEvent(const xcb_expose_event_t *) {} @@ -369,7 +370,8 @@ public: QXcbConnection *connection() const { return const_cast(this); } const QList &screens() const { return m_screens; } - int primaryScreen() const { return m_primaryScreen; } + int primaryScreenNumber() const { return m_primaryScreenNumber; } + QXcbScreen *primaryScreen() const; inline xcb_atom_t atom(QXcbAtom::Atom atom) const { return m_allAtoms[atom]; } QXcbAtom::Atom qatom(xcb_atom_t atom) const; @@ -469,6 +471,7 @@ public: QXcbEventReader *eventReader() const { return m_reader; } + bool canGrab() const { return m_canGrabServer; } protected: bool event(QEvent *e) Q_DECL_OVERRIDE; @@ -550,7 +553,7 @@ private: bool m_canGrabServer; QList m_screens; - int m_primaryScreen; + int m_primaryScreenNumber; xcb_atom_t m_allAtoms[QXcbAtom::NAtoms]; diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index 53437f24ae1..7037e102e2c 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -311,7 +311,7 @@ void QXcbDrag::move(const QMouseEvent *me) return; const QList &screens = connection()->screens(); - QXcbScreen *screen = screens.at(connection()->primaryScreen()); + QXcbScreen *screen = connection()->primaryScreen(); for (int i = 0; i < screens.size(); ++i) { if (screens.at(i)->geometry().contains(globalPos)) { screen = screens.at(i); diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index d3533b8e44c..3818494d99c 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -92,11 +92,11 @@ QT_BEGIN_NAMESPACE -#if defined(QT_DEBUG) && defined(Q_OS_LINUX) // Find out if our parent process is gdb by looking at the 'exe' symlink under /proc,. // or, for older Linuxes, read out 'cmdline'. static bool runningUnderDebugger() { +#if defined(QT_DEBUG) && defined(Q_OS_LINUX) const QString parentProc = QLatin1String("/proc/") + QString::number(getppid()); const QFileInfo parentProcExe(parentProc + QLatin1String("/exe")); if (parentProcExe.isSymLink()) @@ -113,12 +113,15 @@ static bool runningUnderDebugger() s += c; } return s == "gdb"; -} +#else + return false; #endif +} QXcbIntegration::QXcbIntegration(const QStringList ¶meters, int &argc, char **argv) : m_services(new QGenericUnixServices) , m_instanceName(0) + , m_canGrab(true) { qRegisterMetaType(); #ifdef XCB_USE_XLIB @@ -126,16 +129,10 @@ QXcbIntegration::QXcbIntegration(const QStringList ¶meters, int &argc, char #endif m_nativeInterface.reset(new QXcbNativeInterface); - bool canGrab = true; - #if defined(QT_DEBUG) && defined(Q_OS_LINUX) - canGrab = !runningUnderDebugger(); - #endif - static bool canNotGrabEnv = qgetenv("QT_XCB_NO_GRAB_SERVER").length(); - if (canNotGrabEnv) - canGrab = false; - // Parse arguments const char *displayName = 0; + bool noGrabArg = false; + bool doGrabArg = false; if (argc) { int j = 1; for (int i = 1; i < argc; i++) { @@ -146,13 +143,35 @@ QXcbIntegration::QXcbIntegration(const QStringList ¶meters, int &argc, char displayName = argv[++i]; else if (arg == "-name" && i < argc - 1) m_instanceName = argv[++i]; + else if (arg == "-nograb") + noGrabArg = true; + else if (arg == "-dograb") + doGrabArg = true; else argv[j++] = argv[i]; } argc = j; } // argc - m_connections << new QXcbConnection(m_nativeInterface.data(), canGrab, displayName); + bool underDebugger = runningUnderDebugger(); + if (noGrabArg && doGrabArg && underDebugger) { + qWarning() << "Both -nograb and -dograb command line arguments specified. Please pick one. -nograb takes prcedence"; + doGrabArg = false; + } + +#if defined(QT_DEBUG) + if (!noGrabArg && !doGrabArg && underDebugger) { + qDebug("Qt: gdb: -nograb added to command-line options.\n" + "\t Use the -dograb option to enforce grabbing."); + } +#endif + m_canGrab = (!underDebugger && noGrabArg) || (underDebugger && doGrabArg); + + static bool canNotGrabEnv = qEnvironmentVariableIsSet("QT_XCB_NO_GRAB_SERVER"); + if (canNotGrabEnv) + m_canGrab = false; + + m_connections << new QXcbConnection(m_nativeInterface.data(), m_canGrab, displayName); for (int i = 0; i < parameters.size() - 1; i += 2) { #ifdef Q_XCB_DEBUG @@ -408,19 +427,19 @@ QVariant QXcbIntegration::styleHint(QPlatformIntegration::StyleHint hint) const case QPlatformIntegration::StartDragTime: case QPlatformIntegration::KeyboardAutoRepeatRate: case QPlatformIntegration::PasswordMaskDelay: - case QPlatformIntegration::FontSmoothingGamma: case QPlatformIntegration::StartDragVelocity: case QPlatformIntegration::UseRtlExtensions: case QPlatformIntegration::PasswordMaskCharacter: // TODO using various xcb, gnome or KDE settings break; // Not implemented, use defaults + case QPlatformIntegration::FontSmoothingGamma: + // Match Qt 4.8 text rendering, and rendering of other X11 toolkits. + return qreal(1.0); case QPlatformIntegration::StartDragDistance: { // The default (in QPlatformTheme::defaultThemeHint) is 10 pixels, but // on a high-resolution screen it makes sense to increase it. - const QList &screens = defaultConnection()->screens(); qreal dpi = 100.0; - if (screens.length() > 0) { - const QXcbScreen *screen = screens.at(defaultConnection()->primaryScreen()); + if (const QXcbScreen *screen = defaultConnection()->primaryScreen()) { if (screen->logicalDpi().first > dpi) dpi = screen->logicalDpi().first; if (screen->logicalDpi().second > dpi) diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h index ffb068ecb3d..db6ad541eab 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.h +++ b/src/plugins/platforms/xcb/qxcbintegration.h @@ -117,6 +117,7 @@ private: mutable QByteArray m_wmClass; const char *m_instanceName; + bool m_canGrab; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index dae3a79628a..260fb46309a 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -721,7 +721,7 @@ void QXcbKeyboard::updateKeymap() if (xkb_keymap) { new_state = xkb_state_new(xkb_keymap); } else { - printKeymapError("Failed to compile a keymap!"); + printKeymapError("Qt: Failed to compile a keymap!"); m_config = false; return; } @@ -737,6 +737,8 @@ void QXcbKeyboard::updateKeymap() xkb_state = new_state; if (!connection()->hasXKB()) updateXKBMods(); + + checkForLatinLayout(); } #ifndef QT_NO_XKB @@ -824,37 +826,137 @@ void QXcbKeyboard::updateXKBMods() xkb_mods.mod5 = xkb_keymap_mod_get_index(xkb_keymap, "Mod5"); } +static bool isLatin(xkb_keysym_t sym) +{ + return ((sym >= 'a' && sym <= 'z') || (sym >= 'A' && sym <= 'Z')); +} + +void QXcbKeyboard::checkForLatinLayout() +{ + m_hasLatinLayout = false; + const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts(xkb_keymap); + const xcb_keycode_t minKeycode = connection()->setup()->min_keycode; + const xcb_keycode_t maxKeycode = connection()->setup()->max_keycode; + struct xkb_state *kb_state = xkb_state_new(xkb_keymap); + for (xkb_layout_index_t layout = 0; layout < layoutCount; ++layout) { + xkb_state_update_mask(kb_state, 0, 0, 0, 0, 0, layout); + for (xcb_keycode_t code = minKeycode; code < maxKeycode; ++code) { + xkb_keysym_t sym = xkb_state_key_get_one_sym(kb_state, code); + // if layout can produce any of these latin letters (chosen + // arbitrarily) then it must be a latin key based layout + if (sym == XK_q || sym == XK_a || sym == XK_e) { + m_hasLatinLayout = true; + xkb_state_unref(kb_state); + return; + } + } + } + xkb_state_unref(kb_state); +} + +xkb_keysym_t QXcbKeyboard::lookupLatinKeysym(xkb_keycode_t keycode) const +{ + xkb_layout_index_t layout; + xkb_keysym_t sym = XKB_KEY_NoSymbol; + const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts_for_key(xkb_keymap, keycode); + const xkb_layout_index_t currentLayout = xkb_state_key_get_layout(xkb_state, keycode); + // Look at user layouts in the order in which they are defined in system + // settings to find a latin keysym. + for (layout = 0; layout < layoutCount; ++layout) { + if (layout == currentLayout) + continue; + const xkb_keysym_t *syms; + xkb_level_index_t level = xkb_state_key_get_level(xkb_state, keycode, layout); + if (xkb_keymap_key_get_syms_by_level(xkb_keymap, keycode, layout, level, &syms) != 1) + continue; + if (isLatin(syms[0])) { + sym = syms[0]; + break; + } + } + // If user layouts don't contain any layout that results in a latin key, we query a + // key from "US" layout, this allows for latin-key-based shorcuts to work even when + // users have only one (non-latin) layout set. + xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED); + xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED); + if (sym == XKB_KEY_NoSymbol && !m_hasLatinLayout) { + if (!latin_keymap) { + const struct xkb_rule_names names = { xkb_names.rules, xkb_names.model, "us", 0, 0 }; + latin_keymap = xkb_keymap_new_from_names(xkb_context, &names, (xkb_keymap_compile_flags)0); + static bool printFailure = true; + if (!latin_keymap && printFailure) { + // print message about failure to compile US keymap only once, + // no need to do this on every key press. + printFailure = false; + printKeymapError("Qt: Failed to compile US keymap, shortcut handling with " + "non-Latin keyboard layouts may not be fully functional!"); + } + } + if (latin_keymap) { + struct xkb_state *latin_state = xkb_state_new(latin_keymap); + if (latin_state) { + xkb_state_update_mask(latin_state, 0, latchedMods, lockedMods, 0, 0, 0); + sym = xkb_state_key_get_one_sym(latin_state, keycode); + xkb_state_unref(latin_state); + } else { + qWarning("QXcbKeyboard: failed to create a state for US keymap!"); + } + } + } + if (sym == XKB_KEY_NoSymbol) + return sym; + // Check for uniqueness, consider the following setup: + // setxkbmap -layout us,ru,us -variant dvorak,, -option 'grp:ctrl_alt_toggle' (set 'ru' as active). + // In this setup, the user would expect to trigger a ctrl+q shortcut by pressing ctrl+, + // because "US dvorak" is higher up in the layout settings list. This check verifies that an obtained + // 'sym' can not be acquired by any other layout higher up in the user's layout list. If it can be acquired + // then the obtained key is not unique. This prevents ctrl+ from generating a ctrl+q + // shortcut in the above described setup. We don't want ctrl+ and ctrl+ to + // generate the same shortcut event in this case. + const xcb_keycode_t minKeycode = connection()->setup()->min_keycode; + const xcb_keycode_t maxKeycode = connection()->setup()->max_keycode; + struct xkb_state *kb_state = xkb_state_new(xkb_keymap); + for (xkb_layout_index_t prevLayout = 0; prevLayout < layout; ++prevLayout) { + xkb_state_update_mask(kb_state, 0, latchedMods, lockedMods, 0, 0, prevLayout); + for (xcb_keycode_t code = minKeycode; code < maxKeycode; ++code) { + xkb_keysym_t prevSym = xkb_state_key_get_one_sym(kb_state, code); + if (prevSym == sym) { + sym = XKB_KEY_NoSymbol; + break; + } + } + } + xkb_state_unref(kb_state); + return sym; +} + QList QXcbKeyboard::possibleKeys(const QKeyEvent *event) const { // turn off the modifier bits which doesn't participate in shortcuts Qt::KeyboardModifiers notNeeded = Qt::MetaModifier | Qt::KeypadModifier | Qt::GroupSwitchModifier; Qt::KeyboardModifiers modifiers = event->modifiers() &= ~notNeeded; // create a fresh kb state and test against the relevant modifier combinations - // NOTE: it should be possible to query the keymap directly, once it gets - // supported by libxkbcommon - struct xkb_state * kb_state = xkb_state_new(xkb_keymap); + struct xkb_state *kb_state = xkb_state_new(xkb_keymap); if (!kb_state) { - qWarning("QXcbKeyboard: failed to compile xkb keymap"); + qWarning("QXcbKeyboard: failed to compile xkb keymap!"); return QList(); } // get kb state from the master xkb_state and update the temporary kb_state - xkb_layout_index_t baseLayout = xkb_state_serialize_layout(xkb_state, XKB_STATE_LAYOUT_DEPRESSED); - xkb_layout_index_t latchedLayout = xkb_state_serialize_layout(xkb_state, XKB_STATE_LAYOUT_LATCHED); xkb_layout_index_t lockedLayout = xkb_state_serialize_layout(xkb_state, XKB_STATE_LAYOUT_LOCKED); xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED); xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED); - xkb_state_update_mask(kb_state, 0, latchedMods, lockedMods, - baseLayout, latchedLayout, lockedLayout); + xkb_state_update_mask(kb_state, 0, latchedMods, lockedMods, 0, 0, lockedLayout); - xkb_keysym_t sym = xkb_state_key_get_one_sym(kb_state, event->nativeScanCode()); + quint32 keycode = event->nativeScanCode(); + xkb_keysym_t sym = xkb_state_key_get_one_sym(kb_state, keycode); if (sym == XKB_KEY_NoSymbol) { xkb_state_unref(kb_state); return QList(); } QList result; - int baseQtKey = keysymToQtKey(sym, modifiers, lookupString(kb_state, event->nativeScanCode())); + int baseQtKey = keysymToQtKey(sym, modifiers, lookupString(kb_state, keycode)); result += (baseQtKey + modifiers); // The base key is _always_ valid, of course xkb_mod_index_t shiftMod = xkb_keymap_mod_get_index(xkb_keymap, "Shift"); @@ -866,48 +968,33 @@ QList QXcbKeyboard::possibleKeys(const QKeyEvent *event) const Q_ASSERT(controlMod < 32); xkb_mod_mask_t depressed; - struct xkb_keymap *fallback_keymap = 0; int qtKey = 0; - //obtain a list of possible shortcuts for the given key event + // obtain a list of possible shortcuts for the given key event for (uint i = 1; i < sizeof(ModsTbl) / sizeof(*ModsTbl) ; ++i) { Qt::KeyboardModifiers neededMods = ModsTbl[i]; if ((modifiers & neededMods) == neededMods) { - - depressed = 0; - if (neededMods & Qt::AltModifier) - depressed |= (1 << altMod); - if (neededMods & Qt::ShiftModifier) - depressed |= (1 << shiftMod); - if (neededMods & Qt::ControlModifier) - depressed |= (1 << controlMod); - - // update a keyboard state from a set of explicit masks if (i == 8) { - // Add a fall back key for layouts with non Latin-1 characters - if (baseQtKey > 255) { - struct xkb_rule_names names = { xkb_names.rules, xkb_names.model, "us", 0, 0 }; - fallback_keymap = xkb_keymap_new_from_names(xkb_context, &names, (xkb_keymap_compile_flags)0); - if (!fallback_keymap) - continue; - xkb_state_unref(kb_state); - kb_state = xkb_state_new(fallback_keymap); - if (!kb_state) - continue; - } else + if (isLatin(baseQtKey)) continue; + // add a latin key as a fall back key + sym = lookupLatinKeysym(keycode); } else { - xkb_state_update_mask(kb_state, depressed, latchedMods, lockedMods, - baseLayout, latchedLayout, lockedLayout); + depressed = 0; + if (neededMods & Qt::AltModifier) + depressed |= (1 << altMod); + if (neededMods & Qt::ShiftModifier) + depressed |= (1 << shiftMod); + if (neededMods & Qt::ControlModifier) + depressed |= (1 << controlMod); + xkb_state_update_mask(kb_state, depressed, latchedMods, lockedMods, 0, 0, lockedLayout); + sym = xkb_state_key_get_one_sym(kb_state, keycode); } - sym = xkb_state_key_get_one_sym(kb_state, event->nativeScanCode()); - if (sym == XKB_KEY_NoSymbol) continue; Qt::KeyboardModifiers mods = modifiers & ~neededMods; - qtKey = keysymToQtKey(sym, mods, lookupString(kb_state, event->nativeScanCode())); - - if (qtKey == baseQtKey || qtKey == 0) + qtKey = keysymToQtKey(sym, mods, lookupString(kb_state, keycode)); + if (!qtKey || qtKey == baseQtKey) continue; // catch only more specific shortcuts, i.e. Ctrl+Shift+= also generates Ctrl++ and +, @@ -926,8 +1013,6 @@ QList QXcbKeyboard::possibleKeys(const QKeyEvent *event) const } } xkb_state_unref(kb_state); - xkb_keymap_unref(fallback_keymap); - return result; } @@ -1002,6 +1087,8 @@ QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection) , xkb_context(0) , xkb_keymap(0) , xkb_state(0) + , latin_keymap(0) + , m_hasLatinLayout(false) { memset(&xkb_names, 0, sizeof(xkb_names)); #ifndef QT_NO_XKB @@ -1029,6 +1116,7 @@ QXcbKeyboard::~QXcbKeyboard() xkb_state_unref(xkb_state); xkb_keymap_unref(xkb_keymap); xkb_context_unref(xkb_context); + xkb_keymap_unref(latin_keymap); if (!connection()->hasXKB()) xcb_key_symbols_free(m_key_symbols); clearXKBConfig(); @@ -1324,7 +1412,6 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, if (type == QEvent::KeyPress) targetWindow->updateNetWmUserTime(time); - // It is crucial the order of xkb_state_key_get_one_sym & xkb_state_update_key operations is not reversed! xcb_keysym_t sym = xkb_state_key_get_one_sym(xkb_state, code); QPlatformInputContext *inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext(); @@ -1348,15 +1435,22 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, return; } - Qt::KeyboardModifiers modifiers = translateModifiers(state); - QString string = lookupString(xkb_state, code); int count = string.size(); string.truncate(count); - int qtcode = keysymToQtKey(sym, modifiers, string); - bool isAutoRepeat = false; + // Ιf control modifier is set we should prefer latin character, this is + // used for standard shortcuts in checks like "key == QKeySequence::Copy", + // users can still see the actual X11 keysym with QKeyEvent::nativeVirtualKey + Qt::KeyboardModifiers modifiers = translateModifiers(state); + xcb_keysym_t translatedSym = XKB_KEY_NoSymbol; + if (modifiers & Qt::ControlModifier && !isLatin(sym)) + translatedSym = lookupLatinKeysym(code); + if (translatedSym == XKB_KEY_NoSymbol) + translatedSym = sym; + int qtcode = keysymToQtKey(translatedSym, modifiers, string); + bool isAutoRepeat = false; if (type == QEvent::KeyPress) { if (m_autorepeat_code == code) { isAutoRepeat = true; diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h index e71165d824b..9f1cf165cb5 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.h +++ b/src/plugins/platforms/xcb/qxcbkeyboard.h @@ -91,6 +91,9 @@ protected: void updateVModMapping(); void updateVModToRModMapping(); + xkb_keysym_t lookupLatinKeysym(xkb_keycode_t keycode) const; + void checkForLatinLayout(); + private: bool m_config; xcb_keycode_t m_autorepeat_code; @@ -99,6 +102,7 @@ private: struct xkb_keymap *xkb_keymap; struct xkb_state *xkb_state; struct xkb_rule_names xkb_names; + mutable struct xkb_keymap *latin_keymap; struct _mod_masks { uint alt; @@ -128,6 +132,7 @@ private: _mod_masks vmod_masks; int core_device_id; #endif + bool m_hasLatinLayout; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index 0d75a7f0321..3058b29f2df 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -367,7 +367,7 @@ void *QXcbNativeInterface::x11Screen() QXcbIntegration *integration = static_cast(QGuiApplicationPrivate::platformIntegration()); QXcbConnection *defaultConnection = integration->defaultConnection(); if (defaultConnection) - return reinterpret_cast(defaultConnection->primaryScreen()); + return reinterpret_cast(defaultConnection->primaryScreenNumber()); return 0; } diff --git a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp index 9ec4ea80ec7..40a50f61ab4 100644 --- a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp +++ b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp @@ -59,7 +59,7 @@ QXcbSystemTrayTracker *QXcbSystemTrayTracker::create(QXcbConnection *connection) const xcb_atom_t trayAtom = connection->atom(QXcbAtom::_NET_SYSTEM_TRAY_OPCODE); if (!trayAtom) return 0; - const QByteArray netSysTray = QByteArrayLiteral("_NET_SYSTEM_TRAY_S") + QByteArray::number(connection->primaryScreen()); + const QByteArray netSysTray = QByteArrayLiteral("_NET_SYSTEM_TRAY_S") + QByteArray::number(connection->primaryScreenNumber()); const xcb_atom_t selection = connection->internAtom(netSysTray.constData()); if (!selection) return 0; @@ -145,11 +145,8 @@ QRect QXcbSystemTrayTracker::systemTrayWindowGlobalGeometry(xcb_window_t window) inline void QXcbSystemTrayTracker::emitSystemTrayWindowChanged() { - const int screen = m_connection->primaryScreen(); - if (screen >= 0 && screen < m_connection->screens().size()) { - const QPlatformScreen *ps = m_connection->screens().at(screen); + if (const QPlatformScreen *ps = m_connection->primaryScreen()) emit systemTrayWindowChanged(ps->screen()); - } } // Client messages with the "MANAGER" atom on the root window indicate creation of a new tray. diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 0c2e9d047c5..85af8ee1d25 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -2170,6 +2170,9 @@ void QXcbWindow::updateSyncRequestCounter() bool QXcbWindow::setKeyboardGrabEnabled(bool grab) { + if (grab && !connection()->canGrab()) + return false; + if (!grab) { xcb_ungrab_keyboard(xcb_connection(), XCB_TIME_CURRENT_TIME); return true; @@ -2185,6 +2188,9 @@ bool QXcbWindow::setKeyboardGrabEnabled(bool grab) bool QXcbWindow::setMouseGrabEnabled(bool grab) { + if (grab && !connection()->canGrab()) + return false; + if (!grab) { xcb_ungrab_pointer(xcb_connection(), XCB_TIME_CURRENT_TIME); return true; @@ -2380,13 +2386,10 @@ void QXcbWindow::setAlertState(bool enabled) { if (m_alertState == enabled) return; - const NetWmStates oldState = netWmStates(); + m_alertState = enabled; - if (enabled) { - setNetWmStates(oldState | NetWmStateDemandsAttention); - } else { - setNetWmStates(oldState & ~NetWmStateDemandsAttention); - } + + changeNetWmState(enabled, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION)); } bool QXcbWindow::needsSync() const diff --git a/src/plugins/platforms/xcb/qxcbwmsupport.cpp b/src/plugins/platforms/xcb/qxcbwmsupport.cpp index 0458be32f6a..1be9ab3e058 100644 --- a/src/plugins/platforms/xcb/qxcbwmsupport.cpp +++ b/src/plugins/platforms/xcb/qxcbwmsupport.cpp @@ -56,7 +56,7 @@ void QXcbWMSupport::updateNetWMAtoms() { net_wm_atoms.clear(); - xcb_window_t root = connection()->screens().at(connection()->primaryScreen())->root(); + xcb_window_t root = connection()->primaryScreen()->root(); int offset = 0; int remaining = 0; do { @@ -90,7 +90,7 @@ void QXcbWMSupport::updateVirtualRoots() if (!isSupportedByWM(atom(QXcbAtom::_NET_VIRTUAL_ROOTS))) return; - xcb_window_t root = connection()->screens().at(connection()->primaryScreen())->root(); + xcb_window_t root = connection()->primaryScreen()->root(); int offset = 0; int remaining = 0; do { diff --git a/src/plugins/platforms/xcb/qxcbxsettings.cpp b/src/plugins/platforms/xcb/qxcbxsettings.cpp index 6f2e60c9bef..13d42832db0 100644 --- a/src/plugins/platforms/xcb/qxcbxsettings.cpp +++ b/src/plugins/platforms/xcb/qxcbxsettings.cpp @@ -262,6 +262,12 @@ QXcbXSettings::QXcbXSettings(QXcbScreen *screen) d_ptr->initialized = true; } +QXcbXSettings::~QXcbXSettings() +{ + delete d_ptr; + d_ptr = 0; +} + bool QXcbXSettings::initialized() const { Q_D(const QXcbXSettings); diff --git a/src/plugins/platforms/xcb/qxcbxsettings.h b/src/plugins/platforms/xcb/qxcbxsettings.h index 717fe559c99..3496cedf366 100644 --- a/src/plugins/platforms/xcb/qxcbxsettings.h +++ b/src/plugins/platforms/xcb/qxcbxsettings.h @@ -45,6 +45,7 @@ class QXcbXSettings : public QXcbWindowEventListener Q_DECLARE_PRIVATE(QXcbXSettings) public: QXcbXSettings(QXcbScreen *screen); + ~QXcbXSettings(); bool initialized() const; QVariant setting(const QByteArray &property) const; diff --git a/src/plugins/platforms/xcb/xcb-plugin.pro b/src/plugins/platforms/xcb/xcb-plugin.pro index 9aaafadcad8..f14fcde73f4 100644 --- a/src/plugins/platforms/xcb/xcb-plugin.pro +++ b/src/plugins/platforms/xcb/xcb-plugin.pro @@ -60,7 +60,7 @@ contains(QT_CONFIG, xcb-xlib) { # to support custom cursors with depth > 1 contains(QT_CONFIG, xcb-render) { DEFINES += XCB_USE_RENDER - LIBS += -lxcb-render -lxcb-render-util -lXrender + LIBS += -lxcb-render -lxcb-render-util } # build with session management support diff --git a/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp b/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp index c5f8338dabe..d7e73c873d7 100644 --- a/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp +++ b/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp @@ -82,6 +82,7 @@ QGtk2Dialog::QGtk2Dialog(GtkWidget *gtkWidget) : gtkWidget(gtkWidget) QGtk2Dialog::~QGtk2Dialog() { + gtk_clipboard_store(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD)); gtk_widget_destroy(gtkWidget); } diff --git a/src/plugins/printsupport/cups/qppdprintdevice.cpp b/src/plugins/printsupport/cups/qppdprintdevice.cpp index 7a6acf8b78c..d20fbb558b8 100644 --- a/src/plugins/printsupport/cups/qppdprintdevice.cpp +++ b/src/plugins/printsupport/cups/qppdprintdevice.cpp @@ -470,9 +470,10 @@ void QPpdPrintDevice::loadPrinter() m_cupsDest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, m_cupsName, m_cupsInstance); if (m_cupsDest) { const char *ppdFile = cupsGetPPD(m_cupsName); - if (ppdFile) + if (ppdFile) { m_ppd = ppdOpenFile(ppdFile); - unlink(ppdFile); + unlink(ppdFile); + } if (m_ppd) { ppdMarkDefaults(m_ppd); } else { diff --git a/src/printsupport/kernel/qprintengine_win.cpp b/src/printsupport/kernel/qprintengine_win.cpp index 90b204eb0cf..4e0a3e07959 100644 --- a/src/printsupport/kernel/qprintengine_win.cpp +++ b/src/printsupport/kernel/qprintengine_win.cpp @@ -269,7 +269,8 @@ void QWin32PrintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem bool fallBack = state->pen().brush().style() != Qt::SolidPattern || qAlpha(brushColor) != 0xff || d->txop >= QTransform::TxProject - || ti.fontEngine->type() != QFontEngine::Win; + || ti.fontEngine->type() != QFontEngine::Win + || !d->embed_fonts; if (!fallBack) { const QVariantMap userData = ti.fontEngine->userData().toMap(); @@ -716,8 +717,6 @@ void QWin32PrintEnginePrivate::fillPath_dev(const QPainterPath &path, const QCol void QWin32PrintEnginePrivate::strokePath_dev(const QPainterPath &path, const QColor &color, qreal penWidth) { - Q_Q(QWin32PrintEngine); - composeGdiPath(path); LOGBRUSH brush; brush.lbStyle = BS_SOLID; @@ -1003,8 +1002,6 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & // The following keys are settings that are unsupported by the Windows PrintEngine case PPK_CustomBase: break; - case PPK_FontEmbedding: - break; case PPK_PageOrder: break; case PPK_PrinterProgram: @@ -1013,6 +1010,10 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & break; // The following keys are properties and settings that are supported by the Windows PrintEngine + case PPK_FontEmbedding: + d->embed_fonts = value.toBool(); + break; + case PPK_CollateCopies: { if (!d->devMode) @@ -1284,9 +1285,6 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const // The following keys are settings that are unsupported by the Windows PrintEngine // Return sensible default values to ensure consistent behavior across platforms - case PPK_FontEmbedding: - value = false; - break; case PPK_PageOrder: value = QPrinter::FirstPageFirst; break; @@ -1298,6 +1296,10 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const break; // The following keys are properties and settings that are supported by the Windows PrintEngine + case PPK_FontEmbedding: + value = d->embed_fonts; + break; + case PPK_CollateCopies: value = d->devMode->dmCollate == DMCOLLATE_TRUE; break; diff --git a/src/printsupport/kernel/qprintengine_win_p.h b/src/printsupport/kernel/qprintengine_win_p.h index b84bde8a92d..0a87795bb84 100644 --- a/src/printsupport/kernel/qprintengine_win_p.h +++ b/src/printsupport/kernel/qprintengine_win_p.h @@ -125,7 +125,8 @@ public: m_pageLayout(QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0, 0, 0, 0))), num_copies(1), printToFile(false), - reinit(false) + reinit(false), + embed_fonts(true) { } @@ -216,6 +217,7 @@ public: uint has_pen : 1; uint has_brush : 1; uint has_custom_paper_size : 1; + uint embed_fonts : 1; uint txop; diff --git a/src/printsupport/kernel/qprinter.cpp b/src/printsupport/kernel/qprinter.cpp index c13b1574d0b..437a68e6097 100644 --- a/src/printsupport/kernel/qprinter.cpp +++ b/src/printsupport/kernel/qprinter.cpp @@ -1632,8 +1632,6 @@ QPrinter::PaperSource QPrinter::paperSource() const Enabled or disables font embedding depending on \a enable. - Currently this option is only supported on X11. - \sa fontEmbeddingEnabled() */ void QPrinter::setFontEmbeddingEnabled(bool enable) @@ -1647,8 +1645,6 @@ void QPrinter::setFontEmbeddingEnabled(bool enable) Returns \c true if font embedding is enabled. - Currently this option is only supported on X11. - \sa setFontEmbeddingEnabled() */ bool QPrinter::fontEmbeddingEnabled() const diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h index d3443e73909..62982629585 100644 --- a/src/testlib/qtest.h +++ b/src/testlib/qtest.h @@ -46,7 +46,6 @@ #include #include #include -#include #include #include @@ -164,11 +163,6 @@ template<> inline char *toString(const QVariant &v) return qstrdup(vstring.constData()); } -template<> inline char *toString(const QVersionNumber &version) -{ - return toString(version.toString()); -} - template<> inline bool qCompare(QString const &t1, QLatin1String const &t2, const char *actual, const char *expected, const char *file, int line) diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 2d92b3f6bdc..24d563045bf 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -1027,13 +1027,6 @@ QT_BEGIN_NAMESPACE Returns a textual representation of the given \a variant. */ -/*! - \fn char *QTest::toString(const QVersionNumber &version) - \overload - - Returns a textual representation of the given \a version. -*/ - /*! \fn void QTest::qWait(int ms) Waits for \a ms milliseconds. While waiting, events will be processed and @@ -1735,7 +1728,8 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml) } else if (strcmp(argv[i], "-vb") == 0) { QBenchmarkGlobalData::current->verboseOutput = true; #ifdef Q_OS_WINRT - } else if (strncmp(argv[i], "-ServerName:", 12) == 0) { + } else if (strncmp(argv[i], "-ServerName:", 12) == 0 || + strncmp(argv[i], "-qdevel", 7) == 0) { continue; #endif } else if (argv[i][0] == '-') { @@ -2159,7 +2153,7 @@ char *toPrettyUnicode(const ushort *p, int length) break; } - if (*p < 0x7f && *p >= 0x20 && *p != '\\') { + if (*p < 0x7f && *p >= 0x20 && *p != '\\' && *p != '"') { *dst++ = *p; continue; } diff --git a/src/testlib/qtesteventloop.h b/src/testlib/qtesteventloop.h index 9e738d2c474..034655cc501 100644 --- a/src/testlib/qtesteventloop.h +++ b/src/testlib/qtesteventloop.h @@ -40,6 +40,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -101,6 +102,12 @@ inline void QTestEventLoop::enterLoopMSecs(int ms) inline void QTestEventLoop::exitLoop() { + if (thread() != QThread::currentThread()) + { + QMetaObject::invokeMethod(this, "exitLoop", Qt::QueuedConnection); + return; + } + if (timerId != -1) killTimer(timerId); timerId = -1; diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp index 7ea953232f3..e48fdc1ad0d 100644 --- a/src/testlib/qtestlog.cpp +++ b/src/testlib/qtestlog.cpp @@ -279,7 +279,6 @@ namespace QTest { return; QString msg = qFormatLogMessage(type, context, message); - msg.chop(1); // remove trailing newline if (type != QtFatalMsg) { if (counter.load() <= 0) diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index 3924ecfa7fa..e0f55469668 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -142,8 +142,9 @@ mac { } macx { - SOURCES += \ - ../../corelib/io/qstandardpaths_mac.cpp + OBJECTIVE_SOURCES += \ + ../../corelib/tools/qstring_mac.mm \ + ../../corelib/io/qstandardpaths_mac.mm } else:unix { SOURCES += \ ../../corelib/io/qstandardpaths_unix.cpp diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index acc635c5ca1..912fa995fa2 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -501,7 +501,7 @@ void Generator::generateCode() for (int i = 0; i < extraList.count(); ++i) { fprintf(out, " &%s::staticMetaObject,\n", extraList.at(i).constData()); } - fprintf(out, " 0\n};\n\n"); + fprintf(out, " Q_NULLPTR\n};\n\n"); } // @@ -513,24 +513,24 @@ void Generator::generateCode() fprintf(out, "const QMetaObject %s::staticMetaObject = {\n", cdef->qualified.constData()); if (isQObject) - fprintf(out, " { 0, "); + fprintf(out, " { Q_NULLPTR, "); else if (cdef->superclassList.size()) fprintf(out, " { &%s::staticMetaObject, ", purestSuperClass.constData()); else - fprintf(out, " { 0, "); + fprintf(out, " { Q_NULLPTR, "); fprintf(out, "qt_meta_stringdata_%s.data,\n" " qt_meta_data_%s, ", qualifiedClassNameIdentifier.constData(), qualifiedClassNameIdentifier.constData()); if (hasStaticMetaCall) fprintf(out, " qt_static_metacall, "); else - fprintf(out, " 0, "); + fprintf(out, " Q_NULLPTR, "); if (extraList.isEmpty()) - fprintf(out, "0, "); + fprintf(out, "Q_NULLPTR, "); else fprintf(out, "qt_meta_extradata_%s, ", qualifiedClassNameIdentifier.constData()); - fprintf(out, "0}\n};\n\n"); + fprintf(out, "Q_NULLPTR}\n};\n\n"); if(isQt) return; @@ -545,7 +545,7 @@ void Generator::generateCode() // Generate smart cast function // fprintf(out, "\nvoid *%s::qt_metacast(const char *_clname)\n{\n", cdef->qualified.constData()); - fprintf(out, " if (!_clname) return 0;\n"); + fprintf(out, " if (!_clname) return Q_NULLPTR;\n"); fprintf(out, " if (!strcmp(_clname, qt_meta_stringdata_%s.stringdata))\n" " return static_cast(const_cast< %s*>(this));\n", qualifiedClassNameIdentifier.constData(), cdef->classname.constData()); @@ -570,7 +570,7 @@ void Generator::generateCode() QByteArray superClass = purestSuperClass; fprintf(out, " return %s::qt_metacast(_clname);\n", superClass.constData()); } else { - fprintf(out, " return 0;\n"); + fprintf(out, " return Q_NULLPTR;\n"); } fprintf(out, "}\n"); @@ -1450,7 +1450,7 @@ void Generator::generateSignal(FunctionDef *def,int index) fprintf(out, "QPrivateSignal"); fprintf(out, ")%s\n{\n" - " QMetaObject::activate(%s, &staticMetaObject, %d, 0);\n" + " QMetaObject::activate(%s, &staticMetaObject, %d, Q_NULLPTR);\n" "}\n", constQualifier, thisPtr.constData(), index); return; } @@ -1480,7 +1480,7 @@ void Generator::generateSignal(FunctionDef *def,int index) fprintf(out, " void *_a[] = { "); if (def->normalizedType == "void") { - fprintf(out, "0"); + fprintf(out, "Q_NULLPTR"); } else { if (def->returnTypeIsVolatile) fprintf(out, "const_cast(reinterpret_cast(&_t0))"); diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp index 03369816497..687c4f84743 100644 --- a/src/tools/moc/preprocessor.cpp +++ b/src/tools/moc/preprocessor.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -** Copyright (C) 2013 Olivier Goffart +** Copyright (C) 2014 Olivier Goffart ** Contact: http://www.qt-project.org/legal ** ** This file is part of the tools applications of the Qt Toolkit. @@ -1133,10 +1133,6 @@ void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed) macro.symbols.last().token == PP_HASHHASH) { error("'##' cannot appear at either end of a macro expansion"); } - if (macro.symbols.last().token == HASH || - macro.symbols.last().token == PP_HASH) { - error("'#' is not followed by a macro parameter"); - } } macros.insert(name, macro); continue; diff --git a/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp b/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp index ea24c35a071..dc735df2978 100644 --- a/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp +++ b/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp @@ -243,6 +243,8 @@ static QString generateInterfaceXml(const ClassDef *mo) foreach (const FunctionDef &mm, mo->signalList) { if (mm.wasCloned) continue; + if (!mm.isScriptable && !(flags & QDBusConnection::ExportNonScriptableSignals)) + continue; retval += addFunction(mm, true); } @@ -250,10 +252,14 @@ static QString generateInterfaceXml(const ClassDef *mo) if (flags & (QDBusConnection::ExportScriptableSlots | QDBusConnection::ExportNonScriptableSlots)) { foreach (const FunctionDef &slot, mo->slotList) { + if (!slot.isScriptable && !(flags & QDBusConnection::ExportNonScriptableSlots)) + continue; if (slot.access == FunctionDef::Public) retval += addFunction(slot); } foreach (const FunctionDef &method, mo->methodList) { + if (!method.isScriptable && !(flags & QDBusConnection::ExportNonScriptableSlots)) + continue; if (method.access == FunctionDef::Public) retval += addFunction(method); } diff --git a/src/tools/qdoc/cppcodemarker.cpp b/src/tools/qdoc/cppcodemarker.cpp index 48218da5134..92b6ccca6af 100644 --- a/src/tools/qdoc/cppcodemarker.cpp +++ b/src/tools/qdoc/cppcodemarker.cpp @@ -136,7 +136,7 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node, if ((style == Detailed) && !node->parent()->name().isEmpty() && (node->type() != Node::Property) && !node->isQmlNode()) - name.prepend(taggedNode(node->parent()) + "::"); + name.prepend(taggedNode(node->parent()) + "::​"); switch (node->type()) { case Node::Namespace: @@ -212,7 +212,7 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node, bracketed += "slot"; } if (!bracketed.isEmpty()) - extra += " [" + bracketed.join(' ') + QLatin1Char(']'); + extra += QLatin1Char('[') + bracketed.join(' ') + QStringLiteral("] "); } break; case Node::Enum: @@ -283,13 +283,13 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node, if (style == Summary) { if (node->status() == Node::Preliminary) { - extra += " (preliminary)"; + extra += "(preliminary) "; } else if (node->status() == Node::Deprecated) { - extra += " (deprecated)"; + extra += "(deprecated) "; } else if (node->status() == Node::Obsolete) { - extra += " (obsolete)"; + extra += "(obsolete) "; } } @@ -297,7 +297,7 @@ QString CppCodeMarker::markedUpSynopsis(const Node *node, extra.prepend("<@extra>"); extra.append(""); } - return synopsis + extra; + return extra + synopsis; } /*! diff --git a/src/tools/qdoc/doc/images/qt-logo.png b/src/tools/qdoc/doc/images/qt-logo.png index 14ddf2a0289..6b72d5fb72c 100644 Binary files a/src/tools/qdoc/doc/images/qt-logo.png and b/src/tools/qdoc/doc/images/qt-logo.png differ diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp index e158a8dff65..bc79d5ce7fb 100644 --- a/src/tools/qdoc/htmlgenerator.cpp +++ b/src/tools/qdoc/htmlgenerator.cpp @@ -123,7 +123,7 @@ void HtmlGenerator::initializeGenerator(const Config &config) { ATOM_FORMATTING_PARAMETER, "", "" }, { ATOM_FORMATTING_SUBSCRIPT, "", "" }, { ATOM_FORMATTING_SUPERSCRIPT, "", "" }, - { ATOM_FORMATTING_TELETYPE, "", "" }, + { ATOM_FORMATTING_TELETYPE, "", "" }, // tag is not supported in HTML5 { ATOM_FORMATTING_UICONTROL, "", "" }, { ATOM_FORMATTING_UNDERLINE, "", "" }, { 0, 0, 0 } @@ -156,6 +156,10 @@ void HtmlGenerator::initializeGenerator(const Config &config) postPostHeader = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_POSTPOSTHEADER); + prologue = config.getString(HtmlGenerator::format() + + Config::dot + + HTMLGENERATOR_PROLOGUE); + footer = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_FOOTER); @@ -1035,7 +1039,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark out() << "
\n"; } else if (atom->string() == ATOM_LIST_VALUE) { - out() << ""; + out() << "
"; threeColumnEnumValueTable_ = isThreeColumnEnumValueTable(atom); if (threeColumnEnumValueTable_) { if (++numTableRows_ % 2 == 1) @@ -1087,7 +1091,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark // ### Trenton QString t= protectEnc(plainCode(marker->markedUpEnumValue(atom->next()->string(),relative))); - out() << "
" << t << ""; + out() << "
" << t << ""; if (relative->type() == Node::Enum) { out() << ""; @@ -1097,7 +1101,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark if (itemValue.isEmpty()) out() << '?'; else - out() << "" << protectEnc(itemValue) << ""; + out() << "" << protectEnc(itemValue) << ""; } skipAhead = 1; } @@ -1142,7 +1146,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark out() << "\n"; } else if (atom->string() == ATOM_LIST_VALUE) { - out() << "
\n"; + out() << "\n"; } else { out() << "\n"; @@ -1230,7 +1234,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark else if (p2.contains("%")) width = p2; } - out() << "
\n "; @@ -1238,7 +1242,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark } break; case Atom::TableRight: - out() << "
\n"; + out() << "\n"; break; case Atom::TableHeaderLeft: out() << ""; @@ -1652,8 +1656,7 @@ void HtmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker) Generate the TOC for the new doc format. Don't generate a TOC for the home page. */ - if ((dn->name() != QString("index.html")) && - (dn->name() != QString("qtexamplesandtutorials.html"))) + if ((dn->name() != QStringLiteral("index.html"))) generateTableOfContents(dn,marker,0); generateKeywordAnchors(dn); @@ -1905,8 +1908,8 @@ void HtmlGenerator::generateHeader(const QString& title, #else out() << QString("\n"); #endif - out() << "\n"; - out() << QString("\n").arg(naturalLanguage); + out() << "\n"; + out() << QString("\n").arg(naturalLanguage); out() << "\n"; out() << " \n"; if (node && !node->doc().location().isEmpty()) @@ -1973,7 +1976,8 @@ void HtmlGenerator::generateHeader(const QString& title, out() << QString(postHeader).replace("\\" + COMMAND_VERSION, qdb_->version()); generateNavigationBar(title,node,marker); - out() << "
  • \n" << buildversion << "
  • \n"; + if (!buildversion.isEmpty()) + out() << "
  • " << buildversion << "
  • \n"; out() << QString(postPostHeader).replace("\\" + COMMAND_VERSION, qdb_->version()); navigationLinks.clear(); @@ -2047,6 +2051,7 @@ void HtmlGenerator::generateTitle(const QString& title, const Node *relative, CodeMarker *marker) { + out() << QString(prologue).replace("\\" + COMMAND_VERSION, qdb_->version()); if (!title.isEmpty()) out() << "

    " << protectEnc(title) << "

    \n"; if (!subTitle.isEmpty()) { @@ -2091,12 +2096,9 @@ void HtmlGenerator::generateRequisites(InnerNode *inner, CodeMarker *marker) //add the includes to the map if (!inner->includes().isEmpty()) { text.clear(); - text << formattingRightMap()[ATOM_FORMATTING_BOLD] - << formattingLeftMap()[ATOM_FORMATTING_TELETYPE] - << highlightedCode(indent(codeIndent, + text << highlightedCode(indent(codeIndent, marker->markedUpIncludes(inner->includes())), - inner) - << formattingRightMap()[ATOM_FORMATTING_TELETYPE]; + inner); requisites.insert(headerText, text); } @@ -2131,9 +2133,7 @@ void HtmlGenerator::generateRequisites(InnerNode *inner, CodeMarker *marker) ModuleNode* moduleNode = qdb_->findModule(inner->moduleName()); if (moduleNode && !moduleNode->qtVariable().isEmpty()) { text.clear(); - text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_TELETYPE) - << "QT += " + moduleNode->qtVariable() - << Atom(Atom::FormattingRight, ATOM_FORMATTING_TELETYPE); + text << "QT += " + moduleNode->qtVariable(); requisites.insert(qtVariableText, text); } } @@ -2191,7 +2191,7 @@ void HtmlGenerator::generateRequisites(InnerNode *inner, CodeMarker *marker) if (!requisites.isEmpty()) { //generate the table - out() << "\n"; + out() << "
    \n"; QStringList::ConstIterator i; for (i = requisiteorder.begin(); i != requisiteorder.constEnd(); ++i) { @@ -2209,7 +2209,7 @@ void HtmlGenerator::generateRequisites(InnerNode *inner, CodeMarker *marker) out() << ""; } } - out() << "
    "; + out() << ""; } } @@ -2246,10 +2246,7 @@ void HtmlGenerator::generateQmlRequisites(QmlClassNode *qcn, CodeMarker *marker) else qmlModuleVersion = qcn->qmlModuleVersion(); text.clear(); - text << formattingRightMap()[ATOM_FORMATTING_BOLD] - << formattingLeftMap()[ATOM_FORMATTING_TELETYPE] - << "import " + qcn->qmlModuleName() + " " + qmlModuleVersion - << formattingRightMap()[ATOM_FORMATTING_TELETYPE]; + text << "import " + qcn->qmlModuleName() + " " + qmlModuleVersion; requisites.insert(importText, text); //add the since and project into the map @@ -2310,7 +2307,7 @@ void HtmlGenerator::generateQmlRequisites(QmlClassNode *qcn, CodeMarker *marker) if (!requisites.isEmpty()) { //generate the table - out() << "\n"; + out() << "
    \n"; QStringList::ConstIterator i; for (i = requisiteorder.begin(); i != requisiteorder.constEnd(); ++i) { @@ -2328,7 +2325,7 @@ void HtmlGenerator::generateQmlRequisites(QmlClassNode *qcn, CodeMarker *marker) out() << ""; } } - out() << "
    "; + out() << ""; } } @@ -2374,12 +2371,10 @@ void HtmlGenerator::generateTableOfContents(const Node *node, QList toc; if (node->doc().hasTableOfContents()) toc = node->doc().tableOfContents(); - if (toc.isEmpty() && !sections && !node->isModule()) - return; - - //turn off table of contents if HTML.tocdepth is set to 0 - if (tocDepth == 0) + if (tocDepth == 0 || (toc.isEmpty() && !sections && !node->isModule())) { + generateSidebar(); return; + } QStringList sectionNumber; int detailsBase = 0; @@ -2388,6 +2383,7 @@ void HtmlGenerator::generateTableOfContents(const Node *node, inContents_ = true; inLink_ = true; + out() << "
    \n"; out() << "
    \n"; out() << "

    Contents

    \n"; sectionNumber.append("1"); @@ -2485,10 +2481,21 @@ void HtmlGenerator::generateTableOfContents(const Node *node, } out() << "\n"; out() << "
    \n"; + out() << "
    "; + out() << "
    \n"; inContents_ = false; inLink_ = false; } +/*! + Outputs a placeholder div where the style can add customized sidebar content. + */ +void HtmlGenerator::generateSidebar() { + out() << "
    "; + out() << "
    "; + out() << "
    \n"; +} + QString HtmlGenerator::generateListOfAllMemberFile(const InnerNode *inner, CodeMarker *marker) { @@ -2505,6 +2512,7 @@ QString HtmlGenerator::generateListOfAllMemberFile(const InnerNode *inner, beginSubPage(inner, fileName); QString title = "List of All Members for " + inner->name(); generateHeader(title, inner, marker); + generateSidebar(); generateTitle(title, Text(), SmallSubTitle, inner, marker); out() << "

    This is the complete list of members for "; generateFullName(inner, 0); @@ -2536,6 +2544,7 @@ QString HtmlGenerator::generateAllQmlMembersFile(QmlClassNode* qml_cn, CodeMarke beginSubPage(qml_cn, fileName); QString title = "List of All Members for " + qml_cn->name(); generateHeader(title, qml_cn, marker); + generateSidebar(); generateTitle(title, Text(), SmallSubTitle, qml_cn, marker); out() << "

    This is the complete list of members for "; generateFullName(qml_cn, 0); @@ -2620,6 +2629,7 @@ QString HtmlGenerator::generateLowStatusMemberFile(InnerNode *inner, beginSubPage(inner, fileName); generateHeader(title, inner, marker); + generateSidebar(); generateTitle(title, Text(), SmallSubTitle, inner, marker); if (status == CodeMarker::Compat) { @@ -2696,6 +2706,7 @@ QString HtmlGenerator::generateQmlMemberFile(QmlClassNode* qcn, beginSubPage(qcn, fileName); generateHeader(title, qcn, marker); + generateSidebar(); generateTitle(title, Text(), SmallSubTitle, qcn, marker); out() << "

    The following members of QML type " @@ -2813,7 +2824,7 @@ void HtmlGenerator::generateAnnotatedList(const Node *relative, } if (allInternal) return; - out() << "\n"; + out() << "
    \n"; int row = 0; NodeList nodes = nm.values(); foreach (const Node* node, nodes) { @@ -2849,7 +2860,7 @@ void HtmlGenerator::generateAnnotatedList(const Node *relative, } out() << "\n"; } - out() << "
    \n"; + out() << "\n"; } /*! @@ -3101,8 +3112,8 @@ void HtmlGenerator::generateQmlItem(const Node *node, if (summary) marked.replace("@name>", "b>"); - marked.replace("<@extra>", ""); - marked.replace("", ""); + marked.replace("<@extra>", ""); + marked.replace("", ""); if (summary) { marked.remove("<@type>"); @@ -3226,11 +3237,11 @@ void HtmlGenerator::generateSection(const NodeList& nl, alignNames = false; } if (alignNames) { - out() << "\n"; + out() << "
    \n"; } else { if (twoColumn) - out() << "
    \n" + out() << "
    \n" << "
    "; out() << "
      \n"; } @@ -3261,11 +3272,11 @@ void HtmlGenerator::generateSection(const NodeList& nl, ++m; } if (alignNames) - out() << "
    \n"; + out() << "\n"; else { out() << "\n"; if (twoColumn) - out() << "\n\n"; + out() << "\n\n"; } } } @@ -3287,11 +3298,11 @@ void HtmlGenerator::generateSectionList(const Section& section, alignNames = false; } if (alignNames) { - out() << "\n"; + out() << "
    \n"; } else { if (twoColumn) - out() << "
    \n" + out() << "
    \n" << "
    "; out() << "
      \n"; } @@ -3327,11 +3338,11 @@ void HtmlGenerator::generateSectionList(const Section& section, ++m; } if (alignNames) - out() << "
    \n"; + out() << "\n"; else { out() << "\n"; if (twoColumn) - out() << "\n\n"; + out() << "\n\n"; } } @@ -3395,8 +3406,8 @@ void HtmlGenerator::generateSynopsis(const Node *node, extraRegExp.setMinimal(true); marked.remove(extraRegExp); } else { - marked.replace("<@extra>", ""); - marked.replace("", ""); + marked.replace("<@extra>", ""); + marked.replace("", ""); } if (style != CodeMarker::Detailed) { @@ -4236,7 +4247,7 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node, const QmlPropertyGroupNode* qpgn = static_cast(node); NodeList::ConstIterator p = qpgn->childNodes().constBegin(); out() << "

    "; - out() << ""; + out() << "
    "; QString heading = qpgn->name() + " group"; out() << ""; @@ -4261,13 +4272,13 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node, } ++p; } - out() << "
    "; + out() << "
    "; out() << ""; } else if (node->type() == Node::QmlProperty) { qpn = static_cast(node); out() << "
    "; - out() << ""; + out() << "
    "; out() << ""; out() << ""; - out() << "

    "; out() << ""; @@ -4281,43 +4292,43 @@ void HtmlGenerator::generateDetailedQmlMember(Node *node, out() << "default"; generateQmlItem(qpn, relative, marker, false); out() << "

    "; + out() << "
    "; out() << ""; } else if (node->type() == Node::QmlSignal) { const FunctionNode* qsn = static_cast(node); out() << "
    "; - out() << ""; + out() << "
    "; out() << ""; out() << ""; - out() << "

    "; out() << ""; generateSynopsis(qsn,relative,marker,CodeMarker::Detailed,false); out() << "

    "; + out() << "
    "; out() << ""; } else if (node->type() == Node::QmlSignalHandler) { const FunctionNode* qshn = static_cast(node); out() << "
    "; - out() << ""; + out() << "
    "; out() << ""; out() << ""; - out() << "

    "; out() << ""; generateSynopsis(qshn,relative,marker,CodeMarker::Detailed,false); out() << "

    "; + out() << "
    "; out() << ""; } else if (node->type() == Node::QmlMethod) { const FunctionNode* qmn = static_cast(node); out() << "
    "; - out() << ""; + out() << "
    "; out() << ""; out() << ""; - out() << "

    "; out() << ""; generateSynopsis(qmn,relative,marker,CodeMarker::Detailed,false); out() << "

    "; + out() << "
    "; out() << ""; } out() << "
    "; @@ -4479,8 +4490,6 @@ void HtmlGenerator::generateManifestFile(QString manifest, QString element) return; QString fileName = manifest +"-manifest.xml"; QFile file(outputDir() + QLatin1Char('/') + fileName); - if (!file.open(QFile::WriteOnly | QFile::Text)) - return ; bool demos = false; if (manifest == "demos") demos = true; @@ -4501,7 +4510,7 @@ void HtmlGenerator::generateManifestFile(QString manifest, QString element) } ++i; } - if (!proceed) + if (!proceed || !file.open(QFile::WriteOnly | QFile::Text)) return; QXmlStreamWriter writer(&file); diff --git a/src/tools/qdoc/htmlgenerator.h b/src/tools/qdoc/htmlgenerator.h index 3641e88a47d..f7625113f0f 100644 --- a/src/tools/qdoc/htmlgenerator.h +++ b/src/tools/qdoc/htmlgenerator.h @@ -148,6 +148,7 @@ private: void generateTableOfContents(const Node *node, CodeMarker *marker, QList
    * sections = 0); + void generateSidebar(); QString generateListOfAllMemberFile(const InnerNode *inner, CodeMarker *marker); QString generateAllQmlMembersFile(QmlClassNode* qml_cn, CodeMarker* marker); @@ -242,6 +243,7 @@ private: QString endHeader; QString postHeader; QString postPostHeader; + QString prologue; QString footer; QString address; bool pleaseGenerateMacRef; @@ -276,6 +278,7 @@ public: #define HTMLGENERATOR_GENERATEMACREFS "generatemacrefs" // ### document me #define HTMLGENERATOR_POSTHEADER "postheader" #define HTMLGENERATOR_POSTPOSTHEADER "postpostheader" +#define HTMLGENERATOR_PROLOGUE "prologue" #define HTMLGENERATOR_NONAVIGATIONBAR "nonavigationbar" #define HTMLGENERATOR_NOSUBDIRS "nosubdirs" #define HTMLGENERATOR_TOCDEPTH "tocdepth" diff --git a/src/tools/qdoc/qdocindexfiles.cpp b/src/tools/qdoc/qdocindexfiles.cpp index 1e49dd08a01..e152b04ead8 100644 --- a/src/tools/qdoc/qdocindexfiles.cpp +++ b/src/tools/qdoc/qdocindexfiles.cpp @@ -982,6 +982,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer, if (!brief.isEmpty()) writer.writeAttribute("brief", brief); } + break; case Node::QmlModule: { const QmlModuleNode* qmn = static_cast(node); diff --git a/src/tools/qdoc/qmlparser/qqmljs.g b/src/tools/qdoc/qmlparser/qqmljs.g index de4fec4d568..616e3b3166b 100644 --- a/src/tools/qdoc/qmlparser/qqmljs.g +++ b/src/tools/qdoc/qmlparser/qqmljs.g @@ -1,21 +1,31 @@ ---------------------------------------------------------------------------- -- --- Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +-- Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -- Contact: http://www.qt-project.org/legal -- -- This file is part of the QtQml module of the Qt Toolkit. -- --- $QT_BEGIN_LICENSE:LGPL-ONLY$ --- GNU Lesser General Public License Usage --- 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. +-- $QT_BEGIN_LICENSE:LGPL21$ +-- 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. -- --- If you have questions regarding the use of this file, please contact --- us via http://www.qt-project.org/. +-- 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 or version 3 as published by the Free +-- Software Foundation and appearing in the file LICENSE.LGPLv21 and +-- LICENSE.LGPLv3 included in the packaging of this file. Please review the +-- following information to ensure the GNU Lesser General Public License +-- requirements will be met: https://www.gnu.org/licenses/lgpl.html and +-- 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. -- -- $QT_END_LICENSE$ -- @@ -89,41 +99,33 @@ /./**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtQml module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL$ +** $QT_BEGIN_LICENSE:LGPL21$ ** 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 +** 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. +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** 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 +** 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$ ** ****************************************************************************/ @@ -142,41 +144,33 @@ /:/**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtQml module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL$ +** $QT_BEGIN_LICENSE:LGPL21$ ** 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 +** 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. +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** 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 +** 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$ ** ****************************************************************************/ @@ -1090,6 +1084,31 @@ case $rule_number: { } break; ./ +UiObjectMember: T_READONLY T_PROPERTY UiPropertyType JsIdentifier T_COLON UiQualifiedId UiObjectInitializer ; +/. +case $rule_number: { + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4)); + node->isReadonlyMember = true; + node->readonlyToken = loc(1); + node->propertyToken = loc(2); + node->typeToken = loc(3); + node->identifierToken = loc(4); + node->semicolonToken = loc(5); // insert a fake ';' before ':' + + AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(4)); + propertyName->identifierToken = loc(4); + propertyName->next = 0; + + AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding( + propertyName, sym(6).UiQualifiedId, sym(7).UiObjectInitializer); + binding->colonToken = loc(5); + + node->binding = binding; + + sym(1).Node = node; +} break; +./ + UiObjectMember: FunctionDeclaration ; /. case $rule_number: { diff --git a/src/tools/qdoc/qmlparser/qqmljsgrammar.cpp b/src/tools/qdoc/qmlparser/qqmljsgrammar.cpp index d3fb3f8d1f8..2600a5e14c8 100644 --- a/src/tools/qdoc/qmlparser/qqmljsgrammar.cpp +++ b/src/tools/qdoc/qmlparser/qqmljsgrammar.cpp @@ -57,35 +57,35 @@ const short QQmlJSGrammar::lhs [] = { 130, 130, 130, 130, 130, 130, 130, 111, 138, 138, 138, 139, 139, 140, 140, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, - 111, 111, 124, 124, 124, 124, 124, 124, 124, 143, + 111, 111, 111, 124, 124, 124, 124, 124, 124, 124, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - 143, 143, 143, 143, 143, 143, 143, 129, 145, 145, - 145, 145, 144, 144, 149, 149, 149, 147, 147, 150, - 150, 150, 150, 153, 153, 153, 153, 153, 153, 153, + 143, 143, 143, 143, 143, 143, 143, 143, 129, 145, + 145, 145, 145, 144, 144, 149, 149, 149, 147, 147, + 150, 150, 150, 150, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, - 153, 153, 153, 153, 154, 154, 120, 120, 120, 120, - 120, 157, 157, 158, 158, 158, 158, 156, 156, 159, - 159, 160, 160, 161, 161, 161, 162, 162, 162, 162, - 162, 162, 162, 162, 162, 162, 163, 163, 163, 163, - 164, 164, 164, 165, 165, 165, 165, 166, 166, 166, - 166, 166, 166, 166, 167, 167, 167, 167, 167, 167, - 168, 168, 168, 168, 168, 169, 169, 169, 169, 169, - 170, 170, 171, 171, 172, 172, 173, 173, 174, 174, - 175, 175, 176, 176, 177, 177, 178, 178, 179, 179, - 180, 180, 181, 181, 148, 148, 182, 182, 183, 183, + 153, 153, 153, 153, 153, 154, 154, 120, 120, 120, + 120, 120, 157, 157, 158, 158, 158, 158, 156, 156, + 159, 159, 160, 160, 161, 161, 161, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 162, 163, 163, 163, + 163, 164, 164, 164, 165, 165, 165, 165, 166, 166, + 166, 166, 166, 166, 166, 167, 167, 167, 167, 167, + 167, 168, 168, 168, 168, 168, 169, 169, 169, 169, + 169, 170, 170, 171, 171, 172, 172, 173, 173, 174, + 174, 175, 175, 176, 176, 177, 177, 178, 178, 179, + 179, 180, 180, 181, 181, 148, 148, 182, 182, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, - 109, 109, 184, 184, 185, 185, 186, 186, 108, 108, + 183, 109, 109, 184, 184, 185, 185, 186, 186, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 131, 195, 195, 194, 194, 142, 142, - 196, 196, 197, 197, 199, 199, 198, 200, 203, 201, - 201, 204, 202, 202, 132, 133, 133, 134, 134, 187, - 187, 187, 187, 187, 187, 187, 187, 188, 188, 188, - 188, 189, 189, 189, 189, 190, 190, 135, 136, 205, - 205, 208, 208, 206, 206, 209, 207, 191, 192, 192, - 137, 137, 137, 210, 211, 193, 193, 212, 141, 155, - 155, 213, 213, 152, 152, 151, 151, 214, 112, 112, - 215, 215, 110, 110, 146, 146, 216}; + 108, 108, 108, 108, 131, 195, 195, 194, 194, 142, + 142, 196, 196, 197, 197, 199, 199, 198, 200, 203, + 201, 201, 204, 202, 202, 132, 133, 133, 134, 134, + 187, 187, 187, 187, 187, 187, 187, 187, 188, 188, + 188, 188, 189, 189, 189, 189, 190, 190, 135, 136, + 205, 205, 208, 208, 206, 206, 209, 207, 191, 192, + 192, 137, 137, 137, 210, 211, 193, 193, 212, 141, + 155, 155, 213, 213, 152, 152, 151, 151, 214, 112, + 112, 215, 215, 110, 110, 146, 146, 216}; const short QQmlJSGrammar::rhs [] = { 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, @@ -95,110 +95,110 @@ const short QQmlJSGrammar::rhs [] = { 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 0, 1, 2, 4, 6, 6, 3, 3, 7, 7, 4, 4, 5, 5, 5, 6, 6, 10, 6, + 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, - 3, 3, 4, 5, 3, 4, 3, 1, 1, 2, - 3, 4, 1, 2, 3, 7, 8, 1, 3, 1, + 2, 3, 3, 4, 5, 3, 4, 3, 1, 1, + 2, 3, 4, 1, 2, 3, 7, 8, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 4, 3, - 5, 1, 2, 4, 4, 4, 3, 0, 1, 1, - 3, 1, 1, 1, 2, 2, 1, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 3, 3, 3, - 1, 3, 3, 1, 3, 3, 3, 1, 3, 3, - 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, - 1, 3, 3, 3, 3, 1, 3, 3, 3, 3, - 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, - 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, - 1, 5, 1, 5, 1, 3, 1, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, + 3, 5, 1, 2, 4, 4, 4, 3, 0, 1, + 1, 3, 1, 1, 1, 2, 2, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 1, 3, 3, + 3, 1, 3, 3, 1, 3, 3, 3, 1, 3, + 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, + 3, 1, 3, 3, 3, 3, 1, 3, 3, 3, + 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, + 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, + 3, 1, 5, 1, 5, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 3, 0, 1, 1, 3, 0, 1, 1, 1, + 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 3, 1, 2, 0, 1, 3, 3, - 1, 1, 1, 3, 1, 3, 2, 2, 2, 0, - 1, 2, 0, 1, 1, 2, 2, 7, 5, 7, - 7, 7, 5, 9, 10, 7, 8, 2, 2, 3, - 3, 2, 2, 3, 3, 3, 3, 5, 5, 3, - 5, 1, 2, 0, 1, 4, 3, 3, 3, 3, - 3, 3, 4, 5, 2, 2, 2, 1, 8, 8, - 7, 1, 3, 0, 1, 0, 1, 1, 1, 1, - 1, 2, 1, 1, 0, 1, 2}; + 1, 1, 1, 1, 3, 1, 2, 0, 1, 3, + 3, 1, 1, 1, 3, 1, 3, 2, 2, 2, + 0, 1, 2, 0, 1, 1, 2, 2, 7, 5, + 7, 7, 7, 5, 9, 10, 7, 8, 2, 2, + 3, 3, 2, 2, 3, 3, 3, 3, 5, 5, + 3, 5, 1, 2, 0, 1, 4, 3, 3, 3, + 3, 3, 3, 4, 5, 2, 2, 2, 1, 8, + 8, 7, 1, 3, 0, 1, 0, 1, 1, 1, + 1, 1, 2, 1, 1, 0, 1, 2}; const short QQmlJSGrammar::action_default [] = { - 0, 0, 28, 0, 0, 0, 28, 0, 184, 251, - 215, 223, 219, 163, 235, 211, 3, 148, 81, 164, - 227, 231, 152, 181, 162, 167, 147, 201, 188, 0, - 88, 89, 84, 0, 78, 73, 355, 0, 0, 0, - 0, 86, 0, 0, 82, 85, 77, 0, 0, 74, - 76, 79, 75, 87, 80, 0, 83, 0, 0, 177, - 0, 0, 164, 183, 166, 165, 0, 0, 0, 179, - 180, 178, 182, 0, 212, 0, 0, 0, 0, 202, - 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, - 186, 187, 185, 190, 194, 193, 191, 189, 204, 203, - 205, 0, 220, 0, 216, 0, 0, 158, 145, 157, - 146, 114, 115, 116, 141, 117, 142, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 143, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 144, 0, 0, 156, 252, 159, 0, 160, 0, - 161, 155, 0, 248, 241, 239, 246, 247, 245, 244, - 250, 243, 242, 240, 249, 236, 0, 224, 0, 0, - 228, 0, 0, 232, 0, 0, 158, 150, 0, 149, - 0, 154, 168, 0, 344, 344, 345, 0, 342, 0, - 343, 0, 346, 259, 266, 265, 273, 261, 0, 262, - 0, 347, 0, 354, 263, 264, 81, 269, 267, 351, - 348, 353, 270, 0, 281, 0, 0, 0, 0, 338, - 0, 355, 253, 295, 0, 0, 0, 282, 0, 0, - 271, 272, 0, 260, 268, 296, 297, 0, 344, 0, - 0, 346, 0, 339, 340, 0, 328, 352, 0, 312, - 313, 314, 315, 0, 308, 309, 310, 311, 336, 337, - 0, 0, 0, 0, 0, 300, 301, 302, 257, 255, - 217, 225, 221, 237, 213, 258, 0, 164, 229, 233, - 206, 195, 0, 0, 214, 0, 0, 0, 0, 207, - 0, 0, 0, 0, 0, 199, 197, 200, 198, 196, - 209, 208, 210, 0, 222, 0, 218, 0, 256, 164, - 0, 238, 253, 254, 0, 253, 0, 0, 304, 0, - 0, 0, 306, 0, 226, 0, 0, 230, 0, 0, - 234, 293, 0, 285, 294, 288, 0, 292, 0, 253, - 286, 0, 253, 0, 0, 305, 0, 0, 0, 307, - 0, 0, 0, 299, 0, 298, 81, 108, 356, 0, - 0, 113, 275, 278, 0, 114, 281, 117, 142, 119, - 120, 84, 124, 125, 78, 126, 129, 82, 85, 253, - 79, 87, 132, 80, 134, 83, 136, 137, 282, 139, - 140, 144, 0, 110, 109, 112, 96, 111, 95, 0, - 105, 276, 274, 0, 0, 0, 346, 0, 106, 152, - 153, 158, 0, 151, 0, 316, 317, 0, 344, 0, - 0, 346, 0, 107, 0, 0, 0, 319, 324, 322, - 325, 0, 0, 323, 324, 0, 320, 0, 321, 277, - 327, 0, 277, 326, 0, 329, 330, 0, 277, 331, - 332, 0, 0, 333, 0, 0, 0, 334, 335, 170, - 169, 0, 0, 0, 303, 0, 0, 0, 318, 290, - 283, 0, 291, 287, 0, 289, 279, 0, 280, 284, - 0, 0, 346, 0, 341, 99, 0, 0, 103, 90, - 0, 92, 101, 0, 93, 102, 104, 94, 100, 91, - 0, 97, 174, 172, 176, 173, 171, 175, 349, 6, - 350, 4, 2, 71, 98, 0, 0, 74, 76, 75, - 37, 5, 0, 72, 0, 51, 50, 49, 0, 0, + 0, 0, 28, 0, 0, 0, 28, 0, 185, 252, + 216, 224, 220, 164, 236, 212, 3, 149, 82, 165, + 228, 232, 153, 182, 163, 168, 148, 202, 189, 0, + 89, 90, 85, 0, 79, 74, 356, 0, 0, 0, + 0, 87, 0, 0, 83, 86, 78, 0, 0, 75, + 77, 80, 76, 88, 81, 0, 84, 0, 0, 178, + 0, 0, 165, 184, 167, 166, 0, 0, 0, 180, + 181, 179, 183, 0, 213, 0, 0, 0, 0, 203, + 0, 0, 0, 0, 0, 0, 193, 0, 0, 0, + 187, 188, 186, 191, 195, 194, 192, 190, 205, 204, + 206, 0, 221, 0, 217, 0, 0, 159, 146, 158, + 147, 115, 116, 117, 142, 118, 143, 119, 120, 121, + 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, + 144, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 141, 145, 0, 0, 157, 253, 160, 0, 161, 0, + 162, 156, 0, 249, 242, 240, 247, 248, 246, 245, + 251, 244, 243, 241, 250, 237, 0, 225, 0, 0, + 229, 0, 0, 233, 0, 0, 159, 151, 0, 150, + 0, 155, 169, 0, 345, 345, 346, 0, 343, 0, + 344, 0, 347, 260, 267, 266, 274, 262, 0, 263, + 0, 348, 0, 355, 264, 265, 82, 270, 268, 352, + 349, 354, 271, 0, 282, 0, 0, 0, 0, 339, + 0, 356, 254, 296, 0, 0, 0, 283, 0, 0, + 272, 273, 0, 261, 269, 297, 298, 0, 345, 0, + 0, 347, 0, 340, 341, 0, 329, 353, 0, 313, + 314, 315, 316, 0, 309, 310, 311, 312, 337, 338, + 0, 0, 0, 0, 0, 301, 302, 303, 258, 256, + 218, 226, 222, 238, 214, 259, 0, 165, 230, 234, + 207, 196, 0, 0, 215, 0, 0, 0, 0, 208, + 0, 0, 0, 0, 0, 200, 198, 201, 199, 197, + 210, 209, 211, 0, 223, 0, 219, 0, 257, 165, + 0, 239, 254, 255, 0, 254, 0, 0, 305, 0, + 0, 0, 307, 0, 227, 0, 0, 231, 0, 0, + 235, 294, 0, 286, 295, 289, 0, 293, 0, 254, + 287, 0, 254, 0, 0, 306, 0, 0, 0, 308, + 0, 0, 0, 300, 0, 299, 82, 109, 357, 0, + 0, 114, 276, 279, 0, 115, 282, 118, 143, 120, + 121, 85, 125, 126, 79, 127, 130, 83, 86, 254, + 80, 88, 133, 81, 135, 84, 137, 138, 283, 140, + 141, 145, 0, 111, 110, 113, 97, 112, 96, 0, + 106, 277, 275, 0, 0, 0, 347, 0, 107, 153, + 154, 159, 0, 152, 0, 317, 318, 0, 345, 0, + 0, 347, 0, 108, 0, 0, 0, 320, 325, 323, + 326, 0, 0, 324, 325, 0, 321, 0, 322, 278, + 328, 0, 278, 327, 0, 330, 331, 0, 278, 332, + 333, 0, 0, 334, 0, 0, 0, 335, 336, 171, + 170, 0, 0, 0, 304, 0, 0, 0, 319, 291, + 284, 0, 292, 288, 0, 290, 280, 0, 281, 285, + 0, 0, 347, 0, 342, 100, 0, 0, 104, 91, + 0, 93, 102, 0, 94, 103, 105, 95, 101, 92, + 0, 98, 175, 173, 177, 174, 172, 176, 350, 6, + 351, 4, 2, 72, 99, 0, 0, 75, 77, 76, + 37, 5, 0, 73, 0, 51, 50, 49, 0, 0, 64, 0, 65, 41, 42, 43, 44, 46, 47, 68, 45, 0, 51, 0, 0, 0, 0, 0, 60, 0, 61, 0, 0, 32, 0, 0, 69, 33, 0, 36, - 34, 30, 0, 35, 31, 0, 62, 0, 63, 152, - 0, 66, 70, 0, 0, 0, 0, 67, 0, 58, + 34, 30, 0, 35, 31, 0, 62, 0, 63, 153, + 0, 66, 70, 0, 0, 0, 0, 153, 278, 0, + 67, 82, 115, 282, 118, 143, 120, 121, 85, 125, + 126, 127, 130, 83, 86, 254, 88, 133, 81, 135, + 84, 137, 138, 283, 140, 141, 145, 71, 0, 58, 52, 59, 53, 0, 0, 0, 0, 55, 0, 56, - 57, 54, 0, 0, 152, 277, 0, 0, 48, 81, - 114, 281, 117, 142, 119, 120, 84, 124, 125, 126, - 129, 82, 85, 253, 87, 132, 80, 134, 83, 136, - 137, 282, 139, 140, 144, 0, 38, 39, 0, 40, - 8, 0, 0, 9, 0, 11, 0, 10, 0, 1, - 27, 15, 14, 26, 13, 12, 29, 7, 0, 18, - 0, 19, 0, 24, 25, 0, 20, 21, 0, 22, - 23, 16, 17, 357}; + 57, 54, 0, 0, 0, 0, 48, 0, 38, 39, + 0, 40, 8, 0, 0, 9, 0, 11, 0, 10, + 0, 1, 27, 15, 14, 26, 13, 12, 29, 7, + 0, 18, 0, 19, 0, 24, 25, 0, 20, 21, + 0, 22, 23, 16, 17, 358}; const short QQmlJSGrammar::goto_default [] = { - 7, 639, 211, 198, 209, 521, 509, 634, 647, 508, - 633, 637, 635, 643, 22, 640, 638, 636, 18, 520, + 7, 641, 211, 198, 209, 521, 509, 636, 649, 508, + 635, 639, 637, 645, 22, 642, 640, 638, 18, 520, 562, 552, 559, 554, 539, 193, 197, 199, 204, 234, - 212, 231, 543, 583, 582, 203, 233, 26, 487, 486, + 212, 231, 543, 613, 612, 203, 233, 26, 487, 486, 359, 358, 9, 357, 360, 202, 480, 361, 109, 17, 147, 24, 13, 146, 19, 25, 59, 23, 8, 28, 27, 280, 15, 274, 10, 270, 12, 272, 11, 271, @@ -209,295 +209,267 @@ const short QQmlJSGrammar::goto_default [] = { 0}; const short QQmlJSGrammar::action_index [] = { - 239, 1406, 2692, 2692, 2794, 1119, 115, 29, 168, -106, - 26, -23, -60, 225, -106, 306, 33, -106, -106, 732, - -2, 145, 243, 223, -106, -106, -106, 379, 227, 1406, - -106, -106, -106, 539, -106, -106, 2488, 1698, 1406, 1406, - 1406, -106, 1023, 1406, -106, -106, -106, 1406, 1406, -106, - -106, -106, -106, -106, -106, 1406, -106, 1406, 1406, -106, - 1406, 1406, 114, 206, -106, -106, 1406, 1406, 1406, -106, - -106, -106, 211, 1406, 302, 1406, 1406, 1406, 1406, 369, - 1406, 1406, 1406, 1406, 1406, 1406, 226, 1406, 1406, 1406, - 135, 151, 110, 257, 279, 276, 256, 222, 475, 475, - 475, 1406, 7, 1406, 57, 2284, 1406, 1406, -106, -106, + 264, 1225, 2708, 2708, 2606, 938, 94, 104, 119, -106, + 92, 79, 81, 262, -106, 263, 78, -106, -106, 654, + 89, 125, 259, 229, -106, -106, -106, 322, 314, 1225, + -106, -106, -106, 412, -106, -106, 2300, 1713, 1225, 1225, + 1225, -106, 842, 1225, -106, -106, -106, 1225, 1225, -106, + -106, -106, -106, -106, -106, 1225, -106, 1225, 1225, -106, + 1225, 1225, 141, 216, -106, -106, 1225, 1225, 1225, -106, + -106, -106, 209, 1225, 281, 1225, 1225, 1225, 1225, 367, + 1225, 1225, 1225, 1225, 1225, 1225, 219, 1225, 1225, 1225, + 101, 102, 115, 314, 314, 314, 314, 314, 357, 347, + 337, 1225, 71, 1225, 70, 2198, 1225, 1225, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, - -106, -106, 136, 1406, -106, -106, 30, -24, -106, 1406, - -106, -106, 1406, -106, -106, -106, -106, -106, -106, -106, - -106, -106, -106, -106, -106, -106, 1406, 2, 1406, 1406, - 10, 97, 1406, -106, 2284, 1406, 1406, -106, 141, -106, - -45, -106, -106, 4, 457, 386, 89, 79, -106, 448, - -106, 74, 2692, -106, -106, -106, -106, -106, 164, -106, - 460, -106, 85, -106, -106, -106, 96, -106, -106, -106, - 2692, -106, -106, 547, -106, 629, 143, 2794, 62, 54, - 43, 2998, 1406, -106, 51, 1406, 52, -106, 47, 45, - -106, -106, 454, -106, -106, -106, -106, 64, 352, 31, - 61, 2692, 27, -106, -106, 2794, -106, -106, 139, -106, - -106, -106, -106, 126, -106, -106, -106, -106, -106, -106, - -6, 25, 1406, 130, 159, -106, -106, -106, 1600, -106, - 68, 65, 5, -106, 308, 60, 3, 835, 99, 105, - 337, 207, 408, 1406, 317, 1406, 1406, 1406, 1406, 353, - 1406, 1406, 1406, 1406, 1406, 186, 203, 204, 212, 219, - 333, 343, 359, 1406, 20, 1406, 202, 1406, -106, 732, - 1406, -106, 1406, 81, 72, 1406, 77, 2794, -106, 1406, - 149, 2794, -106, 1406, 80, 1406, 1406, 94, 88, 1406, - -106, -8, 128, -25, -106, -106, 1406, -106, 471, 1406, - -106, -53, 1406, -56, 2794, -106, 1406, 134, 2794, -106, - 1406, 138, 2794, -5, 2794, -106, -4, -106, 9, -9, - 37, -106, -106, 2794, -12, 555, 32, 629, 123, 1406, - 2794, 41, 18, 504, 2386, 21, 1023, 49, 46, 1505, - 2386, 42, 16, 44, 1406, 24, -10, 1406, 17, 1406, - -15, -18, 2590, -106, -106, -106, -106, -106, -106, 1406, - -106, -106, -106, -1, -26, -3, 2692, -27, -106, 277, - -106, 1406, -28, -106, 90, -106, -106, 1, 552, -40, - -11, 2692, -29, -106, 1406, 117, 14, -106, 50, -106, - 40, 119, 1406, -106, 11, 35, -106, -54, -106, 2794, - -106, 116, 2794, -106, 267, -106, -106, 121, 2794, -7, - -106, -31, -19, -106, 376, 6, 78, -106, -106, -106, - -106, 1406, 98, 2794, -106, 1406, 106, 2794, -106, 76, - -106, 254, -106, -106, 1406, -106, -106, 552, -106, -106, - 71, 75, 2692, 67, -106, -106, 122, 1992, -106, -106, - 1796, -106, -106, 1894, -106, -106, -106, -106, -106, -106, - 113, -106, -106, -106, -106, -106, -106, -106, -106, -106, - 2692, -106, -106, -106, 111, 22, 929, 152, 39, 48, - -106, -106, 301, -106, 147, -106, -106, -106, 468, 155, - -106, 2182, -106, -106, -106, -106, -106, -106, -106, -106, - -106, 178, -30, 463, 181, -14, 400, 229, -106, -32, - -106, 929, 104, -106, 0, 929, -106, -106, 1311, -106, - -106, -106, 1215, -106, -106, 248, -106, 2182, -106, 392, - 59, -106, -106, 244, 552, 73, 2182, -106, 236, -106, - 237, -106, 70, 15, 368, 214, 355, -106, 103, -106, - -106, -106, 2087, 721, 392, 2896, 1698, 34, -106, 56, - 598, 55, 629, 107, 1406, 2794, 53, 23, 544, 36, - 1023, 58, 66, 1505, 69, 38, 63, 1406, 95, 84, - 1406, 102, 1406, 83, 82, 124, -106, -106, 87, -106, - -106, 929, 813, 91, 929, -106, 271, -106, 86, -106, - -106, 100, 101, -106, -106, -106, -106, -106, 552, -106, - 209, -106, 109, -106, -106, 552, -106, -106, 92, -106, - -106, -106, -106, -106, + -106, -106, 98, 1225, -106, -106, 66, 65, -106, 1225, + -106, -106, 1225, -106, -106, -106, -106, -106, -106, -106, + -106, -106, -106, -106, -106, -106, 1225, 44, 1225, 1225, + 64, 57, 1225, -106, 2198, 1225, 1225, -106, 137, -106, + 49, -106, -106, 93, 344, 474, 95, 86, -106, 390, + -106, 85, 2708, -106, -106, -106, -106, -106, 189, -106, + 474, -106, 80, -106, -106, -106, 83, -106, -106, -106, + 2708, -106, -106, 490, -106, 551, 130, 2606, 46, 51, + 52, 2912, 1225, -106, 63, 1225, 56, -106, 58, 60, + -106, -106, 474, -106, -106, -106, -106, 61, 474, 62, + 67, 2708, 68, -106, -106, 2606, -106, -106, 87, -106, + -106, -106, -106, 110, -106, -106, -106, -106, -106, -106, + -24, 69, 1225, 122, 143, -106, -106, -106, 1419, -106, + 74, 76, 77, -106, 269, 73, 72, 611, 75, 114, + 397, 314, 474, 1225, 287, 1225, 1225, 1225, 1225, 397, + 1225, 1225, 1225, 1225, 1225, 218, 215, 198, 192, 182, + 397, 397, 312, 1225, 55, 1225, 59, 1225, -106, 654, + 1225, -106, 1225, 54, 53, 1225, 50, 2606, -106, 1225, + 124, 2606, -106, 1225, 90, 1225, 1225, 105, 88, 1225, + -106, 84, 157, -27, -106, -106, 1225, -106, 474, 1225, + -106, 82, 1225, 91, 2606, -106, 1225, 120, 2606, -106, + 1225, 103, 2606, -9, 2606, -106, -2, -106, 11, -30, + 17, -106, -106, 2606, -37, 469, 15, 551, 138, 1225, + 2606, 14, -16, 433, 2402, -20, 842, 6, 5, 1324, + 2402, 4, -36, 2, 1225, 7, -18, 1225, 10, 1225, + -26, -13, 2504, -106, -106, -106, -106, -106, -106, 1225, + -106, -106, -106, -33, -59, -25, 2708, 23, -106, 197, + -106, 1225, -12, -106, 140, -106, -106, 22, 474, -4, + 26, 2708, 12, -106, 1225, 113, 30, -106, 142, -106, + 142, 121, 1225, -106, -3, 45, -106, -5, -106, 2606, + -106, 108, 2606, -106, 207, -106, -106, 106, 2606, 37, + -106, 25, 36, -106, 474, 38, 40, -106, -106, -106, + -106, 1225, 136, 2606, -106, 1225, 166, 2606, -106, 13, + -106, 200, -106, -106, 1225, -106, -106, 474, -106, -106, + -17, 16, 2708, -11, -106, -106, 131, 1811, -106, -106, + 1615, -106, -106, 1517, -106, -106, -106, -106, -106, -106, + 109, -106, -106, -106, -106, -106, -106, -106, -106, -106, + 2708, -106, -106, -106, 233, -19, 748, 152, -60, 41, + -106, -106, 191, -106, 177, -106, -106, -106, 387, 203, + -106, 1906, -106, -106, -106, -106, -106, -106, -106, -106, + -106, 180, 43, 376, 174, 48, 474, 240, -106, 8, + -106, 748, 111, -106, -1, 748, -106, -106, 1130, -106, + -106, -106, 1034, -106, -106, 228, -106, 1906, -106, 295, + 21, -106, -106, 184, 379, 39, 2001, 288, 2810, 18, + -106, 34, 482, 33, 551, 138, 1225, 2606, 31, 9, + 399, 3, 643, 19, 29, 1324, 28, 1, 27, 1225, + 24, 0, 1225, 20, 1225, -7, -8, -106, 193, -106, + 205, -106, 47, 42, 329, 208, 319, -106, 128, -106, + -106, -106, 2096, 748, 1713, 35, -106, 132, -106, -106, + 32, -106, -106, 748, 748, 94, 748, -106, 250, -106, + 116, -106, -106, 233, 233, -106, -106, -106, -106, -106, + 393, -106, 214, -106, 100, -106, -106, 474, -106, -106, + 96, -106, -106, -106, -106, -106, - -111, 43, 59, 70, 71, 369, 40, -111, -111, -111, - -111, -111, -111, -111, -111, -111, -111, -111, -111, 21, - -111, -111, -111, -111, -111, -111, -111, -111, -111, 79, - -111, -111, -111, -16, -111, -111, 5, -26, 23, 73, - 91, -111, 83, 61, -111, -111, -111, 88, 87, -111, - -111, -111, -111, -111, -111, 29, -111, 66, 39, -111, - 97, 193, -111, -111, -111, -111, 160, 180, 183, -111, - -111, -111, -111, 176, -111, 167, 151, 155, 152, -111, - 148, 187, 195, 197, 199, 201, -111, 186, 92, 194, + -111, 15, 71, 87, 80, 305, -6, -111, -111, -111, + -111, -111, -111, -111, -111, -111, -111, -111, -111, -42, + -111, -111, -111, -111, -111, -111, -111, -111, -111, 95, + -111, -111, -111, 3, -111, -111, -5, -11, 9, 109, + 91, -111, 62, 45, -111, -111, -111, 50, 63, -111, + -111, -111, -111, -111, -111, 32, -111, 203, 197, -111, + 189, 178, -111, -111, -111, -111, 182, 185, 188, -111, + -111, -111, -111, 193, -111, 198, 168, 113, 114, -111, + 133, 116, 123, 129, 130, 132, -111, 136, 139, 142, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, - -111, 103, -111, 108, -111, 181, -2, -42, -111, -111, + -111, 148, -111, 151, -111, 186, 6, -37, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, - -111, -111, -111, 34, -111, -111, -111, -111, -111, 3, - -111, -111, 10, -111, -111, -111, -111, -111, -111, -111, - -111, -111, -111, -111, -111, -111, 127, -111, 109, 15, - -111, -111, 16, -111, 225, 44, 128, -111, -111, -111, - -111, -111, -111, -111, 25, 157, -111, -111, -111, 26, - -111, -111, 24, -111, -111, -111, -111, -111, -111, -111, - 22, -111, -111, -111, -111, -111, -111, -111, -111, -111, - 179, -111, -111, 45, -111, 46, -111, 107, -111, 48, - -111, 106, 62, -111, -111, 163, -3, -111, -111, -111, - -111, -111, -14, -111, -111, -111, -111, -111, 57, -111, - -111, 224, -111, -111, -111, 227, -111, -111, -111, -111, + -111, -111, -111, 42, -111, -111, -111, -111, -111, 22, + -111, -111, 2, -111, -111, -111, -111, -111, -111, -111, + -111, -111, -111, -111, -111, -111, 96, -111, 66, 21, + -111, -111, 0, -111, 274, 35, 88, -111, -111, -111, + -111, -111, -111, -111, 41, 75, -111, -111, -111, 49, + -111, -111, 48, -111, -111, -111, -111, -111, -111, -111, + 57, -111, -111, -111, -111, -111, -111, -111, -111, -111, + 77, -111, -111, 54, -111, 27, -111, 243, -111, 25, + -111, 160, 36, -111, -111, 169, 40, -111, -111, -111, + -111, -111, 56, -111, -111, -111, -111, -111, 180, -111, + -111, 163, -111, -111, -111, 246, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, - -111, -111, 35, -111, -111, -111, -111, -111, 72, -111, + -111, -111, 8, -111, -111, -111, -111, -111, 69, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, - -111, -111, 12, 264, -111, 258, 246, 254, 209, -111, - 60, 51, 52, 27, 53, -111, -111, -111, -111, -111, - -111, -111, -111, 244, -111, 255, -111, 203, -111, -111, - 207, -111, 217, -111, -111, 198, -111, 208, -111, 8, - -111, 215, -111, 232, -111, 233, 234, -111, -111, 223, - -111, -111, -111, -111, -111, -111, 230, -111, 95, 113, - -111, -111, 153, -111, 156, -111, 2, -111, 147, -111, - 58, -111, 137, -111, 100, -111, -111, -111, -111, -111, - -111, -111, -111, 135, -111, 41, -111, 54, -111, 117, - 162, -111, -111, 50, 169, -111, 174, -111, -111, 32, - 178, -111, -111, -111, 31, -111, 7, 144, -111, 130, - -111, -111, 142, -111, -111, -111, -111, -111, -111, 11, - -111, -111, -111, -111, -111, -111, 214, -111, -111, -111, - -111, 140, -111, -111, -111, -111, -111, -111, 158, -111, - -111, 149, -111, -111, 47, -111, -111, -111, -111, -111, - -55, -111, 38, -111, -67, -111, -111, -111, -111, 263, - -111, -111, 262, -111, -111, -111, -111, -111, 190, -76, - -111, -111, 30, -111, 19, -111, 14, -111, -111, -111, - -111, 33, -111, 272, -111, 64, -111, 175, -111, -111, - -111, -111, -111, -111, 18, -111, -111, 69, -111, -111, - -111, -111, 114, -111, -111, -111, -111, 20, -111, -111, - 110, -111, -111, 28, -111, -111, -111, -111, -111, -111, + -111, -111, 61, 211, -111, 272, 257, 256, 236, -111, + 81, 83, 85, 68, 94, -111, -111, -111, -111, -111, + -111, -111, -111, 235, -111, 218, -111, 209, -111, -111, + 244, -111, 227, -111, -111, 228, -111, 238, -111, 33, + -111, 167, -111, 245, -111, 253, 254, -111, -111, 225, + -111, -111, -111, -111, -111, -111, 217, -111, 194, 213, + -111, -111, 208, -111, 207, -111, 52, -111, 205, -111, + 55, -111, 201, -111, 199, -111, -111, -111, -111, -111, + -111, -111, -111, 278, -111, 39, -111, 34, -111, 173, + 219, -111, -111, 53, 231, -111, 73, -111, -111, 44, + 59, -111, -111, -111, 47, -111, 24, 102, -111, 101, + -111, -111, 111, -111, -111, -111, -111, -111, -111, 26, + -111, -111, -111, -111, -111, -111, 65, -111, -111, -111, + -111, 76, -111, -111, -111, -111, -111, -111, 79, -111, + -111, 89, -111, -111, 51, -111, -111, -111, -111, -111, + -62, -111, 37, -111, -63, -111, -111, -111, -111, 387, + -111, -111, 264, -111, -111, -111, -111, -111, 158, -54, + -111, -111, 28, -111, 38, -111, 23, -111, -111, -111, + -111, 43, -111, 78, -111, 58, -111, 67, -111, -111, + -111, -111, -111, -111, 18, -111, -111, 195, -111, -111, + -111, -111, 161, -111, -111, -111, -111, 20, -111, -111, + 157, -111, -111, 31, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, - 86, -111, -111, -111, -111, -111, 55, -111, -111, -111, - -111, -111, -111, -111, -7, -111, -111, -111, 1, -111, - -111, 329, -111, -111, -111, -111, -111, -111, -111, -111, - -111, -111, -111, 0, -11, -111, -10, -111, -111, -111, - -111, 204, -111, -111, -111, 205, -111, -111, 317, -111, - -111, -111, 311, -111, -111, -111, -111, 370, -111, -111, - -9, -111, -111, -4, -12, -111, 337, -111, -111, -111, - -18, -111, -111, -111, -1, -17, -6, -111, -111, -111, - -111, -111, 466, 78, -111, 82, 307, -13, -111, -111, - -8, -111, 6, -111, 74, 76, -111, -111, 9, -111, - 85, -111, -111, 17, -111, -111, -111, 4, -111, -22, - 84, -111, 67, -111, -111, -111, -111, -111, 49, -111, - -111, 37, 42, 68, 77, -111, -111, -111, -111, -111, - -111, -111, -111, -111, -111, -111, -111, -111, 13, -111, - -111, -111, -111, -111, -111, 36, -111, -111, -111, -111, - -111, -111, -111, -111}; + 206, -111, -111, -111, -111, -111, -7, -111, -111, -111, + -111, -111, -111, -111, -24, -111, -111, -111, -12, -111, + -111, 342, -111, -111, -111, -111, -111, -111, -111, -111, + -111, -111, -111, -16, -32, -111, 5, -111, -111, -111, + -111, 152, -111, -111, -111, 248, -111, -111, 330, -111, + -111, -111, 324, -111, -111, -111, -111, 385, -111, -111, + -21, -111, -111, 1, 14, -111, 367, -111, 232, 12, + -111, -111, 11, -111, 10, -111, 164, 141, -111, -111, + 7, -111, 64, -111, -111, 19, -111, -111, -111, 17, + -111, -1, 60, -111, 46, -111, -111, -111, -111, -111, + -15, -111, -111, -111, -2, -17, -4, -111, -111, -111, + -111, -111, 484, 138, 313, -3, -111, -111, -111, -111, + 4, -111, -111, 13, 16, 97, 127, -111, -111, -111, + -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, + -14, -111, -111, -111, -111, -111, -111, -8, -111, -111, + -111, -111, -111, -111, -111, -111}; const short QQmlJSGrammar::action_info [] = { - 166, 438, 551, 245, 344, 454, 346, 544, 342, 336, - 546, 354, 166, 452, 448, 181, 432, 392, 465, 103, - 420, 461, 421, 448, -138, 101, 423, 73, 408, 663, - 406, -135, 413, 558, 405, 404, 151, 418, 149, -141, - 185, 143, 439, 402, 399, 432, 398, 428, -122, -111, - 101, -133, 424, -112, 268, 432, -130, 350, 73, 268, - -122, 262, -141, 245, 312, -130, 456, 558, 307, 283, - -133, 261, 350, -112, 424, 588, -111, 578, 585, 350, - 576, 465, 243, 461, 305, 448, 103, 424, 524, 143, - 184, 240, 558, 474, 241, 329, 323, 189, 268, 305, - 238, 323, -135, 245, 172, 573, 143, 192, 482, -138, - 0, 448, 555, 303, 143, 174, 174, 448, 465, 461, - 558, 143, 484, 442, 143, 143, 174, 451, 303, 435, - 490, 481, 555, 315, 175, 175, 338, 317, 143, 191, - 244, 452, 143, 0, 143, 175, 143, 662, 661, 143, - 60, 416, 415, 660, 659, 325, 64, 143, 463, 326, - 556, 61, 531, 0, 590, 589, 467, 65, 259, 258, - 654, 653, 143, 501, 436, 60, 525, 426, 491, 0, - 626, 542, 631, 632, 259, 258, 61, 257, 256, 339, - 264, 60, 144, 174, 348, 168, 0, 179, 352, 169, - 252, 251, 61, 283, 259, 258, 631, 632, 60, 321, - 525, 87, 175, 88, 411, 0, 532, 530, 66, 61, - 267, 265, 527, 66, 89, 236, 235, 527, 87, 87, - 88, 88, 87, 526, 88, 66, 549, 87, 526, 88, - 105, 89, 89, 525, 87, 89, 88, 87, 266, 88, - 89, 87, 87, 88, 88, 567, 527, 89, 174, 106, - 89, 107, 477, 67, 89, 89, 525, 526, 67, 68, - 657, 656, 580, 525, 68, 143, 0, 175, 0, 176, - 67, 87, 87, 88, 88, 0, 68, 0, 0, 527, - 550, 548, 174, 0, 89, 89, 0, 581, 579, 0, - 526, 87, 655, 88, 87, 0, 88, 0, 592, 568, - 566, 175, 527, 411, 89, 478, 476, 89, 650, 527, - 75, 76, 0, 526, 75, 76, 285, 286, 446, 445, - 526, 0, 651, 649, 558, 285, 286, 6, 5, 4, - 1, 3, 2, 0, 0, 0, 0, 77, 78, 0, - 0, 77, 78, 287, 288, 0, 290, 291, 0, 0, - 290, 291, 287, 288, 648, 292, 290, 291, 293, 292, - 294, 0, 293, 0, 294, 292, 290, 291, 293, 0, - 294, 35, 290, 291, 35, 292, 0, 0, 293, 0, - 294, 292, 80, 81, 293, 593, 294, 35, 0, 0, - 82, 83, 80, 81, 84, 35, 85, 174, 0, 0, - 82, 83, 0, 0, 84, 35, 85, 0, 49, 52, - 50, 49, 52, 50, 0, -98, 175, 0, 176, 35, - 0, 0, 0, 0, 49, 52, 50, 35, 0, 0, - 0, 0, 49, 52, 50, 0, 46, 34, 51, 46, - 34, 51, 49, 52, 50, 0, 0, 0, 0, 0, - 0, 0, 46, 34, 51, 0, 49, 52, 50, 0, - 46, 34, 51, 0, 49, 52, 50, 35, 0, 0, - 46, 34, 51, 35, 0, 0, 35, 0, 0, 35, - 0, 0, 35, 0, 46, 34, 51, 35, 80, 81, - 35, 0, 46, 34, 51, 0, 82, 83, 0, 0, - 84, 0, 85, 0, 49, 52, 50, 0, 0, 0, - 49, 52, 50, 49, 52, 50, 49, 52, 50, 49, - 52, 50, 0, 35, 49, 52, 50, 49, 52, 50, - 184, 0, 46, 34, 51, 0, 0, 0, 46, 34, - 51, 46, 34, 51, 46, 34, 51, 46, 34, 51, - 0, 0, 46, 34, 51, 46, 34, 51, 35, 0, - 49, 52, 50, 35, 0, 184, 35, 0, 0, 0, - 184, 35, 0, 0, 35, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 46, 34, - 51, 0, 0, 0, 0, 49, 52, 50, 250, 249, - 49, 52, 50, 49, 52, 50, 250, 249, 49, 52, - 50, 49, 52, 50, 0, 0, 0, 35, 0, 0, + 424, 405, 432, 404, 346, 245, 573, 354, 406, -134, + 461, -112, -113, -131, -136, 448, 350, -139, 402, 392, + 268, -123, -142, 465, 399, 398, -131, -139, 465, 461, + 474, -136, 558, 448, -134, -112, -113, 424, -123, 350, + -142, 245, 551, 481, 484, 268, 576, 524, 413, 482, + 438, 558, 439, 261, 558, 615, 420, 452, 418, 421, + 283, 454, 143, 428, 172, 558, 166, 423, 558, 448, + 608, 73, 546, 448, 149, 283, 0, 323, 408, 0, + 544, 307, 268, 0, 0, 0, 143, 184, 350, 448, + 245, 166, 101, 73, 461, 329, 465, 238, 456, 424, + 241, 336, 618, 189, 665, 262, 143, 323, 0, 181, + 317, 143, 451, 0, 315, 442, 143, 143, 192, 555, + 0, 143, 240, 243, 303, 151, 452, 101, 143, 185, + 143, 435, 143, 312, 305, 244, 0, 0, 303, 490, + 555, 60, 60, 342, 143, 143, 191, 432, 252, 251, + 103, 344, 61, 61, 144, 60, 305, 662, 661, 60, + 103, 656, 655, 352, 325, 338, 61, 556, 326, 501, + 61, 257, 256, 426, 143, 168, 436, 664, 663, 169, + 348, 542, 264, 64, 321, 633, 634, 491, 628, 620, + 619, 259, 258, 179, 65, 174, 463, 143, 622, 259, + 258, 416, 415, 525, 267, 265, 525, 87, 477, 88, + 531, 0, 174, 525, 175, 143, 411, 87, 339, 88, + 89, 66, 0, 87, 558, 88, 467, 527, 66, 610, + 89, 175, 266, 411, 525, 567, 89, 525, 526, 0, + 87, 66, 88, 87, 87, 88, 88, 549, 174, 527, + 236, 235, 527, 89, 611, 609, 89, 89, 0, 527, + 526, 478, 476, 526, 532, 530, 67, 175, 446, 445, + 526, 0, 68, 67, 174, 659, 658, 105, 0, 68, + 527, 75, 76, 527, 0, 623, 67, 285, 286, 568, + 566, 526, 68, 175, 526, 176, 106, 652, 107, 75, + 76, 550, 548, 174, 0, 285, 286, 657, 77, 78, + 174, 653, 651, 0, 287, 288, 0, 0, 0, 0, + 0, -99, 175, 0, 176, 0, 77, 78, -99, 175, + 0, 176, 287, 288, 0, 290, 291, 0, 0, 87, + 0, 88, 0, 650, 292, 80, 81, 293, 35, 294, + 0, 0, 89, 82, 83, 0, 0, 84, 35, 85, + 80, 81, 6, 5, 4, 1, 3, 2, 82, 83, + 80, 81, 84, 35, 85, 0, 0, 0, 82, 83, + 80, 81, 84, 0, 85, 49, 52, 50, 82, 83, + 80, 81, 84, 0, 85, 49, 52, 50, 82, 83, + 0, 0, 84, 0, 85, 35, 0, 0, 35, 0, + 49, 52, 50, 46, 34, 51, 35, 0, 0, 35, + 290, 291, 35, 46, 34, 51, 0, 0, 35, 292, + 0, 0, 293, 0, 294, 184, 0, 0, 46, 34, + 51, 35, 49, 52, 50, 49, 52, 50, 184, 0, + 0, 0, 0, 49, 52, 50, 49, 52, 50, 49, + 52, 50, 35, 0, 0, 49, 52, 50, 0, 184, + 46, 34, 51, 46, 34, 51, 0, 0, 49, 52, + 50, 46, 34, 51, 46, 34, 51, 46, 34, 51, + 0, 0, 0, 46, 34, 51, 0, 0, 35, 49, + 52, 50, 0, 35, 0, 0, 46, 34, 51, 0, + 0, 35, 0, 0, 0, 0, 0, 0, 0, 35, + 0, 0, 0, 0, 0, 0, 0, 46, 34, 51, + 250, 249, 0, 0, 0, 49, 52, 50, 0, 0, + 49, 52, 50, 250, 249, 0, 0, 0, 49, 52, + 50, 250, 249, 0, 0, 0, 49, 52, 50, 0, 0, 0, 0, 46, 34, 51, 0, 0, 46, 34, - 51, 46, 34, 51, 0, 0, 46, 34, 51, 46, - 34, 51, 0, 0, 0, 0, 0, 0, 35, 250, - 249, 0, 0, 0, 49, 52, 50, 0, 0, 0, + 51, 0, 0, 0, 0, 0, 46, 34, 51, 0, + 35, 0, 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 255, 254, 46, 34, 51, 49, 52, 50, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 46, 34, 51, 0, 0, 0, 0, - 0, 0, 0, 30, 31, 153, 0, 0, 0, 0, - 0, 0, 0, 33, 0, 154, 0, 0, 0, 155, - 35, 0, 0, 0, 36, 37, 0, 38, 156, 0, - 157, 0, 0, 0, 516, 0, 0, 0, 45, 0, - 0, 158, 0, 159, 64, 0, 0, 0, 0, 0, - 0, 160, 0, 0, 161, 65, 53, 49, 52, 50, - 162, 54, 0, 0, 0, 0, 163, 0, 0, 0, - 0, 0, 44, 56, 32, 0, 0, 0, 41, 0, - 0, 0, 164, 0, 0, 46, 34, 51, 0, 0, - 0, 0, 0, 0, 0, 30, 31, 0, 0, 0, - 0, 0, 0, 0, 0, 33, 0, 0, 153, 0, - 0, 0, 35, 0, 0, 0, 36, 37, 154, 38, - 0, 0, 155, 0, 0, 0, 516, 0, 0, 0, - 45, 156, 0, 157, 0, 0, 319, 0, 0, 0, - 0, 0, 0, 0, 158, 0, 159, 64, 53, 49, - 52, 50, 0, 54, 160, 0, 0, 161, 65, 0, - 0, 0, 0, 162, 44, 56, 32, 0, 0, 163, - 41, 0, 0, 0, 0, 0, 0, 46, 34, 51, - 0, 0, 0, 0, 0, 164, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 30, 31, 0, 0, 0, 0, 0, 0, 0, - 0, 33, 0, 0, 0, 0, 0, 0, 35, 0, - 0, 0, 36, 37, 0, 38, 0, 0, 0, 0, - 0, 0, 516, 0, 0, 0, 45, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 53, 49, 52, 50, 0, 54, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 44, 56, 32, 0, 0, 0, 41, 0, 0, 0, - 0, 0, 0, 46, 34, 51, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 30, 31, 0, 0, 0, - 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, - 0, 0, 35, 0, 0, 0, 36, 37, 0, 38, - 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, - 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 53, 49, - 52, 50, 0, 54, 0, 0, 0, 0, 0, 0, + 0, 0, 255, 254, 153, 0, 0, 49, 52, 50, + 0, 0, 0, 0, 154, 0, 0, 0, 155, 0, + 0, 0, 0, 0, 0, 0, 0, 156, 0, 157, + 0, 0, 319, 0, 0, 46, 34, 51, 0, 0, + 158, 0, 159, 64, 0, 30, 31, 153, 0, 0, + 160, 0, 0, 161, 65, 33, 0, 154, 0, 162, + 0, 155, 35, 0, 0, 163, 36, 37, 0, 38, + 156, 0, 157, 0, 0, 0, 42, 0, 0, 0, + 45, 164, 0, 158, 0, 159, 64, 0, 0, 0, + 0, 0, 0, 160, 0, 0, 161, 65, 53, 49, + 52, 50, 162, 54, 0, 0, 0, 0, 163, 0, 0, 0, 0, 0, 44, 56, 32, 0, 0, 0, - 41, 0, 0, 0, 0, 0, 0, 46, 34, 51, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 515, - 0, 30, 31, 0, 0, 0, 0, 0, 0, 0, - 0, 219, 0, 0, 0, 0, 0, 0, 35, 0, - 0, 0, 36, 37, 0, 38, 0, 0, 0, 0, - 0, 0, 516, 0, 0, 0, 45, 0, 0, 0, + 41, 0, 0, 0, 164, 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 53, 517, 519, 518, 0, 54, - 0, 0, 0, 0, 227, 0, 0, 0, 0, 0, - 44, 56, 32, 214, 0, 0, 41, 0, 0, 0, - 0, 0, 0, 46, 34, 51, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 515, 0, 30, 31, 0, - 0, 0, 0, 0, 0, 0, 0, 219, 0, 0, - 0, 0, 0, 0, 35, 0, 0, 0, 36, 37, - 0, 38, 0, 0, 0, 0, 0, 0, 516, 0, - 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, - 563, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 53, 517, 519, 518, 0, 54, 0, 0, 0, 0, - 227, 0, 0, 0, 0, 0, 44, 56, 32, 214, - 0, 0, 41, 0, 0, 0, 0, 0, 0, 46, - 34, 51, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 515, 0, 30, 31, 0, 0, 0, 0, 0, - 0, 0, 0, 219, 0, 0, 0, 0, 0, 0, - 35, 0, 0, 0, 36, 37, 0, 38, 0, 0, - 0, 0, 0, 0, 516, 0, 0, 0, 45, 0, - 0, 0, 0, 0, 0, 0, 560, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 53, 517, 519, 518, - 0, 54, 0, 0, 0, 0, 227, 0, 0, 0, - 0, 0, 44, 56, 32, 214, 0, 0, 41, 0, - 0, 0, 0, 0, 0, 46, 34, 51, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 29, 30, 31, - 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, - 0, 0, 0, 0, 0, 35, 0, 0, 0, 36, - 37, 0, 38, 0, 0, 0, 39, 0, 40, 42, - 43, 0, 0, 45, 0, 0, 0, 47, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 53, 49, 52, 50, 0, 54, 0, 55, 0, - 57, 0, 58, 0, 0, 0, 0, 44, 56, 32, - 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, - 46, 34, 51, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -131, 0, 0, 0, 29, 30, 31, 0, + 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, + 33, 0, 0, 0, 0, 0, 0, 35, 0, 0, + 0, 36, 37, 0, 38, 0, 0, 0, 0, 0, + 0, 516, 0, 0, 0, 45, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 53, 49, 52, 50, 0, 54, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, + 56, 32, 0, 0, 0, 41, 0, 0, 0, 0, + 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 31, 0, 0, 0, 0, + 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, + 0, 35, 0, 0, 0, 36, 37, 0, 38, 0, + 0, 0, 0, 0, 0, 42, 0, 0, 0, 45, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 53, 49, 52, + 50, 0, 54, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 44, 56, 32, 0, 0, 0, 41, + 0, 0, 0, 0, 0, 0, 46, 34, 51, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 515, 0, + 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, + 219, 0, 0, 0, 0, 0, 0, 35, 0, 0, + 0, 36, 37, 0, 38, 0, 0, 0, 0, 0, + 0, 516, 0, 0, 0, 45, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 53, 517, 519, 518, 0, 54, 0, + 0, 0, 0, 227, 0, 0, 0, 0, 0, 44, + 56, 32, 214, 0, 0, 41, 0, 0, 0, 0, + 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 515, 0, 30, 31, 0, 0, + 0, 0, 0, 0, 0, 0, 219, 0, 0, 0, + 0, 0, 0, 35, 0, 0, 0, 36, 37, 0, + 38, 0, 0, 0, 0, 0, 0, 516, 0, 0, + 0, 45, 0, 0, 0, 0, 0, 0, 0, 563, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, + 517, 519, 518, 0, 54, 0, 0, 0, 0, 227, + 0, 0, 0, 0, 0, 44, 56, 32, 214, 0, + 0, 41, 0, 0, 0, 0, 0, 0, 46, 34, + 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 515, 0, 30, 31, 0, 0, 0, 0, 0, 0, + 0, 0, 219, 0, 0, 0, 0, 0, 0, 35, + 0, 0, 0, 36, 37, 0, 38, 0, 0, 0, + 0, 0, 0, 516, 0, 0, 0, 45, 0, 0, + 0, 0, 0, 0, 0, 560, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 53, 517, 519, 518, 0, + 54, 0, 0, 0, 0, 227, 0, 0, 0, 0, + 0, 44, 56, 32, 214, 0, 0, 41, 0, 0, + 0, 0, 0, 0, 46, 34, 51, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 36, 37, 0, 38, 0, 0, 0, 39, 0, 40, 42, 43, @@ -507,198 +479,228 @@ const short QQmlJSGrammar::action_info [] = { 0, 58, 0, 0, 0, 0, 44, 56, 32, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, - 0, 0, 33, 0, 0, 0, 0, 0, 0, 35, - 0, 0, 0, 36, 37, 0, 38, 0, 0, 0, - 39, 0, 40, 42, 43, 0, 0, 45, 0, 0, - 0, 47, 0, 48, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 53, 49, 52, 50, 0, - 54, 0, 55, 0, 57, 282, 58, 0, 0, 0, - 0, 44, 56, 32, 0, 0, 0, 41, 0, 0, - 0, 0, 0, 0, 46, 34, 51, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 488, 0, 0, 29, - 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 35, 0, 0, - 0, 36, 37, 0, 38, 0, 0, 0, 39, 0, - 40, 42, 43, 0, 0, 45, 0, 0, 0, 47, - 0, 48, 0, 0, 489, 0, 0, 0, 0, 0, - 0, 0, 0, 53, 49, 52, 50, 0, 54, 0, - 55, 0, 57, 0, 58, 0, 0, 0, 0, 44, - 56, 32, 0, 0, 0, 41, 0, 0, 0, 0, - 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 488, 0, 0, 29, 30, 31, - 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, - 0, 0, 0, 0, 0, 35, 0, 0, 0, 36, - 37, 0, 38, 0, 0, 0, 39, 0, 40, 42, - 43, 0, 0, 45, 0, 0, 0, 47, 0, 48, - 0, 0, 494, 0, 0, 0, 0, 0, 0, 0, - 0, 53, 49, 52, 50, 0, 54, 0, 55, 0, - 57, 0, 58, 0, 0, 0, 0, 44, 56, 32, - 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, - 46, 34, 51, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 496, 0, 0, 29, 30, 31, 0, 0, + 0, -132, 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 36, 37, 0, 38, 0, 0, 0, 39, 0, 40, 42, 43, 0, 0, 45, 0, 0, 0, 47, 0, 48, 0, 0, - 497, 0, 0, 0, 0, 0, 0, 0, 0, 53, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 49, 52, 50, 0, 54, 0, 55, 0, 57, 0, 58, 0, 0, 0, 0, 44, 56, 32, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 496, 0, 0, 29, 30, 31, 0, 0, 0, 0, - 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, - 0, 35, 0, 0, 0, 36, 37, 0, 38, 0, - 0, 0, 39, 0, 40, 42, 43, 0, 0, 45, - 0, 0, 0, 47, 0, 48, 0, 0, 499, 0, - 0, 0, 0, 0, 0, 0, 0, 53, 49, 52, - 50, 0, 54, 0, 55, 0, 57, 0, 58, 0, - 0, 0, 0, 44, 56, 32, 0, 0, 0, 41, - 0, 0, 0, 0, 0, 0, 46, 34, 51, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 29, 30, + 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, + 0, 33, 0, 0, 0, 0, 0, 0, 35, 0, + 0, 0, 36, 37, 0, 38, 0, 0, 0, 39, + 0, 40, 42, 43, 0, 0, 45, 0, 0, 0, + 47, 0, 48, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 53, 49, 52, 50, 0, 54, + 0, 55, 0, 57, 282, 58, 0, 0, 0, 0, + 44, 56, 32, 0, 0, 0, 41, 0, 0, 0, + 0, 0, 0, 46, 34, 51, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 496, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, - 0, 0, 0, 0, 0, 0, 35, 220, 0, 0, - 595, 596, 0, 38, 0, 0, 0, 39, 0, 40, + 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, + 36, 37, 0, 38, 0, 0, 0, 39, 0, 40, 42, 43, 0, 0, 45, 0, 0, 0, 47, 0, - 48, 0, 0, 0, 0, 0, 0, 0, 223, 0, - 0, 0, 53, 49, 52, 50, 224, 54, 0, 55, - 226, 57, 0, 58, 0, 229, 0, 0, 44, 56, + 48, 0, 0, 497, 0, 0, 0, 0, 0, 0, + 0, 0, 53, 49, 52, 50, 0, 54, 0, 55, + 0, 57, 0, 58, 0, 0, 0, 0, 44, 56, 32, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, - 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, - 0, 35, 220, 0, 0, 221, 37, 0, 38, 0, - 0, 0, 39, 0, 40, 42, 43, 0, 0, 45, - 0, 0, 0, 47, 0, 48, 0, 0, 0, 0, - 0, 0, 0, 223, 0, 0, 0, 53, 49, 52, - 50, 224, 54, 0, 55, 226, 57, 0, 58, 0, - 229, 0, 0, 44, 56, 32, 0, 0, 0, 41, + 0, 0, 0, 488, 0, 0, 29, 30, 31, 0, + 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, + 0, 0, 0, 0, 35, 0, 0, 0, 36, 37, + 0, 38, 0, 0, 0, 39, 0, 40, 42, 43, + 0, 0, 45, 0, 0, 0, 47, 0, 48, 0, + 0, 494, 0, 0, 0, 0, 0, 0, 0, 0, + 53, 49, 52, 50, 0, 54, 0, 55, 0, 57, + 0, 58, 0, 0, 0, 0, 44, 56, 32, 0, + 0, 0, 41, 0, 0, 0, 0, 0, 0, 46, + 34, 51, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 488, 0, 0, 29, 30, 31, 0, 0, 0, + 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, + 0, 0, 35, 0, 0, 0, 36, 37, 0, 38, + 0, 0, 0, 39, 0, 40, 42, 43, 0, 0, + 45, 0, 0, 0, 47, 0, 48, 0, 0, 489, + 0, 0, 0, 0, 0, 0, 0, 0, 53, 49, + 52, 50, 0, 54, 0, 55, 0, 57, 0, 58, + 0, 0, 0, 0, 44, 56, 32, 0, 0, 0, + 41, 0, 0, 0, 0, 0, 0, 46, 34, 51, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 496, + 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, + 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, + 35, 0, 0, 0, 36, 37, 0, 38, 0, 0, + 0, 39, 0, 40, 42, 43, 0, 0, 45, 0, + 0, 0, 47, 0, 48, 0, 0, 499, 0, 0, + 0, 0, 0, 0, 0, 0, 53, 49, 52, 50, + 0, 54, 0, 55, 0, 57, 0, 58, 0, 0, + 0, 0, 44, 56, 32, 0, 0, 0, 41, 0, + 0, 0, 0, 0, 0, 46, 34, 51, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 29, 30, 31, + 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, + 0, 0, 0, 0, 0, 35, 220, 0, 0, 221, + 37, 0, 38, 0, 0, 0, 39, 0, 40, 42, + 43, 0, 0, 45, 0, 0, 0, 47, 0, 48, + 0, 0, 0, 0, 0, 0, 0, 223, 0, 0, + 0, 53, 49, 52, 50, 224, 54, 0, 55, 226, + 57, 0, 58, 0, 229, 0, 0, 44, 56, 32, + 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, + 46, 34, 51, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, + 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, + 35, 220, 0, 0, 578, 37, 0, 38, 0, 0, + 0, 39, 0, 40, 42, 43, 0, 0, 45, 0, + 0, 0, 47, 0, 48, 0, 0, 0, 0, 0, + 0, 0, 223, 0, 0, 0, 53, 49, 52, 50, + 224, 54, 0, 55, 226, 57, 0, 58, 0, 229, + 0, 0, 44, 56, 32, 0, 0, 0, 41, 0, + 0, 0, 0, 0, 0, 46, 34, 51, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 29, 30, 31, + 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, + 0, 0, 0, 0, 0, 35, 220, 0, 0, 578, + 624, 0, 38, 0, 0, 0, 39, 0, 40, 42, + 43, 0, 0, 45, 0, 0, 0, 47, 0, 48, + 0, 0, 0, 0, 0, 0, 0, 223, 0, 0, + 0, 53, 49, 52, 50, 224, 54, 0, 55, 226, + 57, 0, 58, 0, 229, 0, 0, 44, 56, 32, + 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, + 46, 34, 51, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 111, 112, 113, 0, 0, 115, 117, 118, + 0, 0, 119, 0, 120, 0, 0, 0, 122, 123, + 124, 0, 0, 0, 0, 0, 0, 35, 125, 126, + 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 131, 0, 0, + 0, 0, 0, 0, 49, 52, 50, 132, 133, 134, + 0, 136, 137, 138, 139, 140, 141, 0, 0, 129, + 135, 121, 114, 116, 130, 0, 0, 0, 0, 0, + 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 111, 112, 113, 0, 0, 115, + 117, 118, 0, 0, 119, 0, 120, 0, 0, 0, + 122, 123, 124, 0, 0, 0, 0, 0, 0, 35, + 125, 126, 127, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 128, 0, 0, 0, 395, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, + 0, 0, 0, 0, 0, 397, 49, 52, 50, 132, + 133, 134, 0, 136, 137, 138, 139, 140, 141, 0, + 0, 129, 135, 121, 114, 116, 130, 0, 0, 0, + 0, 0, 0, 0, 46, 374, 380, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 111, 112, 113, 0, + 0, 115, 117, 118, 0, 0, 119, 0, 120, 0, + 0, 0, 122, 123, 124, 0, 0, 0, 0, 0, + 0, 35, 125, 126, 127, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 128, 0, 0, 0, 395, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 131, 0, 0, 0, 0, 0, 397, 49, 52, + 50, 132, 133, 134, 0, 136, 137, 138, 139, 140, + 141, 0, 0, 129, 135, 121, 114, 116, 130, 0, 0, 0, 0, 0, 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 112, 113, 0, 0, 115, 117, 118, 0, 0, 119, 0, 120, 0, 0, 0, 122, 123, 124, 0, 0, 0, 0, 0, 0, 35, 125, 126, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 131, 0, 0, 0, 0, 0, 0, + 0, 395, 0, 0, 0, 0, 0, 0, 0, 396, + 0, 0, 0, 131, 0, 0, 0, 0, 0, 397, 49, 52, 50, 132, 133, 134, 0, 136, 137, 138, 139, 140, 141, 0, 0, 129, 135, 121, 114, 116, - 130, 0, 0, 0, 0, 0, 0, 0, 46, 34, - 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 111, 112, 113, 0, 0, 115, 117, 118, 0, 0, - 119, 0, 120, 0, 0, 0, 122, 123, 124, 0, - 0, 0, 0, 0, 0, 35, 125, 126, 127, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, - 0, 0, 0, 395, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 131, 0, 0, 0, 0, - 0, 397, 49, 52, 50, 132, 133, 134, 0, 136, - 137, 138, 139, 140, 141, 0, 0, 129, 135, 121, - 114, 116, 130, 0, 0, 0, 0, 0, 0, 0, + 130, 0, 0, 0, 0, 0, 0, 0, 46, 374, + 380, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 213, 0, 0, 0, 0, 215, 0, 29, 30, 31, + 217, 0, 0, 0, 0, 0, 0, 218, 33, 0, + 0, 0, 0, 0, 0, 35, 220, 0, 0, 221, + 37, 0, 38, 0, 0, 0, 39, 0, 40, 42, + 43, 0, 0, 45, 0, 0, 0, 47, 0, 48, + 0, 0, 0, 0, 0, 222, 0, 223, 0, 0, + 0, 53, 49, 52, 50, 224, 54, 225, 55, 226, + 57, 227, 58, 228, 229, 0, 0, 44, 56, 32, + 214, 216, 0, 41, 0, 0, 0, 0, 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 111, 112, 113, 0, 0, 115, 117, 118, - 0, 0, 119, 0, 120, 0, 0, 0, 122, 123, - 124, 0, 0, 0, 0, 0, 0, 35, 125, 126, - 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 128, 0, 0, 0, 395, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 131, 0, 0, - 0, 0, 0, 397, 49, 52, 50, 132, 133, 134, - 0, 136, 137, 138, 139, 140, 141, 0, 0, 129, - 135, 121, 114, 116, 130, 0, 0, 0, 0, 0, - 0, 0, 46, 374, 380, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 111, 112, 113, 0, 0, 115, - 117, 118, 0, 0, 119, 0, 120, 0, 0, 0, - 122, 123, 124, 0, 0, 0, 0, 0, 0, 35, - 125, 126, 127, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 128, 0, 0, 0, 395, 0, 0, - 0, 0, 0, 0, 0, 396, 0, 0, 0, 131, - 0, 0, 0, 0, 0, 397, 49, 52, 50, 132, - 133, 134, 0, 136, 137, 138, 139, 140, 141, 0, - 0, 129, 135, 121, 114, 116, 130, 0, 0, 0, + 0, 0, 213, 0, 0, 0, 0, 215, 0, 29, + 30, 31, 217, 0, 0, 0, 0, 0, 0, 218, + 219, 0, 0, 0, 0, 0, 0, 35, 220, 0, + 0, 221, 37, 0, 38, 0, 0, 0, 39, 0, + 40, 42, 43, 0, 0, 45, 0, 0, 0, 47, + 0, 48, 0, 0, 0, 0, 0, 222, 0, 223, + 0, 0, 0, 53, 49, 52, 50, 224, 54, 225, + 55, 226, 57, 227, 58, 228, 229, 0, 0, 44, + 56, 32, 214, 216, 0, 41, 0, 0, 0, 0, + 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 582, 112, 113, 0, 0, 584, + 117, 586, 30, 31, 587, 0, 120, 0, 0, 0, + 122, 589, 590, 0, 0, 0, 0, 0, 0, 35, + 591, 126, 127, 221, 37, 0, 38, 0, 0, 0, + 39, 0, 40, 592, 43, 0, 0, 594, 0, 0, + 0, 47, 0, 48, 0, 0, 0, 0, 0, 595, + 0, 223, 0, 0, 0, 596, 49, 52, 50, 597, + 598, 599, 55, 601, 602, 603, 604, 605, 606, 0, + 0, 593, 600, 588, 583, 585, 130, 41, 0, 0, 0, 0, 0, 0, 46, 374, 380, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 213, 0, 0, 0, - 0, 215, 0, 29, 30, 31, 217, 0, 0, 0, - 0, 0, 0, 218, 219, 0, 0, 0, 0, 0, - 0, 35, 220, 0, 0, 221, 37, 0, 38, 0, - 0, 0, 39, 0, 40, 42, 43, 0, 0, 45, - 0, 0, 0, 47, 0, 48, 0, 0, 0, 0, - 0, 222, 0, 223, 0, 0, 0, 53, 49, 52, - 50, 224, 54, 225, 55, 226, 57, 227, 58, 228, - 229, 0, 0, 44, 56, 32, 214, 216, 0, 41, - 0, 0, 0, 0, 0, 0, 46, 34, 51, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 213, 0, - 0, 0, 0, 215, 0, 29, 30, 31, 217, 0, - 0, 0, 0, 0, 0, 218, 33, 0, 0, 0, - 0, 0, 0, 35, 220, 0, 0, 221, 37, 0, - 38, 0, 0, 0, 39, 0, 40, 42, 43, 0, - 0, 45, 0, 0, 0, 47, 0, 48, 0, 0, - 0, 0, 0, 222, 0, 223, 0, 0, 0, 53, - 49, 52, 50, 224, 54, 225, 55, 226, 57, 227, - 58, 228, 229, 0, 0, 44, 56, 32, 214, 216, - 0, 41, 0, 0, 0, 0, 0, 0, 46, 34, - 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 600, 112, 113, 0, 0, 602, 117, 604, 30, 31, - 605, 0, 120, 0, 0, 0, 122, 607, 608, 0, - 0, 0, 0, 0, 0, 35, 609, 126, 127, 221, - 37, 0, 38, 0, 0, 0, 39, 0, 40, 610, - 43, 0, 0, 612, 0, 0, 0, 47, 0, 48, - 0, 0, 0, 0, 0, 613, 0, 223, 0, 0, - 0, 614, 49, 52, 50, 615, 616, 617, 55, 619, - 620, 621, 622, 623, 624, 0, 0, 611, 618, 606, - 601, 603, 130, 41, 0, 0, 0, 0, 0, 0, - 46, 374, 380, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 365, 112, 113, 0, 0, 367, 117, 369, - 30, 31, 370, 0, 120, 0, 0, 0, 122, 372, - 373, 0, 0, 0, 0, 0, 0, 35, 375, 126, - 127, 221, 37, 0, 38, 0, 0, 0, 39, 0, - 40, 376, 43, 0, 0, 378, 0, 0, 0, 47, - 0, 48, 0, -277, 0, 0, 0, 379, 0, 223, - 0, 0, 0, 381, 49, 52, 50, 382, 383, 384, - 55, 386, 387, 388, 389, 390, 391, 0, 0, 377, - 385, 371, 366, 368, 130, 41, 0, 0, 0, 0, - 0, 0, 46, 374, 380, 0, 0, 0, 0, 0, - 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 365, 112, 113, 0, + 0, 367, 117, 369, 30, 31, 370, 0, 120, 0, + 0, 0, 122, 372, 373, 0, 0, 0, 0, 0, + 0, 35, 375, 126, 127, 221, 37, 0, 38, 0, + 0, 0, 39, 0, 40, 376, 43, 0, 0, 378, + 0, 0, 0, 47, 0, 48, 0, -278, 0, 0, + 0, 379, 0, 223, 0, 0, 0, 381, 49, 52, + 50, 382, 383, 384, 55, 386, 387, 388, 389, 390, + 391, 0, 0, 377, 385, 371, 366, 368, 130, 41, + 0, 0, 0, 0, 0, 0, 46, 374, 380, 0, + 0, 0, 0, 0, 0, 0, 0, 0, - 148, 142, 183, 447, 469, 347, 575, 444, 547, 627, - 248, 320, 587, 572, 584, 586, 485, 591, 565, 529, - 313, 545, 447, 393, 253, 528, 500, 183, 574, 453, - 331, 652, 447, 437, 444, 313, 462, 455, 263, 457, - 237, 441, 206, 188, 190, 150, 16, 178, 433, 630, - 425, 641, 165, 400, 658, 458, 642, 171, 173, 248, - 475, 351, 498, 248, 253, 313, 183, 466, 183, 541, - 495, 629, 253, 512, 511, 188, 145, 206, 260, 645, - 644, 62, 0, 62, 362, 507, 298, 469, 206, 206, - 247, 514, 514, 62, 206, 460, 646, 409, 152, 409, - 599, 628, 355, 239, 206, 62, 62, 62, 362, 260, - 296, 297, 299, 331, 62, 62, 313, 504, 206, 295, - 62, 62, 459, 460, 356, 206, 277, 62, 62, 502, - 182, 281, 206, 62, 410, 182, 410, 401, 62, 353, - 459, 62, 62, 506, 505, 62, 62, 503, 493, 349, - 91, 62, 492, 206, 63, 206, 313, 62, 345, 483, - 393, 479, 62, 62, 260, 206, 444, 206, 510, 102, - 148, 62, 104, 182, 206, 188, 188, 468, 180, 170, - 206, 62, 148, 247, 62, 394, 460, 393, 409, 340, - 412, 341, 362, 206, 422, 167, 393, 206, 62, 108, - 459, 313, 62, 187, 419, 62, 62, 86, 206, 62, - 318, 98, 100, 403, 62, 99, 69, 322, 514, 514, - 313, 62, 417, 553, 557, 410, 206, 79, 110, 246, - 62, 343, 206, 206, 62, 0, 70, 62, 74, 71, - 62, 62, 206, 108, 90, 206, 93, 62, 62, 62, - 72, 62, 92, 62, 94, 62, 95, 309, 96, 407, - 97, 309, 281, 62, 362, 362, 281, 0, 281, 242, - 302, 0, 110, 177, 464, 0, 316, 309, 0, 308, - 206, 206, 281, 311, 309, 0, 62, 62, 309, 281, - 206, 281, 281, 281, 0, 314, 0, 0, 62, 330, - 62, 324, 0, 281, 327, 281, 337, 300, 62, 62, - 328, 304, 62, 281, 281, 301, 564, 281, 62, 289, - 306, 569, 561, 281, 0, 514, 553, 284, 625, 0, - 0, 514, 0, 0, 522, 0, 0, 0, 0, 0, - 522, 0, 0, 0, 0, 0, 513, 523, 0, 485, - 443, 440, 513, 523, 533, 534, 535, 536, 540, 537, - 538, 577, 533, 534, 535, 536, 540, 537, 538, 0, + 545, 572, 565, 632, 654, 148, 529, 541, 528, 142, + 660, 263, 500, 393, 617, 616, 621, 614, 16, 629, + 444, 183, 313, 547, 447, 183, 631, 643, 253, 248, + 644, 485, 575, 574, 607, 152, 320, 437, 178, 313, + 441, 433, 173, 183, 165, 253, 462, 313, 457, 447, + 444, 453, 253, 458, 425, 347, 455, 248, 351, 188, + 475, 466, 498, 171, 150, 447, 206, 190, 400, 468, + 0, 183, 248, 495, 469, 237, 409, 393, 409, 331, + 464, 247, 512, 206, 145, 206, 62, 409, 507, 206, + 0, 511, 0, 188, 0, 206, 206, 188, 206, 62, + 62, 504, 460, 417, 62, 206, 505, 206, 647, 646, + 407, 0, 0, 410, 62, 410, 459, 62, 148, 506, + 62, 187, 62, 277, 410, 419, 412, 298, 281, 393, + 148, 0, 0, 0, 422, 62, 170, 62, 180, 62, + 295, 514, 296, 260, 297, 62, 648, 503, 62, 62, + 62, 182, 514, 299, 394, 62, 62, 460, 459, 206, + 362, 630, 362, 62, 167, 502, 514, 62, 62, 322, + 62, 553, 444, 99, 100, 93, 206, 62, 356, 206, + 510, 206, 94, 62, 62, 206, 62, 62, 95, 96, + 62, 97, 86, 62, 90, 493, 62, 91, 188, 492, + 92, 355, 62, 353, 108, 62, 483, 349, 242, 345, + 247, 313, 331, 469, 102, 104, 313, 206, 62, 206, + 182, 260, 62, 206, 206, 206, 239, 62, 98, 182, + 313, 313, 62, 110, 362, 72, 62, 206, 69, 62, + 318, 70, 62, 62, 71, 260, 63, 62, 246, 393, + 581, 62, 62, 460, 0, 74, 206, 62, 79, 459, + 0, 206, 514, 309, 206, 62, 362, 557, 281, 0, + 281, 309, 62, 0, 284, 403, 281, 281, 0, 309, + 401, 0, 206, 306, 281, 308, 343, 479, 340, 62, + 62, 341, 108, 337, 281, 281, 206, 302, 309, 62, + 0, 330, 304, 281, 281, 314, 316, 62, 309, 0, + 62, 62, 281, 281, 324, 281, 281, 301, 300, 514, + 311, 110, 177, 0, 327, 0, 62, 569, 522, 564, + 328, 281, 553, 289, 627, 561, 0, 0, 514, 0, + 513, 523, 0, 0, 514, 0, 0, 522, 0, 0, + 0, 0, 443, 522, 0, 485, 0, 0, 0, 513, + 523, 0, 0, 0, 0, 513, 523, 533, 534, 535, + 536, 540, 537, 538, 0, 0, 0, 0, 0, 0, + 0, 577, 0, 0, 0, 0, 0, 0, 0, 362, + 579, 580, 533, 534, 535, 536, 540, 537, 538, 569, + 0, 0, 0, 0, 0, 206, 0, 0, 570, 571, + 533, 534, 535, 536, 540, 537, 538, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 514, 569, 0, 0, 0, 0, 0, - 0, 0, 522, 570, 571, 533, 534, 535, 536, 540, - 537, 538, 0, 0, 513, 523, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 440, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 577, 0, + 0, 0, 0, 0, 0, 0, 0, 625, 626, 533, + 534, 535, 536, 540, 537, 538, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -706,170 +708,133 @@ const short QQmlJSGrammar::action_info [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 594, 0, 0, 0, 0, 0, 0, 0, 0, 597, - 598, 533, 534, 535, 536, 540, 537, 538, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0}; + 0, 0, 0, 0, 0}; const short QQmlJSGrammar::action_check [] = { - 2, 55, 34, 7, 60, 36, 31, 37, 61, 17, - 24, 16, 2, 20, 33, 60, 5, 8, 36, 79, - 60, 36, 33, 33, 7, 48, 55, 1, 55, 0, - 33, 7, 60, 33, 60, 36, 60, 36, 8, 7, - 36, 8, 7, 55, 7, 5, 55, 33, 7, 7, - 48, 7, 36, 7, 36, 5, 7, 36, 1, 36, - 7, 36, 7, 7, 61, 7, 60, 33, 8, 1, - 7, 77, 36, 7, 36, 60, 7, 29, 8, 36, - 7, 36, 55, 36, 79, 33, 79, 36, 66, 8, - 36, 60, 33, 17, 33, 7, 2, 8, 36, 79, - 36, 2, 7, 7, 7, 66, 8, 33, 33, 7, - -1, 33, 8, 48, 8, 15, 15, 33, 36, 36, - 33, 8, 55, 7, 8, 8, 15, 6, 48, 10, - 8, 60, 8, 61, 34, 34, 8, 60, 8, 60, - 55, 20, 8, -1, 8, 34, 8, 61, 62, 8, - 40, 61, 62, 61, 62, 50, 42, 8, 60, 54, - 56, 51, 7, -1, 61, 62, 60, 53, 61, 62, - 61, 62, 8, 60, 55, 40, 29, 60, 56, -1, - 56, 29, 91, 92, 61, 62, 51, 61, 62, 61, - 60, 40, 56, 15, 60, 50, -1, 56, 60, 54, - 61, 62, 51, 1, 61, 62, 91, 92, 40, 60, - 29, 25, 34, 27, 36, -1, 61, 62, 12, 51, - 61, 62, 75, 12, 38, 61, 62, 75, 25, 25, - 27, 27, 25, 86, 27, 12, 7, 25, 86, 27, - 15, 38, 38, 29, 25, 38, 27, 25, 89, 27, - 38, 25, 25, 27, 27, 7, 75, 38, 15, 34, - 38, 36, 8, 57, 38, 38, 29, 86, 57, 63, - 61, 62, 36, 29, 63, 8, -1, 34, -1, 36, - 57, 25, 25, 27, 27, -1, 63, -1, -1, 75, - 61, 62, 15, -1, 38, 38, -1, 61, 62, -1, - 86, 25, 93, 27, 25, -1, 27, -1, 7, 61, - 62, 34, 75, 36, 38, 61, 62, 38, 47, 75, - 18, 19, -1, 86, 18, 19, 18, 19, 61, 62, - 86, -1, 61, 62, 33, 18, 19, 98, 99, 100, - 101, 102, 103, -1, -1, -1, -1, 45, 46, -1, - -1, 45, 46, 45, 46, -1, 23, 24, -1, -1, - 23, 24, 45, 46, 93, 32, 23, 24, 35, 32, - 37, -1, 35, -1, 37, 32, 23, 24, 35, -1, - 37, 29, 23, 24, 29, 32, -1, -1, 35, -1, - 37, 32, 23, 24, 35, 94, 37, 29, -1, -1, - 31, 32, 23, 24, 35, 29, 37, 15, -1, -1, - 31, 32, -1, -1, 35, 29, 37, -1, 66, 67, - 68, 66, 67, 68, -1, 33, 34, -1, 36, 29, - -1, -1, -1, -1, 66, 67, 68, 29, -1, -1, - -1, -1, 66, 67, 68, -1, 94, 95, 96, 94, - 95, 96, 66, 67, 68, -1, -1, -1, -1, -1, - -1, -1, 94, 95, 96, -1, 66, 67, 68, -1, - 94, 95, 96, -1, 66, 67, 68, 29, -1, -1, - 94, 95, 96, 29, -1, -1, 29, -1, -1, 29, - -1, -1, 29, -1, 94, 95, 96, 29, 23, 24, - 29, -1, 94, 95, 96, -1, 31, 32, -1, -1, - 35, -1, 37, -1, 66, 67, 68, -1, -1, -1, - 66, 67, 68, 66, 67, 68, 66, 67, 68, 66, - 67, 68, -1, 29, 66, 67, 68, 66, 67, 68, - 36, -1, 94, 95, 96, -1, -1, -1, 94, 95, - 96, 94, 95, 96, 94, 95, 96, 94, 95, 96, - -1, -1, 94, 95, 96, 94, 95, 96, 29, -1, - 66, 67, 68, 29, -1, 36, 29, -1, -1, -1, - 36, 29, -1, -1, 29, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 94, 95, - 96, -1, -1, -1, -1, 66, 67, 68, 61, 62, - 66, 67, 68, 66, 67, 68, 61, 62, 66, 67, - 68, 66, 67, 68, -1, -1, -1, 29, -1, -1, + 36, 60, 5, 36, 31, 7, 66, 16, 33, 7, + 36, 7, 7, 7, 7, 33, 36, 7, 55, 8, + 36, 7, 7, 36, 7, 55, 7, 7, 36, 36, + 17, 7, 33, 33, 7, 7, 7, 36, 7, 36, + 7, 7, 34, 60, 55, 36, 7, 66, 60, 33, + 55, 33, 7, 77, 33, 8, 60, 20, 36, 33, + 1, 36, 8, 33, 7, 33, 2, 55, 33, 33, + 29, 1, 24, 33, 8, 1, -1, 2, 55, -1, + 37, 8, 36, -1, -1, -1, 8, 36, 36, 33, + 7, 2, 48, 1, 36, 7, 36, 36, 60, 36, + 33, 17, 60, 8, 0, 36, 8, 2, -1, 60, + 60, 8, 6, -1, 61, 7, 8, 8, 33, 8, + -1, 8, 60, 55, 48, 60, 20, 48, 8, 36, + 8, 10, 8, 61, 79, 55, -1, -1, 48, 8, + 8, 40, 40, 61, 8, 8, 60, 5, 61, 62, + 79, 60, 51, 51, 56, 40, 79, 61, 62, 40, + 79, 61, 62, 60, 50, 8, 51, 56, 54, 60, + 51, 61, 62, 60, 8, 50, 55, 61, 62, 54, + 60, 29, 60, 42, 60, 91, 92, 56, 56, 61, + 62, 61, 62, 56, 53, 15, 60, 8, 7, 61, + 62, 61, 62, 29, 61, 62, 29, 25, 8, 27, + 7, -1, 15, 29, 34, 8, 36, 25, 61, 27, + 38, 12, -1, 25, 33, 27, 60, 75, 12, 36, + 38, 34, 89, 36, 29, 7, 38, 29, 86, -1, + 25, 12, 27, 25, 25, 27, 27, 7, 15, 75, + 61, 62, 75, 38, 61, 62, 38, 38, -1, 75, + 86, 61, 62, 86, 61, 62, 57, 34, 61, 62, + 86, -1, 63, 57, 15, 61, 62, 15, -1, 63, + 75, 18, 19, 75, -1, 94, 57, 18, 19, 61, + 62, 86, 63, 34, 86, 36, 34, 47, 36, 18, + 19, 61, 62, 15, -1, 18, 19, 93, 45, 46, + 15, 61, 62, -1, 45, 46, -1, -1, -1, -1, + -1, 33, 34, -1, 36, -1, 45, 46, 33, 34, + -1, 36, 45, 46, -1, 23, 24, -1, -1, 25, + -1, 27, -1, 93, 32, 23, 24, 35, 29, 37, + -1, -1, 38, 31, 32, -1, -1, 35, 29, 37, + 23, 24, 98, 99, 100, 101, 102, 103, 31, 32, + 23, 24, 35, 29, 37, -1, -1, -1, 31, 32, + 23, 24, 35, -1, 37, 66, 67, 68, 31, 32, + 23, 24, 35, -1, 37, 66, 67, 68, 31, 32, + -1, -1, 35, -1, 37, 29, -1, -1, 29, -1, + 66, 67, 68, 94, 95, 96, 29, -1, -1, 29, + 23, 24, 29, 94, 95, 96, -1, -1, 29, 32, + -1, -1, 35, -1, 37, 36, -1, -1, 94, 95, + 96, 29, 66, 67, 68, 66, 67, 68, 36, -1, + -1, -1, -1, 66, 67, 68, 66, 67, 68, 66, + 67, 68, 29, -1, -1, 66, 67, 68, -1, 36, + 94, 95, 96, 94, 95, 96, -1, -1, 66, 67, + 68, 94, 95, 96, 94, 95, 96, 94, 95, 96, + -1, -1, -1, 94, 95, 96, -1, -1, 29, 66, + 67, 68, -1, 29, -1, -1, 94, 95, 96, -1, + -1, 29, -1, -1, -1, -1, -1, -1, -1, 29, + -1, -1, -1, -1, -1, -1, -1, 94, 95, 96, + 61, 62, -1, -1, -1, 66, 67, 68, -1, -1, + 66, 67, 68, 61, 62, -1, -1, -1, 66, 67, + 68, 61, 62, -1, -1, -1, 66, 67, 68, -1, -1, -1, -1, 94, 95, 96, -1, -1, 94, 95, - 96, 94, 95, 96, -1, -1, 94, 95, 96, 94, - 95, 96, -1, -1, -1, -1, -1, -1, 29, 61, - 62, -1, -1, -1, 66, 67, 68, -1, -1, -1, + 96, -1, -1, -1, -1, -1, 94, 95, 96, -1, + 29, -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 61, 62, 94, 95, 96, 66, 67, 68, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, - -1, -1, -1, 12, 13, 3, -1, -1, -1, -1, - -1, -1, -1, 22, -1, 13, -1, -1, -1, 17, - 29, -1, -1, -1, 33, 34, -1, 36, 26, -1, - 28, -1, -1, -1, 43, -1, -1, -1, 47, -1, - -1, 39, -1, 41, 42, -1, -1, -1, -1, -1, - -1, 49, -1, -1, 52, 53, 65, 66, 67, 68, - 58, 70, -1, -1, -1, -1, 64, -1, -1, -1, - -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, - -1, -1, 80, -1, -1, 94, 95, 96, -1, -1, - -1, -1, -1, -1, -1, 12, 13, -1, -1, -1, - -1, -1, -1, -1, -1, 22, -1, -1, 3, -1, - -1, -1, 29, -1, -1, -1, 33, 34, 13, 36, - -1, -1, 17, -1, -1, -1, 43, -1, -1, -1, - 47, 26, -1, 28, -1, -1, 31, -1, -1, -1, - -1, -1, -1, -1, 39, -1, 41, 42, 65, 66, - 67, 68, -1, 70, 49, -1, -1, 52, 53, -1, - -1, -1, -1, 58, 81, 82, 83, -1, -1, 64, - 87, -1, -1, -1, -1, -1, -1, 94, 95, 96, - -1, -1, -1, -1, -1, 80, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12, 13, -1, -1, -1, -1, -1, -1, -1, - -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, - -1, -1, 33, 34, -1, 36, -1, -1, -1, -1, - -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, - -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12, 13, -1, -1, -1, - -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, - -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, - -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, - 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, - 67, 68, -1, 70, -1, -1, -1, -1, -1, -1, + -1, -1, 61, 62, 3, -1, -1, 66, 67, 68, + -1, -1, -1, -1, 13, -1, -1, -1, 17, -1, + -1, -1, -1, -1, -1, -1, -1, 26, -1, 28, + -1, -1, 31, -1, -1, 94, 95, 96, -1, -1, + 39, -1, 41, 42, -1, 12, 13, 3, -1, -1, + 49, -1, -1, 52, 53, 22, -1, 13, -1, 58, + -1, 17, 29, -1, -1, 64, 33, 34, -1, 36, + 26, -1, 28, -1, -1, -1, 43, -1, -1, -1, + 47, 80, -1, 39, -1, 41, 42, -1, -1, -1, + -1, -1, -1, 49, -1, -1, 52, 53, 65, 66, + 67, 68, 58, 70, -1, -1, -1, -1, 64, -1, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, - 87, -1, -1, -1, -1, -1, -1, 94, 95, 96, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, - -1, 12, 13, -1, -1, -1, -1, -1, -1, -1, - -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, - -1, -1, 33, 34, -1, 36, -1, -1, -1, -1, - -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, + 87, -1, -1, -1, 80, -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, - -1, -1, -1, -1, 75, -1, -1, -1, -1, -1, - 81, 82, 83, 84, -1, -1, 87, -1, -1, -1, - -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 10, -1, 12, 13, -1, - -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, - -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, - -1, 36, -1, -1, -1, -1, -1, -1, 43, -1, - -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, - 55, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 65, 66, 67, 68, -1, 70, -1, -1, -1, -1, - 75, -1, -1, -1, -1, -1, 81, 82, 83, 84, - -1, -1, 87, -1, -1, -1, -1, -1, -1, 94, - 95, 96, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 10, -1, 12, 13, -1, -1, -1, -1, -1, - -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, - 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, - -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, - -1, -1, -1, -1, -1, -1, 55, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, - -1, 70, -1, -1, -1, -1, 75, -1, -1, -1, - -1, -1, 81, 82, 83, 84, -1, -1, 87, -1, - -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 11, 12, 13, - -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, - -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, - 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, - 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, - 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, - -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, - 94, 95, 96, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 7, -1, -1, -1, 11, 12, 13, -1, + 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, + 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, + -1, 33, 34, -1, 36, -1, -1, -1, -1, -1, + -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 81, + 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, + -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 12, 13, -1, -1, -1, -1, + -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, + -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, + -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, + 68, -1, 70, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, + -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, + 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, + 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, + -1, 33, 34, -1, 36, -1, -1, -1, -1, -1, + -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, + -1, -1, -1, 75, -1, -1, -1, -1, -1, 81, + 82, 83, 84, -1, -1, 87, -1, -1, -1, -1, + -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 10, -1, 12, 13, -1, -1, + -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, + -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, + 36, -1, -1, -1, -1, -1, -1, 43, -1, -1, + -1, 47, -1, -1, -1, -1, -1, -1, -1, 55, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, + 66, 67, 68, -1, 70, -1, -1, -1, -1, 75, + -1, -1, -1, -1, -1, 81, 82, 83, 84, -1, + -1, 87, -1, -1, -1, -1, -1, -1, 94, 95, + 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 10, -1, 12, 13, -1, -1, -1, -1, -1, -1, + -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, + -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, + -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, + -1, -1, -1, -1, -1, 55, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, + 70, -1, -1, -1, -1, 75, -1, -1, -1, -1, + -1, 81, 82, 83, 84, -1, -1, 87, -1, -1, + -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, @@ -879,101 +844,100 @@ const short QQmlJSGrammar::action_check [] = { -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, - -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, - -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, - 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, - -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, - 70, -1, 72, -1, 74, 75, 76, -1, -1, -1, - -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, - -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 8, -1, -1, 11, - 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, - 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, - -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, - 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, - -1, 53, -1, -1, 56, -1, -1, -1, -1, -1, - -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, - 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, - 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, - -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, - -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, - -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, - 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, - 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, - -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, - -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, - 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, - -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, - 94, 95, 96, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 8, -1, -1, 11, 12, 13, -1, -1, + -1, 7, -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, - 56, -1, -1, -1, -1, -1, -1, -1, -1, 65, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, - -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, - -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, - -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, - -1, -1, -1, 51, -1, 53, -1, -1, 56, -1, - -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, - 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, - -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, - -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 11, 12, + 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, + -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, + -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, + -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, + 51, -1, 53, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, + -1, 72, -1, 74, 75, 76, -1, -1, -1, -1, + 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, + -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, - -1, -1, -1, -1, -1, -1, 29, 30, -1, -1, + -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, - 53, -1, -1, -1, -1, -1, -1, -1, 61, -1, - -1, -1, 65, 66, 67, 68, 69, 70, -1, 72, - 73, 74, -1, 76, -1, 78, -1, -1, 81, 82, + 53, -1, -1, 56, -1, -1, -1, -1, -1, -1, + -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, + -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, - -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, - -1, 29, 30, -1, -1, 33, 34, -1, 36, -1, - -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, - -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, - -1, -1, -1, 61, -1, -1, -1, 65, 66, 67, - 68, 69, 70, -1, 72, 73, 74, -1, 76, -1, - 78, -1, -1, 81, 82, 83, -1, -1, -1, 87, - -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, - 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, - 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, - -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 59, -1, -1, -1, -1, -1, -1, - 66, 67, 68, 69, 70, 71, -1, 73, 74, 75, - 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, - 86, -1, -1, -1, -1, -1, -1, -1, 94, 95, - 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 4, 5, 6, -1, -1, 9, 10, 11, -1, -1, - 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, - -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, - -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 59, -1, -1, -1, -1, - -1, 65, 66, 67, 68, 69, 70, 71, -1, 73, - 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, - 84, 85, 86, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, + -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, + -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, + -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, + -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, + -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, + 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, + -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, + -1, -1, 87, -1, -1, -1, -1, -1, -1, 94, + 95, 96, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, + -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, + -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, + -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, + 47, -1, -1, -1, 51, -1, 53, -1, -1, 56, + -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, + 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, + -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, + 87, -1, -1, -1, -1, -1, -1, 94, 95, 96, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, + -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, + -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, + 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, + -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, + -1, -1, 51, -1, 53, -1, -1, 56, -1, -1, + -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, + -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, + -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, + -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 11, 12, 13, + -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, + -1, -1, -1, -1, -1, 29, 30, -1, -1, 33, + 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, + 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, + -1, -1, -1, -1, -1, -1, -1, 61, -1, -1, + -1, 65, 66, 67, 68, 69, 70, -1, 72, 73, + 74, -1, 76, -1, 78, -1, -1, 81, 82, 83, + -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, + 94, 95, 96, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, + -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, + 29, 30, -1, -1, 33, 34, -1, 36, -1, -1, + -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, + -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, + -1, -1, 61, -1, -1, -1, 65, 66, 67, 68, + 69, 70, -1, 72, 73, 74, -1, 76, -1, 78, + -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, + -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 11, 12, 13, + -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, + -1, -1, -1, -1, -1, 29, 30, -1, -1, 33, + 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, + 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, + -1, -1, -1, -1, -1, -1, -1, 61, -1, -1, + -1, 65, 66, 67, 68, 69, 70, -1, 72, 73, + 74, -1, 76, -1, 78, -1, -1, 81, 82, 83, + -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, + -1, 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 59, -1, -1, - -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, + -1, -1, -1, -1, 66, 67, 68, 69, 70, 71, -1, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, -1, -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, @@ -982,95 +946,126 @@ const short QQmlJSGrammar::action_check [] = { 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, - -1, -1, -1, -1, -1, 55, -1, -1, -1, 59, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 59, -1, -1, -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, -1, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, -1, -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, - -1, 9, -1, 11, 12, 13, 14, -1, -1, -1, - -1, -1, -1, 21, 22, -1, -1, -1, -1, -1, - -1, 29, 30, -1, -1, 33, 34, -1, 36, -1, - -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, - -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, - -1, 59, -1, 61, -1, -1, -1, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, - 78, -1, -1, 81, 82, 83, 84, 85, -1, 87, + -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, + -1, 9, 10, 11, -1, -1, 14, -1, 16, -1, + -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, + -1, 29, 30, 31, 32, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 59, -1, -1, -1, -1, -1, 65, 66, 67, + 68, 69, 70, 71, -1, 73, 74, 75, 76, 77, + 78, -1, -1, 81, 82, 83, 84, 85, 86, -1, -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, - -1, -1, -1, 9, -1, 11, 12, 13, 14, -1, - -1, -1, -1, -1, -1, 21, 22, -1, -1, -1, - -1, -1, -1, 29, 30, -1, -1, 33, 34, -1, - 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, - -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, - -1, -1, -1, 59, -1, 61, -1, -1, -1, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, + -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, + 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, + 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, + -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, + -1, 47, -1, -1, -1, -1, -1, -1, -1, 55, + -1, -1, -1, 59, -1, -1, -1, -1, -1, 65, + 66, 67, 68, 69, 70, 71, -1, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, - -1, 87, -1, -1, -1, -1, -1, -1, 94, 95, + 86, -1, -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 4, 5, 6, -1, -1, 9, 10, 11, 12, 13, - 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, - -1, -1, -1, -1, -1, 29, 30, 31, 32, 33, + 4, -1, -1, -1, -1, 9, -1, 11, 12, 13, + 14, -1, -1, -1, -1, -1, -1, 21, 22, -1, + -1, -1, -1, -1, -1, 29, 30, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, 59, -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, - 84, 85, 86, 87, -1, -1, -1, -1, -1, -1, + 84, 85, -1, 87, -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, - 12, 13, 14, -1, 16, -1, -1, -1, 20, 21, - 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, - 32, 33, 34, -1, 36, -1, -1, -1, 40, -1, + -1, -1, 4, -1, -1, -1, -1, 9, -1, 11, + 12, 13, 14, -1, -1, -1, -1, -1, -1, 21, + 22, -1, -1, -1, -1, -1, -1, 29, 30, -1, + -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, - -1, 53, -1, 55, -1, -1, -1, 59, -1, 61, + -1, 53, -1, -1, -1, -1, -1, 59, -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, - 82, 83, 84, 85, 86, 87, -1, -1, -1, -1, + 82, 83, 84, 85, -1, 87, -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, - -1, -1, -1, -1, + -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, + 10, 11, 12, 13, 14, -1, 16, -1, -1, -1, + 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, + 30, 31, 32, 33, 34, -1, 36, -1, -1, -1, + 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, + -1, 51, -1, 53, -1, -1, -1, -1, -1, 59, + -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, + -1, 81, 82, 83, 84, 85, 86, 87, -1, -1, + -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, + -1, 9, 10, 11, 12, 13, 14, -1, 16, -1, + -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, + -1, 29, 30, 31, 32, 33, 34, -1, 36, -1, + -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, + -1, -1, -1, 51, -1, 53, -1, 55, -1, -1, + -1, 59, -1, 61, -1, -1, -1, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, + 78, -1, -1, 81, 82, 83, 84, 85, 86, 87, + -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, + -1, -1, -1, -1, -1, -1, -1, -1, - 42, 3, 18, 25, 18, 3, 18, 3, 18, 22, - 18, 3, 18, 22, 32, 32, 42, 18, 18, 18, - 3, 32, 25, 18, 18, 32, 3, 18, 32, 105, - 18, 18, 25, 100, 3, 3, 3, 18, 3, 25, - 18, 3, 18, 18, 18, 42, 3, 3, 103, 9, - 3, 14, 42, 42, 18, 25, 14, 42, 42, 18, - 42, 3, 42, 18, 18, 3, 18, 3, 18, 14, - 42, 22, 18, 2, 4, 18, 42, 18, 2, 11, - 12, 54, -1, 54, 2, 56, 59, 18, 18, 18, - 4, 14, 14, 54, 18, 56, 19, 14, 77, 14, - 18, 23, 2, 46, 18, 54, 54, 54, 2, 2, - 59, 59, 59, 18, 54, 54, 3, 56, 18, 59, - 54, 54, 56, 56, 18, 18, 54, 54, 54, 56, - 56, 59, 18, 54, 51, 56, 51, 2, 54, 2, - 56, 54, 54, 56, 56, 54, 54, 56, 38, 2, - 58, 54, 42, 18, 57, 18, 3, 54, 2, 45, - 18, 92, 54, 54, 2, 18, 3, 18, 109, 66, - 42, 54, 64, 56, 18, 18, 18, 2, 50, 70, - 18, 54, 42, 4, 54, 43, 56, 18, 14, 94, - 50, 78, 2, 18, 45, 68, 18, 18, 54, 18, - 56, 3, 54, 46, 46, 54, 54, 59, 18, 54, - 2, 60, 60, 44, 54, 60, 56, 2, 14, 14, - 3, 54, 44, 19, 19, 51, 18, 60, 47, 2, - 54, 78, 18, 18, 54, -1, 56, 54, 62, 56, - 54, 54, 18, 18, 58, 18, 59, 54, 54, 54, - 57, 54, 58, 54, 59, 54, 59, 54, 59, 45, - 59, 54, 59, 54, 2, 2, 59, -1, 59, 45, - 61, -1, 47, 48, 2, -1, 78, 54, -1, 76, - 18, 18, 59, 76, 54, -1, 54, 54, 54, 59, - 18, 59, 59, 59, -1, 78, -1, -1, 54, 76, - 54, 69, -1, 59, 71, 59, 76, 61, 54, 54, - 76, 67, 54, 59, 59, 61, 5, 59, 54, 61, - 65, 14, 5, 59, -1, 14, 19, 63, 21, -1, - -1, 14, -1, -1, 23, -1, -1, -1, -1, -1, - 23, -1, -1, -1, -1, -1, 35, 36, -1, 42, - 88, 88, 35, 36, 25, 26, 27, 28, 29, 30, - 31, 24, 25, 26, 27, 28, 29, 30, 31, -1, + 32, 22, 18, 9, 18, 42, 18, 14, 32, 3, + 18, 3, 3, 18, 18, 32, 18, 32, 3, 22, + 3, 18, 3, 18, 25, 18, 22, 14, 18, 18, + 14, 42, 18, 32, 22, 77, 3, 100, 3, 3, + 3, 103, 42, 18, 42, 18, 3, 3, 25, 25, + 3, 105, 18, 25, 3, 3, 18, 18, 3, 18, + 42, 3, 42, 42, 42, 25, 18, 18, 42, 2, + -1, 18, 18, 42, 18, 18, 14, 18, 14, 18, + 2, 4, 2, 18, 42, 18, 54, 14, 56, 18, + -1, 4, -1, 18, -1, 18, 18, 18, 18, 54, + 54, 56, 56, 44, 54, 18, 56, 18, 11, 12, + 45, -1, -1, 51, 54, 51, 56, 54, 42, 56, + 54, 46, 54, 54, 51, 46, 50, 59, 59, 18, + 42, -1, -1, -1, 45, 54, 70, 54, 50, 54, + 59, 14, 59, 2, 59, 54, 19, 56, 54, 54, + 54, 56, 14, 59, 43, 54, 54, 56, 56, 18, + 2, 23, 2, 54, 68, 56, 14, 54, 54, 2, + 54, 19, 3, 60, 60, 59, 18, 54, 18, 18, + 109, 18, 59, 54, 54, 18, 54, 54, 59, 59, + 54, 59, 59, 54, 58, 38, 54, 58, 18, 42, + 58, 2, 54, 2, 18, 54, 45, 2, 45, 2, + 4, 3, 18, 18, 66, 64, 3, 18, 54, 18, + 56, 2, 54, 18, 18, 18, 46, 54, 60, 56, + 3, 3, 54, 47, 2, 57, 54, 18, 56, 54, + 2, 56, 54, 54, 56, 2, 57, 54, 2, 18, + 18, 54, 54, 56, -1, 62, 18, 54, 60, 56, + -1, 18, 14, 54, 18, 54, 2, 19, 59, -1, + 59, 54, 54, -1, 63, 44, 59, 59, -1, 54, + 2, -1, 18, 65, 59, 76, 78, 92, 94, 54, + 54, 78, 18, 76, 59, 59, 18, 61, 54, 54, + -1, 76, 67, 59, 59, 78, 78, 54, 54, -1, + 54, 54, 59, 59, 69, 59, 59, 61, 61, 14, + 76, 47, 48, -1, 71, -1, 54, 14, 23, 5, + 76, 59, 19, 61, 21, 5, -1, -1, 14, -1, + 35, 36, -1, -1, 14, -1, -1, 23, -1, -1, + -1, -1, 88, 23, -1, 42, -1, -1, -1, 35, + 36, -1, -1, -1, -1, 35, 36, 25, 26, 27, + 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, + -1, 14, -1, -1, -1, -1, -1, -1, -1, 2, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 14, + -1, -1, -1, -1, -1, 18, -1, -1, 23, 24, + 25, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 14, 14, -1, -1, -1, -1, -1, - -1, -1, 23, 23, 24, 25, 26, 27, 28, 29, - 30, 31, -1, -1, 35, 36, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 88, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, + -1, -1, -1, -1, -1, -1, -1, 23, 24, 25, + 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -1078,15 +1073,6 @@ const short QQmlJSGrammar::action_check [] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 14, -1, -1, -1, -1, -1, -1, -1, -1, 23, - 24, 25, 26, 27, 28, 29, 30, 31, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1}; + -1, -1, -1, -1, -1}; QT_END_NAMESPACE diff --git a/src/tools/qdoc/qmlparser/qqmljsgrammar_p.h b/src/tools/qdoc/qmlparser/qqmljsgrammar_p.h index 6b3d1c80135..7a369be194e 100644 --- a/src/tools/qdoc/qmlparser/qqmljsgrammar_p.h +++ b/src/tools/qdoc/qmlparser/qqmljsgrammar_p.h @@ -161,15 +161,15 @@ public: T_XOR = 79, T_XOR_EQ = 80, - ACCEPT_STATE = 663, - RULE_COUNT = 357, - STATE_COUNT = 664, + ACCEPT_STATE = 665, + RULE_COUNT = 358, + STATE_COUNT = 666, TERMINAL_COUNT = 106, NON_TERMINAL_COUNT = 111, - GOTO_INDEX_OFFSET = 664, - GOTO_INFO_OFFSET = 3104, - GOTO_CHECK_OFFSET = 3104 + GOTO_INDEX_OFFSET = 666, + GOTO_INFO_OFFSET = 3018, + GOTO_CHECK_OFFSET = 3018 }; static const char *const spell []; diff --git a/src/tools/qdoc/qmlparser/qqmljsparser.cpp b/src/tools/qdoc/qmlparser/qqmljsparser.cpp index 262043b3b80..762e60c8276 100644 --- a/src/tools/qdoc/qmlparser/qqmljsparser.cpp +++ b/src/tools/qdoc/qmlparser/qqmljsparser.cpp @@ -567,56 +567,78 @@ case 69: { } break; case 70: { - sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4)); + node->isReadonlyMember = true; + node->readonlyToken = loc(1); + node->propertyToken = loc(2); + node->typeToken = loc(3); + node->identifierToken = loc(4); + node->semicolonToken = loc(5); // insert a fake ';' before ':' + + AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(4)); + propertyName->identifierToken = loc(4); + propertyName->next = 0; + + AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding( + propertyName, sym(6).UiQualifiedId, sym(7).UiObjectInitializer); + binding->colonToken = loc(5); + + node->binding = binding; + + sym(1).Node = node; } break; case 71: { sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); } break; -case 79: { +case 72: { + sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); +} break; + +case 80: { AST::ThisExpression *node = new (pool) AST::ThisExpression(); node->thisToken = loc(1); sym(1).Node = node; } break; -case 80: { +case 81: { AST::IdentifierExpression *node = new (pool) AST::IdentifierExpression(stringRef(1)); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 81: { +case 82: { AST::NullExpression *node = new (pool) AST::NullExpression(); node->nullToken = loc(1); sym(1).Node = node; } break; -case 82: { +case 83: { AST::TrueLiteral *node = new (pool) AST::TrueLiteral(); node->trueToken = loc(1); sym(1).Node = node; } break; -case 83: { +case 84: { AST::FalseLiteral *node = new (pool) AST::FalseLiteral(); node->falseToken = loc(1); sym(1).Node = node; } break; -case 84: { +case 85: { AST::NumericLiteral *node = new (pool) AST::NumericLiteral(sym(1).dval); node->literalToken = loc(1); sym(1).Node = node; } break; -case 85: -case 86: { +case 86: +case 87: { AST::StringLiteral *node = new (pool) AST::StringLiteral(stringRef(1)); node->literalToken = loc(1); sym(1).Node = node; } break; -case 87: { +case 88: { bool rx = lexer->scanRegExp(Lexer::NoPrefix); if (!rx) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); @@ -632,7 +654,7 @@ case 87: { sym(1).Node = node; } break; -case 88: { +case 89: { bool rx = lexer->scanRegExp(Lexer::EqualPrefix); if (!rx) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); @@ -648,28 +670,28 @@ case 88: { sym(1).Node = node; } break; -case 89: { +case 90: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral((AST::Elision *) 0); node->lbracketToken = loc(1); node->rbracketToken = loc(2); sym(1).Node = node; } break; -case 90: { +case 91: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).Elision->finish()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; } break; -case 91: { +case 92: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish ()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; } break; -case 92: { +case 93: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (), (AST::Elision *) 0); node->lbracketToken = loc(1); @@ -678,7 +700,7 @@ case 92: { sym(1).Node = node; } break; -case 93: { +case 94: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (), sym(4).Elision->finish()); node->lbracketToken = loc(1); @@ -687,7 +709,7 @@ case 93: { sym(1).Node = node; } break; -case 94: { +case 95: { AST::ObjectLiteral *node = 0; if (sym(2).Node) node = new (pool) AST::ObjectLiteral( @@ -699,7 +721,7 @@ case 94: { sym(1).Node = node; } break; -case 95: { +case 96: { AST::ObjectLiteral *node = new (pool) AST::ObjectLiteral( sym(2).PropertyAssignmentList->finish ()); node->lbraceToken = loc(1); @@ -707,14 +729,14 @@ case 95: { sym(1).Node = node; } break; -case 96: { +case 97: { AST::NestedExpression *node = new (pool) AST::NestedExpression(sym(2).Expression); node->lparenToken = loc(1); node->rparenToken = loc(3); sym(1).Node = node; } break; -case 97: { +case 98: { if (AST::ArrayMemberExpression *mem = AST::cast(sym(1).Expression)) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken, QLatin1String("Ignored annotation"))); @@ -734,48 +756,48 @@ case 97: { } } break; -case 98: { +case 99: { sym(1).Node = new (pool) AST::ElementList((AST::Elision *) 0, sym(1).Expression); } break; -case 99: { +case 100: { sym(1).Node = new (pool) AST::ElementList(sym(1).Elision->finish(), sym(2).Expression); } break; -case 100: { +case 101: { AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList, (AST::Elision *) 0, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 101: { +case 102: { AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList, sym(3).Elision->finish(), sym(4).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 102: { +case 103: { AST::Elision *node = new (pool) AST::Elision(); node->commaToken = loc(1); sym(1).Node = node; } break; -case 103: { +case 104: { AST::Elision *node = new (pool) AST::Elision(sym(1).Elision); node->commaToken = loc(2); sym(1).Node = node; } break; -case 104: { +case 105: { AST::PropertyNameAndValue *node = new (pool) AST::PropertyNameAndValue( sym(1).PropertyName, sym(3).Expression); node->colonToken = loc(2); sym(1).Node = node; } break; -case 105: { +case 106: { AST::PropertyGetterSetter *node = new (pool) AST::PropertyGetterSetter( sym(2).PropertyName, sym(6).FunctionBody); node->getSetToken = loc(1); @@ -786,7 +808,7 @@ case 105: { sym(1).Node = node; } break; -case 106: { +case 107: { AST::PropertyGetterSetter *node = new (pool) AST::PropertyGetterSetter( sym(2).PropertyName, sym(4).FormalParameterList, sym(7).FunctionBody); node->getSetToken = loc(1); @@ -797,56 +819,56 @@ case 106: { sym(1).Node = node; } break; -case 107: { +case 108: { sym(1).Node = new (pool) AST::PropertyAssignmentList(sym(1).PropertyAssignment); } break; -case 108: { +case 109: { AST::PropertyAssignmentList *node = new (pool) AST::PropertyAssignmentList( sym(1).PropertyAssignmentList, sym(3).PropertyAssignment); node->commaToken = loc(2); sym(1).Node = node; } break; -case 109: { - AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); - node->propertyNameToken = loc(1); - sym(1).Node = node; -} break; - case 110: { - AST::StringLiteralPropertyName *node = new (pool) AST::StringLiteralPropertyName(stringRef(1)); + AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; case 111: { - AST::NumericLiteralPropertyName *node = new (pool) AST::NumericLiteralPropertyName(sym(1).dval); + AST::StringLiteralPropertyName *node = new (pool) AST::StringLiteralPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; case 112: { + AST::NumericLiteralPropertyName *node = new (pool) AST::NumericLiteralPropertyName(sym(1).dval); + node->propertyNameToken = loc(1); + sym(1).Node = node; +} break; + +case 113: { AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 148: { +case 149: { AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; } break; -case 149: { +case 150: { AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; -case 150: { +case 151: { AST::NewMemberExpression *node = new (pool) AST::NewMemberExpression(sym(2).Expression, sym(4).ArgumentList); node->newToken = loc(1); node->lparenToken = loc(3); @@ -854,19 +876,12 @@ case 150: { sym(1).Node = node; } break; -case 152: { +case 153: { AST::NewExpression *node = new (pool) AST::NewExpression(sym(2).Expression); node->newToken = loc(1); sym(1).Node = node; } break; -case 153: { - AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); - node->lparenToken = loc(2); - node->rparenToken = loc(4); - sym(1).Node = node; -} break; - case 154: { AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); @@ -875,363 +890,370 @@ case 154: { } break; case 155: { + AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; + +case 156: { AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; } break; -case 156: { +case 157: { AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; -case 157: { +case 158: { sym(1).Node = 0; } break; -case 158: { +case 159: { sym(1).Node = sym(1).ArgumentList->finish(); } break; -case 159: { +case 160: { sym(1).Node = new (pool) AST::ArgumentList(sym(1).Expression); } break; -case 160: { +case 161: { AST::ArgumentList *node = new (pool) AST::ArgumentList(sym(1).ArgumentList, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 164: { +case 165: { AST::PostIncrementExpression *node = new (pool) AST::PostIncrementExpression(sym(1).Expression); node->incrementToken = loc(2); sym(1).Node = node; } break; -case 165: { +case 166: { AST::PostDecrementExpression *node = new (pool) AST::PostDecrementExpression(sym(1).Expression); node->decrementToken = loc(2); sym(1).Node = node; } break; -case 167: { +case 168: { AST::DeleteExpression *node = new (pool) AST::DeleteExpression(sym(2).Expression); node->deleteToken = loc(1); sym(1).Node = node; } break; -case 168: { +case 169: { AST::VoidExpression *node = new (pool) AST::VoidExpression(sym(2).Expression); node->voidToken = loc(1); sym(1).Node = node; } break; -case 169: { +case 170: { AST::TypeOfExpression *node = new (pool) AST::TypeOfExpression(sym(2).Expression); node->typeofToken = loc(1); sym(1).Node = node; } break; -case 170: { +case 171: { AST::PreIncrementExpression *node = new (pool) AST::PreIncrementExpression(sym(2).Expression); node->incrementToken = loc(1); sym(1).Node = node; } break; -case 171: { +case 172: { AST::PreDecrementExpression *node = new (pool) AST::PreDecrementExpression(sym(2).Expression); node->decrementToken = loc(1); sym(1).Node = node; } break; -case 172: { +case 173: { AST::UnaryPlusExpression *node = new (pool) AST::UnaryPlusExpression(sym(2).Expression); node->plusToken = loc(1); sym(1).Node = node; } break; -case 173: { +case 174: { AST::UnaryMinusExpression *node = new (pool) AST::UnaryMinusExpression(sym(2).Expression); node->minusToken = loc(1); sym(1).Node = node; } break; -case 174: { +case 175: { AST::TildeExpression *node = new (pool) AST::TildeExpression(sym(2).Expression); node->tildeToken = loc(1); sym(1).Node = node; } break; -case 175: { +case 176: { AST::NotExpression *node = new (pool) AST::NotExpression(sym(2).Expression); node->notToken = loc(1); sym(1).Node = node; } break; -case 177: { +case 178: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Mul, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 178: { +case 179: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Div, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 179: { +case 180: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Mod, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 181: { +case 182: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Add, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 182: { +case 183: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Sub, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 184: { +case 185: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::LShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 185: { +case 186: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::RShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 186: { +case 187: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::URShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 188: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Lt, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - case 189: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Gt, sym(3).Expression); + QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 190: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Le, sym(3).Expression); + QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 191: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Ge, sym(3).Expression); + QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 192: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::InstanceOf, sym(3).Expression); + QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 193: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::In, sym(3).Expression); + QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 195: { +case 194: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Lt, sym(3).Expression); + QSOperator::In, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 196: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Gt, sym(3).Expression); + QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 197: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Le, sym(3).Expression); + QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 198: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Ge, sym(3).Expression); + QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 199: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::InstanceOf, sym(3).Expression); + QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 201: { +case 200: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Equal, sym(3).Expression); + QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 202: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::NotEqual, sym(3).Expression); + QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 203: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::StrictEqual, sym(3).Expression); + QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 204: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::StrictNotEqual, sym(3).Expression); + QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 206: { +case 205: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::Equal, sym(3).Expression); + QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 207: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::NotEqual, sym(3).Expression); + QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 208: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - QSOperator::StrictEqual, sym(3).Expression); + QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 209: { + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, + QSOperator::StrictEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 210: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 211: { +case 212: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitAnd, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 213: { +case 214: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitAnd, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 215: { +case 216: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitXor, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 217: { +case 218: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitXor, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 219: { +case 220: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitOr, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 221: { +case 222: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitOr, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 223: { +case 224: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::And, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 225: { +case 226: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::And, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 227: { +case 228: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Or, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 229: { +case 230: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Or, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 231: { +case 232: { AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); @@ -1239,7 +1261,7 @@ case 231: { sym(1).Node = node; } break; -case 233: { +case 234: { AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); @@ -1247,14 +1269,7 @@ case 233: { sym(1).Node = node; } break; -case 235: { - AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, - sym(2).ival, sym(3).Expression); - node->operatorToken = loc(2); - sym(1).Node = node; -} break; - -case 237: { +case 236: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression); node->operatorToken = loc(2); @@ -1262,97 +1277,104 @@ case 237: { } break; case 238: { - sym(1).ival = QSOperator::Assign; + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, + sym(2).ival, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; } break; case 239: { - sym(1).ival = QSOperator::InplaceMul; + sym(1).ival = QSOperator::Assign; } break; case 240: { - sym(1).ival = QSOperator::InplaceDiv; + sym(1).ival = QSOperator::InplaceMul; } break; case 241: { - sym(1).ival = QSOperator::InplaceMod; + sym(1).ival = QSOperator::InplaceDiv; } break; case 242: { - sym(1).ival = QSOperator::InplaceAdd; + sym(1).ival = QSOperator::InplaceMod; } break; case 243: { - sym(1).ival = QSOperator::InplaceSub; + sym(1).ival = QSOperator::InplaceAdd; } break; case 244: { - sym(1).ival = QSOperator::InplaceLeftShift; + sym(1).ival = QSOperator::InplaceSub; } break; case 245: { - sym(1).ival = QSOperator::InplaceRightShift; + sym(1).ival = QSOperator::InplaceLeftShift; } break; case 246: { - sym(1).ival = QSOperator::InplaceURightShift; + sym(1).ival = QSOperator::InplaceRightShift; } break; case 247: { - sym(1).ival = QSOperator::InplaceAnd; + sym(1).ival = QSOperator::InplaceURightShift; } break; case 248: { - sym(1).ival = QSOperator::InplaceXor; + sym(1).ival = QSOperator::InplaceAnd; } break; case 249: { + sym(1).ival = QSOperator::InplaceXor; +} break; + +case 250: { sym(1).ival = QSOperator::InplaceOr; } break; -case 251: { - AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression); - node->commaToken = loc(2); - sym(1).Node = node; -} break; - case 252: { - sym(1).Node = 0; -} break; - -case 255: { AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; +case 253: { + sym(1).Node = 0; +} break; + case 256: { + AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; + +case 257: { sym(1).Node = 0; } break; -case 273: { +case 274: { AST::Block *node = new (pool) AST::Block(sym(2).StatementList); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; -case 274: { +case 275: { sym(1).Node = new (pool) AST::StatementList(sym(1).Statement); } break; -case 275: { +case 276: { sym(1).Node = new (pool) AST::StatementList(sym(1).StatementList, sym(2).Statement); } break; -case 276: { +case 277: { sym(1).Node = 0; } break; -case 277: { +case 278: { sym(1).Node = sym(1).StatementList->finish (); } break; -case 279: { +case 280: { AST::VariableStatement *node = new (pool) AST::VariableStatement( sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST)); node->declarationKindToken = loc(1); @@ -1360,37 +1382,31 @@ case 279: { sym(1).Node = node; } break; -case 280: { +case 281: { sym(1).ival = T_CONST; } break; -case 281: { +case 282: { sym(1).ival = T_VAR; } break; -case 282: { +case 283: { sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration); } break; -case 283: { +case 284: { AST::VariableDeclarationList *node = new (pool) AST::VariableDeclarationList( sym(1).VariableDeclarationList, sym(3).VariableDeclaration); node->commaToken = loc(2); sym(1).Node = node; } break; -case 284: { +case 285: { sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration); } break; -case 285: { - sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclarationList, sym(3).VariableDeclaration); -} break; - case 286: { - AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression); - node->identifierToken = loc(1); - sym(1).Node = node; + sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclarationList, sym(3).VariableDeclaration); } break; case 287: { @@ -1400,36 +1416,42 @@ case 287: { } break; case 288: { - // ### TODO: AST for initializer - sym(1) = sym(2); + AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression); + node->identifierToken = loc(1); + sym(1).Node = node; } break; case 289: { - sym(1).Node = 0; -} break; - -case 291: { // ### TODO: AST for initializer sym(1) = sym(2); } break; -case 292: { +case 290: { sym(1).Node = 0; } break; -case 294: { +case 292: { + // ### TODO: AST for initializer + sym(1) = sym(2); +} break; + +case 293: { + sym(1).Node = 0; +} break; + +case 295: { AST::EmptyStatement *node = new (pool) AST::EmptyStatement(); node->semicolonToken = loc(1); sym(1).Node = node; } break; -case 296: { +case 297: { AST::ExpressionStatement *node = new (pool) AST::ExpressionStatement(sym(1).Expression); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 297: { +case 298: { AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement, sym(7).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); @@ -1438,7 +1460,7 @@ case 297: { sym(1).Node = node; } break; -case 298: { +case 299: { AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); @@ -1446,7 +1468,7 @@ case 298: { sym(1).Node = node; } break; -case 301: { +case 302: { AST::DoWhileStatement *node = new (pool) AST::DoWhileStatement(sym(2).Statement, sym(5).Expression); node->doToken = loc(1); node->whileToken = loc(3); @@ -1456,7 +1478,7 @@ case 301: { sym(1).Node = node; } break; -case 302: { +case 303: { AST::WhileStatement *node = new (pool) AST::WhileStatement(sym(3).Expression, sym(5).Statement); node->whileToken = loc(1); node->lparenToken = loc(2); @@ -1464,7 +1486,7 @@ case 302: { sym(1).Node = node; } break; -case 303: { +case 304: { AST::ForStatement *node = new (pool) AST::ForStatement(sym(3).Expression, sym(5).Expression, sym(7).Expression, sym(9).Statement); node->forToken = loc(1); @@ -1475,7 +1497,7 @@ case 303: { sym(1).Node = node; } break; -case 304: { +case 305: { AST::LocalForStatement *node = new (pool) AST::LocalForStatement( sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression, sym(8).Expression, sym(10).Statement); @@ -1488,7 +1510,7 @@ case 304: { sym(1).Node = node; } break; -case 305: { +case 306: { AST:: ForEachStatement *node = new (pool) AST::ForEachStatement(sym(3).Expression, sym(5).Expression, sym(7).Statement); node->forToken = loc(1); @@ -1498,7 +1520,7 @@ case 305: { sym(1).Node = node; } break; -case 306: { +case 307: { AST::LocalForEachStatement *node = new (pool) AST::LocalForEachStatement( sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement); node->forToken = loc(1); @@ -1509,14 +1531,14 @@ case 306: { sym(1).Node = node; } break; -case 308: { +case 309: { AST::ContinueStatement *node = new (pool) AST::ContinueStatement(); node->continueToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 310: { +case 311: { AST::ContinueStatement *node = new (pool) AST::ContinueStatement(stringRef(2)); node->continueToken = loc(1); node->identifierToken = loc(2); @@ -1524,14 +1546,14 @@ case 310: { sym(1).Node = node; } break; -case 312: { +case 313: { AST::BreakStatement *node = new (pool) AST::BreakStatement(QStringRef()); node->breakToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 314: { +case 315: { AST::BreakStatement *node = new (pool) AST::BreakStatement(stringRef(2)); node->breakToken = loc(1); node->identifierToken = loc(2); @@ -1539,14 +1561,14 @@ case 314: { sym(1).Node = node; } break; -case 316: { +case 317: { AST::ReturnStatement *node = new (pool) AST::ReturnStatement(sym(2).Expression); node->returnToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; -case 317: { +case 318: { AST::WithStatement *node = new (pool) AST::WithStatement(sym(3).Expression, sym(5).Statement); node->withToken = loc(1); node->lparenToken = loc(2); @@ -1554,7 +1576,7 @@ case 317: { sym(1).Node = node; } break; -case 318: { +case 319: { AST::SwitchStatement *node = new (pool) AST::SwitchStatement(sym(3).Expression, sym(5).CaseBlock); node->switchToken = loc(1); node->lparenToken = loc(2); @@ -1562,83 +1584,83 @@ case 318: { sym(1).Node = node; } break; -case 319: { +case 320: { AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; -case 320: { +case 321: { AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(5); sym(1).Node = node; } break; -case 321: { +case 322: { sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClause); } break; -case 322: { +case 323: { sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClauses, sym(2).CaseClause); } break; -case 323: { +case 324: { sym(1).Node = 0; } break; -case 324: { +case 325: { sym(1).Node = sym(1).CaseClauses->finish (); } break; -case 325: { +case 326: { AST::CaseClause *node = new (pool) AST::CaseClause(sym(2).Expression, sym(4).StatementList); node->caseToken = loc(1); node->colonToken = loc(3); sym(1).Node = node; } break; -case 326: { +case 327: { AST::DefaultClause *node = new (pool) AST::DefaultClause(sym(3).StatementList); node->defaultToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; -case 327: { +case 328: { AST::LabelledStatement *node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement); node->identifierToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; -case 329: { +case 330: { AST::ThrowStatement *node = new (pool) AST::ThrowStatement(sym(2).Expression); node->throwToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; -case 330: { +case 331: { AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch); node->tryToken = loc(1); sym(1).Node = node; } break; -case 331: { +case 332: { AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; -case 332: { +case 333: { AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch, sym(4).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; -case 333: { +case 334: { AST::Catch *node = new (pool) AST::Catch(stringRef(3), sym(5).Block); node->catchToken = loc(1); node->lparenToken = loc(2); @@ -1647,20 +1669,20 @@ case 333: { sym(1).Node = node; } break; -case 334: { +case 335: { AST::Finally *node = new (pool) AST::Finally(sym(2).Block); node->finallyToken = loc(1); sym(1).Node = node; } break; -case 336: { +case 337: { AST::DebuggerStatement *node = new (pool) AST::DebuggerStatement(); node->debuggerToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 338: { +case 339: { AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); node->identifierToken = loc(2); @@ -1671,7 +1693,7 @@ case 338: { sym(1).Node = node; } break; -case 339: { +case 340: { AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); if (! stringRef(2).isNull()) @@ -1683,7 +1705,7 @@ case 339: { sym(1).Node = node; } break; -case 340: { +case 341: { AST::FunctionExpression *node = new (pool) AST::FunctionExpression(QStringRef(), sym(3).FormalParameterList, sym(6).FunctionBody); node->functionToken = loc(1); node->lparenToken = loc(2); @@ -1693,56 +1715,56 @@ case 340: { sym(1).Node = node; } break; -case 341: { +case 342: { AST::FormalParameterList *node = new (pool) AST::FormalParameterList(stringRef(1)); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 342: { +case 343: { AST::FormalParameterList *node = new (pool) AST::FormalParameterList(sym(1).FormalParameterList, stringRef(3)); node->commaToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; -case 343: { - sym(1).Node = 0; -} break; - case 344: { - sym(1).Node = sym(1).FormalParameterList->finish (); + sym(1).Node = 0; } break; case 345: { + sym(1).Node = sym(1).FormalParameterList->finish (); +} break; + +case 346: { sym(1).Node = 0; } break; -case 347: { +case 348: { sym(1).Node = new (pool) AST::FunctionBody(sym(1).SourceElements->finish ()); } break; -case 349: { +case 350: { sym(1).Node = new (pool) AST::Program(sym(1).SourceElements->finish ()); } break; -case 350: { +case 351: { sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElement); } break; -case 351: { +case 352: { sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElements, sym(2).SourceElement); } break; -case 352: { +case 353: { sym(1).Node = new (pool) AST::StatementSourceElement(sym(1).Statement); } break; -case 353: { +case 354: { sym(1).Node = new (pool) AST::FunctionSourceElement(sym(1).FunctionDeclaration); } break; -case 354: { +case 355: { sym(1).Node = 0; } break; diff --git a/src/tools/qdoc/qmlparser/qqmljsparser_p.h b/src/tools/qdoc/qmlparser/qqmljsparser_p.h index b0abf06b251..cf9f641fbc5 100644 --- a/src/tools/qdoc/qmlparser/qqmljsparser_p.h +++ b/src/tools/qdoc/qmlparser/qqmljsparser_p.h @@ -240,9 +240,9 @@ protected: -#define J_SCRIPT_REGEXPLITERAL_RULE1 87 +#define J_SCRIPT_REGEXPLITERAL_RULE1 88 -#define J_SCRIPT_REGEXPLITERAL_RULE2 88 +#define J_SCRIPT_REGEXPLITERAL_RULE2 89 QT_QML_END_NAMESPACE diff --git a/src/tools/qlalr/doc/src/images/qt-logo.png b/src/tools/qlalr/doc/src/images/qt-logo.png index 2dc67161c1b..6e7d000c047 100644 Binary files a/src/tools/qlalr/doc/src/images/qt-logo.png and b/src/tools/qlalr/doc/src/images/qt-logo.png differ diff --git a/src/tools/rcc/rcc.cpp b/src/tools/rcc/rcc.cpp index 9d8a7b70510..5769ed552c6 100644 --- a/src/tools/rcc/rcc.cpp +++ b/src/tools/rcc/rcc.cpp @@ -730,33 +730,37 @@ bool RCCResourceLibrary::output(QIODevice &outDevice, QIODevice &tempDevice, QIO { m_errorDevice = &errorDevice; - const char pattern[] = { 'Q', 'R', 'C', '_', 'D', 'A', 'T', 'A' }; if (m_format == Pass2) { - char c; - for (int i = 0; i < 8; ) { - if (!tempDevice.getChar(&c)) { - m_errorDevice->write("No data signature found\n"); - return false; - } - if (c == pattern[i]) { - ++i; - } else { - for (int k = 0; k < i; ++k) - outDevice.putChar(pattern[k]); - outDevice.putChar(c); - i = 0; + const char pattern[] = { 'Q', 'R', 'C', '_', 'D', 'A', 'T', 'A' }; + bool foundSignature = false; + + while (true) { + char c; + for (int i = 0; i < 8; ) { + if (!tempDevice.getChar(&c)) { + if (foundSignature) + return true; + m_errorDevice->write("No data signature found\n"); + return false; + } + if (c == pattern[i]) { + ++i; + } else { + for (int k = 0; k < i; ++k) + outDevice.putChar(pattern[k]); + outDevice.putChar(c); + i = 0; + } } + + m_outDevice = &outDevice; + quint64 start = outDevice.pos(); + writeDataBlobs(); + quint64 len = outDevice.pos() - start; + + tempDevice.seek(tempDevice.pos() + len - 8); + foundSignature = true; } - - m_outDevice = &outDevice; - quint64 start = outDevice.pos(); - writeDataBlobs(); - quint64 len = outDevice.pos() - start; - - tempDevice.seek(tempDevice.pos() + len - 8); - outDevice.write(tempDevice.readAll()); - - return true; } //write out @@ -889,6 +893,8 @@ bool RCCResourceLibrary::writeDataBlobs() if (m_format == C_Code) writeString("\n};\n\n"); else if (m_format == Pass1) { + if (offset < 8) + offset = 8; writeString("\nstatic const unsigned char qt_resource_data["); writeByteArray(QByteArray::number(offset)); writeString("] = { 'Q', 'R', 'C', '_', 'D', 'A', 'T', 'A' };\n\n"); diff --git a/src/widgets/accessible/simplewidgets.cpp b/src/widgets/accessible/simplewidgets.cpp index ade5cfe3dcf..41692d11bd3 100644 --- a/src/widgets/accessible/simplewidgets.cpp +++ b/src/widgets/accessible/simplewidgets.cpp @@ -414,12 +414,14 @@ QString QAccessibleDisplay::text(QAccessible::Text t) const if (qobject_cast(object())) { QLabel *label = qobject_cast(object()); str = label->text(); +#ifndef QT_NO_TEXTHTMLPARSER if (label->textFormat() == Qt::RichText || (label->textFormat() == Qt::AutoText && Qt::mightBeRichText(str))) { QTextDocument doc; doc.setHtml(str); str = doc.toPlainText(); } +#endif if (label->buddy()) str = qt_accStripAmp(str); #ifndef QT_NO_LCDNUMBER diff --git a/src/widgets/dialogs/images/qtlogo-64.png b/src/widgets/dialogs/images/qtlogo-64.png index 4f68e162de4..af87e98cf50 100644 Binary files a/src/widgets/dialogs/images/qtlogo-64.png and b/src/widgets/dialogs/images/qtlogo-64.png differ diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 0ba3ea40e0e..6065ad015e2 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -510,7 +510,7 @@ bool QFileDialog::restoreState(const QByteArray &state) if (!d->qFileDialogUi->splitter->restoreState(d->splitterState)) return false; QList list = d->qFileDialogUi->splitter->sizes(); - if (list.count() >= 2 && list.at(0) == 0 && list.at(1) == 0) { + if (list.count() >= 2 && (list.at(0) == 0 || list.at(1) == 0)) { for (int i = 0; i < list.count(); ++i) list[i] = d->qFileDialogUi->splitter->widget(i)->sizeHint().width(); d->qFileDialogUi->splitter->setSizes(list); diff --git a/src/widgets/dialogs/qfiledialog.ui b/src/widgets/dialogs/qfiledialog.ui index 89adaf530ec..7f6e59c908c 100644 --- a/src/widgets/dialogs/qfiledialog.ui +++ b/src/widgets/dialogs/qfiledialog.ui @@ -179,6 +179,9 @@ Qt::Horizontal + + false + Sidebar diff --git a/src/widgets/dialogs/qfiledialog_embedded.ui b/src/widgets/dialogs/qfiledialog_embedded.ui index 16128dc0a01..4cdc620437b 100644 --- a/src/widgets/dialogs/qfiledialog_embedded.ui +++ b/src/widgets/dialogs/qfiledialog_embedded.ui @@ -1,4 +1,5 @@ - + + ********************************************************************* ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). @@ -40,8 +41,8 @@ ** ********************************************************************* QFileDialog - - + + 0 0 @@ -49,14 +50,14 @@ 320 - + true - + - - - + + + 1 0 @@ -64,45 +65,45 @@ - + - - + + Back - - + + Forward - - + + Parent Directory - - + + Create New Folder - - + + List View - - + + Detail View @@ -110,75 +111,89 @@ - - - + + + 0 0 - + Qt::Horizontal - - - + + false + + + + QFrame::NoFrame - + QFrame::Raised - - + + 0 - + + 0 + + + 0 + + + 0 + + 0 - - + + 0 - - - - 0 - 0 - 108 - 164 - - - - + + + 0 - + + 0 + + + 0 + + + 0 + + 0 - + - - - - 0 - 0 - 100 - 30 - - - - + + + 0 - + + 0 + + + 0 + + + 0 + + 0 - + @@ -189,31 +204,31 @@ - - - - - + + + + + 1 0 - - - + + + Qt::Vertical - + QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - + + + + 0 0 @@ -223,23 +238,23 @@ - - + + false - - + + 0 0 - + 0 0 - + 0 0 @@ -248,45 +263,45 @@ - - + + false - - + + 0 0 - + 0 0 - + Files of type: - - + + false - - + + 0 0 - + 0 0 - + Look in: @@ -297,27 +312,27 @@ QFileDialogTreeView QTreeView -
    qfiledialog_p.h
    +
    private/qfiledialog_p.h
    QFileDialogListView QListView -
    qfiledialog_p.h
    +
    private/qfiledialog_p.h
    QSidebar QListWidget -
    qsidebar_p.h
    +
    private/qsidebar_p.h
    QFileDialogLineEdit QLineEdit -
    qfiledialog_p.h
    +
    private/qfiledialog_p.h
    QFileDialogComboBox QComboBox -
    qfiledialog_p.h
    +
    private/qfiledialog_p.h
    diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index 988d3ad3c73..baa55cb88fd 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -76,7 +76,7 @@ QT_BEGIN_NAMESPACE QFileSystemModel can be accessed using the standard interface provided by QAbstractItemModel, but it also provides some convenience functions that are specific to a directory model. - The fileInfo(), isDir(), name(), and path() functions provide information + The fileInfo(), isDir(), fileName() and filePath() functions provide information about the underlying files and directories related to items in the model. Directories can be created and removed using mkdir(), rmdir(). diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp index 1f7b18e8247..a378daa3d33 100644 --- a/src/widgets/dialogs/qwizard.cpp +++ b/src/widgets/dialogs/qwizard.cpp @@ -2571,6 +2571,14 @@ void QWizard::setWizardStyle(WizardStyle style) d->disableUpdates(); d->wizStyle = style; d->updateButtonTexts(); +#if !defined(QT_NO_STYLE_WINDOWSVISTA) + if (aeroStyleChange) { + //Send a resizeevent since the antiflicker widget probably needs a new size + //because of the backbutton in the window title + QResizeEvent ev(geometry().size(), geometry().size()); + QApplication::sendEvent(this, &ev); + } +#endif d->updateLayout(); updateGeometry(); d->enableUpdates(); diff --git a/src/widgets/doc/snippets/code/doc_src_layout.cpp b/src/widgets/doc/snippets/code/doc_src_layout.cpp index 5ea8ce5a5ff..a10cd52e2ec 100644 --- a/src/widgets/doc/snippets/code/doc_src_layout.cpp +++ b/src/widgets/doc/snippets/code/doc_src_layout.cpp @@ -42,7 +42,7 @@ #ifndef CARD_H #define CARD_H -#include +#include #include class CardLayout : public QLayout diff --git a/src/widgets/doc/snippets/qlistview-dnd/main.cpp b/src/widgets/doc/snippets/qlistview-dnd/main.cpp index c4a8aebb01e..422ce35c6b8 100644 --- a/src/widgets/doc/snippets/qlistview-dnd/main.cpp +++ b/src/widgets/doc/snippets/qlistview-dnd/main.cpp @@ -38,7 +38,7 @@ ** ****************************************************************************/ -#include +#include #include "mainwindow.h" diff --git a/src/widgets/doc/snippets/qlistview-dnd/mainwindow.cpp b/src/widgets/doc/snippets/qlistview-dnd/mainwindow.cpp index ed06819dd9d..3b192956765 100644 --- a/src/widgets/doc/snippets/qlistview-dnd/mainwindow.cpp +++ b/src/widgets/doc/snippets/qlistview-dnd/mainwindow.cpp @@ -38,7 +38,7 @@ ** ****************************************************************************/ -#include +#include #include "mainwindow.h" #include "model.h" diff --git a/src/widgets/doc/snippets/qlistview-dnd/model.cpp b/src/widgets/doc/snippets/qlistview-dnd/model.cpp index 6ebeb2eb562..aa12cef3a2f 100644 --- a/src/widgets/doc/snippets/qlistview-dnd/model.cpp +++ b/src/widgets/doc/snippets/qlistview-dnd/model.cpp @@ -65,18 +65,31 @@ DragDropListModel::DragDropListModel(const QStringList &strings, } //! [0] -bool DragDropListModel::dropMimeData(const QMimeData *data, +bool DragDropListModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) { - if (action == Qt::IgnoreAction) - return true; + Q_UNUSED(action); + Q_UNUSED(row); + Q_UNUSED(parent); if (!data->hasFormat("application/vnd.text.list")) return false; if (column > 0) -//! [0] //! [1] return false; + + return true; +} +//! [0] +//! [1] +bool DragDropListModel::dropMimeData(const QMimeData *data, + Qt::DropAction action, int row, int column, const QModelIndex &parent) +{ + if (!canDropMimeData(data, action, row, column, parent)) + return false; + + if (action == Qt::IgnoreAction) + return true; //! [1] //! [2] diff --git a/src/widgets/doc/snippets/qlistview-dnd/model.h b/src/widgets/doc/snippets/qlistview-dnd/model.h index 9b667ad4a38..9217052971d 100644 --- a/src/widgets/doc/snippets/qlistview-dnd/model.h +++ b/src/widgets/doc/snippets/qlistview-dnd/model.h @@ -63,6 +63,8 @@ public: Qt::ItemFlags flags(const QModelIndex &index) const; + bool canDropMimeData(const QMimeData *data, Qt::DropAction action, + int row, int column, const QModelIndex &parent); bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); QMimeData *mimeData(const QModelIndexList &indexes) const; diff --git a/src/widgets/doc/snippets/qlistview-dnd/qlistview-dnd.pro b/src/widgets/doc/snippets/qlistview-dnd/qlistview-dnd.pro index 71fa273a69a..bc2a1f0dce2 100644 --- a/src/widgets/doc/snippets/qlistview-dnd/qlistview-dnd.pro +++ b/src/widgets/doc/snippets/qlistview-dnd/qlistview-dnd.pro @@ -3,3 +3,4 @@ SOURCES = main.cpp \ model.cpp HEADERS = mainwindow.h \ model.h +QT += widgets diff --git a/src/widgets/doc/src/model-view-programming.qdoc b/src/widgets/doc/src/model-view-programming.qdoc index 8978efa1e35..ada0460689d 100644 --- a/src/widgets/doc/src/model-view-programming.qdoc +++ b/src/widgets/doc/src/model-view-programming.qdoc @@ -1769,6 +1769,9 @@ dropped onto existing items separately to data dropped into the top level of the model (i.e., onto an invalid item). + Models can forbid dropping on certain items, or depending on the dropped data, + by reimplementing QAbstractItemModel::canDropMimeData(). + The model first has to make sure that the operation should be acted on, the data supplied is in a format that can be used, and that its destination within the model is valid: diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp index 67d135271c7..03f22a270f2 100644 --- a/src/widgets/graphicsview/qgraphicsitem.cpp +++ b/src/widgets/graphicsview/qgraphicsitem.cpp @@ -1968,8 +1968,10 @@ QGraphicsItem::CacheMode QGraphicsItem::cacheMode() const Caching can speed up rendering if your item spends a significant time redrawing itself. In some cases the cache can also slow down rendering, in particular when the item spends less time redrawing than QGraphicsItem - spends redrawing from the cache. When enabled, the item's paint() function - will be called only once for each call to update(); for any subsequent + spends redrawing from the cache. + + When caching is enabled, an item's paint() function will generally draw into an + offscreen pixmap cache; for any subsequent repaint requests, the Graphics View framework will redraw from the cache. This approach works particularly well with QGLWidget, which stores all the cache as OpenGL textures. @@ -1980,6 +1982,12 @@ QGraphicsItem::CacheMode QGraphicsItem::cacheMode() const You can read more about the different cache modes in the CacheMode documentation. + \note Enabling caching does not imply that the item's paint() function will be + called only in response to an explicit update() call. For instance, under + memory pressure, Qt may decide to drop some of the cache information; + in such cases an item's paint() function will be called even if there + was no update() call (that is, exactly as if there were no caching enabled). + \sa CacheMode, QPixmapCache::setCacheLimit() */ void QGraphicsItem::setCacheMode(CacheMode mode, const QSize &logicalCacheSize) @@ -2439,7 +2447,12 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, Items are visible by default; it is unnecessary to call setVisible() on a new item. - \sa isVisible(), show(), hide() + \note An item with opacity set to 0 will still be considered visible, + although it will be treated like an invisible item: mouse events will pass + through it, it will not be included in the items returned by + QGraphicsView::items(), and so on. However, the item will retain the focus. + + \sa isVisible(), show(), hide(), setOpacity() */ void QGraphicsItem::setVisible(bool visible) { @@ -2707,7 +2720,11 @@ qreal QGraphicsItem::effectiveOpacity() const with the parent: ItemIgnoresParentOpacity and ItemDoesntPropagateOpacityToChildren. - \sa opacity(), effectiveOpacity() + \note Setting the opacity of an item to 0 will not make the item invisible + (according to isVisible()), but the item will be treated like an invisible + one. See the documentation of setVisible() for more information. + + \sa opacity(), effectiveOpacity(), setVisible() */ void QGraphicsItem::setOpacity(qreal opacity) { @@ -4487,7 +4504,7 @@ void QGraphicsItem::resetTransform() Use \code - setRotation(rotation() + angle); + item->setTransform(QTransform().rotate(angle), true); \endcode instead. @@ -5337,6 +5354,16 @@ void QGraphicsItem::setBoundingRegionGranularity(qreal granularity) All painting is done in local coordinates. + \note It is mandatory that an item will always redraw itself in the exact + same way, unless update() was called; otherwise visual artifacts may + occur. In other words, two subsequent calls to paint() must always produce + the same output, unless update() was called between them. + + \note Enabling caching for an item does not guarantee that paint() + will be invoked only once by the Graphics View framework, + even without any explicit call to update(). See the documentation of + setCacheMode() for more details. + \sa setCacheMode(), QPen::width(), {Item Coordinates}, ItemUsesExtendedStyleOption */ @@ -9764,6 +9791,7 @@ QVariant QGraphicsPixmapItem::extension(const QVariant &variant) const using textWidth(). \note In order to align HTML text in the center, the item's text width must be set. + Otherwise, you can call adjustSize() after setting the item's text. \image graphicsview-textitem.png diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index a6361bd7504..9d38a330c84 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -1905,7 +1905,7 @@ void QAbstractItemView::dragEnterEvent(QDragEnterEvent *event) && (event->source() != this|| !(event->possibleActions() & Qt::MoveAction))) return; - if (d_func()->canDecode(event)) { + if (d_func()->canDrop(event)) { event->accept(); setState(DraggingState); } else { @@ -1934,7 +1934,7 @@ void QAbstractItemView::dragMoveEvent(QDragMoveEvent *event) QModelIndex index = indexAt(event->pos()); d->hover = index; if (!d->droppingOnItself(event, index) - && d->canDecode(event)) { + && d->canDrop(event)) { if (index.isValid() && d->showDropIndicator) { QRect rect = visualRect(index); @@ -1979,7 +1979,7 @@ void QAbstractItemView::dragMoveEvent(QDragMoveEvent *event) } } d->viewport->update(); - } // can decode + } // can drop if (d->shouldAutoScroll(event->pos())) startAutoScroll(); diff --git a/src/widgets/itemviews/qabstractitemview_p.h b/src/widgets/itemviews/qabstractitemview_p.h index 047533b22cc..c3bd1fb504d 100644 --- a/src/widgets/itemviews/qabstractitemview_p.h +++ b/src/widgets/itemviews/qabstractitemview_p.h @@ -164,13 +164,15 @@ public: #ifndef QT_NO_DRAGANDDROP virtual QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const; - inline bool canDecode(QDropEvent *e) const { - QStringList modelTypes = model->mimeTypes(); - const QMimeData *mime = e->mimeData(); - for (int i = 0; i < modelTypes.count(); ++i) - if (mime->hasFormat(modelTypes.at(i)) - && (e->dropAction() & model->supportedDropActions())) - return true; + inline bool canDrop(QDropEvent *event) { + QModelIndex index; + int col = -1; + int row = -1; + if (dropOn(event, &row, &col, &index)) { + return model->canDropMimeData(event->mimeData(), + dragDropMode == QAbstractItemView::InternalMove ? Qt::MoveAction : event->dropAction(), + row, col, index); + } return false; } diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp index a097228846f..e7d18092f12 100644 --- a/src/widgets/itemviews/qlistview.cpp +++ b/src/widgets/itemviews/qlistview.cpp @@ -1977,7 +1977,7 @@ void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event) ? intersectVector.last() : QModelIndex(); dd->hover = index; if (!dd->droppingOnItself(event, index) - && dd->canDecode(event)) { + && dd->canDrop(event)) { if (index.isValid() && dd->showDropIndicator) { QRect rect = qq->visualRect(index); @@ -2023,7 +2023,7 @@ void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event) } } dd->viewport->update(); - } // can decode + } // can drop if (dd->shouldAutoScroll(event->pos())) qq->startAutoScroll(); @@ -2757,7 +2757,7 @@ bool QIconModeViewBase::filterDragLeaveEvent(QDragLeaveEvent *e) bool QIconModeViewBase::filterDragMoveEvent(QDragMoveEvent *e) { - if (e->source() != qq || !dd->canDecode(e)) + if (e->source() != qq || !dd->canDrop(e)) return false; // ignore by default diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 9abec13b5be..500e812e284 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -53,6 +53,7 @@ #include "qtranslator.h" #include "qvariant.h" #include "qwidget.h" +#include "qgraphicssceneevent.h" #include "private/qdnd_p.h" #include "private/qguiapplication_p.h" #include "qcolormap.h" @@ -2291,6 +2292,31 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool return w; } +Qt::MouseEventSource QApplicationPrivate::mouseEventSource(const QEvent *e) +{ + switch (e->type()) { + case QEvent::NonClientAreaMouseButtonDblClick: + case QEvent::NonClientAreaMouseButtonPress: + case QEvent::NonClientAreaMouseButtonRelease: + case QEvent::NonClientAreaMouseMove: + case QEvent::MouseButtonDblClick: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseMove: + return static_cast(e)->source(); +#ifndef QT_NO_GRAPHICSVIEW + case QEvent::GraphicsSceneMouseDoubleClick: + case QEvent::GraphicsSceneMousePress: + case QEvent::GraphicsSceneMouseRelease: + case QEvent::GraphicsSceneMouseMove: + return static_cast(e)->source(); +#endif // !QT_NO_GRAPHICSVIEW + default: + break; + } + return Qt::MouseEventNotSynthesized; +} + /*! \fn void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, const QPointF &globalPosF) \internal @@ -4211,8 +4237,9 @@ bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy) return true; } -void QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent) +bool QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent) { + bool containsPress = false; for (int i = 0; i < touchEvent->touchPoints().count(); ++i) { QTouchEvent::TouchPoint &touchPoint = touchEvent->_touchPoints[i]; @@ -4225,7 +4252,11 @@ void QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEven touchPoint.d->rect = rect; touchPoint.d->startPos = widget->mapFromGlobal(touchPoint.startScreenPos().toPoint()) + delta; touchPoint.d->lastPos = widget->mapFromGlobal(touchPoint.lastScreenPos().toPoint()) + delta; + + if (touchPoint.state() == Qt::TouchPointPressed) + containsPress = true; } + return containsPress; } void QApplicationPrivate::initializeMultitouch() @@ -4372,11 +4403,14 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, QApplication::keyboardModifiers(), it.value().first, it.value().second); - updateTouchPointsForWidget(widget, &touchEvent); + bool containsPress = updateTouchPointsForWidget(widget, &touchEvent); touchEvent.setTimestamp(timestamp); touchEvent.setWindow(window->windowHandle()); touchEvent.setTarget(widget); + if (containsPress) + widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent); + switch (touchEvent.type()) { case QEvent::TouchBegin: { diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index 156bf341946..b24b592fbe2 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -168,6 +168,7 @@ public: static void setFocusWidget(QWidget *focus, Qt::FocusReason reason); static QWidget *focusNextPrevChild_helper(QWidget *toplevel, bool next, bool *wrappingOccurred = 0); + static Qt::MouseEventSource mouseEventSource(const QEvent *e); #ifndef QT_NO_GRAPHICSVIEW // Maintain a list of all scenes to ensure font and palette propagation to @@ -275,7 +276,7 @@ public: QPixmap *ignore_cursor; #endif - static void updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent); + static bool updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent); void initializeMultitouch(); void initializeMultitouch_sys(); void cleanupMultitouch(); diff --git a/src/widgets/kernel/qgesture_p.h b/src/widgets/kernel/qgesture_p.h index 8668145d8ad..26d9ede59dd 100644 --- a/src/widgets/kernel/qgesture_p.h +++ b/src/widgets/kernel/qgesture_p.h @@ -80,7 +80,7 @@ class QPanGesturePrivate : public QGesturePrivate public: QPanGesturePrivate() - : acceleration(0), xVelocity(0), yVelocity(0) + : acceleration(0), xVelocity(0), yVelocity(0), pointCount(2) { } @@ -95,6 +95,7 @@ public: qreal acceleration; qreal xVelocity; qreal yVelocity; + int pointCount; // ### fixme Qt 5.5: Add accessor to QPanGesture. }; class QPinchGesturePrivate : public QGesturePrivate @@ -134,11 +135,17 @@ class QSwipeGesturePrivate : public QGesturePrivate Q_DECLARE_PUBLIC(QSwipeGesture) public: + enum State { + NoGesture, + Started, + ThreePointsReached + }; + QSwipeGesturePrivate() : horizontalDirection(QSwipeGesture::NoDirection), verticalDirection(QSwipeGesture::NoDirection), swipeAngle(0), - started(false), velocityValue(0) + state(NoGesture), velocityValue(0) { } @@ -150,7 +157,7 @@ public: qreal swipeAngle; QPoint lastPositions[3]; - bool started; + State state; qreal velocityValue; QElapsedTimer time; }; diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp index 739e6b1870c..c9af3062d33 100644 --- a/src/widgets/kernel/qgesturemanager.cpp +++ b/src/widgets/kernel/qgesturemanager.cpp @@ -63,6 +63,24 @@ QT_BEGIN_NAMESPACE +static inline int panTouchPoints() +{ + // Override by environment variable for testing. + static const char panTouchPointVariable[] = "QT_PAN_TOUCHPOINTS"; + if (qEnvironmentVariableIsSet(panTouchPointVariable)) { + bool ok; + const int result = qgetenv(panTouchPointVariable).toInt(&ok); + if (ok && result >= 1) + return result; + qWarning() << "Ignoring invalid value of " << panTouchPointVariable; + } + // Pan should use 1 finger on a touch screen and 2 fingers on touch pads etc. + // where 1 finger movements are used for mouse event synthetization. For now, + // default to 2 until all classes inheriting QScrollArea are fixed to handle it + // correctly. + return 2; +} + QGestureManager::QGestureManager(QObject *parent) : QObject(parent), state(NotGesture), m_lastCustomGestureId(Qt::CustomGesture) { @@ -73,7 +91,7 @@ QGestureManager::QGestureManager(QObject *parent) registerGestureRecognizer(new QMacPinchGestureRecognizer); registerGestureRecognizer(new QMacPanGestureRecognizer); #else - registerGestureRecognizer(new QPanGestureRecognizer); + registerGestureRecognizer(new QPanGestureRecognizer(panTouchPoints())); registerGestureRecognizer(new QPinchGestureRecognizer); registerGestureRecognizer(new QSwipeGestureRecognizer); registerGestureRecognizer(new QTapGestureRecognizer); diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index 8a4e0c8ffdd..db116b070cd 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -471,7 +471,7 @@ class QOpenGLWidgetPaintDevice : public QOpenGLPaintDevice { public: QOpenGLWidgetPaintDevice(QOpenGLWidget *widget) - : QOpenGLPaintDevice(new QOpenGLWidgetPaintDevicePrivate(widget)) { } + : QOpenGLPaintDevice(*new QOpenGLWidgetPaintDevicePrivate(widget)) { } void ensureActiveTarget() Q_DECL_OVERRIDE; }; @@ -578,12 +578,22 @@ GLuint QOpenGLWidgetPrivate::textureId() const void QOpenGLWidgetPrivate::reset() { + Q_Q(QOpenGLWidget); + + // Destroy the OpenGL resources first. These need the context to be current. + if (initialized) + q->makeCurrent(); + delete paintDevice; paintDevice = 0; delete fbo; fbo = 0; delete resolvedFbo; resolvedFbo = 0; + + if (initialized) + q->doneCurrent(); + // Delete the context first, then the surface. Slots connected to // the context's aboutToBeDestroyed() may still call makeCurrent() // to perform some cleanup. diff --git a/src/widgets/kernel/qstandardgestures.cpp b/src/widgets/kernel/qstandardgestures.cpp index 0822c04033f..53e5d091faf 100644 --- a/src/widgets/kernel/qstandardgestures.cpp +++ b/src/widgets/kernel/qstandardgestures.cpp @@ -38,16 +38,13 @@ #include "qwidget.h" #include "qabstractscrollarea.h" #include +#include #include "qdebug.h" #ifndef QT_NO_GESTURES QT_BEGIN_NAMESPACE -QPanGestureRecognizer::QPanGestureRecognizer() -{ -} - QGesture *QPanGestureRecognizer::create(QObject *target) { if (target && target->isWidgetType()) { @@ -62,8 +59,35 @@ QGesture *QPanGestureRecognizer::create(QObject *target) return new QPanGesture; } +static QPointF panOffset(const QList &touchPoints, int maxCount) +{ + QPointF result; + const int count = qMin(touchPoints.size(), maxCount); + for (int p = 0; p < count; ++p) + result += touchPoints.at(p).pos() - touchPoints.at(p).startPos(); + return result / qreal(count); +} + +// ### fixme: Remove this +// Use single finger pan to scroll QPlainTextEdit/QTextEdit +// by changing the number of pan points to 1 for these classes. +// This used to be Qt 4's behavior on Windows which was achieved using native +// Windows gesture recognizers for these classes. +// The other classes inheriting QScrollArea still use standard 2 finger pan. +// In the long run, they should also use single finger pan to +// scroll on touch screens, however, this requires a distinct Tap&Hold-followed-by-pan +// type gesture to avoid clashes with item view selection and DnD. + +static inline int panTouchPoints(const QTouchEvent *event, const QObject *object, + int defaultTouchPoints) +{ + return event->device()->type() == QTouchDevice::TouchScreen && object && object->parent() + && (object->parent()->inherits("QPlainTextEdit") || object->parent()->inherits("QTextEdit")) + ? 1 : defaultTouchPoints; +} + QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state, - QObject *, + QObject *object, QEvent *event) { QPanGesture *q = static_cast(state); @@ -76,18 +100,15 @@ QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state, result = QGestureRecognizer::MayBeGesture; QTouchEvent::TouchPoint p = ev->touchPoints().at(0); d->lastOffset = d->offset = QPointF(); + d->pointCount = panTouchPoints(ev, object, m_pointCount); break; } case QEvent::TouchEnd: { if (q->state() != Qt::NoGesture) { const QTouchEvent *ev = static_cast(event); - if (ev->touchPoints().size() == 2) { - QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0); - QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1); + if (ev->touchPoints().size() == d->pointCount) { d->lastOffset = d->offset; - d->offset = - QPointF(p1.pos().x() - p1.startPos().x() + p2.pos().x() - p2.startPos().x(), - p1.pos().y() - p1.startPos().y() + p2.pos().y() - p2.startPos().y()) / 2; + d->offset = panOffset(ev->touchPoints(), d->pointCount); } result = QGestureRecognizer::FinishGesture; } else { @@ -97,16 +118,12 @@ QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state, } case QEvent::TouchUpdate: { const QTouchEvent *ev = static_cast(event); - if (ev->touchPoints().size() >= 2) { - QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0); - QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1); + if (ev->touchPoints().size() >= d->pointCount) { d->lastOffset = d->offset; - d->offset = - QPointF(p1.pos().x() - p1.startPos().x() + p2.pos().x() - p2.startPos().x(), - p1.pos().y() - p1.startPos().y() + p2.pos().y() - p2.startPos().y()) / 2; + d->offset = panOffset(ev->touchPoints(), d->pointCount); if (d->offset.x() > 10 || d->offset.y() > 10 || d->offset.x() < -10 || d->offset.y() < -10) { - q->setHotSpot(p1.startScreenPos()); + q->setHotSpot(ev->touchPoints().first().startScreenPos()); result = QGestureRecognizer::TriggerGesture; } else { result = QGestureRecognizer::MayBeGesture; @@ -283,7 +300,7 @@ QGestureRecognizer::Result QSwipeGestureRecognizer::recognize(QGesture *state, case QEvent::TouchBegin: { d->velocityValue = 1; d->time.start(); - d->started = true; + d->state = QSwipeGesturePrivate::Started; result = QGestureRecognizer::MayBeGesture; break; } @@ -297,9 +314,10 @@ QGestureRecognizer::Result QSwipeGestureRecognizer::recognize(QGesture *state, } case QEvent::TouchUpdate: { const QTouchEvent *ev = static_cast(event); - if (!d->started) + if (d->state == QSwipeGesturePrivate::NoGesture) result = QGestureRecognizer::CancelGesture; else if (ev->touchPoints().size() == 3) { + d->state = QSwipeGesturePrivate::ThreePointsReached; QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0); QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1); QTouchEvent::TouchPoint p3 = ev->touchPoints().at(2); @@ -354,12 +372,18 @@ QGestureRecognizer::Result QSwipeGestureRecognizer::recognize(QGesture *state, } else if (ev->touchPoints().size() > 3) { result = QGestureRecognizer::CancelGesture; } else { // less than 3 touch points - if (d->started && (ev->touchPointStates() & Qt::TouchPointPressed)) - result = QGestureRecognizer::CancelGesture; - else if (d->started) - result = QGestureRecognizer::Ignore; - else + switch (d->state) { + case QSwipeGesturePrivate::NoGesture: result = QGestureRecognizer::MayBeGesture; + break; + case QSwipeGesturePrivate::Started: + result = QGestureRecognizer::Ignore; + break; + case QSwipeGesturePrivate::ThreePointsReached: + result = (ev->touchPointStates() & Qt::TouchPointPressed) + ? QGestureRecognizer::CancelGesture : QGestureRecognizer::Ignore; + break; + } } break; } @@ -378,7 +402,7 @@ void QSwipeGestureRecognizer::reset(QGesture *state) d->swipeAngle = 0; d->lastPositions[0] = d->lastPositions[1] = d->lastPositions[2] = QPoint(); - d->started = false; + d->state = QSwipeGesturePrivate::NoGesture; d->velocityValue = 0; d->time.invalidate(); diff --git a/src/widgets/kernel/qstandardgestures_p.h b/src/widgets/kernel/qstandardgestures_p.h index aeabd9cc7ee..15ba31f26a3 100644 --- a/src/widgets/kernel/qstandardgestures_p.h +++ b/src/widgets/kernel/qstandardgestures_p.h @@ -55,11 +55,14 @@ QT_BEGIN_NAMESPACE class QPanGestureRecognizer : public QGestureRecognizer { public: - QPanGestureRecognizer(); + explicit QPanGestureRecognizer(int pointCount = 2) : m_pointCount(pointCount) {} QGesture *create(QObject *target); QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event); void reset(QGesture *state); + +private: + const int m_pointCount; }; class QPinchGestureRecognizer : public QGestureRecognizer diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 63497ce745a..7f2e5a5e173 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1403,6 +1403,8 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO if (q->testAttribute(Qt::WA_ShowWithoutActivating)) win->setProperty("_q_showWithoutActivating", QVariant(true)); + if (q->testAttribute(Qt::WA_MacAlwaysShowToolWindow)) + win->setProperty("_q_macAlwaysShowToolWindow", QVariant::fromValue(QVariant(true))); win->setFlags(data.window_flags); fixPosIncludesFrame(); if (q->testAttribute(Qt::WA_Moved) @@ -7151,10 +7153,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) } } - // generate a move event for QWidgets without window handles. QWidgets with native - // window handles already receive a move event from - // QGuiApplicationPrivate::processGeometryChangeEvent. - if (isMove && (!q->windowHandle() || q->testAttribute(Qt::WA_DontShowOnScreen))) { + if (isMove) { QMoveEvent e(q->pos(), oldPos); QApplication::sendEvent(q, &e); } @@ -10510,8 +10509,9 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f) QWidget *parentWithWindow = newparent ? (newparent->windowHandle() ? newparent : newparent->nativeParentWidget()) : 0; if (parentWithWindow) { - if (f & Qt::Window) { - q->windowHandle()->setTransientParent(parentWithWindow->windowHandle()); + QWidget *topLevel = parentWithWindow->window(); + if ((f & Qt::Window) && topLevel && topLevel->windowHandle()) { + q->windowHandle()->setTransientParent(topLevel->windowHandle()); q->windowHandle()->setParent(0); } else { q->windowHandle()->setTransientParent(0); diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index 2f2db328528..38f02b2ed91 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -863,7 +863,7 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy) QRect scrollRect = rect & clipRect(); bool overlapped = false; - bool accelerateScroll = accelEnv && isOpaque + bool accelerateScroll = accelEnv && isOpaque && !q_func()->testAttribute(Qt::WA_WState_InPaintEvent) && !(overlapped = isOverlapped(scrollRect.translated(data.crect.topLeft()))); if (!accelerateScroll) { diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 7b52638e28e..de8f11e5ecd 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -434,14 +434,19 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) QWindow *win = w->windowHandle(); if (!win) win = w->nativeParentWidget()->windowHandle(); - if (win && win->geometry().contains(event->globalPos())) { - // Use postEvent() to ensure the local QEventLoop terminates when called from QMenu::exec() - const QPoint localPos = win->mapFromGlobal(event->globalPos()); - QMouseEvent *e = new QMouseEvent(QEvent::MouseButtonPress, localPos, localPos, event->globalPos(), event->button(), event->buttons(), event->modifiers()); - QCoreApplicationPrivate::setEventSpontaneous(e, true); - QGuiApplicationPrivate::setMouseEventSource(e, QGuiApplicationPrivate::mouseEventSource(event)); - e->setTimestamp(event->timestamp()); - QCoreApplication::postEvent(win, e); + if (win) { + const QRect globalGeometry = win->isTopLevel() + ? win->geometry() + : QRect(win->mapToGlobal(QPoint(0, 0)), win->size()); + if (globalGeometry.contains(event->globalPos())) { + // Use postEvent() to ensure the local QEventLoop terminates when called from QMenu::exec() + const QPoint localPos = win->mapFromGlobal(event->globalPos()); + QMouseEvent *e = new QMouseEvent(QEvent::MouseButtonPress, localPos, localPos, event->globalPos(), event->button(), event->buttons(), event->modifiers()); + QCoreApplicationPrivate::setEventSpontaneous(e, true); + QGuiApplicationPrivate::setMouseEventSource(e, QGuiApplicationPrivate::mouseEventSource(event)); + e->setTimestamp(event->timestamp()); + QCoreApplication::postEvent(win, e); + } } } } @@ -539,14 +544,36 @@ void QWidgetWindow::handleKeyEvent(QKeyEvent *event) QGuiApplication::sendSpontaneousEvent(receiver, event); } -void QWidgetWindow::updateGeometry() +bool QWidgetWindow::updateSize() { + bool changed = false; if (m_widget->testAttribute(Qt::WA_OutsideWSRange)) - return; + return changed; + if (m_widget->data->crect.size() != geometry().size()) { + changed = true; + m_widget->data->crect.setSize(geometry().size()); + } + updateMargins(); + return changed; +} + +bool QWidgetWindow::updatePos() +{ + bool changed = false; + if (m_widget->testAttribute(Qt::WA_OutsideWSRange)) + return changed; + if (m_widget->data->crect.topLeft() != geometry().topLeft()) { + changed = true; + m_widget->data->crect.moveTopLeft(geometry().topLeft()); + } + updateMargins(); + return changed; +} + +void QWidgetWindow::updateMargins() +{ const QMargins margins = frameMargins(); - - m_widget->data->crect = geometry(); QTLWExtra *te = m_widget->d_func()->topData(); te->posIncludesFrame= false; te->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom()); @@ -605,24 +632,25 @@ void QWidgetWindow::updateNormalGeometry() void QWidgetWindow::handleMoveEvent(QMoveEvent *event) { - updateGeometry(); - QGuiApplication::sendSpontaneousEvent(m_widget, event); + if (updatePos()) + QGuiApplication::sendSpontaneousEvent(m_widget, event); } void QWidgetWindow::handleResizeEvent(QResizeEvent *event) { QSize oldSize = m_widget->data->crect.size(); - updateGeometry(); - QGuiApplication::sendSpontaneousEvent(m_widget, event); + if (updateSize()) { + QGuiApplication::sendSpontaneousEvent(m_widget, event); - if (m_widget->d_func()->paintOnScreen()) { - QRegion updateRegion(geometry()); - if (m_widget->testAttribute(Qt::WA_StaticContents)) - updateRegion -= QRect(0, 0, oldSize.width(), oldSize.height()); - m_widget->d_func()->syncBackingStore(updateRegion); - } else { - m_widget->d_func()->syncBackingStore(); + if (m_widget->d_func()->paintOnScreen()) { + QRegion updateRegion(geometry()); + if (m_widget->testAttribute(Qt::WA_StaticContents)) + updateRegion -= QRect(0, 0, oldSize.width(), oldSize.height()); + m_widget->d_func()->syncBackingStore(updateRegion); + } else { + m_widget->d_func()->syncBackingStore(); + } } } diff --git a/src/widgets/kernel/qwidgetwindow_p.h b/src/widgets/kernel/qwidgetwindow_p.h index 7f12ae8e206..0632a5c3647 100644 --- a/src/widgets/kernel/qwidgetwindow_p.h +++ b/src/widgets/kernel/qwidgetwindow_p.h @@ -108,7 +108,9 @@ private slots: private: void repaintWindow(); - void updateGeometry(); + bool updateSize(); + bool updatePos(); + void updateMargins(); void updateNormalGeometry(); enum FocusWidgets { diff --git a/src/widgets/styles/qandroidstyle.cpp b/src/widgets/styles/qandroidstyle.cpp index 38c7497ffa6..5b4b346da92 100644 --- a/src/widgets/styles/qandroidstyle.cpp +++ b/src/widgets/styles/qandroidstyle.cpp @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -55,105 +54,33 @@ QT_BEGIN_NAMESPACE namespace { - const int textStyle_bold = 1; - const int textStyle_italic = 2; - - const int typeface_sans = 1; - const int typeface_serif = 2; - const int typeface_monospace = 3; - const quint32 NO_COLOR = 1; const quint32 TRANSPARENT_COLOR = 0; } -static int fontType(const QString &androidControl) -{ - if (androidControl == QLatin1String("textViewStyle")) - return QPlatformTheme::SystemFont; - else if (androidControl == QLatin1String("buttonStyle")) - return QPlatformTheme::PushButtonFont; - else if (androidControl == QLatin1String("checkboxStyle")) - return QPlatformTheme::CheckBoxFont; - else if (androidControl == QLatin1String("radioButtonStyle")) - return QPlatformTheme::RadioButtonFont; - else if (androidControl == QLatin1String("simple_list_item_single_choice")) - return QPlatformTheme::ItemViewFont; - else if (androidControl == QLatin1String("simple_spinner_dropdown_item")) - return QPlatformTheme::ComboMenuItemFont; - else if (androidControl == QLatin1String("spinnerStyle")) - return QPlatformTheme::ComboLineEditFont; - else if (androidControl == QLatin1String("simple_list_item")) - return QPlatformTheme::ListViewFont; - return -1; -} - -static int paletteType(const QString &androidControl) -{ - if (androidControl == QLatin1String("textViewStyle")) - return QPlatformTheme::SystemPalette; - else if (androidControl == QLatin1String("buttonStyle")) - return QPlatformTheme::ButtonPalette; - else if (androidControl == QLatin1String("checkboxStyle")) - return QPlatformTheme::CheckBoxPalette; - else if (androidControl == QLatin1String("radioButtonStyle")) - return QPlatformTheme::RadioButtonPalette; - else if (androidControl == QLatin1String("simple_list_item_single_choice")) - return QPlatformTheme::ItemViewPalette; - else if (androidControl == QLatin1String("editTextStyle")) - return QPlatformTheme::TextLineEditPalette; - else if (androidControl == QLatin1String("spinnerStyle")) - return QPlatformTheme::ComboBoxPalette; - return -1; -} - QAndroidStyle::QAndroidStyle() : QFusionStyle() { QPixmapCache::clear(); checkBoxControl = NULL; - QString stylePath(QLatin1String(qgetenv("MINISTRO_ANDROID_STYLE_PATH"))); - const QLatin1Char slashChar('/'); - if (!stylePath.isEmpty() && !stylePath.endsWith(slashChar)) - stylePath += slashChar; - - QString androidTheme = QLatin1String(qgetenv("QT_ANDROID_THEME")); - if (!androidTheme.isEmpty() && !androidTheme.endsWith(slashChar)) - androidTheme += slashChar; - - if (stylePath.isEmpty()) { - stylePath = QLatin1String("/data/data/org.kde.necessitas.ministro/files/dl/style/") - + QLatin1String(qgetenv("QT_ANDROID_THEME_DISPLAY_DPI")) + slashChar; - } - Q_ASSERT(!stylePath.isEmpty()); - - if (!androidTheme.isEmpty() && QFileInfo(stylePath + androidTheme + QLatin1String("style.json")).exists()) - stylePath += androidTheme; - - QFile f(stylePath + QLatin1String("style.json")); - if (!f.open(QIODevice::ReadOnly)) - return; - - QJsonParseError error; - QJsonDocument document = QJsonDocument::fromJson(f.readAll(), &error); - if (document.isNull()) { - qCritical() << error.errorString(); - return; - } - - if (!document.isObject()) { - qCritical() << "Style.json does not contain a valid style."; - return; - } - QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); + QPalette *standardPalette = reinterpret_cast(nativeInterface->nativeResourceForIntegration("AndroidStandardPalette")); + if (standardPalette) + m_standardPalette = *standardPalette; - QHash *palettes = reinterpret_cast *>(nativeInterface->nativeResourceForIntegration("AndroidStylePalettes")); - QHash *fonts = reinterpret_cast *>(nativeInterface->nativeResourceForIntegration("AndroidStyleFonts")); - palettes->clear(); - fonts->clear(); - QJsonObject object = document.object(); - for (QJsonObject::const_iterator objectIterator = object.constBegin(); - objectIterator != object.constEnd(); + QHash *qwidgetsFonts = reinterpret_cast *>(nativeInterface->nativeResourceForIntegration("AndroidQWidgetFonts")); + if (qwidgetsFonts) { + for (auto it = qwidgetsFonts->constBegin(); it != qwidgetsFonts->constEnd(); ++it) + QApplication::setFont(it.value(), it.key()); + qwidgetsFonts->clear(); // free the memory + } + + QJsonObject *object = reinterpret_cast(nativeInterface->nativeResourceForIntegration("AndroidStyleData")); + if (!object) + return; + + for (QJsonObject::const_iterator objectIterator = object->constBegin(); + objectIterator != object->constEnd(); ++objectIterator) { QString key = objectIterator.key(); QJsonValue value = objectIterator.value(); @@ -163,85 +90,6 @@ QAndroidStyle::QAndroidStyle() } QJsonObject item = value.toObject(); - QJsonObject::const_iterator attributeIterator = item.find(QLatin1String("qtClass")); - QString qtClassName; - if (attributeIterator != item.constEnd()) { - // The item has palette and font information for a specific Qt Class (e.g. QWidget, QPushButton, etc.) - qtClassName = attributeIterator.value().toString(); - } - const int ft = fontType(key); - if (ft > -1 || !qtClassName.isEmpty()) { - // Extract font information - QFont font; - - // Font size (in pixels) - attributeIterator = item.find(QLatin1String("TextAppearance_textSize")); - if (attributeIterator != item.constEnd()) - font.setPixelSize(int(attributeIterator.value().toDouble())); - - // Font style - attributeIterator = item.find(QLatin1String("TextAppearance_textStyle")); - if (attributeIterator != item.constEnd()) { - const int style = int(attributeIterator.value().toDouble()); - font.setBold(style & textStyle_bold); - font.setItalic(style & textStyle_italic); - } - - // Font typeface - attributeIterator = item.find(QLatin1String("TextAppearance_typeface")); - if (attributeIterator != item.constEnd()) { - QFont::StyleHint styleHint = QFont::AnyStyle; - switch (int(attributeIterator.value().toDouble())) { - case typeface_sans: - styleHint = QFont::SansSerif; - break; - case typeface_serif: - styleHint = QFont::Serif; - break; - case typeface_monospace: - styleHint = QFont::Monospace; - break; - } - font.setStyleHint(styleHint, QFont::PreferMatch); - } - if (!qtClassName.isEmpty()) - QApplication::setFont(font, qtClassName.toUtf8()); - if (ft > -1) - fonts->insert(ft, font); - // Extract font information - } - - const int pt = paletteType(key); - if (pt > -1 || !qtClassName.isEmpty()) { - // Extract palette information - QPalette palette; - attributeIterator = item.find(QLatin1String("defaultTextColorPrimary")); - if (attributeIterator != item.constEnd()) - palette.setColor(QPalette::WindowText, QRgb(int(attributeIterator.value().toDouble()))); - - attributeIterator = item.find(QLatin1String("defaultBackgroundColor")); - if (attributeIterator != item.constEnd()) - palette.setColor(QPalette::Background, QRgb(int(attributeIterator.value().toDouble()))); - - attributeIterator = item.find(QLatin1String("TextAppearance_textColor")); - if (attributeIterator != item.constEnd()) - setPaletteColor(attributeIterator.value().toObject().toVariantMap(), palette, QPalette::WindowText); - - attributeIterator = item.find(QLatin1String("TextAppearance_textColorLink")); - if (attributeIterator != item.constEnd()) - setPaletteColor(attributeIterator.value().toObject().toVariantMap(), palette, QPalette::Link); - - attributeIterator = item.find(QLatin1String("TextAppearance_textColorHighlight")); - if (attributeIterator != item.constEnd()) - palette.setColor(QPalette::Highlight, QRgb(int(attributeIterator.value().toDouble()))); - - if (QLatin1String("QWidget") == qtClassName) - m_standardPalette = palette; - - if (pt > -1) - palettes->insert(pt, palette); - // Extract palette information - } QAndroidStyle::ItemType itemType = qtControl(key); if (QC_UnknownType == itemType) continue; @@ -277,6 +125,7 @@ QAndroidStyle::QAndroidStyle() break; } } + *object = QJsonObject(); // free memory } QAndroidStyle::~QAndroidStyle() @@ -284,81 +133,6 @@ QAndroidStyle::~QAndroidStyle() qDeleteAll(m_androidControlsHash); } - -void QAndroidStyle::setPaletteColor(const QVariantMap &object, - QPalette &palette, - QPalette::ColorRole role) -{ - // QPalette::Active -> ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET - palette.setColor(QPalette::Active, - role, - QRgb(object.value(QLatin1String("ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET")).toInt())); - - // QPalette::Inactive -> ENABLED_STATE_SET - palette.setColor(QPalette::Inactive, - role, - QRgb(object.value(QLatin1String("ENABLED_STATE_SET")).toInt())); - - // QPalette::Disabled -> EMPTY_STATE_SET - palette.setColor(QPalette::Disabled, - role, - QRgb(object.value(QLatin1String("EMPTY_STATE_SET")).toInt())); - - palette.setColor(QPalette::Current, role, palette.color(QPalette::Active, role)); - - if (role == QPalette::WindowText) { - // QPalette::BrightText -> PRESSED - // QPalette::Active -> PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET - palette.setColor(QPalette::Active, - QPalette::BrightText, - QRgb(object.value(QLatin1String("PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET")).toInt())); - - // QPalette::Inactive -> PRESSED_ENABLED_STATE_SET - palette.setColor(QPalette::Inactive, - QPalette::BrightText, - QRgb(object.value(QLatin1String("PRESSED_ENABLED_STATE_SET")).toInt())); - - // QPalette::Disabled -> PRESSED_STATE_SET - palette.setColor(QPalette::Disabled, - QPalette::BrightText, - QRgb(object.value(QLatin1String("PRESSED_STATE_SET")).toInt())); - - palette.setColor(QPalette::Current, QPalette::BrightText, palette.color(QPalette::Active, QPalette::BrightText)); - - // QPalette::HighlightedText -> SELECTED - // QPalette::Active -> ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET - palette.setColor(QPalette::Active, - QPalette::HighlightedText, - QRgb(object.value(QLatin1String("ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET")).toInt())); - - // QPalette::Inactive -> ENABLED_SELECTED_STATE_SET - palette.setColor(QPalette::Inactive, - QPalette::HighlightedText, - QRgb(object.value(QLatin1String("ENABLED_SELECTED_STATE_SET")).toInt())); - - // QPalette::Disabled -> SELECTED_STATE_SET - palette.setColor(QPalette::Disabled, - QPalette::HighlightedText, - QRgb(object.value(QLatin1String("SELECTED_STATE_SET")).toInt())); - - palette.setColor(QPalette::Current, - QPalette::HighlightedText, - palette.color(QPalette::Active, QPalette::HighlightedText)); - - // Same colors for Text - palette.setColor(QPalette::Active, QPalette::Text, palette.color(QPalette::Active, role)); - palette.setColor(QPalette::Inactive, QPalette::Text, palette.color(QPalette::Inactive, role)); - palette.setColor(QPalette::Disabled, QPalette::Text, palette.color(QPalette::Disabled, role)); - palette.setColor(QPalette::Current, QPalette::Text, palette.color(QPalette::Current, role)); - - // And for ButtonText - palette.setColor(QPalette::Active, QPalette::ButtonText, palette.color(QPalette::Active, role)); - palette.setColor(QPalette::Inactive, QPalette::ButtonText, palette.color(QPalette::Inactive, role)); - palette.setColor(QPalette::Disabled, QPalette::ButtonText, palette.color(QPalette::Disabled, role)); - palette.setColor(QPalette::Current, QPalette::ButtonText, palette.color(QPalette::Current, role)); - } -} - QAndroidStyle::ItemType QAndroidStyle::qtControl(const QString &android) { if (android == QLatin1String("buttonStyle")) @@ -470,6 +244,10 @@ QAndroidStyle::ItemType QAndroidStyle::qtControl(QStyle::PrimitiveElement primit case QStyle::PE_FrameLineEdit: return QC_EditText; + case QStyle::PE_IndicatorViewItemCheck: + case QStyle::PE_IndicatorCheckBox: + return QC_Checkbox; + case QStyle::PE_FrameWindow: case QStyle::PE_Widget: case QStyle::PE_Frame: @@ -583,37 +361,8 @@ void QAndroidStyle::drawControl(QStyle::ControlElement element, } break; default: - break; - } - } else if (element == CE_ItemViewItem) { - const QStyleOptionViewItem *vopt = qstyleoption_cast(opt); - if (vopt && vopt->features & QStyleOptionViewItem::HasCheckIndicator) { - p->save(); - p->setClipRect(opt->rect); - - QRect checkRect = proxy()->subElementRect(SE_ItemViewItemCheckIndicator, vopt, w); - - // draw the background - proxy()->drawPrimitive(PE_PanelItemViewItem, opt, p, w); - - // draw the check mark - QStyleOptionViewItem option(*vopt); - option.rect = checkRect; - option.state = option.state & ~QStyle::State_HasFocus; - - switch (vopt->checkState) { - case Qt::Unchecked: - option.state |= QStyle::State_Off; - break; - default: - option.state |= QStyle::State_On; - break; - } - QPixmap pixmap = checkBoxControl->imgCheckBox(&option); - p->drawPixmap(checkRect, pixmap); - p->restore(); - } else { QFusionStyle::drawControl(element, opt, p, w); + break; } } else { QFusionStyle::drawControl(element, opt, p, w); @@ -758,7 +507,7 @@ QRect QAndroidStyle::subControlRect(ComplexControl cc, case CC_GroupBox: { if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast(opt)) { QSize textSize = opt->fontMetrics.boundingRect(groupBox->text).size() + QSize(2, 2); - QSize checkBoxSize = checkBoxControl->sizeCheckBox(opt); + QSize checkBoxSize = checkBoxControl->size(opt); int indicatorWidth = checkBoxSize.width(); int indicatorHeight = checkBoxSize.height(); QRect checkBoxRect; @@ -815,9 +564,9 @@ int QAndroidStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, case PM_ScrollBarExtent: return 0; case PM_IndicatorWidth: - return checkBoxControl->sizeCheckBox(option).width(); + return checkBoxControl->size(option).width(); case PM_IndicatorHeight: - return checkBoxControl->sizeCheckBox(option).height(); + return checkBoxControl->size(option).height(); default: return QFusionStyle::pixelMetric(metric, option, widget); } @@ -834,7 +583,7 @@ QSize QAndroidStyle::sizeFromContents(ContentsType ct, if (const QStyleOptionHeader *hdr = qstyleoption_cast(opt)) { bool nullIcon = hdr->icon.isNull(); int margin = pixelMetric(QStyle::PM_HeaderMargin, hdr, w); - int iconSize = nullIcon ? 0 : checkBoxControl->sizeCheckBox(opt).width(); + int iconSize = nullIcon ? 0 : checkBoxControl->size(opt).width(); QSize txt; /* * These next 4 lines are a bad hack to fix a bug in case a QStyleSheet is applied at QApplication level. @@ -868,7 +617,7 @@ QSize QAndroidStyle::sizeFromContents(ContentsType ct, if (ct == CT_GroupBox) { if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast(opt)) { QSize textSize = opt->fontMetrics.boundingRect(groupBox->text).size() + QSize(2, 2); - QSize checkBoxSize = checkBoxControl->sizeCheckBox(opt); + QSize checkBoxSize = checkBoxControl->size(opt); int indicatorWidth = checkBoxSize.width(); int indicatorHeight = checkBoxSize.height(); QRect checkBoxRect; @@ -964,13 +713,6 @@ QSize QAndroidStyle::AndroidDrawable::size() const return QSize(); } -QPixmap QAndroidStyle::AndroidDrawable::img() const -{ - if (type() == Image || type() == NinePatch) - return static_cast(this)->img(); - - return QPixmap(); -} QAndroidStyle::AndroidDrawable * QAndroidStyle::AndroidDrawable::fromMap(const QVariantMap &drawable, ItemType itemType) @@ -1036,19 +778,7 @@ void QAndroidStyle::AndroidImageDrawable::draw(QPainter *painter, const QStyleOp QPixmapCache::insert(m_hashKey, pm); } - painter->drawPixmap(opt->rect.x(), (opt->rect.height() - pm.height()) / 2, pm); -} -QPixmap QAndroidStyle::AndroidImageDrawable::img() const -{ - if (m_hashKey.isEmpty()) - m_hashKey = QFileInfo(m_filePath).fileName(); - - QPixmap pm; - if (!QPixmapCache::find(m_hashKey, &pm)) { - pm.load(m_filePath); - QPixmapCache::insert(m_hashKey, pm); - } - return pm; + painter->drawPixmap(opt->rect.x(), opt->rect.y() + (opt->rect.height() - pm.height()) / 2, pm); } QSize QAndroidStyle::AndroidImageDrawable::size() const @@ -1446,14 +1176,6 @@ QSize QAndroidStyle::AndroidStateDrawable::sizeImage(const QStyleOption *opt) co s = drawable->size(); return s; } -QPixmap QAndroidStyle::AndroidStateDrawable::img(const QStyleOption *opt) const -{ - QPixmap pm; - const AndroidDrawable *drawable = bestAndroidStateMatch(opt); - if (drawable) - pm = drawable->img(); - return pm; -} const QAndroidStyle::AndroidDrawable * QAndroidStyle::AndroidStateDrawable::bestAndroidStateMatch(const QStyleOption *opt) const { @@ -1733,7 +1455,6 @@ QRect QAndroidStyle::AndroidControl::subElementRect(QStyle::SubElement /* subEle return visualRect(option->direction, option->rect, r); } return option->rect; - } QRect QAndroidStyle::AndroidControl::subControlRect(const QStyleOptionComplex *option, @@ -1778,6 +1499,16 @@ QMargins QAndroidStyle::AndroidControl::padding() return QMargins(); } +QSize QAndroidStyle::AndroidControl::size(const QStyleOption *option) +{ + if (const AndroidDrawable *drawable = backgroundDrawable()) { + if (drawable->type() == State) + drawable = static_cast(backgroundDrawable())->bestAndroidStateMatch(option); + return drawable->size(); + } + return QSize(); +} + const QAndroidStyle::AndroidDrawable *QAndroidStyle::AndroidControl::backgroundDrawable() const { return m_background; @@ -1788,11 +1519,12 @@ QAndroidStyle::AndroidCompoundButtonControl::AndroidCompoundButtonControl(const : AndroidControl(control, itemType) { QVariantMap::const_iterator it = control.find(QLatin1String("CompoundButton_button")); - if (it != control.end()) + if (it != control.end()) { m_button = AndroidDrawable::fromMap(it.value().toMap(), itemType); - else + const_cast(m_button)->setPaddingLeftToSizeWidth(); + } else { m_button = 0; - const_cast(m_button)->setPaddingLeftToSizeWidth(); + } } QAndroidStyle::AndroidCompoundButtonControl::~AndroidCompoundButtonControl() @@ -1808,16 +1540,24 @@ void QAndroidStyle::AndroidCompoundButtonControl::drawControl(const QStyleOption if (m_button) m_button->draw(p, opt); } -QSize QAndroidStyle::AndroidCompoundButtonControl::sizeCheckBox(const QStyleOption *opt) const + +QMargins QAndroidStyle::AndroidCompoundButtonControl::padding() { - const AndroidDrawable *drawable = m_button; - return static_cast(drawable)->sizeImage(opt); + if (m_button) + return m_button->padding(); + return AndroidControl::padding(); } -QPixmap QAndroidStyle::AndroidCompoundButtonControl::imgCheckBox(const QStyleOption *opt) const + +QSize QAndroidStyle::AndroidCompoundButtonControl::size(const QStyleOption *option) { - const AndroidDrawable *drawable = m_button; - return static_cast(drawable)->img(opt); + if (m_button) { + if (m_button->type() == State) + return static_cast(m_button)->bestAndroidStateMatch(option)->size(); + return m_button->size(); + } + return AndroidControl::size(option); } + const QAndroidStyle::AndroidDrawable * QAndroidStyle::AndroidCompoundButtonControl::backgroundDrawable() const { return m_background ? m_background : m_button; @@ -1908,7 +1648,6 @@ QRect QAndroidStyle::AndroidProgressBarControl::subElementRect(QStyle::SubElemen p |= QRect(padding.left(), padding.top(), padding.right() - padding.left(), padding.bottom() - padding.top()); padding = m_progressDrawable->padding(); p |= QRect(padding.left(), padding.top(), padding.right() - padding.left(), padding.bottom() - padding.top()); - QRect r = option->rect.adjusted(p.left(), p.top(), -p.right(), -p.bottom()); if (horizontal) { @@ -1991,15 +1730,15 @@ void QAndroidStyle::AndroidSeekBarControl::drawControl(const QStyleOption *optio if (drawable->type() == State) drawable = static_cast(m_seekBarThumb)->bestAndroidStateMatch(option); QStyleOption copy(*option); - copy.rect.setY((copy.rect.height() - m_minSize.height()) / 2); - copy.rect.setHeight(m_minSize.height()); + copy.rect.setHeight(m_progressDrawable->size().height()); copy.rect.setWidth(copy.rect.width() - drawable->size().width()); - copy.rect.translate(drawable->size().width() / 2, 0); + const int yTranslate = abs(drawable->size().height() - copy.rect.height()) / 2; + copy.rect.translate(drawable->size().width() / 2, yTranslate); m_progressDrawable->draw(p, ©); if (styleOption->orientation == Qt::Vertical) qCritical() << "Vertical slider are not supported"; - int pos = copy.rect.width()*factor - drawable->size().width() / 2; - copy.rect.translate(pos, 0); + int pos = copy.rect.width() * factor - drawable->size().width() / 2; + copy.rect.translate(pos, -yTranslate); copy.rect.setSize(drawable->size()); m_seekBarThumb->draw(p, ©); } diff --git a/src/widgets/styles/qandroidstyle_p.h b/src/widgets/styles/qandroidstyle_p.h index 65fa4cd0969..d8e77683807 100644 --- a/src/widgets/styles/qandroidstyle_p.h +++ b/src/widgets/styles/qandroidstyle_p.h @@ -124,7 +124,6 @@ public: static AndroidDrawable *fromMap(const QVariantMap &drawable, ItemType itemType); static QMargins extractMargins(const QVariantMap &value); virtual void setPaddingLeftToSizeWidth(); - QPixmap img() const; protected: ItemType m_itemType; QMargins m_padding; @@ -149,7 +148,6 @@ public: virtual void draw(QPainter *painter,const QStyleOption *opt) const; virtual QSize size() const; - QPixmap img() const; protected: QString m_filePath; mutable QString m_hashKey; @@ -223,7 +221,6 @@ public: static int extractState(const QVariantMap &value); virtual void setPaddingLeftToSizeWidth(); QSize sizeImage(const QStyleOption *opt) const; - QPixmap img(const QStyleOption *opt) const; private: typedef QPair StateType; QList m_states; @@ -263,6 +260,7 @@ public: const QSize &contentsSize, const QWidget *w) const; virtual QMargins padding(); + virtual QSize size(const QStyleOption *option); protected: virtual const AndroidDrawable * backgroundDrawable() const; const AndroidDrawable *m_background; @@ -276,8 +274,8 @@ public: AndroidCompoundButtonControl(const QVariantMap &control, ItemType itemType); virtual ~AndroidCompoundButtonControl(); virtual void drawControl(const QStyleOption *opt, QPainter *p, const QWidget *w); - QSize sizeCheckBox(const QStyleOption *opt) const; - QPixmap imgCheckBox(const QStyleOption *opt) const; + virtual QMargins padding(); + virtual QSize size(const QStyleOption *option); protected: virtual const AndroidDrawable * backgroundDrawable() const; const AndroidDrawable *m_button; @@ -376,9 +374,6 @@ private: static ItemType qtControl(QStyle::SubElement subElement); static ItemType qtControl(const QString &android); - static void setPaletteColor(const QVariantMap &object, - QPalette &palette, - QPalette::ColorRole role); private: typedef QHash AndroidControlsHash; AndroidControlsHash m_androidControlsHash; diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index 815b10c9214..7e9a631c5e0 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -1114,7 +1114,7 @@ void QCommonStylePrivate::tabLayout(const QStyleOptionTabV3 *opt, const QWidget (opt->state & QStyle::State_Enabled) ? QIcon::Normal : QIcon::Disabled, (opt->state & QStyle::State_Selected) ? QIcon::On : QIcon::Off ); // High-dpi icons do not need adjustmet; make sure tabIconSize is not larger than iconSize - tabIconSize = QSize(qMin(tabIconSize.width(), iconSize.width()), qMin(tabIconSize.height(), iconSize.width())); + tabIconSize = QSize(qMin(tabIconSize.width(), iconSize.width()), qMin(tabIconSize.height(), iconSize.height())); *iconRect = QRect(tr.left(), tr.center().y() - tabIconSize.height() / 2, tabIconSize.width(), tabIconSize .height()); diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index ef3795c9a11..817f16b297d 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -553,7 +553,9 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor); } else if (header->sortIndicator & QStyleOptionHeader::SortDown) { arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, 180); - } if (!arrow.isNull()) { + } + + if (!arrow.isNull()) { r.setSize(QSize(arrow.width()/2, arrow.height()/2)); r.moveCenter(header->rect.center()); painter->drawPixmap(r.translated(offset), arrow); diff --git a/src/widgets/styles/qgtkstyle_p.cpp b/src/widgets/styles/qgtkstyle_p.cpp index 06ee74bdfee..61d1cd796ea 100644 --- a/src/widgets/styles/qgtkstyle_p.cpp +++ b/src/widgets/styles/qgtkstyle_p.cpp @@ -701,10 +701,12 @@ GtkWidget* QGtkStylePrivate::getTextColorWidget() const void QGtkStylePrivate::setupGtkWidget(GtkWidget* widget) { if (Q_GTK_IS_WIDGET(widget)) { - static GtkWidget* protoLayout = 0; + GtkWidget *protoLayout = gtkWidgetMap()->value("GtkContainer"); if (!protoLayout) { protoLayout = QGtkStylePrivate::gtk_fixed_new(); QGtkStylePrivate::gtk_container_add((GtkContainer*)(gtkWidgetMap()->value("GtkWindow")), protoLayout); + QHashableLatin1Literal widgetPath = QHashableLatin1Literal::fromData(strdup("GtkContainer")); + gtkWidgetMap()->insert(widgetPath, protoLayout); } Q_ASSERT(protoLayout); diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index fb0bafa66db..328378cb8ed 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -296,14 +296,12 @@ void drawTabShape(QPainter *p, const QStyleOptionTabV3 *tabOpt, bool isUnified) p->fillRect(rect, QColor(Qt::transparent)); p->restore(); } else if (active) { - int d = (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) ? 16 : 0; - p->fillRect(rect, QColor(151 + d, 151 + d, 151 + d)); + p->fillRect(rect, QColor(167, 167, 167)); } else { - int d = (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) ? 9 : 0; QLinearGradient gradient(rect.topLeft(), rect.bottomLeft()); - gradient.setColorAt(0, QColor(207 + d, 207 + d, 207 + d)); - gradient.setColorAt(0.5, QColor(206 + d, 206 + d, 206 + d)); - gradient.setColorAt(1, QColor(201 + d, 201 + d, 201 + d)); + gradient.setColorAt(0, QColor(216, 216, 216)); + gradient.setColorAt(0.5, QColor(215, 215, 215)); + gradient.setColorAt(1, QColor(210, 210, 210)); p->fillRect(rect, gradient); } @@ -881,13 +879,6 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg gbi.size = sz == QAquaSizeSmall ? kHIThemeGrowBoxSizeSmall : kHIThemeGrowBoxSizeNormal; if (HIThemeGetGrowBoxBounds(&p, &gbi, &r) == noErr) { int width = 0; - // Snow Leopard and older get a size grip, as well as QMdiSubWindows. - if (QSysInfo::MacintoshVersion <= QSysInfo::MV_10_6 -#ifndef QT_NO_MDIAREA - || (widg && widg->parentWidget() && qobject_cast(widg->parentWidget())) -#endif - ) - width = r.size.width; ret = QSize(width, r.size.height); } } @@ -1830,7 +1821,7 @@ static QCocoaWidget cocoaWidgetFromHIThemeButtonKind(ThemeButtonKind kind) return w; } -NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget, QPoint *offset) const +NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget) const { NSView *bv = cocoaControls[widget]; if (!bv) { @@ -1903,37 +1894,39 @@ NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget, QPoint *offset) cons const_cast(this)->cocoaControls.insert(widget, bv); } - if (offset) { - if (widget == QCocoaWidget(QCocoaRadioButton, QAquaSizeLarge)) - offset->setY(2); - else if (widget == QCocoaWidget(QCocoaRadioButton, QAquaSizeSmall)) - *offset = QPoint(-1, 2); - else if (widget == QCocoaWidget(QCocoaRadioButton, QAquaSizeMini)) - offset->setY(2); - else if (widget == QCocoaWidget(QCocoaPopupButton, QAquaSizeSmall) - || widget == QCocoaWidget(QCocoaCheckBox, QAquaSizeLarge)) - offset->setY(1); - else if (widget == QCocoaWidget(QCocoaCheckBox, QAquaSizeSmall)) - offset->setX(-1); - else if (widget == QCocoaWidget(QCocoaCheckBox, QAquaSizeMini)) - *offset = QPoint(7, 5); - else if (widget == QCocoaWidget(QCocoaPopupButton, QAquaSizeMini)) - *offset = QPoint(2, -1); - else if (widget == QCocoaWidget(QCocoaPullDownButton, QAquaSizeLarge)) - *offset = QPoint(3, -1); - else if (widget == QCocoaWidget(QCocoaPullDownButton, QAquaSizeSmall)) - *offset = QPoint(2, 1); - else if (widget == QCocoaWidget(QCocoaPullDownButton, QAquaSizeMini)) - *offset = QPoint(5, 0); - } - return bv; } -void QMacStylePrivate::drawNSViewInRect(NSView *view, const QRect &qtRect, QPainter *p, QCocoaDrawRectBlock drawRectBlock) const +void QMacStylePrivate::drawNSViewInRect(QCocoaWidget widget, NSView *view, const QRect &qtRect, QPainter *p, bool isQWidget, QCocoaDrawRectBlock drawRectBlock) const { + QPoint offset; + if (widget == QCocoaWidget(QCocoaRadioButton, QAquaSizeLarge)) + offset.setY(2); + else if (widget == QCocoaWidget(QCocoaRadioButton, QAquaSizeSmall)) + offset = QPoint(-1, 2); + else if (widget == QCocoaWidget(QCocoaRadioButton, QAquaSizeMini)) + offset.setY(2); + else if (widget == QCocoaWidget(QCocoaPopupButton, QAquaSizeSmall) + || widget == QCocoaWidget(QCocoaCheckBox, QAquaSizeLarge)) + offset.setY(1); + else if (widget == QCocoaWidget(QCocoaCheckBox, QAquaSizeSmall)) + offset.setX(-1); + else if (widget == QCocoaWidget(QCocoaCheckBox, QAquaSizeMini)) + offset = QPoint(7, 5); + else if (widget == QCocoaWidget(QCocoaPopupButton, QAquaSizeMini)) + offset = QPoint(2, -1); + else if (widget == QCocoaWidget(QCocoaPullDownButton, QAquaSizeLarge)) + offset = isQWidget ? QPoint(3, -1) : QPoint(-1, -3); + else if (widget == QCocoaWidget(QCocoaPullDownButton, QAquaSizeSmall)) + offset = QPoint(2, 1); + else if (widget == QCocoaWidget(QCocoaPullDownButton, QAquaSizeMini)) + offset = QPoint(5, 0); + else if (widget == QCocoaWidget(QCocoaComboBox, QAquaSizeLarge)) + offset = QPoint(3, 0); + QMacCGContext ctx(p); CGContextSaveGState(ctx); + CGContextTranslateCTM(ctx, offset.x(), offset.y()); [NSGraphicsContext saveGraphicsState]; [NSGraphicsContext setCurrentContext:[NSGraphicsContext @@ -2046,8 +2039,8 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD } pm = QPixmap::fromImage(image); } else if ((usingYosemiteOrLater && combo && !editableCombo) || button) { - QPoint offset; - NSButton *bc = (NSButton *)cocoaControl(cocoaWidgetFromHIThemeButtonKind(bdi->kind), &offset); + QCocoaWidget cw = cocoaWidgetFromHIThemeButtonKind(bdi->kind); + NSButton *bc = (NSButton *)cocoaControl(cw); [bc highlight:pressed]; bc.enabled = bdi->state != kThemeStateUnavailable && bdi->state != kThemeStateUnavailableInactive; bc.allowsMixedState = YES; @@ -2057,9 +2050,7 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD QRect rect = opt->rect; if (bdi->kind == kThemePopupButtonMini) rect.adjust(0, 0, -5, 0); - p->translate(offset); - drawNSViewInRect(bc, rect, p); - p->translate(-offset); + drawNSViewInRect(cw, bc, rect, p); return; } else if (usingYosemiteOrLater && editableCombo) { QImage image = activePixmap.toImage(); @@ -2131,34 +2122,26 @@ QMacStyle::QMacStyle() : QCommonStyle(*new QMacStylePrivate) { Q_D(QMacStyle); -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) { - d->receiver = [[NotificationReceiver alloc] initWithPrivate:d]; - NotificationReceiver *receiver = static_cast(d->receiver); + d->receiver = [[NotificationReceiver alloc] initWithPrivate:d]; + NotificationReceiver *receiver = static_cast(d->receiver); - [[NSNotificationCenter defaultCenter] addObserver:receiver - selector:@selector(scrollBarStyleDidChange:) - name:NSPreferredScrollerStyleDidChangeNotification - object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:receiver + selector:@selector(scrollBarStyleDidChange:) + name:NSPreferredScrollerStyleDidChangeNotification + object:nil]; - d->nsscroller = [[NSScroller alloc] init]; - } -#endif + d->nsscroller = [[NSScroller alloc] init]; d->indicatorBranchButtonCell = nil; } QMacStyle::~QMacStyle() { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 Q_D(QMacStyle); - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) { - [reinterpret_cast(d->nsscroller) release]; + [reinterpret_cast(d->nsscroller) release]; - NotificationReceiver *receiver = static_cast(d->receiver); - [[NSNotificationCenter defaultCenter] removeObserver:receiver]; - [receiver release]; - } -#endif + NotificationReceiver *receiver = static_cast(d->receiver); + [[NSNotificationCenter defaultCenter] removeObserver:receiver]; + [receiver release]; delete qt_mac_backgroundPattern; qt_mac_backgroundPattern = 0; @@ -2256,7 +2239,7 @@ void QMacStyle::polish(QWidget* w) } if (qobject_cast(w) || qobject_cast(w)) { - w->setWindowOpacity(QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5 ? 0.985 : 0.94); + w->setWindowOpacity(0.985); if (!w->testAttribute(Qt::WA_SetPalette)) { QPixmap px(64, 64); px.fill(Qt::white); @@ -2541,9 +2524,7 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW } break; case PM_ScrollBarExtent: { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7 && - [NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay) { + if ([NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay) { switch (d->aquaSizeConstrain(opt, widget)) { case QAquaSizeUnknown: case QAquaSizeLarge: @@ -2556,7 +2537,6 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW } break; } -#endif switch (d->aquaSizeConstrain(opt, widget)) { case QAquaSizeUnknown: case QAquaSizeLarge: @@ -2747,13 +2727,8 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW ret = 1; break; case PM_ScrollView_ScrollBarOverlap: -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - ret = (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7 && - [NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay) ? + ret = [NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay ? pixelMetric(PM_ScrollBarExtent, opt, widget) : 0; -#else - ret = 0; -#endif break; default: ret = QCommonStyle::pixelMetric(metric, opt, widget); @@ -3083,11 +3058,7 @@ int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w || (opt && QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ScrollBar)) #endif ) { - ret = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - if (ret) - ret = [NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay; -#endif + ret = [NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay; } break; default: @@ -3795,9 +3766,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter alignment |= Qt::TextHideMnemonic; if (down) cr.translate(shiftX, shiftY); - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5 - && (tbstyle == Qt::ToolButtonTextOnly - || (tbstyle != Qt::ToolButtonTextOnly && !down))) { + if (tbstyle == Qt::ToolButtonTextOnly + || (tbstyle != Qt::ToolButtonTextOnly && !down)) { QPen pen = p->pen(); QColor light = down ? Qt::black : Qt::white; light.setAlphaF(0.375f); @@ -3812,12 +3782,6 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter } proxy()->drawItemText(p, cr, alignment, pal, tb->state & State_Enabled, tb->text, role); - if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_5 && - (tb->state & State_Sunken)) { - // Draw a "drop shadow" in earlier versions. - proxy()->drawItemText(p, cr.adjusted(0, 1, 0, 1), alignment, - tb->palette, tb->state & State_Enabled, tb->text); - } } } else { QCommonStyle::drawControl(ce, &myTb, p, w); @@ -3938,17 +3902,15 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter } if (hasMenu && yosemiteOrLater && bdi.kind != kThemeBevelButton) { - QCocoaWidget w = cocoaWidgetFromHIThemeButtonKind(bdi.kind); - QPoint offset; - NSPopUpButton *pdb = (NSPopUpButton *)d->cocoaControl(QCocoaWidget(QCocoaPullDownButton, w.second), &offset); + QCocoaWidget cw = cocoaWidgetFromHIThemeButtonKind(bdi.kind); + cw.first = QCocoaPullDownButton; + NSPopUpButton *pdb = (NSPopUpButton *)d->cocoaControl(cw); [pdb highlight:(bdi.state == kThemeStatePressed)]; pdb.enabled = bdi.state != kThemeStateUnavailable && bdi.state != kThemeStateUnavailableInactive; QRect rect = opt->rect; - rect.adjust(0, 0, w.second == QAquaSizeSmall ? -4 : w.second == QAquaSizeMini ? -9 : -6, 0); - p->translate(offset); - d->drawNSViewInRect(pdb, rect, p); - p->translate(-offset); - } else if (hasMenu && bdi.state == kThemeStatePressed && QSysInfo::macVersion() > QSysInfo::MV_10_6) + rect.adjust(0, 0, cw.second == QAquaSizeSmall ? -4 : cw.second == QAquaSizeMini ? -9 : -6, 0); + d->drawNSViewInRect(cw, pdb, rect, p, w != 0); + } else if (hasMenu && bdi.state == kThemeStatePressed) d->drawColorlessButton(newRect, &bdi, p, opt); else HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0); @@ -3987,16 +3949,10 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter if (hasMenu && (!yosemiteOrLater || bdi.kind == kThemeBevelButton)) { int mbi = proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w); QRect ir = btn->rect; - int arrowXOffset = 0; - if (QSysInfo::macVersion() > QSysInfo::MV_10_6) - arrowXOffset = bdi.kind == kThemePushButton ? 6 : + int arrowXOffset = bdi.kind == kThemePushButton ? 6 : bdi.kind == kThemePushButtonSmall ? 7 : 8; - int arrowYOffset; - if (QSysInfo::macVersion() > QSysInfo::MV_10_6) - arrowYOffset = bdi.kind == kThemePushButton ? 3 : + int arrowYOffset = bdi.kind == kThemePushButton ? 3 : bdi.kind == kThemePushButtonSmall ? 1 : 2; - else - arrowYOffset = bdi.kind == kThemePushButton ? 4 : 2; if (!w) { // adjustment for Qt Quick Controls arrowYOffset -= ir.top(); @@ -4012,17 +3968,10 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter pdi.version = qt_mac_hitheme_version; pdi.state = tds == kThemeStateInactive ? kThemeStateActive : tds; pdi.orientation = kThemeArrowDown; - if (QSysInfo::macVersion() > QSysInfo::MV_10_6) { - if (bdi.kind == kThemePushButtonMini) - pdi.size = kThemeArrow5pt; - else if (bdi.kind == kThemePushButton || bdi.kind == kThemePushButtonSmall) - pdi.size = kThemeArrow7pt; - } else { - if (arrowRect.size.width < 8.) - pdi.size = kThemeArrow5pt; - else - pdi.size = kThemeArrow9pt; - } + if (bdi.kind == kThemePushButtonMini) + pdi.size = kThemeArrow5pt; + else if (bdi.kind == kThemePushButton || bdi.kind == kThemePushButtonSmall) + pdi.size = kThemeArrow7pt; HIThemeDrawPopupArrow(&arrowRect, &pdi, cg, kHIThemeOrientationNormal); } } @@ -4101,10 +4050,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter QRect textRect = itemTextRect( btn.fontMetrics, freeContentRect, Qt::AlignCenter, btn.state & State_Enabled, btn.text); if (hasMenu) { - if (QSysInfo::macVersion() > QSysInfo::MV_10_6) - textRect.moveTo(w ? 15 : 11, textRect.top()); // Supports Qt Quick Controls - else - textRect.adjust(-1, 0, -1, 0); + textRect.moveTo(w ? 15 : 11, textRect.top()); // Supports Qt Quick Controls } // Draw the icon: if (hasIcon) { @@ -4145,9 +4091,10 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter if (const QStyleOptionComboBox *cb = qstyleoption_cast(opt)) { QStyleOptionComboBox comboCopy = *cb; comboCopy.direction = Qt::LeftToRight; - if ((opt->state & QStyle::State_Small) && QSysInfo::macVersion() > QSysInfo::MV_10_6) - comboCopy.rect.translate(0, w ? (QSysInfo::macVersion() > QSysInfo::MV_10_8 ? 0 : -1) : -2); // Supports Qt Quick Controls - else if (QSysInfo::macVersion() > QSysInfo::MV_10_8) + if (opt->state & QStyle::State_Small) + comboCopy.rect.translate(0, w ? (QSysInfo::macVersion() > QSysInfo::MV_10_8 ? 0 : -1) : + (QSysInfo::macVersion() > QSysInfo::MV_10_9 ? 0 : -2)); // Supports Qt Quick Controls + else if (QSysInfo::macVersion() == QSysInfo::MV_10_9) comboCopy.rect.translate(0, 1); QCommonStyle::drawControl(CE_ComboBoxLabel, &comboCopy, p, w); } @@ -4284,10 +4231,9 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter ThemeTabDirection ttd = getTabDirection(myTab.shape); bool verticalTabs = ttd == kThemeTabWest || ttd == kThemeTabEast; bool selected = (myTab.state & QStyle::State_Selected); - bool usingLionOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_6; bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9; - if (usingLionOrLater && selected && !myTab.documentMode + if (selected && !myTab.documentMode && (!usingYosemiteOrLater || myTab.state & State_Active)) myTab.palette.setColor(QPalette::WindowText, Qt::white); @@ -4296,7 +4242,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter // outside world, unless they read the source, in which case, it's // their own fault). bool nonDefaultFont = p->font() != qt_app_fonts_hash()->value("QComboMenuItem"); - bool isSelectedAndNeedsShadow = selected && usingLionOrLater && !usingYosemiteOrLater; + bool isSelectedAndNeedsShadow = selected && !usingYosemiteOrLater; if (isSelectedAndNeedsShadow || verticalTabs || nonDefaultFont || !tab->icon.isNull() || !myTab.leftButtonSize.isEmpty() || !myTab.rightButtonSize.isEmpty()) { int heightOffset = 0; @@ -4768,14 +4714,6 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter case CE_ProgressBarGroove: break; case CE_SizeGrip: { - // We do not draw size grips on versions > 10.6 unless it's a QMdiSubWindow - if (QSysInfo::MacintoshVersion > QSysInfo::MV_10_6 -#ifndef QT_NO_MDIAREA - && !(w && w->parentWidget() && qobject_cast(w->parentWidget())) -#endif - ) - break; - if (w && w->testAttribute(Qt::WA_MacOpaqueSizeGrip)) { HIThemeGrowBoxDrawInfo gdi; gdi.version = qt_mac_hitheme_version; @@ -5444,7 +5382,6 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9; const bool isHorizontal = slider->orientation == Qt::Horizontal; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 if (cc == CC_ScrollBar && proxy()->styleHint(SH_ScrollBar_Transient, opt, widget)) { bool wasActive = false; CGFloat opacity = 0.0; @@ -5607,9 +5544,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex [NSGraphicsContext restoreGraphicsState]; CGContextRestoreGState(cg); - } else -#endif - { + } else { d->stopAnimation(opt->styleObject); if (usingYosemiteOrLater && cc == CC_Slider) { @@ -5641,12 +5576,13 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex // Yosemite demands its blue progress track when no tickmarks are present if (!(slider->subControls & SC_SliderTickmarks)) { QCocoaWidgetKind sliderKind = slider->orientation == Qt::Horizontal ? QCocoaHorizontalSlider : QCocoaVerticalSlider; - NSSlider *sl = (NSSlider *)d->cocoaControl(QCocoaWidget(sliderKind, QAquaSizeLarge), 0); + QCocoaWidget cw = QCocoaWidget(sliderKind, QAquaSizeLarge); + NSSlider *sl = (NSSlider *)d->cocoaControl(cw); sl.minValue = slider->minimum; sl.maxValue = slider->maximum; sl.intValue = slider->sliderValue; sl.enabled = slider->state & QStyle::State_Enabled; - d->drawNSViewInRect(sl, opt->rect, p, ^(NSRect rect, CGContextRef ctx) { + d->drawNSViewInRect(cw, sl, opt->rect, p, widget != 0, ^(NSRect rect, CGContextRef ctx) { if (slider->upsideDown) { if (isHorizontal) { CGContextTranslateCTM(ctx, rect.size.width, 0); @@ -5819,12 +5755,21 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex break; case CC_ComboBox: if (const QStyleOptionComboBox *combo = qstyleoption_cast(opt)){ + const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9; HIThemeButtonDrawInfo bdi; - d->initComboboxBdi(combo, &bdi, widget, d->getDrawState(opt->state)); + d->initComboboxBdi(combo, &bdi, widget, tds); + HIRect rect = qt_hirectForQRect(combo->rect); + if (combo->editable && usingYosemiteOrLater) + rect.origin.y += tds == kThemeStateInactive ? 1 : 2; if (tds != kThemeStateInactive) - QMacStylePrivate::drawCombobox(qt_hirectForQRect(combo->rect), bdi, p); - else - d->drawColorlessButton(qt_hirectForQRect(combo->rect), &bdi, p, opt); + QMacStylePrivate::drawCombobox(rect, bdi, p); + else if (!widget && combo->editable && usingYosemiteOrLater) { + QCocoaWidget cw = cocoaWidgetFromHIThemeButtonKind(bdi.kind); + NSView *cb = d->cocoaControl(cw); + QRect r = combo->rect.adjusted(3, 0, 0, 0); + d->drawNSViewInRect(cw, cb, r, p, widget != 0); + } else + d->drawColorlessButton(rect, &bdi, p, opt); } break; case CC_TitleBar: @@ -5880,11 +5825,6 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex uint sc = SC_TitleBarMinButton; ThemeTitleBarWidget tbw = kThemeWidgetCollapseBox; bool active = titlebar->state & State_Active; - if (QSysInfo::macVersion() < QSysInfo::MV_10_6) { - int border = 2; - titleBarRect.origin.x += border; - titleBarRect.origin.y -= border; - } while (sc <= SC_TitleBarCloseButton) { if (sc & titlebar->subControls) { @@ -6023,23 +5963,12 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex path.addRoundedRect(QRectF(tb->rect.x(), tb->rect.y(), tb->rect.width(), tb->rect.height() + 4), 4, 4); p->setRenderHint(QPainter::Antialiasing); p->fillPath(path, brush); - } else if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { + } else { static QPixmap pm(QLatin1String(":/qt-project.org/mac/style/images/leopard-unified-toolbar-on.png")); p->save(); p->setRenderHint(QPainter::SmoothPixmapTransform); QStyleHelper::drawBorderPixmap(pm, p, tb->rect, 2, 2, 2, 2); p->restore(); - } else { - QPen oldPen = p->pen(); - p->setPen(QColor(0, 0, 0, 0x3a)); - p->fillRect(tb->rect.adjusted(1, 1, -1, -1), QColor(0, 0, 0, 0x12)); - p->drawLine(tb->rect.left() + 1, tb->rect.top(), - tb->rect.right() - 1, tb->rect.top()); - p->drawLine(tb->rect.left() + 1, tb->rect.bottom(), - tb->rect.right() - 1, tb->rect.bottom()); - p->drawLine(tb->rect.topLeft(), tb->rect.bottomLeft()); - p->drawLine(tb->rect.topRight(), tb->rect.bottomRight()); - p->setPen(oldPen); } } proxy()->drawControl(CE_ToolButtonLabel, opt, p, widget); @@ -6192,10 +6121,7 @@ QStyle::SubControl QMacStyle::hitTestComplexControl(ComplexControl cc, HIRect macSBRect = qt_hirectForQRect(sb->rect); ControlPartCode part; bool reverseHorizontal = (sb->direction == Qt::RightToLeft - && sb->orientation == Qt::Horizontal - && (!sb->upsideDown || - (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4 - && sb->upsideDown))); + && sb->orientation == Qt::Horizontal); if (HIThemeHitTestScrollBarArrows(&macSBRect, &sbi, sb->orientation == Qt::Horizontal, &pos, 0, &part)) { if (part == kControlUpButtonPart) @@ -6381,6 +6307,8 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op switch (sc) { case SC_ComboBoxEditField:{ ret = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); + if (QSysInfo::MacintoshVersion > QSysInfo::MV_10_9) + ret.setHeight(ret.height() - 1); break; } case SC_ComboBoxArrow:{ ret = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); @@ -6822,10 +6750,13 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, sz.rwidth() += 10; sz.rheight() += 10; return sz; - case CT_ComboBox: + case CT_ComboBox: { sz.rwidth() += 50; - sz.rheight() += 2; + const QStyleOptionComboBox *cb = qstyleoption_cast(opt); + if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_10 || (cb && !cb->editable)) + sz.rheight() += 2; break; + } case CT_Menu: { QStyleHintReturnMask menuMask; QStyleOption myOption = *opt; diff --git a/src/widgets/styles/qmacstyle_mac_p_p.h b/src/widgets/styles/qmacstyle_mac_p_p.h index 080f944ef8f..89a95713b76 100644 --- a/src/widgets/styles/qmacstyle_mac_p_p.h +++ b/src/widgets/styles/qmacstyle_mac_p_p.h @@ -204,9 +204,9 @@ public: void setAutoDefaultButton(QObject *button) const; - NSView *cocoaControl(QCocoaWidget widget, QPoint *offset) const; + NSView *cocoaControl(QCocoaWidget widget) const; - void drawNSViewInRect(NSView *view, const QRect &rect, QPainter *p, QCocoaDrawRectBlock drawRectBlock = nil) const; + void drawNSViewInRect(QCocoaWidget widget, NSView *view, const QRect &rect, QPainter *p, bool isQWidget = true, QCocoaDrawRectBlock drawRectBlock = nil) const; void resolveCurrentNSView(QWindow *window); public: @@ -222,10 +222,8 @@ public: mutable QPointer focusWidget; CFAbsoluteTime defaultButtonStart; bool mouseDown; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 void* receiver; void *nsscroller; -#endif void *indicatorBranchButtonCell; NSView *backingStoreNSView; QHash cocoaControls; diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp index 7c4d239894e..109a0ea451b 100644 --- a/src/widgets/styles/qstyle.cpp +++ b/src/widgets/styles/qstyle.cpp @@ -1772,8 +1772,7 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, \value SH_ComboBox_Popup Allows popups as a combobox drop-down menu. - \omitvalue SH_ComboBox_UseNativePopup Whether we should use a native popup. - Only supported for non-editable combo boxes on Mac OS X so far. + \omitvalue SH_ComboBox_UseNativePopup \value SH_Workspace_FillSpaceOnMaximize The workspace should maximize the client area. diff --git a/src/widgets/styles/qstyle.h b/src/widgets/styles/qstyle.h index 12ada3f6e4a..fa15a0d4c4d 100644 --- a/src/widgets/styles/qstyle.h +++ b/src/widgets/styles/qstyle.h @@ -698,6 +698,8 @@ public: SH_ToolTip_FallAsleepDelay, SH_Widget_Animate, SH_Splitter_OpaqueResize, + // Whether we should use a native popup. + // Only supported for non-editable combo boxes on Mac OS X so far. SH_ComboBox_UseNativePopup, SH_LineEdit_PasswordMaskDelay, SH_TabBar_ChangeCurrentDelay, diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp index 3619c3ff290..9deeb725f95 100644 --- a/src/widgets/styles/qwindowsstyle.cpp +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -1832,6 +1832,20 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai } return; #endif // QT_NO_DOCKWIDGET +#ifndef QT_NO_COMBOBOX + case CE_ComboBoxLabel: + if (const QStyleOptionComboBox *cb = qstyleoption_cast(opt)) { + if (cb->state & State_HasFocus) { + p->setPen(cb->palette.highlightedText().color()); + p->setBackground(cb->palette.highlight()); + } else { + p->setPen(cb->palette.text().color()); + p->setBackground(cb->palette.background()); + } + } + QCommonStyle::drawControl(ce, opt, p, widget); + break; +#endif // QT_NO_COMBOBOX default: QCommonStyle::drawControl(ce, opt, p, widget); } diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index 007952192ae..463b120e043 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -1473,7 +1473,11 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption break; } #endif // QT_NO_ITEMVIEWS - +#ifndef QT_NO_COMBOBOX + case CE_ComboBoxLabel: + QCommonStyle::drawControl(element, option, painter, widget); + break; +#endif // QT_NO_COMBOBOX default: QWindowsXPStyle::drawControl(element, option, painter, widget); break; diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index c18bbb34310..c1f7b599b38 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -963,7 +963,8 @@ void QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa QImage img; if (!haveCachedPixmap) { // If the pixmap is not cached, generate it! ------------------------- - buffer(w, h); // Ensure a buffer of at least (w, h) in size + if (!buffer(w, h)) // Ensure a buffer of at least (w, h) in size + return; HDC dc = bufferHDC(); // Clear the buffer @@ -2539,7 +2540,7 @@ QRect QWindowsXPStylePrivate::scrollBarGripperBounds(QStyle::State flags, const const int hSpace = theme->rect.width() - size.width(); const int vSpace = theme->rect.height() - size.height(); - const bool sufficientSpace = horizontal && hSpace > (contentsMargin.left() + contentsMargin.right()) + const bool sufficientSpace = (horizontal && hSpace > (contentsMargin.left() + contentsMargin.right())) || vSpace > contentsMargin.top() + contentsMargin.bottom(); return sufficientSpace ? QRect(theme->rect.topLeft() + QPoint(hSpace, vSpace) / 2, size) : QRect(); } diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index 815afe85f26..3db7781accc 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -1520,13 +1520,16 @@ void QLineEdit::mouseMoveEvent(QMouseEvent * e) #else const bool select = (d->imHints & Qt::ImhNoPredictiveText); #endif +#ifndef QT_NO_IM 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 { + } else +#endif + { d->control->moveCursor(d->xToPos(e->pos().x()), select); } } @@ -1577,6 +1580,7 @@ void QLineEdit::mouseDoubleClickEvent(QMouseEvent* e) int position = d->xToPos(e->pos().x()); // exit composition mode +#ifndef QT_NO_IM if (d->control->composeMode()) { int preeditPos = d->control->cursor(); int posInPreedit = position - d->control->cursor(); @@ -1601,6 +1605,7 @@ void QLineEdit::mouseDoubleClickEvent(QMouseEvent* e) position += (sizeChange - preeditLength); } } +#endif if (position >= 0) d->control->selectWordAtPos(position); diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp index 0731c890949..f1126322d8f 100644 --- a/src/widgets/widgets/qlineedit_p.cpp +++ b/src/widgets/widgets/qlineedit_p.cpp @@ -47,8 +47,8 @@ #ifndef QT_NO_IM #include "qinputmethod.h" #include "qlist.h" -#include #endif +#include QT_BEGIN_NAMESPACE diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp index f9376a78d5c..ddecea81bfb 100644 --- a/src/widgets/widgets/qmainwindow.cpp +++ b/src/widgets/widgets/qmainwindow.cpp @@ -1500,6 +1500,13 @@ bool QMainWindow::event(QEvent *event) /*! \property QMainWindow::unifiedTitleAndToolBarOnMac \brief whether the window uses the unified title and toolbar look on Mac OS X + + Note that the Qt 5 implementation has several limitations compared to Qt 4: + \list + \li Use in windows with OpenGL content is not supported. This includes QGLWidget and QOpenGLWidget. + \li Using dockable or movable toolbars may result in painting errors and is not recommended + \endlist + \since 5.2 */ void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool set) diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp index 43f168ecd81..8f8642a72a2 100644 --- a/src/widgets/widgets/qmainwindowlayout.cpp +++ b/src/widgets/widgets/qmainwindowlayout.cpp @@ -68,7 +68,7 @@ QT_BEGIN_NAMESPACE -#ifndef QT_NO_DOCKWIDGET +#ifdef QT_NO_DOCKWIDGET extern QMainWindowLayout *qt_mainwindow_layout(const QMainWindow *window); #endif @@ -615,11 +615,8 @@ static QList findChildrenHelper(const QObject *o) } //pre4.3 tests the format that was used before 4.3 -bool QMainWindowLayoutState::checkFormat(QDataStream &stream, bool pre43) +bool QMainWindowLayoutState::checkFormat(QDataStream &stream) { -#ifdef QT_NO_TOOLBAR - Q_UNUSED(pre43); -#endif while (!stream.atEnd()) { uchar marker; stream >> marker; @@ -630,8 +627,7 @@ bool QMainWindowLayoutState::checkFormat(QDataStream &stream, bool pre43) case QToolBarAreaLayout::ToolBarStateMarkerEx: { QList toolBars = findChildrenHelper(mainWindow); - if (!toolBarAreaLayout.restoreState(stream, toolBars, marker, - pre43 /*testing 4.3 format*/, true /*testing*/)) { + if (!toolBarAreaLayout.restoreState(stream, toolBars, marker, true /*testing*/)) { return false; } } @@ -672,14 +668,8 @@ bool QMainWindowLayoutState::restoreState(QDataStream &_stream, } QDataStream ds(copy); - const bool oldFormat = !checkFormat(ds, false); - if (oldFormat) { - //we should try with the old format - QDataStream ds2(copy); - if (!checkFormat(ds2, true)) { - return false; //format unknown - } - } + if (!checkFormat(ds)) + return false; QDataStream stream(copy); @@ -719,7 +709,7 @@ bool QMainWindowLayoutState::restoreState(QDataStream &_stream, case QToolBarAreaLayout::ToolBarStateMarkerEx: { QList toolBars = findChildrenHelper(mainWindow); - if (!toolBarAreaLayout.restoreState(stream, toolBars, marker, oldFormat)) + if (!toolBarAreaLayout.restoreState(stream, toolBars, marker)) return false; for (int i = 0; i < toolBars.size(); ++i) { diff --git a/src/widgets/widgets/qmainwindowlayout_p.h b/src/widgets/widgets/qmainwindowlayout_p.h index abec34af148..d9e18b03f4c 100644 --- a/src/widgets/widgets/qmainwindowlayout_p.h +++ b/src/widgets/widgets/qmainwindowlayout_p.h @@ -133,7 +133,7 @@ public: QLayoutItem *unplug(const QList &path, QMainWindowLayoutState *savedState = 0); void saveState(QDataStream &stream) const; - bool checkFormat(QDataStream &stream, bool pre43); + bool checkFormat(QDataStream &stream); bool restoreState(QDataStream &stream, const QMainWindowLayoutState &oldState); }; diff --git a/src/widgets/widgets/qmdiarea.cpp b/src/widgets/widgets/qmdiarea.cpp index 1e291f469e3..3553baf68a1 100644 --- a/src/widgets/widgets/qmdiarea.cpp +++ b/src/widgets/widgets/qmdiarea.cpp @@ -1511,7 +1511,7 @@ void QMdiAreaPrivate::highlightNextSubWindow(int increaseFactor) #ifndef QT_NO_RUBBERBAND if (!rubberBand) { - rubberBand = new QRubberBand(QRubberBand::Rectangle, viewport); + rubberBand = new QRubberBand(QRubberBand::Rectangle, q); // For accessibility to identify this special widget. rubberBand->setObjectName(QLatin1String("qt_rubberband")); rubberBand->setWindowFlags(rubberBand->windowFlags() | Qt::WindowStaysOnTopHint); @@ -1528,6 +1528,20 @@ void QMdiAreaPrivate::highlightNextSubWindow(int increaseFactor) Q_ASSERT(indexToHighlighted >= 0); } +void QMdiAreaPrivate::showRubberBandFor(QMdiSubWindow *subWindow) +{ + if (!subWindow || !rubberBand) + return; + + if (viewMode == QMdiArea::TabbedView) + rubberBand->setGeometry(tabBar->tabRect(childWindows.indexOf(subWindow))); + else + rubberBand->setGeometry(subWindow->geometry()); + + rubberBand->raise(); + rubberBand->show(); +} + /*! \internal \since 4.4 diff --git a/src/widgets/widgets/qmdiarea_p.h b/src/widgets/widgets/qmdiarea_p.h index 1092fd9a30a..ba531adaad0 100644 --- a/src/widgets/widgets/qmdiarea_p.h +++ b/src/widgets/widgets/qmdiarea_p.h @@ -248,14 +248,7 @@ public: } #ifndef QT_NO_RUBBERBAND - inline void showRubberBandFor(QMdiSubWindow *subWindow) - { - if (!subWindow || !rubberBand) - return; - rubberBand->setGeometry(subWindow->geometry()); - rubberBand->raise(); - rubberBand->show(); - } + void showRubberBandFor(QMdiSubWindow *subWindow); inline void hideRubberBand() { diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index a4c22de15b0..2c27344a4a0 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -3189,8 +3189,10 @@ void QMenu::actionEvent(QActionEvent *e) delete menuItem; } else if (e->type() == QEvent::ActionChanged) { QPlatformMenuItem *menuItem = d->platformMenu->menuItemForTag(reinterpret_cast(e->action())); - copyActionToPlatformItem(e->action(), menuItem); - d->platformMenu->syncMenuItem(menuItem); + if (menuItem) { + copyActionToPlatformItem(e->action(), menuItem); + d->platformMenu->syncMenuItem(menuItem); + } } d->platformMenu->syncSeparatorsCollapsible(d->collapsibleSeparators); diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp index b6a21f183a8..72a556db7c1 100644 --- a/src/widgets/widgets/qplaintextedit.cpp +++ b/src/widgets/widgets/qplaintextedit.cpp @@ -2042,11 +2042,13 @@ void QPlainTextEdit::mouseMoveEvent(QMouseEvent *e) d->sendControlEvent(e); if (!(e->buttons() & Qt::LeftButton)) return; - QRect visible = d->viewport->rect(); - if (visible.contains(pos)) - d->autoScrollTimer.stop(); - else if (!d->autoScrollTimer.isActive()) - d->autoScrollTimer.start(100, this); + if (e->source() == Qt::MouseEventNotSynthesized) { + const QRect visible = d->viewport->rect(); + if (visible.contains(pos)) + d->autoScrollTimer.stop(); + else if (!d->autoScrollTimer.isActive()) + d->autoScrollTimer.start(100, this); + } } /*! \reimp @@ -2055,7 +2057,7 @@ void QPlainTextEdit::mouseReleaseEvent(QMouseEvent *e) { Q_D(QPlainTextEdit); d->sendControlEvent(e); - if (d->autoScrollTimer.isActive()) { + if (e->source() == Qt::MouseEventNotSynthesized && d->autoScrollTimer.isActive()) { d->autoScrollTimer.stop(); d->ensureCursorVisible(); } diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp index 2d95009eb39..7ef864139fe 100644 --- a/src/widgets/widgets/qtextedit.cpp +++ b/src/widgets/widgets/qtextedit.cpp @@ -1574,11 +1574,13 @@ void QTextEdit::mouseMoveEvent(QMouseEvent *e) d->sendControlEvent(e); if (!(e->buttons() & Qt::LeftButton)) return; - QRect visible = d->viewport->rect(); - if (visible.contains(pos)) - d->autoScrollTimer.stop(); - else if (!d->autoScrollTimer.isActive()) - d->autoScrollTimer.start(100, this); + if (e->source() == Qt::MouseEventNotSynthesized) { + const QRect visible = d->viewport->rect(); + if (visible.contains(pos)) + d->autoScrollTimer.stop(); + else if (!d->autoScrollTimer.isActive()) + d->autoScrollTimer.start(100, this); + } } /*! \reimp @@ -1587,7 +1589,7 @@ void QTextEdit::mouseReleaseEvent(QMouseEvent *e) { Q_D(QTextEdit); d->sendControlEvent(e); - if (d->autoScrollTimer.isActive()) { + if (e->source() == Qt::MouseEventNotSynthesized && d->autoScrollTimer.isActive()) { d->autoScrollTimer.stop(); ensureCursorVisible(); } diff --git a/src/widgets/widgets/qtoolbararealayout.cpp b/src/widgets/widgets/qtoolbararealayout.cpp index 5494d49232d..1dd39174ac9 100644 --- a/src/widgets/widgets/qtoolbararealayout.cpp +++ b/src/widgets/widgets/qtoolbararealayout.cpp @@ -1286,21 +1286,15 @@ void QToolBarAreaLayout::saveState(QDataStream &stream) const } } -static inline int getInt(QDataStream &stream, Qt::Orientation o, bool pre43) +static inline int getInt(QDataStream &stream) { - if (pre43) { - QPoint p; - stream >> p; - return pick(o, p); - } else { - int x; - stream >> x; - return x; - } + int x; + stream >> x; + return x; } -bool QToolBarAreaLayout::restoreState(QDataStream &stream, const QList &_toolBars, uchar tmarker, bool pre43, bool testing) +bool QToolBarAreaLayout::restoreState(QDataStream &stream, const QList &_toolBars, uchar tmarker, bool testing) { QList toolBars = _toolBars; int lines; @@ -1325,8 +1319,8 @@ bool QToolBarAreaLayout::restoreState(QDataStream &stream, const QList> objectName; uchar shown; stream >> shown; - item.pos = getInt(stream, dock.o, pre43); - item.size = getInt(stream, dock.o, pre43); + item.pos = getInt(stream); + item.size = getInt(stream); /* 4.3.0 added floating toolbars, but failed to add the ability to restore them. @@ -1339,9 +1333,9 @@ bool QToolBarAreaLayout::restoreState(QDataStream &stream, const QList &path, QToolBarAreaLayout *other); void saveState(QDataStream &stream) const; - bool restoreState(QDataStream &stream, const QList &toolBars, uchar tmarker, bool pre43, bool testing = false); + bool restoreState(QDataStream &stream, const QList &toolBars, uchar tmarker, bool testing = false); bool isEmpty() const; }; diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp index a82dd99591a..e6385ba390b 100644 --- a/src/widgets/widgets/qwidgetlinecontrol.cpp +++ b/src/widgets/widgets/qwidgetlinecontrol.cpp @@ -179,6 +179,7 @@ void QWidgetLineControl::paste(QClipboard::Mode clipboardMode) */ void QWidgetLineControl::commitPreedit() { +#ifndef QT_NO_IM if (!composeMode()) return; @@ -190,6 +191,7 @@ void QWidgetLineControl::commitPreedit() setPreeditArea(-1, QString()); m_textLayout.clearAdditionalFormats(); updateDisplayText(/*force*/ true); +#endif } diff --git a/src/widgets/widgets/qwidgetlinecontrol_p.h b/src/widgets/widgets/qwidgetlinecontrol_p.h index 328faf79260..f21d88177c6 100644 --- a/src/widgets/widgets/qwidgetlinecontrol_p.h +++ b/src/widgets/widgets/qwidgetlinecontrol_p.h @@ -228,8 +228,10 @@ public: } void setText(const QString &txt) { +#ifndef QT_NO_IM if (composeMode()) qApp->inputMethod()->reset(); +#endif internalSetText(txt, -1, false); } void commitPreedit(); diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp index 954cae345fa..93835156daa 100644 --- a/src/widgets/widgets/qwidgettextcontrol.cpp +++ b/src/widgets/widgets/qwidgettextcontrol.cpp @@ -1582,8 +1582,10 @@ void QWidgetTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton butto cursor.clearSelection(); } } + // Do not start selection on a mouse event synthesized from a touch event. if (!(button & Qt::LeftButton) || - !((interactionFlags & Qt::TextSelectableByMouse) || (interactionFlags & Qt::TextEditable))) { + !((interactionFlags & Qt::TextSelectableByMouse) || (interactionFlags & Qt::TextEditable)) + || QApplicationPrivate::mouseEventSource(e) != Qt::MouseEventNotSynthesized) { e->ignore(); return; } @@ -1754,6 +1756,11 @@ void QWidgetTextControlPrivate::mouseReleaseEvent(QEvent *e, Qt::MouseButton but { Q_Q(QWidgetTextControl); + if (QApplicationPrivate::mouseEventSource(e) != Qt::MouseEventNotSynthesized) { + setCursorPosition(pos); // Emulate Tap to set cursor for events synthesized from touch. + return; + } + const QTextCursor oldSelection = cursor; if (sendMouseEventToInputContext( e, QEvent::MouseButtonRelease, button, pos, modifiers, buttons, globalPos)) { diff --git a/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp b/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp index 4e3d5c64bc5..df2f97ce0e7 100644 --- a/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp +++ b/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp @@ -1996,6 +1996,10 @@ void tst_QTextCodec::codecForHtml_data() "auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; display: inline !important; float: " "none;\">ͻ\000"; QTest::newRow("greek text UTF-8") << html << 106 << 106; + + html = "" + "

    bla

    "; // QTBUG-41998, ICU will return UTF-16. + QTest::newRow("legacy unicode UTF-8") << html << 106 << 106; } void tst_QTextCodec::codecForHtml() diff --git a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp index 35bd518b3aa..0a55da5b7e8 100644 --- a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp +++ b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp @@ -886,25 +886,25 @@ void tst_qmessagehandler::formatLogMessage_data() #define BA QByteArrayLiteral QTest::newRow("basic") << "%{type} %{file} %{line} %{function} %{message}" - << "debug main.cpp 1 func msg\n" + << "debug main.cpp 1 func msg" << QtDebugMsg << BA("main.cpp") << 1 << BA("func") << BA("") << "msg"; // test the if conditions QString format = "[%{if-debug}D%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{if-category}%{category}: %{endif}%{message}"; QTest::newRow("if-debug") - << format << "[D] msg\n" + << format << "[D] msg" << QtDebugMsg << BA("") << 0 << BA("func") << QByteArray() << "msg"; QTest::newRow("if_warning") - << format << "[W] msg\n" + << format << "[W] msg" << QtWarningMsg << BA("") << 0 << BA("func") << QByteArray() << "msg"; QTest::newRow("if_critical") - << format << "[C] msg\n" + << format << "[C] msg" << QtCriticalMsg << BA("") << 0 << BA("func") << QByteArray() << "msg"; QTest::newRow("if_fatal") - << format << "[F] msg\n" + << format << "[F] msg" << QtFatalMsg << BA("") << 0 << BA("func") << QByteArray() << "msg"; QTest::newRow("if_cat") - << format << "[F] cat: msg\n" + << format << "[F] cat: msg" << QtFatalMsg << BA("") << 0 << BA("func") << BA("cat") << "msg"; } diff --git a/tests/auto/corelib/io/qsettings/bom.ini b/tests/auto/corelib/io/qsettings/bom.ini new file mode 100644 index 00000000000..8d46ee8d91d --- /dev/null +++ b/tests/auto/corelib/io/qsettings/bom.ini @@ -0,0 +1,4 @@ +[section1] +foo1=bar1 +[section2] +foo2=bar2 diff --git a/tests/auto/corelib/io/qsettings/qsettings.qrc b/tests/auto/corelib/io/qsettings/qsettings.qrc index 587c22ebe3d..c0be7e013fa 100644 --- a/tests/auto/corelib/io/qsettings/qsettings.qrc +++ b/tests/auto/corelib/io/qsettings/qsettings.qrc @@ -1,9 +1,10 @@ - - - resourcefile.ini - resourcefile2.ini - resourcefile3.ini - resourcefile4.ini - resourcefile5.ini - + + + resourcefile.ini + resourcefile2.ini + resourcefile3.ini + resourcefile4.ini + resourcefile5.ini + bom.ini + diff --git a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp index 3e68e4859fc..c89923f1595 100644 --- a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp +++ b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp @@ -161,6 +161,7 @@ private slots: void testByteArray_data(); void testByteArray(); void iniCodec(); + void bom(); private: const bool m_canWriteNativeSystemSettings; @@ -730,6 +731,15 @@ void tst_QSettings::iniCodec() } +void tst_QSettings::bom() +{ + QSettings s(":/bom.ini", QSettings::IniFormat); + QStringList allkeys = s.allKeys(); + QCOMPARE(allkeys.size(), 2); + QVERIFY(allkeys.contains("section1/foo1")); + QVERIFY(allkeys.contains("section2/foo2")); +} + void tst_QSettings::testErrorHandling_data() { QTest::addColumn("filePerms"); // -1 means file should not exist diff --git a/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp b/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp index e07dda250f9..3abbb71960a 100644 --- a/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp +++ b/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp @@ -154,6 +154,11 @@ void tst_QStorageInfo::tempFile() QVERIFY(file.open()); QStorageInfo storage1(file.fileName()); +#ifdef Q_OS_LINUX + if (storage1.fileSystemType() == "btrfs") + QSKIP("This test doesn't work on btrfs, probably due to a btrfs bug"); +#endif + qint64 free = storage1.bytesFree(); file.write(QByteArray(1024*1024, '1')); @@ -170,6 +175,11 @@ void tst_QStorageInfo::caching() QVERIFY(file.open()); QStorageInfo storage1(file.fileName()); +#ifdef Q_OS_LINUX + if (storage1.fileSystemType() == "btrfs") + QSKIP("This test doesn't work on btrfs, probably due to a btrfs bug"); +#endif + qint64 free = storage1.bytesFree(); QStorageInfo storage2(storage1); QVERIFY(free == storage2.bytesFree()); diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp index 5b5161e24a6..6d801f75c1f 100644 --- a/tests/auto/corelib/io/qurl/tst_qurl.cpp +++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp @@ -1179,6 +1179,12 @@ void tst_QUrl::toLocalFile_data() QTest::newRow("data0") << QString::fromLatin1("file:/a.txt") << QString::fromLatin1("/a.txt"); QTest::newRow("data4") << QString::fromLatin1("file:///a.txt") << QString::fromLatin1("/a.txt"); + QTest::newRow("data4a") << QString::fromLatin1("webdavs://somewebdavhost/somedir/somefile") +#ifdef Q_OS_WIN // QTBUG-42346, WebDAV is visible as local file on Windows only. + << QString::fromLatin1("//somewebdavhost@SSL/somedir/somefile"); +#else + << QString(); +#endif #ifdef Q_OS_WIN QTest::newRow("data5") << QString::fromLatin1("file:///c:/a.txt") << QString::fromLatin1("c:/a.txt"); #else @@ -1227,6 +1233,9 @@ void tst_QUrl::fromLocalFile_data() QTest::newRow("data3") << QString::fromLatin1("c:/a.txt") << QString::fromLatin1("file:///c:/a.txt") << QString::fromLatin1("/c:/a.txt"); QTest::newRow("data4") << QString::fromLatin1("//somehost/somedir/somefile") << QString::fromLatin1("file://somehost/somedir/somefile") << QString::fromLatin1("/somedir/somefile"); + QTest::newRow("data4a") << QString::fromLatin1("//somewebdavhost@SSL/somedir/somefile") + << QString::fromLatin1("webdavs://somewebdavhost/somedir/somefile") + << QString::fromLatin1("/somedir/somefile"); QTest::newRow("data5") << QString::fromLatin1("//somehost") << QString::fromLatin1("file://somehost") << QString::fromLatin1(""); QTest::newRow("data6") << QString::fromLatin1("//somehost/") << QString::fromLatin1("file://somehost/") diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp index ed84c111c61..d05ed6c20f5 100644 --- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp @@ -95,6 +95,7 @@ private slots: void changeFilter(); void changeSourceData_data(); void changeSourceData(); + void changeSourceDataKeepsStableSorting_qtbug1548(); void sortFilterRole(); void selectionFilteredOut(); void match_data(); @@ -143,6 +144,7 @@ private slots: void noMapAfterSourceDelete(); void forwardDropApi(); + void canDropMimeData(); protected: void buildHierarchy(const QStringList &data, QAbstractItemModel *model); @@ -2009,6 +2011,79 @@ void tst_QSortFilterProxyModel::changeSourceData() } } +// Checks that the model is a table, and that each and every row is like this: +// i-th row: ( rows.at(i), i ) +static void checkSortedTableModel(const QAbstractItemModel *model, const QStringList &rows) +{ + QCOMPARE(model->rowCount(), rows.length()); + QCOMPARE(model->columnCount(), 2); + + for (int row = 0; row < model->rowCount(); ++row) { + const QString column0 = model->index(row, 0).data().toString(); + const int column1 = model->index(row, 1).data().toString().toInt(); + + QCOMPARE(column0, rows.at(row)); + QCOMPARE(column1, row); + } +} + +void tst_QSortFilterProxyModel::changeSourceDataKeepsStableSorting_qtbug1548() +{ + // Check that emitting dataChanged from the source model + // for a change of a role which is not the sorting role + // doesn't alter the sorting. In this case, we sort on the DisplayRole, + // and play with other roles. + + static const QStringList rows + = QStringList() << "a" << "b" << "b" << "b" << "c" << "c" << "x"; + + // Build a table of pairs (string, #row) in each row + QStandardItemModel model(0, 2); + + for (int rowNumber = 0; rowNumber < rows.length(); ++rowNumber) { + QStandardItem *column0 = new QStandardItem(rows.at(rowNumber)); + column0->setCheckable(true); + column0->setCheckState(Qt::Unchecked); + + QStandardItem *column1 = new QStandardItem(QString::number(rowNumber)); + + const QList row + = QList() << column0 << column1; + + model.appendRow(row); + } + + checkSortedTableModel(&model, rows); + + // Build the proxy model + QSortFilterProxyModel proxy; + proxy.setSourceModel(&model); + proxy.setDynamicSortFilter(true); + proxy.sort(0); + + // The proxy is now sorted by the first column, check that the sorting + // * is correct (the input is already sorted, so it must not have changed) + // * was stable (by looking at the second column) + checkSortedTableModel(&model, rows); + + // Change the check status of an item. That must not break the stable sorting + // changes the middle "b" + model.item(2)->setCheckState(Qt::Checked); + checkSortedTableModel(&model, rows); + + // changes the starting "a" + model.item(0)->setCheckState(Qt::Checked); + checkSortedTableModel(&model, rows); + + // change the background color of the first "c" + model.item(4)->setBackground(Qt::red); + checkSortedTableModel(&model, rows); + + // change the background color of the second "c" + model.item(5)->setBackground(Qt::red); + checkSortedTableModel(&model, rows); +} + void tst_QSortFilterProxyModel::sortFilterRole() { QStandardItemModel model; @@ -3835,6 +3910,36 @@ void tst_QSortFilterProxyModel::chainedProxyModelRoleNames() QVERIFY(proxy2.roleNames().value(Qt::UserRole + 1) == "custom"); } +// A source model with ABABAB rows, where only A rows accept drops. +// It will then be sorted by a QSFPM. +class DropOnOddRows : public QAbstractListModel +{ + Q_OBJECT +public: + DropOnOddRows(QObject *parent = 0) : QAbstractListModel(parent) {} + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const + { + if (role == Qt::DisplayRole) + return (index.row() % 2 == 0) ? "A" : "B"; + return QVariant(); + } + + int rowCount(const QModelIndex &parent = QModelIndex()) const + { + Q_UNUSED(parent); + return 10; + } + + bool canDropMimeData(const QMimeData *, Qt::DropAction, + int row, int column, const QModelIndex &parent) const Q_DECL_OVERRIDE + { + Q_UNUSED(row); + Q_UNUSED(column); + return parent.row() % 2 == 0; + } +}; + class SourceAssertion : public QSortFilterProxyModel { Q_OBJECT @@ -3899,5 +4004,30 @@ void tst_QSortFilterProxyModel::forwardDropApi() QVERIFY(model.dropMimeData(0, Qt::CopyAction, 0, 0, QModelIndex())); } +static QString rowTexts(QAbstractItemModel *model) { + QString str; + for (int row = 0 ; row < model->rowCount(); ++row) + str += model->index(row, 0).data().toString(); + return str; +} + +void tst_QSortFilterProxyModel::canDropMimeData() +{ + // Given a source model which only supports dropping on even rows + DropOnOddRows sourceModel; + QCOMPARE(rowTexts(&sourceModel), QString("ABABABABAB")); + + // and a proxy model that sorts the rows + QSortFilterProxyModel proxy; + proxy.setSourceModel(&sourceModel); + proxy.sort(0, Qt::AscendingOrder); + QCOMPARE(rowTexts(&proxy), QString("AAAAABBBBB")); + + // the proxy should correctly map canDropMimeData to the source model, + // i.e. accept drops on the first 5 rows and refuse drops on the next 5. + for (int row = 0; row < proxy.rowCount(); ++row) + QCOMPARE(proxy.canDropMimeData(0, Qt::CopyAction, -1, -1, proxy.index(row, 0)), row < 5); +} + QTEST_MAIN(tst_QSortFilterProxyModel) #include "tst_qsortfilterproxymodel.moc" diff --git a/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp b/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp index 5cfbce0d7ae..befd45018a8 100644 --- a/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp +++ b/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp @@ -40,6 +40,7 @@ #include #if defined(Q_OS_UNIX) #include + #include #if defined(HAVE_GLIB) #include #endif @@ -172,7 +173,9 @@ private slots: void execAfterExit(); void wakeUp(); void quit(); +#if defined(Q_OS_UNIX) void processEventsExcludeSocket(); +#endif void processEventsExcludeTimers(); void deliverInDefinedOrder(); @@ -383,6 +386,7 @@ void tst_QEventLoop::customEvent(QEvent *e) } } +#if defined(Q_OS_UNIX) class SocketEventsTester: public QObject { Q_OBJECT @@ -391,8 +395,10 @@ public: { socket = 0; server = 0; - dataArrived = false; + dataSent = false; + dataReadable = false; testResult = false; + dataArrived = false; } ~SocketEventsTester() { @@ -415,8 +421,10 @@ public: QTcpSocket *socket; QTcpServer *server; - bool dataArrived; + bool dataSent; + bool dataReadable; bool testResult; + bool dataArrived; public slots: void sendAck() { @@ -428,12 +436,26 @@ public slots: qint64 size = sizeof(data); QTcpSocket *serverSocket = server->nextPendingConnection(); + QCoreApplication::processEvents(); serverSocket->write(data, size); - serverSocket->flush(); - QTest::qSleep(200); //allow the TCP/IP stack time to loopback the data, so our socket is ready to read - QCoreApplication::processEvents(QEventLoop::ExcludeSocketNotifiers); - testResult = dataArrived; - QCoreApplication::processEvents(); //check the deferred event is processed + dataSent = serverSocket->waitForBytesWritten(-1); + + if (dataSent) { + fd_set fdread; + int fd = socket->socketDescriptor(); + FD_ZERO(&fdread); + FD_SET(fd, &fdread); + dataReadable = (1 == qt_safe_select(fd + 1, &fdread, 0, 0, 0)); + } + + if (!dataReadable) { + testResult = dataArrived; + } else { + QCoreApplication::processEvents(QEventLoop::ExcludeSocketNotifiers); + testResult = dataArrived; + // to check if the deferred event is processed + QCoreApplication::processEvents(); + } serverSocket->close(); QThread::currentThread()->exit(0); } @@ -449,12 +471,16 @@ public: SocketEventsTester *tester = new SocketEventsTester(); if (tester->init()) exec(); + dataSent = tester->dataSent; + dataReadable = tester->dataReadable; testResult = tester->testResult; dataArrived = tester->dataArrived; delete tester; } - bool testResult; - bool dataArrived; + bool dataSent; + bool dataReadable; + bool testResult; + bool dataArrived; }; void tst_QEventLoop::processEventsExcludeSocket() @@ -462,9 +488,17 @@ void tst_QEventLoop::processEventsExcludeSocket() SocketTestThread thread; thread.start(); QVERIFY(thread.wait()); + QVERIFY(thread.dataSent); + QVERIFY(thread.dataReadable); + #if defined(HAVE_GLIB) + QAbstractEventDispatcher *eventDispatcher = QCoreApplication::eventDispatcher(); + if (qobject_cast(eventDispatcher)) + QEXPECT_FAIL("", "ExcludeSocketNotifiers is currently broken in the Glib dispatchers", Continue); + #endif QVERIFY(!thread.testResult); QVERIFY(thread.dataArrived); } +#endif class TimerReceiver : public QObject { diff --git a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp index 78c75b44e8f..5833123dfe6 100644 --- a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp +++ b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp @@ -642,18 +642,25 @@ struct CountedStruct QThread *thread; }; -static QEventLoop _e; +static QScopedPointer _e; static QThread *_t = Q_NULLPTR; class StaticEventLoop { public: - static void quitEventLoop() { _e.quit(); if (_t) QCOMPARE(QThread::currentThread(), _t); } + static void quitEventLoop() + { + QVERIFY(!_e.isNull()); + _e->quit(); + if (_t) + QCOMPARE(QThread::currentThread(), _t); + } }; void tst_QTimer::singleShotToFunctors() { int count = 0; + _e.reset(new QEventLoop); QEventLoop e; QTimer::singleShot(0, CountedStruct(&count)); @@ -661,7 +668,7 @@ void tst_QTimer::singleShotToFunctors() QCOMPARE(count, 1); QTimer::singleShot(0, &StaticEventLoop::quitEventLoop); - QCOMPARE(_e.exec(), 0); + QCOMPARE(_e->exec(), 0); QThread t1; QObject c1; @@ -687,7 +694,7 @@ void tst_QTimer::singleShotToFunctors() QCOMPARE(e.exec(), 0); QTimer::singleShot(0, &c2, &StaticEventLoop::quitEventLoop); - QCOMPARE(_e.exec(), 0); + QCOMPARE(_e->exec(), 0); _t->quit(); _t->wait(); @@ -721,8 +728,10 @@ void tst_QTimer::singleShotToFunctors() thread.quit(); thread.wait(); #endif -} + _e.reset(); + _t = Q_NULLPTR; +} class DontBlockEvents : public QObject { diff --git a/tests/auto/corelib/kernel/qvariant/qvariant.pro b/tests/auto/corelib/kernel/qvariant/qvariant.pro index f8d054f70cf..39178ba9e67 100644 --- a/tests/auto/corelib/kernel/qvariant/qvariant.pro +++ b/tests/auto/corelib/kernel/qvariant/qvariant.pro @@ -6,3 +6,4 @@ INCLUDEPATH += $$PWD/../../../other/qvariant_common SOURCES = tst_qvariant.cpp RESOURCES += qvariant.qrc DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 +contains(QT_CONFIG, c++11): CONFIG += c++11 diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index eae6311854e..301db372339 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -3840,11 +3840,10 @@ struct ContainerAPI } }; -// We have no built-in defines to check the stdlib features. -// #define TEST_FORWARD_LIST - -#ifdef TEST_FORWARD_LIST -#include +#ifdef __has_include +# if __has_include() +# define TEST_FORWARD_LIST +# include Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::forward_list) @@ -3898,7 +3897,8 @@ struct ContainerAPI > return variant == value; } }; -#endif +# endif // __has_include() +#endif // __has_include template struct KeyGetter diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp index 57473021aaf..e001440045d 100644 --- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp @@ -4447,6 +4447,28 @@ void tst_QString::section_data() << QString("o") << 1 << 2 << int(QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep) << QString("o1o2o") << false; + QTest::newRow( "range1" ) << QString("o1o2o") + << QString("o") << -5 << -5 + << int(QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep) + << QString() << false; + QTest::newRow( "range2" ) << QString("oo1o2o") + << QString("o") << -5 << 1 + << int(QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep + |QString::SectionSkipEmpty) + << QString("oo1o2o") << false; + QTest::newRow( "range3" ) << QString("o1o2o") + << QString("o") << 2 << 1 + << int(QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep) + << QString() << false; + QTest::newRow( "range4" ) << QString("o1o2o") + << QString("o") << 4 << 4 + << int(QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep) + << QString() << false; + QTest::newRow( "range5" ) << QString("o1oo2o") + << QString("o") << -2 << -1 + << int(QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep + |QString::SectionSkipEmpty) + << QString("o1oo2o") << false; QTest::newRow( "rx1" ) << QString("o1o2o") << QString("[a-z]") << 0 << 0 << int(QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep) diff --git a/tests/auto/corelib/tools/qversionnumber/qversionnumber.pro b/tests/auto/corelib/tools/qversionnumber/qversionnumber.pro index 08ee0dd3d99..1e74d42bbd8 100644 --- a/tests/auto/corelib/tools/qversionnumber/qversionnumber.pro +++ b/tests/auto/corelib/tools/qversionnumber/qversionnumber.pro @@ -1,4 +1,4 @@ CONFIG += testcase parallel_test TARGET = tst_qversionnumber -QT = core testlib +QT = core-private testlib SOURCES = tst_qversionnumber.cpp diff --git a/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp b/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp index 18bc86620a1..f97b8a4df84 100644 --- a/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp +++ b/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp @@ -33,7 +33,7 @@ ****************************************************************************/ #include -#include +#include class tst_QVersionNumber : public QObject { diff --git a/tests/auto/dbus/qdbusabstractadaptor/qmyserver/qmyserver.cpp b/tests/auto/dbus/qdbusabstractadaptor/qmyserver/qmyserver.cpp index 5263d431d0a..b4c16c6fa38 100644 --- a/tests/auto/dbus/qdbusabstractadaptor/qmyserver/qmyserver.cpp +++ b/tests/auto/dbus/qdbusabstractadaptor/qmyserver/qmyserver.cpp @@ -75,6 +75,11 @@ public slots: return m_conn.isConnected(); } + Q_NOREPLY void requestSync(const QString &seq) + { + emit syncReceived(seq); + } + void emitSignal(const QString& interface, const QString& name, const QDBusVariant& parameter) { if (interface.endsWith('2')) @@ -126,10 +131,14 @@ public slots: valueSpy.clear(); } +signals: + Q_SCRIPTABLE void syncReceived(const QString &sequence); + private slots: - void handleConnection(const QDBusConnection& con) + void handleConnection(QDBusConnection con) { m_conn = con; + con.registerObject(objectPath, this, QDBusConnection::ExportScriptableSignals); } private: diff --git a/tests/auto/dbus/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp b/tests/auto/dbus/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp index 6d25bf22135..9fe6bc790ea 100644 --- a/tests/auto/dbus/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp +++ b/tests/auto/dbus/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp @@ -338,6 +338,24 @@ void registerMyObjectPeer(const QString & path, QDBusConnection::RegisterOptions QDBusMessage reply = QDBusConnection::sessionBus().call(req); } +void syncPeer() +{ + static int counter = 0; + QString reqId = QString::number(++counter); + + // wait for the sync signal with the right ID + QEventLoop loop; + QDBusConnection con("peer"); + con.connect(serviceName, objectPath, interfaceName, "syncReceived", + QStringList() << reqId, QString(), &loop, SLOT(quit())); + + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "requestSync"); + req << reqId; + QDBusConnection::sessionBus().send(req); + + loop.exec(); +} + void emitSignalPeer(const QString &interface, const QString &name, const QVariant ¶meter) { if (parameter.isValid()) @@ -1159,6 +1177,8 @@ void tst_QDBusAbstractAdaptor::signalEmissionsPeer() // connect all signals and emit only one { + syncPeer(); + QDBusSignalSpy spy; con.connect(QString(), "/", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage))); @@ -1186,6 +1206,8 @@ void tst_QDBusAbstractAdaptor::signalEmissionsPeer() // connect one signal and emit them all { + syncPeer(); + QDBusSignalSpy spy; con.connect(QString(), "/", interface, name, &spy, SLOT(slot(QDBusMessage))); emitSignalPeer("local.Interface2", "signal", QVariant()); @@ -1214,6 +1236,7 @@ void tst_QDBusAbstractAdaptor::sameSignalDifferentPathsPeer() registerMyObjectPeer("/p1"); registerMyObjectPeer("/p2"); + syncPeer(); QDBusSignalSpy spy; con.connect(QString(), "/p1", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage))); emitSignalPeer("local.Interface2", QString(), QVariant()); @@ -1241,6 +1264,7 @@ void tst_QDBusAbstractAdaptor::sameObjectDifferentPathsPeer() registerMyObjectPeer("/p1"); registerMyObjectPeer("/p2", 0); // don't export anything + syncPeer(); QDBusSignalSpy spy; con.connect(QString(), "/p1", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage))); con.connect(QString(), "/p2", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage))); @@ -1263,6 +1287,7 @@ void tst_QDBusAbstractAdaptor::scriptableSignalOrNotPeer() registerMyObjectPeer("/p1", QDBusConnection::ExportScriptableSignals); registerMyObjectPeer("/p2", 0); // don't export anything + syncPeer(); QDBusSignalSpy spy; con.connect(QString(), "/p1", "local.MyObject", "scriptableSignalVoid", &spy, SLOT(slot(QDBusMessage))); con.connect(QString(), "/p2", "local.MyObject", "scriptableSignalVoid", &spy, SLOT(slot(QDBusMessage))); @@ -1286,6 +1311,7 @@ void tst_QDBusAbstractAdaptor::scriptableSignalOrNotPeer() registerMyObjectPeer("/p2", QDBusConnection::ExportScriptableSignals | QDBusConnection::ExportNonScriptableSignals); + syncPeer(); QDBusSignalSpy spy; con.connect(QString(), "/p1", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage))); con.connect(QString(), "/p2", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage))); @@ -1338,6 +1364,7 @@ void tst_QDBusAbstractAdaptor::overloadedSignalEmissionPeer() // connect all signals and emit only one { + syncPeer(); QDBusSignalSpy spy; con.connect(QString(), "/", "local.Interface4", "signal", "", &spy, SLOT(slot(QDBusMessage))); @@ -1358,6 +1385,7 @@ void tst_QDBusAbstractAdaptor::overloadedSignalEmissionPeer() QFETCH(QString, signature); // connect one signal and emit them all { + syncPeer(); QDBusSignalSpy spy; con.connect(QString(), "/", interface, name, signature, &spy, SLOT(slot(QDBusMessage))); emitSignalPeer("local.Interface4", "signal", QVariant()); diff --git a/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_1.jpg b/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_1.jpg new file mode 100644 index 00000000000..aaa4ac4e10f Binary files /dev/null and b/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_1.jpg differ diff --git a/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_2.jpg b/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_2.jpg new file mode 100644 index 00000000000..a61d2723d7c Binary files /dev/null and b/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_2.jpg differ diff --git a/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_3.jpg b/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_3.jpg new file mode 100644 index 00000000000..43e56dcef70 Binary files /dev/null and b/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_3.jpg differ diff --git a/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_4.jpg b/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_4.jpg new file mode 100644 index 00000000000..d5d06f74092 Binary files /dev/null and b/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_4.jpg differ diff --git a/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_5.jpg b/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_5.jpg new file mode 100644 index 00000000000..1886f3775e0 Binary files /dev/null and b/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_5.jpg differ diff --git a/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_6.jpg b/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_6.jpg new file mode 100644 index 00000000000..5cec7573542 Binary files /dev/null and b/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_6.jpg differ diff --git a/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_7.jpg b/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_7.jpg new file mode 100644 index 00000000000..b3dcc466a90 Binary files /dev/null and b/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_7.jpg differ diff --git a/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_8.jpg b/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_8.jpg new file mode 100644 index 00000000000..8bc390e2b9a Binary files /dev/null and b/tests/auto/gui/image/qimage/images/jpeg_exif_orientation_value_8.jpg differ diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp index 4cb70612ea7..676f8084a1f 100644 --- a/tests/auto/gui/image/qimage/tst_qimage.cpp +++ b/tests/auto/gui/image/qimage/tst_qimage.cpp @@ -173,6 +173,8 @@ private slots: void invertPixelsRGB_data(); void invertPixelsRGB(); + void exifOrientation(); + void cleanupFunctions(); private: @@ -2639,6 +2641,22 @@ void tst_QImage::invertPixelsRGB() QCOMPARE(qBlue(pixel) >> 4, (255 - 96) >> 4); } +void tst_QImage::exifOrientation() +{ + for (unsigned int i = 1; i <= 8; ++i) { + QImage img; + QRgb px; + + QVERIFY(img.load(m_prefix + QString::fromLatin1("jpeg_exif_orientation_value_%1.jpg").arg(i))); + + px = img.pixel(0, 0); + QVERIFY(qRed(px) > 250 && qGreen(px) < 5 && qBlue(px) < 5); + + px = img.pixel(img.width() - 1, 0); + QVERIFY(qRed(px) < 5 && qGreen(px) < 5 && qBlue(px) > 250); + } +} + static void cleanupFunction(void* info) { bool *called = static_cast(info); diff --git a/tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp b/tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp index e08af2491d3..a63183e5fc2 100644 --- a/tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp +++ b/tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp @@ -59,30 +59,39 @@ void tst_QDoubleValidator::validateThouSep_data() { QTest::addColumn("localeName"); QTest::addColumn("value"); + QTest::addColumn("rejectGroupSeparator"); QTest::addColumn("result"); - QTest::newRow("1,000C") << "C" << QString("1,000") << ACC; - QTest::newRow("1.000C") << "C" << QString("1.000") << ACC; + QTest::newRow("1,000C") << "C" << QString("1,000") << false << ACC; + QTest::newRow("1,000.1C") << "C" << QString("1,000.1") << false << ACC; + QTest::newRow("1,000.1C_reject") << "C" << QString("1,000.1") << true << INV; + QTest::newRow("1.000C") << "C" << QString("1.000") << false << ACC; - QTest::newRow("1,000de") << "de" << QString("1,000") << ACC; - QTest::newRow("1.000de") << "de" << QString("1.000") << ACC; + QTest::newRow("1,000de") << "de" << QString("1,000") << false << ACC; + QTest::newRow("1.000de") << "de" << QString("1.000") << false << ACC; - QTest::newRow(".C") << "C" << QString(".") << ITM; - QTest::newRow(".de") << "de" << QString(".") << INV; - QTest::newRow(",C") << "C" << QString(",") << INV; - QTest::newRow(",de") << "de" << QString(",") << ITM; + QTest::newRow(".C") << "C" << QString(".") << false << ITM; + QTest::newRow(".de") << "de" << QString(".") << false << INV; + QTest::newRow("1.000,1de") << "de" << QString("1.000,1") << false << ACC; + QTest::newRow("1.000,1de_reject") << "de" << QString("1.000,1") << true << INV; + QTest::newRow(",C") << "C" << QString(",") << false << INV; + QTest::newRow(",de") << "de" << QString(",") << false << ITM; } void tst_QDoubleValidator::validateThouSep() { QFETCH(QString, localeName); QFETCH(QString, value); + QFETCH(bool, rejectGroupSeparator); QFETCH(QValidator::State, result); int dummy = 0; QDoubleValidator iv(-10000, 10000, 3, 0); iv.setNotation(QDoubleValidator::ScientificNotation); - iv.setLocale(QLocale(localeName)); + QLocale locale(localeName); + if (rejectGroupSeparator) + locale.setNumberOptions(QLocale::RejectGroupSeparator); + iv.setLocale(locale); QCOMPARE(iv.validate(value, dummy), result); } diff --git a/tests/auto/gui/util/qregularexpressionvalidator/tst_qregularexpressionvalidator.cpp b/tests/auto/gui/util/qregularexpressionvalidator/tst_qregularexpressionvalidator.cpp index 31853f7015f..eff07ad07f0 100644 --- a/tests/auto/gui/util/qregularexpressionvalidator/tst_qregularexpressionvalidator.cpp +++ b/tests/auto/gui/util/qregularexpressionvalidator/tst_qregularexpressionvalidator.cpp @@ -74,6 +74,9 @@ void tst_QRegularExpressionValidator::validate_data() QTest::newRow("data14") << QRegularExpression("\\w\\d\\d") << QString("E5") << QValidator::Intermediate; QTest::newRow("data15") << QRegularExpression("\\w\\d\\d") << QString("+9") << QValidator::Invalid; + QTest::newRow("emptystr1") << QRegularExpression("[T][e][s][t]") << QString("") << QValidator::Intermediate; + QTest::newRow("emptystr2") << QRegularExpression("[T][e][s][t]") << QString() << QValidator::Intermediate; + QTest::newRow("empty01") << QRegularExpression() << QString() << QValidator::Acceptable; QTest::newRow("empty02") << QRegularExpression() << QString("test") << QValidator::Acceptable; } diff --git a/tests/auto/network/access/qnetworkreply/BLACKLIST b/tests/auto/network/access/qnetworkreply/BLACKLIST index fbd72492d8b..7792e05e0f5 100644 --- a/tests/auto/network/access/qnetworkreply/BLACKLIST +++ b/tests/auto/network/access/qnetworkreply/BLACKLIST @@ -7,3 +7,6 @@ osx [SslHandshakeFailedError] osx [httpAbort] +* +[backgroundRequestInterruption:ftp, bg, nobg] +* diff --git a/tests/auto/network/socket/qsocks5socketengine/BLACKLIST b/tests/auto/network/socket/qsocks5socketengine/BLACKLIST new file mode 100644 index 00000000000..bf4afa8c450 --- /dev/null +++ b/tests/auto/network/socket/qsocks5socketengine/BLACKLIST @@ -0,0 +1,4 @@ +[udpTest] +* +[passwordAuth] +* diff --git a/tests/auto/network/ssl/ssl.pro b/tests/auto/network/ssl/ssl.pro index 0cf910df73e..4e30a9cded1 100644 --- a/tests/auto/network/ssl/ssl.pro +++ b/tests/auto/network/ssl/ssl.pro @@ -5,19 +5,21 @@ SUBDIRS=\ qsslerror \ qsslkey \ -contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked): +contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) { contains(QT_CONFIG, private_tests) { SUBDIRS += \ qsslsocket \ qsslsocket_onDemandCertificates_member \ qsslsocket_onDemandCertificates_static \ } +} winrt: SUBDIRS -= \ qsslsocket_onDemandCertificates_member \ qsslsocket_onDemandCertificates_static \ -contains(QT_CONFIG, ssl) | contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked): +contains(QT_CONFIG, ssl) | contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) { contains(QT_CONFIG, private_tests) { - SUBDIRS += qasn1element + SUBDIRS += qasn1element + } } diff --git a/tests/auto/opengl/qgl/tst_qgl.cpp b/tests/auto/opengl/qgl/tst_qgl.cpp index 0ba464a82c8..56198ceb650 100644 --- a/tests/auto/opengl/qgl/tst_qgl.cpp +++ b/tests/auto/opengl/qgl/tst_qgl.cpp @@ -42,6 +42,8 @@ #include #include #include +#include +#include #include #include @@ -78,6 +80,7 @@ private slots: void glWidgetRendering(); void glFBOSimpleRendering(); void glFBORendering(); + void currentFboSync(); void multipleFBOInterleavedRendering(); void glFBOUseInGLWidget(); void glPBufferRendering(); @@ -1138,6 +1141,93 @@ void tst_QGL::glFBORendering() qt_opengl_check_test_pattern(fb); } +class QOpenGLFramebufferObjectPaintDevice : public QOpenGLPaintDevice +{ +public: + QOpenGLFramebufferObjectPaintDevice(int width, int height) + : QOpenGLPaintDevice(width, height) + , m_fbo(width, height, QOpenGLFramebufferObject::CombinedDepthStencil) + { + } + + void ensureActiveTarget() + { + m_fbo.bind(); + } + + QImage toImage() const + { + return m_fbo.toImage(); + } + +private: + QOpenGLFramebufferObject m_fbo; +}; + +void tst_QGL::currentFboSync() +{ + if (!QGLFramebufferObject::hasOpenGLFramebufferObjects()) + QSKIP("QGLFramebufferObject not supported on this platform"); + +#if defined(Q_OS_QNX) + QSKIP("Reading the QGLFramebufferObject is unsupported on this platform"); +#endif + + QGLWidget glw; + glw.makeCurrent(); + + { + QGLFramebufferObject fbo1(256, 256, QGLFramebufferObject::CombinedDepthStencil); + + QOpenGLFramebufferObjectPaintDevice fbo2(256, 256); + + QImage sourceImage(256, 256, QImage::Format_ARGB32_Premultiplied); + QPainter sourcePainter(&sourceImage); + qt_opengl_draw_test_pattern(&sourcePainter, 256, 256); + + QPainter fbo1Painter(&fbo1); + + QPainter fbo2Painter(&fbo2); + fbo2Painter.drawImage(0, 0, sourceImage); + fbo2Painter.end(); + + QImage fbo2Image = fbo2.toImage(); + + fbo1Painter.drawImage(0, 0, sourceImage); + fbo1Painter.end(); + + QGLFramebufferObject::bindDefault(); + + QCOMPARE(fbo1.toImage(), fbo2Image); + } + + { + QGLFramebufferObject fbo1(512, 512, QGLFramebufferObject::CombinedDepthStencil); + + QOpenGLFramebufferObjectPaintDevice fbo2(256, 256); + + QImage sourceImage(256, 256, QImage::Format_ARGB32_Premultiplied); + QPainter sourcePainter(&sourceImage); + qt_opengl_draw_test_pattern(&sourcePainter, 256, 256); + + QPainter fbo2Painter(&fbo2); + fbo2Painter.drawImage(0, 0, sourceImage); + QImage fbo2Image1 = fbo2.toImage(); + fbo2Painter.fillRect(0, 0, 256, 256, Qt::white); + + QPainter fbo1Painter(&fbo1); + fbo1Painter.drawImage(0, 0, sourceImage); + fbo1Painter.end(); + + // check that the OpenGL paint engine now knows it needs to sync + fbo2Painter.drawImage(0, 0, sourceImage); + QImage fbo2Image2 = fbo2.toImage(); + + fbo2Painter.end(); + + QCOMPARE(fbo2Image1, fbo2Image2); + } +} // Tests multiple QPainters active on different FBOs at the same time, with // interleaving painting. Performance-wise, this is sub-optimal, but it still diff --git a/tests/auto/other/qaccessibility/BLACKLIST b/tests/auto/other/qaccessibility/BLACKLIST deleted file mode 100644 index 11598aece65..00000000000 --- a/tests/auto/other/qaccessibility/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[abstractScrollAreaTest] -osx diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp index 1c8121f1424..af0a0b446e9 100644 --- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp @@ -2648,57 +2648,67 @@ void tst_QAccessibility::abstractScrollAreaTest() // Horizontal scrollBar. abstractScrollArea.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - QCOMPARE(interface->childCount(), 2); QWidget *horizontalScrollBar = abstractScrollArea.horizontalScrollBar(); + + // On OS X >= 10.9 the scrollbar will be hidden unless explicitly enabled in the preferences + bool scrollBarsVisible = !horizontalScrollBar->style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, horizontalScrollBar); + int childCount = scrollBarsVisible ? 2 : 1; + QCOMPARE(interface->childCount(), childCount); QWidget *horizontalScrollBarContainer = horizontalScrollBar->parentWidget(); - QVERIFY(verifyChild(horizontalScrollBarContainer, interface, 1, globalGeometry)); + if (scrollBarsVisible) + QVERIFY(verifyChild(horizontalScrollBarContainer, interface, 1, globalGeometry)); // Horizontal scrollBar widgets. QLabel *secondLeftLabel = new QLabel(QLatin1String("L2")); abstractScrollArea.addScrollBarWidget(secondLeftLabel, Qt::AlignLeft); - QCOMPARE(interface->childCount(), 2); + QCOMPARE(interface->childCount(), childCount); QLabel *firstLeftLabel = new QLabel(QLatin1String("L1")); abstractScrollArea.addScrollBarWidget(firstLeftLabel, Qt::AlignLeft); - QCOMPARE(interface->childCount(), 2); + QCOMPARE(interface->childCount(), childCount); QLabel *secondRightLabel = new QLabel(QLatin1String("R2")); abstractScrollArea.addScrollBarWidget(secondRightLabel, Qt::AlignRight); - QCOMPARE(interface->childCount(), 2); + QCOMPARE(interface->childCount(), childCount); QLabel *firstRightLabel = new QLabel(QLatin1String("R1")); abstractScrollArea.addScrollBarWidget(firstRightLabel, Qt::AlignRight); - QCOMPARE(interface->childCount(), 2); + QCOMPARE(interface->childCount(), childCount); // Vertical scrollBar. abstractScrollArea.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - QCOMPARE(interface->childCount(), 3); + if (scrollBarsVisible) + ++childCount; + QCOMPARE(interface->childCount(), childCount); QWidget *verticalScrollBar = abstractScrollArea.verticalScrollBar(); QWidget *verticalScrollBarContainer = verticalScrollBar->parentWidget(); - QVERIFY(verifyChild(verticalScrollBarContainer, interface, 2, globalGeometry)); + if (scrollBarsVisible) + QVERIFY(verifyChild(verticalScrollBarContainer, interface, 2, globalGeometry)); // Vertical scrollBar widgets. QLabel *secondTopLabel = new QLabel(QLatin1String("T2")); abstractScrollArea.addScrollBarWidget(secondTopLabel, Qt::AlignTop); - QCOMPARE(interface->childCount(), 3); + QCOMPARE(interface->childCount(), childCount); QLabel *firstTopLabel = new QLabel(QLatin1String("T1")); abstractScrollArea.addScrollBarWidget(firstTopLabel, Qt::AlignTop); - QCOMPARE(interface->childCount(), 3); + QCOMPARE(interface->childCount(), childCount); QLabel *secondBottomLabel = new QLabel(QLatin1String("B2")); abstractScrollArea.addScrollBarWidget(secondBottomLabel, Qt::AlignBottom); - QCOMPARE(interface->childCount(), 3); + QCOMPARE(interface->childCount(), childCount); QLabel *firstBottomLabel = new QLabel(QLatin1String("B1")); abstractScrollArea.addScrollBarWidget(firstBottomLabel, Qt::AlignBottom); - QCOMPARE(interface->childCount(), 3); + QCOMPARE(interface->childCount(), childCount); // CornerWidget. + ++childCount; abstractScrollArea.setCornerWidget(new QLabel(QLatin1String("C"))); - QCOMPARE(interface->childCount(), 4); + QCOMPARE(interface->childCount(), childCount); QWidget *cornerWidget = abstractScrollArea.cornerWidget(); - QVERIFY(verifyChild(cornerWidget, interface, 3, globalGeometry)); + if (scrollBarsVisible) + QVERIFY(verifyChild(cornerWidget, interface, 3, globalGeometry)); QCOMPARE(verifyHierarchy(interface), 0); diff --git a/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp b/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp index 1be570e4b86..e3a72f4ab4d 100644 --- a/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp +++ b/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp @@ -1103,9 +1103,7 @@ void tst_QPrinter::fontEmbedding() { // fontEmbeddingEnabled() / setFontEmbeddingEnabled() / PPK_FontEmbedding // PdfFormat: Supported, default true - // NativeFormat, Cups: Supported, default true - // NativeFormat, Win: Unsupported, always false - // NativeFormat, Mac: Unsupported, always false + // NativeFormat: Supported, default true QPrinter pdf; pdf.setOutputFormat(QPrinter::PdfFormat); @@ -1116,25 +1114,17 @@ void tst_QPrinter::fontEmbedding() QPrinter native; if (native.outputFormat() == QPrinter::NativeFormat) { // Test default -#if defined Q_OS_MAC || defined Q_OS_WIN - QCOMPARE(native.fontEmbeddingEnabled(), false); -#else QCOMPARE(native.fontEmbeddingEnabled(), true); -#endif // Q_OS_MAC || Q_OS_WIN // Test set/get - bool expected = true; - native.setFontEmbeddingEnabled(expected); -#if defined Q_OS_MAC || defined Q_OS_WIN - expected = false; -#endif // Q_OS_MAC || Q_OS_WIN - QCOMPARE(native.fontEmbeddingEnabled(), expected); + native.setFontEmbeddingEnabled(true); + QCOMPARE(native.fontEmbeddingEnabled(), true); // Test value preservation native.setOutputFormat(QPrinter::PdfFormat); - QCOMPARE(native.fontEmbeddingEnabled(), expected); + QCOMPARE(native.fontEmbeddingEnabled(), true); native.setOutputFormat(QPrinter::NativeFormat); - QCOMPARE(native.fontEmbeddingEnabled(), expected); + QCOMPARE(native.fontEmbeddingEnabled(), true); } else { QSKIP("No printers installed, cannot test NativeFormat, please install printers to test"); } diff --git a/tests/auto/tools/moc/parse-defines.h b/tests/auto/tools/moc/parse-defines.h index c9b5d13b1f3..9a009558463 100644 --- a/tests/auto/tools/moc/parse-defines.h +++ b/tests/auto/tools/moc/parse-defines.h @@ -77,6 +77,8 @@ #define DEFINE_CMDLINE_SIGNAL void cmdlineSignal(const QMap &i) #endif +#define HASH_SIGN # + PD_BEGIN_NAMESPACE class DEFINE_CMDLINE_EMPTY PD_CLASSNAME DEFINE_CMDLINE_EMPTY diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index 965a16e7c2e..fe6ad6637a8 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -1565,7 +1565,7 @@ public slots: void doAnotherThing(bool a = (1 < 3), bool b = (1 > 4)) { Q_UNUSED(a); Q_UNUSED(b); } -#if defined(Q_MOC_RUN) || (defined(Q_COMPILER_AUTO_TYPE) && !(defined(Q_CC_CLANG) && (__clang_major__ * 100) + __clang_minor__) < 304) +#if defined(Q_MOC_RUN) || (defined(Q_COMPILER_AUTO_TYPE) && !(defined(Q_CC_CLANG) && Q_CC_CLANG < 304)) // There is no Q_COMPILER_>> but if compiler support auto, it should also support >> void performSomething(QVector> e = QVector>(8 < 1), QHash> h = QHash>()) diff --git a/tests/auto/widgets/dialogs/qfiledialog2/qfiledialog2.pro b/tests/auto/widgets/dialogs/qfiledialog2/qfiledialog2.pro index 5239614fc7e..fb432a7d218 100644 --- a/tests/auto/widgets/dialogs/qfiledialog2/qfiledialog2.pro +++ b/tests/auto/widgets/dialogs/qfiledialog2/qfiledialog2.pro @@ -20,4 +20,3 @@ wince* { DEFINES += SRCDIR=\\\"$$PWD/\\\" } -macx:CONFIG += insignificant_test # QTBUG-39183 diff --git a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp index 2ffb81a7513..241e6d0e7e6 100644 --- a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp +++ b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp @@ -448,6 +448,8 @@ void tst_QFileDialog2::task180459_lastDirectory_data() void tst_QFileDialog2::task180459_lastDirectory() { + if (qApp->platformName().toLower() == QStringLiteral("cocoa")) + QSKIP("Insignificant on OSX"); //QTBUG-39183 //first visit the temp directory and close the dialog QNonNativeFileDialog *dlg = new QNonNativeFileDialog(0, "", tempDir.path()); QFileSystemModel *model = dlg->findChild("qt_filesystem_model"); diff --git a/tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp b/tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp index 833494f25ef..bdf610e4264 100644 --- a/tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp +++ b/tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp @@ -71,6 +71,7 @@ tst_QGestureRecognizer::tst_QGestureRecognizer() : m_fingerDistance(qRound(QGuiApplication::primaryScreen()->physicalDotsPerInch() / 2.0)) , m_touchDevice(new QTouchDevice) { + qputenv("QT_PAN_TOUCHPOINTS", "2"); // Prevent device detection of pan touch point count. } void tst_QGestureRecognizer::initTestCase() diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/qgraphicsview.pro b/tests/auto/widgets/graphicsview/qgraphicsview/qgraphicsview.pro index 201085aecdb..d1f9bede0bf 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/qgraphicsview.pro +++ b/tests/auto/widgets/graphicsview/qgraphicsview/qgraphicsview.pro @@ -9,5 +9,4 @@ SOURCES += tst_qgraphicsview.cpp tst_qgraphicsview_2.cpp HEADERS += tst_qgraphicsview.h DEFINES += QT_NO_CAST_TO_ASCII -mac:CONFIG+=insignificant_test # QTBUG-26580 DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp index 8171277f362..04852721db3 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp @@ -143,6 +143,10 @@ class tst_QGraphicsView : public QObject { Q_OBJECT +public: + tst_QGraphicsView() + : platformName(qApp->platformName().toLower()) + { } private slots: void initTestCase(); void cleanup(); @@ -272,6 +276,7 @@ private: #if defined Q_OS_BLACKBERRY QScopedPointer rootWindow; #endif + QString platformName; }; void tst_QGraphicsView::initTestCase() @@ -2827,6 +2832,8 @@ void tst_QGraphicsView::scrollBarRanges() if (style == QLatin1String("GTK+") && useStyledPanel) QSKIP("GTK + style test skipped, see QTBUG-29002"); + if (useStyledPanel && style == QStringLiteral("Macintosh") && platformName == QStringLiteral("cocoa")) + QSKIP("Insignificant on OSX"); QGraphicsScene scene; QGraphicsView view(&scene); view.setRenderHint(QPainter::Antialiasing); @@ -4733,6 +4740,8 @@ public: void tst_QGraphicsView::hoverLeave() { + if (platformName == QStringLiteral("cocoa")) + QSKIP("Insignificant on OSX"); const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry(); QGraphicsScene scene; QGraphicsView view(&scene); diff --git a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp index 766065acda1..f000907e0e1 100644 --- a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp +++ b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp @@ -782,10 +782,8 @@ void tst_QItemDelegate::dateTimeEditor() widget.setFocus(); widget.editItem(item2); - QTestEventLoop::instance().enterLoop(1); - + QTRY_VERIFY(widget.viewport()->findChild()); QDateEdit *dateEditor = widget.viewport()->findChild(); - QVERIFY(dateEditor); QCOMPARE(dateEditor->date(), date); dateEditor->setDate(date.addDays(60)); diff --git a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp index 565eac2cbae..389ff6572d4 100644 --- a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp +++ b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp @@ -434,7 +434,7 @@ public: { QTableView::setModel(model); connect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), - this, SLOT(currentChanged(QModelIndex,QModelIndex))); + this, SLOT(slotCurrentChanged(QModelIndex,QModelIndex))); connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(itemSelectionChanged(QItemSelection,QItemSelection))); } @@ -495,7 +495,7 @@ public: bool checkSignalOrder; public slots: - void currentChanged(QModelIndex , QModelIndex ) { + void slotCurrentChanged(QModelIndex, QModelIndex) { hasCurrentChanged++; if (checkSignalOrder) QVERIFY(hasCurrentChanged > hasSelectionChanged); diff --git a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp index 7904848faf1..4b7e2a71981 100644 --- a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp +++ b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp @@ -61,6 +61,7 @@ private slots: void setText(); void setIconText_data() { setText_data(); } void setIconText(); + void setUnknownFont(); void actionEvent(); void setStandardKeys(); void alternateShortcuts(); @@ -184,6 +185,15 @@ void tst_QAction::setIconText() QCOMPARE(action.text(), textFromIconText); } +void tst_QAction::setUnknownFont() // QTBUG-42728 +{ + QAction action(0); + QFont font("DoesNotExist", 11); + action.setFont(font); + + QMenu menu; + menu.addAction(&action); // should not crash +} void tst_QAction::updateState(QActionEvent *e) { diff --git a/tests/auto/widgets/kernel/qwidget_window/qwidget_window.pro b/tests/auto/widgets/kernel/qwidget_window/qwidget_window.pro old mode 100755 new mode 100644 diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp old mode 100755 new mode 100644 index c6c74641941..36791293ab9 --- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp +++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp @@ -95,6 +95,8 @@ private slots: void tst_updateWinId_QTBUG40681(); void tst_recreateWindow_QTBUG40817(); + void tst_resize_count(); + void tst_move_count(); }; void tst_QWidget_window::initTestCase() @@ -660,6 +662,105 @@ void tst_QWidget_window::tst_recreateWindow_QTBUG40817() tab.setCurrentIndex(1); } +class ResizeWidget : public QWidget +{ +Q_OBJECT +public: + ResizeWidget(QWidget *parent = 0) + : QWidget(parent) + , resizeCount(0) + { } + + int resizeCount; + +protected: + void resizeEvent(QResizeEvent *) Q_DECL_OVERRIDE + { + resizeCount++; + } +}; + +void tst_QWidget_window::tst_resize_count() +{ + { + ResizeWidget resize; + resize.show(); + QVERIFY(QTest::qWaitForWindowExposed(&resize)); + QCOMPARE(resize.resizeCount, 1); + resize.resizeCount = 0; + QSize size = resize.size(); + size.rwidth() += 10; + resize.resize(size); + QGuiApplication::sync(); + QTRY_COMPARE(resize.resizeCount, 1); + + resize.resizeCount = 0; + + ResizeWidget child(&resize); + child.resize(200,200); + child.winId(); + child.show(); + QVERIFY(QTest::qWaitForWindowExposed(&child)); + QGuiApplication::sync(); + QTRY_COMPARE(child.resizeCount, 1); + child.resizeCount = 0; + size = child.size(); + size.rwidth() += 10; + child.resize(size); + QGuiApplication::sync(); + QCOMPARE(resize.resizeCount, 0); + QCOMPARE(child.resizeCount, 1); + } + { + ResizeWidget parent; + ResizeWidget child(&parent); + child.resize(200,200); + child.winId(); + parent.show(); + QVERIFY(QTest::qWaitForWindowExposed(&parent)); + parent.resizeCount = 0; + QGuiApplication::sync(); + QTRY_COMPARE(child.resizeCount, 1); + child.resizeCount = 0; + QSize size = child.size(); + size.rwidth() += 10; + child.resize(size); + QGuiApplication::sync(); + QCOMPARE(parent.resizeCount, 0); + QCOMPARE(child.resizeCount, 1); + } + +} + +class MoveWidget : public QWidget +{ +Q_OBJECT +public: + MoveWidget(QWidget *parent = 0) + : QWidget(parent) + , moveCount(0) + { } + + void moveEvent(QMoveEvent *) Q_DECL_OVERRIDE + { + moveCount++; + } + + int moveCount; +}; + +void tst_QWidget_window::tst_move_count() +{ + MoveWidget move; + move.move(500,500); + move.show(); + QVERIFY(QTest::qWaitForWindowExposed(&move)); + QTRY_VERIFY(move.moveCount >= 1); + move.moveCount = 0; + + move.move(220,250); + QTRY_VERIFY(move.moveCount >= 1); +} QTEST_MAIN(tst_QWidget_window) #include "tst_qwidget_window.moc" diff --git a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp index 27c803b43d7..751a16c59d9 100644 --- a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp +++ b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp @@ -104,6 +104,7 @@ public: tst_QMainWindow(); private slots: + void cleanup(); void getSetCheck(); void constructor(); void iconSize(); @@ -147,6 +148,12 @@ private slots: void QTBUG21378_animationFinished(); }; + +void tst_QMainWindow::cleanup() +{ + QVERIFY(QApplication::topLevelWidgets().isEmpty()); +} + // Testing get/set functions void tst_QMainWindow::getSetCheck() { @@ -854,6 +861,7 @@ void tst_QMainWindow::takeCentralWidget() { QVERIFY(!w2.isNull()); QCOMPARE(w2.data(), hopefullyW2); + delete w2; } void tst_QMainWindow::corner() diff --git a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp index f4579556578..ff9bc7c4a27 100644 --- a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp +++ b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp @@ -104,7 +104,7 @@ static bool tabBetweenSubWindowsIn(QMdiArea *mdiArea, int tabCount = -1, bool re if (tabCount > 1) QTest::qWait(500); if (walkThrough) { - QRubberBand *rubberBand = mdiArea->viewport()->findChild(); + QRubberBand *rubberBand = mdiArea->findChild(); if (!rubberBand) { qWarning("No rubber band"); return false; diff --git a/tests/manual/diaglib/README.txt b/tests/manual/diaglib/README.txt new file mode 100644 index 00000000000..13387f5a2a2 --- /dev/null +++ b/tests/manual/diaglib/README.txt @@ -0,0 +1,34 @@ +This is a collection of functions and classes helpful for diagnosing bugs +in Qt 4 and Qt 5. It can be included in the application's .pro file by +adding: + +include([path to Qt sources]/tests/manual/diaglib/diaglib.pri) + +For Qt 4, the environment variable QTDIR may be used: +include($$(QTDIR)/tests/manual/diaglib/diaglib.pri) + +The .pri file adds the define QT_DIAG_LIB, so, diagnostic +code can be enlosed within #ifdef to work without it as well. + +All functions and classes are in the QtDiag namespace. + +class EventFilter (eventfilter.h): + An event filter that logs Qt events to qDebug() depending on + configured categories (for example mouse, keyboard, etc). + +function glInfo() (glinfo.h): + Returns a string describing the Open GL configuration (obtained + by querying GL_VENDOR and GL_RENDERER). Available only + when the QT qmake variable contains opengl. + +functions dumpNativeWindows(), dumpNativeQtTopLevels(): + These functions du,p out the hierarchy of native Windows. Currently + implemented for Windows only. + +function dumpAllWidgets() (qwidgetdump.h): + Dumps the hierarchy of QWidgets including information about flags, + visibility, geometry, etc. + +function dumpAllWindows() (qwindowdump.h): + Dumps the hierarchy of QWindows including information about flags, + visibility, geometry, etc. diff --git a/tests/manual/diaglib/diaglib.pri b/tests/manual/diaglib/diaglib.pri new file mode 100644 index 00000000000..138660f85ea --- /dev/null +++ b/tests/manual/diaglib/diaglib.pri @@ -0,0 +1,43 @@ +INCLUDEPATH += $$PWD +SOURCES += \ + $$PWD/eventfilter.cpp \ + $$PWD/qwindowdump.cpp \ + +HEADERS += \ + $$PWD/eventfilter.h \ + $$PWD/qwindowdump.h \ + $$PWD/nativewindowdump.h + +win32 { + SOURCES += $$PWD/nativewindowdump_win.cpp + LIBS *= -luser32 +} else { + SOURCES += $$PWD/nativewindowdump.cpp +} + +greaterThan(QT_MAJOR_VERSION, 4) { + QT += gui-private core-private + contains(QT, widgets) { + HEADERS += \ + $$PWD/$$PWD/qwidgetdump.h + + SOURCES += \ + $$PWD/qwidgetdump.cpp + } +} else { + HEADERS += \ + $$PWD/$$PWD/qwidgetdump.h + + SOURCES += \ + $$PWD/qwidgetdump.cpp +} + +contains(QT, opengl) { +HEADERS += \ + $$PWD/glinfo.h + +SOURCES += \ + $$PWD/glinfo.cpp +} + +DEFINES += QT_DIAG_LIB diff --git a/tests/manual/diaglib/eventfilter.cpp b/tests/manual/diaglib/eventfilter.cpp new file mode 100644 index 00000000000..f0573975f67 --- /dev/null +++ b/tests/manual/diaglib/eventfilter.cpp @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** 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. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "eventfilter.h" +#include +#include +#include + +namespace QtDiag { + +EventFilter::EventFilter(EventCategories eventCategories, QObject *p) + : QObject(p) +{ + init(eventCategories); +} + +EventFilter::EventFilter(QObject *p) + : QObject(p) +{ + init(EventCategories(0xFFFFFFF)); +} + +void EventFilter::init(EventCategories eventCategories) +{ + if (eventCategories & MouseEvents) { + m_eventTypes << QEvent::MouseButtonPress << QEvent::MouseButtonRelease + << QEvent::MouseButtonDblClick << QEvent::NonClientAreaMouseButtonPress + << QEvent::NonClientAreaMouseButtonRelease + << QEvent::NonClientAreaMouseButtonDblClick + << QEvent::Enter << QEvent::Leave; + } + if (eventCategories & MouseMoveEvents) + m_eventTypes << QEvent::MouseMove << QEvent::NonClientAreaMouseMove; + if (eventCategories & TouchEvents) { + m_eventTypes << QEvent::TouchBegin << QEvent::TouchUpdate << QEvent::TouchEnd; +#if QT_VERSION >= 0x050000 + m_eventTypes << QEvent::TouchCancel; +#endif + } + if (eventCategories & TabletEvents) { + m_eventTypes << QEvent::TabletEnterProximity << QEvent::TabletLeaveProximity + << QEvent::TabletMove << QEvent::TabletPress << QEvent::TabletRelease; + } + if (eventCategories & DragAndDropEvents) { + m_eventTypes << QEvent::DragEnter << QEvent::DragMove << QEvent::DragLeave + << QEvent::Drop << QEvent::DragResponse; + } + if (eventCategories & KeyEvents) { + m_eventTypes << QEvent::KeyPress << QEvent::KeyRelease << QEvent::ShortcutOverride + << QEvent::Shortcut; + } + if (eventCategories & GeometryEvents) + m_eventTypes << QEvent::Move << QEvent::Resize; + if (eventCategories & PaintEvents) { + m_eventTypes << QEvent::UpdateRequest << QEvent::Paint + << QEvent::Show << QEvent::Hide; +#if QT_VERSION >= 0x050000 + m_eventTypes << QEvent::Expose; +#endif + } + if (eventCategories & TimerEvents) + m_eventTypes << QEvent::Timer << QEvent::ZeroTimerEvent; + if (eventCategories & ObjectEvents) { + m_eventTypes << QEvent::ChildAdded << QEvent::ChildPolished + << QEvent::ChildRemoved << QEvent::Create << QEvent::Destroy; + } +} + +bool EventFilter::eventFilter(QObject *o, QEvent *e) +{ + static int n = 0; + if (m_eventTypes.contains(e->type())) { + QDebug debug = qDebug().nospace(); + const QString on = o->objectName(); + debug << '#' << n++ << ' ' << o->metaObject()->className(); + if (!on.isEmpty()) + debug << '/' << on; + debug << ' ' << e; + } + return false; +} + +} // namespace QtDiag diff --git a/tests/manual/diaglib/eventfilter.h b/tests/manual/diaglib/eventfilter.h new file mode 100644 index 00000000000..d87ac68b076 --- /dev/null +++ b/tests/manual/diaglib/eventfilter.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** 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. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _EVENTFILTER_ +#define _EVENTFILTER_ + +#include +#include +#include + +namespace QtDiag { + +// Event filter that can for example be installed on QApplication +// to log relevant events. + +class EventFilter : public QObject { +public: + enum EventCategory { + MouseEvents = 0x00001, + MouseMoveEvents = 0x00002, + TouchEvents = 0x00004, + TabletEvents = 0x00008, + DragAndDropEvents = 0x00010, + KeyEvents = 0x00020, + GeometryEvents = 0x00040, + PaintEvents = 0x00080, + TimerEvents = 0x00100, + ObjectEvents = 0x00200 + }; + Q_DECLARE_FLAGS(EventCategories, EventCategory) + + explicit EventFilter(EventCategories eventCategories, QObject *p = 0); + explicit EventFilter(QObject *p = 0); + + bool eventFilter(QObject *, QEvent *); + +private: + void init(EventCategories eventCategories); + + QList m_eventTypes; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(EventFilter::EventCategories) + +} // namespace QtDiag + +#endif diff --git a/tests/manual/diaglib/glinfo.cpp b/tests/manual/diaglib/glinfo.cpp new file mode 100644 index 00000000000..cd30e46b451 --- /dev/null +++ b/tests/manual/diaglib/glinfo.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** 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. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "glinfo.h" + +#include +#include +#if QT_VERSION > 0x050000 +# if QT_VERSION >= 0x050400 +# include +# include +# else // 5.4 +# include +# endif // 5.0..5.4 +# include +# include +# include +#endif +#include +#include +#include + +namespace QtDiag { + +#if QT_VERSION > 0x050000 + +static QString getGlString(const QOpenGLContext *ctx, GLenum name) +{ + if (const GLubyte *p = ctx->functions()->glGetString(name)) + return QString::fromLatin1(reinterpret_cast(p)); + return QString(); +} + +static QString glInfo(const QOpenGLContext *ctx) +{ + return getGlString(ctx, GL_VENDOR) + + QLatin1Char('\n') + + getGlString(ctx, GL_RENDERER); +} + +static QString glInfo(const QGLContext *ctx) +{ + return glInfo(ctx->contextHandle()); +} + +QString glInfo(const QObject *o) +{ +# if QT_VERSION >= 0x050400 + if (o->isWindowType()) { + if (const QOpenGLWindow *oglw = qobject_cast(o)) + return glInfo(oglw->context()); + return QString(); + } +# endif // 5.4 + if (o->isWidgetType()) { + if (const QGLWidget *g = qobject_cast(o)) + return glInfo(g->context()); +# if QT_VERSION >= 0x050400 + if (const QOpenGLWidget *g = qobject_cast(o)) + return glInfo(g->context()); +# endif // 5.4 + } + return QString(); +} + +#else // Qt4: + +static QString getGlString(GLenum name) +{ + if (const GLubyte *p = glGetString(name)) + return QString::fromLatin1(reinterpret_cast(p)); + return QString(); +} + +QString glInfo(const QWidget *) +{ + return getGlString(GL_VENDOR) + QLatin1Char('\n') + getGlString(GL_RENDERER); +} + +#endif + +} // namespace QtDiag diff --git a/tests/manual/diaglib/glinfo.h b/tests/manual/diaglib/glinfo.h new file mode 100644 index 00000000000..1f515267f2d --- /dev/null +++ b/tests/manual/diaglib/glinfo.h @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** 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. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _GLINFO_ +#define _GLINFO_ + +#include + +QT_FORWARD_DECLARE_CLASS(QObject) +QT_FORWARD_DECLARE_CLASS(QString) + +namespace QtDiag { + +QString glInfo(const QObject *o); + +} // namespace QtDiag + +#endif diff --git a/tests/manual/diaglib/nativewindowdump.cpp b/tests/manual/diaglib/nativewindowdump.cpp new file mode 100644 index 00000000000..a6c741a0856 --- /dev/null +++ b/tests/manual/diaglib/nativewindowdump.cpp @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** 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. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "nativewindowdump.h" + +namespace QtDiag { + +void dumpNativeWindows(WId) +{ +} + +void dumpNativeQtTopLevels() +{ +} + +} // namespace QtDiag diff --git a/tests/manual/diaglib/nativewindowdump.h b/tests/manual/diaglib/nativewindowdump.h new file mode 100644 index 00000000000..405998feeaa --- /dev/null +++ b/tests/manual/diaglib/nativewindowdump.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** 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. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _NATIVEWINDOWDUMP_ +#define _NATIVEWINDOWDUMP_ + +#include + +namespace QtDiag { + +void dumpNativeWindows(WId root = 0); +void dumpNativeQtTopLevels(); + +} // namespace QtDiag + +#endif diff --git a/tests/manual/diaglib/nativewindowdump_win.cpp b/tests/manual/diaglib/nativewindowdump_win.cpp new file mode 100644 index 00000000000..814b580f4b0 --- /dev/null +++ b/tests/manual/diaglib/nativewindowdump_win.cpp @@ -0,0 +1,207 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** 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. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "nativewindowdump.h" +#include "qwindowdump.h" + +#include +#include +#include +#include + +#include + +namespace QtDiag { + +struct DumpContext { + DumpContext() : indentation(0) {} + + int indentation; + QSharedPointer stream; +}; + +#define debugWinStyle(str, style, styleConstant) \ +if (style & styleConstant) \ + str << ' ' << #styleConstant; + +static void formatNativeWindow(HWND hwnd, QTextStream &str) +{ + str << hex << showbase << quintptr(hwnd) << noshowbase << dec; + RECT rect; + if (GetWindowRect(hwnd, &rect)) { + str << ' ' << (rect.right - rect.left) << 'x' << (rect.bottom - rect.top) + << '+' << rect.left << '+' << rect.top; + } + if (IsWindowVisible(hwnd)) + str << " [visible]"; + + str << hex << showbase; + if (const LONG_PTR style = GetWindowLongPtr(hwnd, GWL_STYLE)) { + str << " style=" << style; + debugWinStyle(str, style, WS_OVERLAPPED) + debugWinStyle(str, style, WS_POPUP) + debugWinStyle(str, style, WS_MINIMIZE) + debugWinStyle(str, style, WS_CHILD) + debugWinStyle(str, style, WS_VISIBLE) + debugWinStyle(str, style, WS_DISABLED) + debugWinStyle(str, style, WS_CLIPSIBLINGS) + debugWinStyle(str, style, WS_CLIPCHILDREN) + debugWinStyle(str, style, WS_MAXIMIZE) + debugWinStyle(str, style, WS_CAPTION) + debugWinStyle(str, style, WS_BORDER) + debugWinStyle(str, style, WS_DLGFRAME) + debugWinStyle(str, style, WS_VSCROLL) + debugWinStyle(str, style, WS_HSCROLL) + debugWinStyle(str, style, WS_SYSMENU) + debugWinStyle(str, style, WS_THICKFRAME) + debugWinStyle(str, style, WS_GROUP) + debugWinStyle(str, style, WS_TABSTOP) + debugWinStyle(str, style, WS_MINIMIZEBOX) + debugWinStyle(str, style, WS_MAXIMIZEBOX) + } + if (const LONG_PTR exStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE)) { + str << " exStyle=" << exStyle; + debugWinStyle(str, exStyle, WS_EX_DLGMODALFRAME) + debugWinStyle(str, exStyle, WS_EX_NOPARENTNOTIFY) + debugWinStyle(str, exStyle, WS_EX_TOPMOST) + debugWinStyle(str, exStyle, WS_EX_ACCEPTFILES) + debugWinStyle(str, exStyle, WS_EX_TRANSPARENT) + debugWinStyle(str, exStyle, WS_EX_MDICHILD) + debugWinStyle(str, exStyle, WS_EX_TOOLWINDOW) + debugWinStyle(str, exStyle, WS_EX_WINDOWEDGE) + debugWinStyle(str, exStyle, WS_EX_CLIENTEDGE) + debugWinStyle(str, exStyle, WS_EX_CONTEXTHELP) + debugWinStyle(str, exStyle, WS_EX_RIGHT) + debugWinStyle(str, exStyle, WS_EX_LEFT) + debugWinStyle(str, exStyle, WS_EX_RTLREADING) + debugWinStyle(str, exStyle, WS_EX_LTRREADING) + debugWinStyle(str, exStyle, WS_EX_LEFTSCROLLBAR) + debugWinStyle(str, exStyle, WS_EX_RIGHTSCROLLBAR) + debugWinStyle(str, exStyle, WS_EX_CONTROLPARENT) + debugWinStyle(str, exStyle, WS_EX_STATICEDGE) + debugWinStyle(str, exStyle, WS_EX_APPWINDOW) + debugWinStyle(str, exStyle, WS_EX_LAYERED) + debugWinStyle(str, exStyle, WS_EX_NOINHERITLAYOUT) + debugWinStyle(str, exStyle, WS_EX_NOREDIRECTIONBITMAP) + debugWinStyle(str, exStyle, WS_EX_LAYOUTRTL) + debugWinStyle(str, exStyle, WS_EX_COMPOSITED) + debugWinStyle(str, exStyle, WS_EX_NOACTIVATE) + } + str << noshowbase << dec; + + wchar_t buf[512]; + if (GetWindowText(hwnd, buf, sizeof(buf)/sizeof(buf[0]))) + str << " title=\"" << QString::fromWCharArray(buf) << '"'; + if (GetClassName(hwnd, buf, sizeof(buf)/sizeof(buf[0]))) + str << " class=\"" << QString::fromWCharArray(buf) << '"'; + str << '\n'; +} + +static void dumpNativeWindowRecursion(HWND hwnd, DumpContext *dc); + +BOOL CALLBACK dumpWindowEnumChildProc(HWND hwnd, LPARAM lParam) +{ + dumpNativeWindowRecursion(hwnd, reinterpret_cast(lParam)); + return TRUE; +} + +static void dumpNativeWindowRecursion(HWND hwnd, DumpContext *dc) +{ + indentStream(*dc->stream, dc->indentation); + formatNativeWindow(hwnd, *dc->stream); + DumpContext nextLevel = *dc; + nextLevel.indentation += 2; + EnumChildWindows(hwnd, dumpWindowEnumChildProc, reinterpret_cast(&nextLevel)); +} + +/* recurse by Z order, same result */ +static void dumpNativeWindowRecursionByZ(HWND hwnd, DumpContext *dc) +{ + indentStream(*dc->stream, dc->indentation); + formatNativeWindow(hwnd, *dc->stream); + if (const HWND topChild = GetTopWindow(hwnd)) { + DumpContext nextLevel = *dc; + nextLevel.indentation += 2; + for (HWND child = topChild; child ; child = GetNextWindow(child, GW_HWNDNEXT)) + dumpNativeWindowRecursionByZ(child, &nextLevel); + } +} + +typedef QVector WIdVector; + +static void dumpNativeWindows(const WIdVector& wins) +{ + DumpContext dc; + QString s; + dc.stream = QSharedPointer(new QTextStream(&s)); + foreach (WId win, wins) + dumpNativeWindowRecursion(reinterpret_cast(win), &dc); +#if QT_VERSION > 0x050000 + qDebug().noquote() << s; +#else + qDebug("%s", qPrintable(s)); +#endif +} + +void dumpNativeWindows(WId rootIn) +{ + const WId root = rootIn ? rootIn : reinterpret_cast(GetDesktopWindow()); + dumpNativeWindows(WIdVector(1, root)); +} + +BOOL CALLBACK findQtTopLevelEnumChildProc(HWND hwnd, LPARAM lParam) +{ + WIdVector *v = reinterpret_cast(lParam); + wchar_t buf[512]; + if (GetClassName(hwnd, buf, sizeof(buf)/sizeof(buf[0]))) { + if (wcsstr(buf, L"Qt")) + v->append(reinterpret_cast(hwnd)); + } + return TRUE; +} + +static WIdVector findQtTopLevels() +{ + WIdVector result; + EnumChildWindows(GetDesktopWindow(), + findQtTopLevelEnumChildProc, + reinterpret_cast(&result)); + return result; +} + +void dumpNativeQtTopLevels() +{ + dumpNativeWindows(findQtTopLevels()); +} + +} // namespace QtDiag diff --git a/tests/manual/diaglib/qwidgetdump.cpp b/tests/manual/diaglib/qwidgetdump.cpp new file mode 100644 index 00000000000..d4f985c7c82 --- /dev/null +++ b/tests/manual/diaglib/qwidgetdump.cpp @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** 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. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwidgetdump.h" + +#include +#if QT_VERSION > 0x050000 +# include +# include +#endif +#include +#include +#include +#include + +namespace QtDiag { + +static void dumpWidgetRecursion(QTextStream &str, const QWidget *w, + FormatWindowOptions options, int depth = 0) +{ + indentStream(str, 2 * depth); + formatObject(str, w); + str << ' ' << (w->isVisible() ? "[visible] " : "[hidden] "); + if (const WId nativeWinId = w->internalWinId()) + str << "[native: " << hex << showbase << nativeWinId << dec << noshowbase << "] "; + if (w->isWindow()) + str << "[top] "; + str << (w->testAttribute(Qt::WA_Mapped) ? "[mapped] " : "[not mapped] "); + if (w->testAttribute(Qt::WA_DontCreateNativeAncestors)) + str << "[NoNativeAncestors] "; + formatRect(str, w->geometry()); + if (!(options & DontPrintWindowFlags)) { + str << ' '; + formatWindowFlags(str, w->windowFlags()); + } + str << '\n'; +#if QT_VERSION > 0x050000 + if (const QWindow *win = w->windowHandle()) { + indentStream(str, 2 * (1 + depth)); + formatWindow(str, win, options); + str << '\n'; + } +#endif // Qt 5 + foreach (const QObject *co, w->children()) { + if (co->isWidgetType()) + dumpWidgetRecursion(str, static_cast(co), options, depth + 1); + } +} + +void dumpAllWidgets(FormatWindowOptions options) +{ + QString d; + QTextStream str(&d); + str << "### QWidgets:\n"; + foreach (QWidget *tw, QApplication::topLevelWidgets()) + dumpWidgetRecursion(str, tw, options); +#if QT_VERSION > 0x050000 + qDebug().noquote() << d; +#else + qDebug("%s", qPrintable(d)); +#endif +} + +} // namespace QtDiag diff --git a/tests/manual/diaglib/qwidgetdump.h b/tests/manual/diaglib/qwidgetdump.h new file mode 100644 index 00000000000..f9615b5d2fe --- /dev/null +++ b/tests/manual/diaglib/qwidgetdump.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** 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. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _WIDGETDUMP_ +#define _WIDGETDUMP_ + +#include "qwindowdump.h" + +namespace QtDiag { + +void dumpAllWidgets(FormatWindowOptions options = 0); + +} // namespace QtDiag + +#endif diff --git a/tests/manual/diaglib/qwindowdump.cpp b/tests/manual/diaglib/qwindowdump.cpp new file mode 100644 index 00000000000..2ecc52ca779 --- /dev/null +++ b/tests/manual/diaglib/qwindowdump.cpp @@ -0,0 +1,176 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** 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. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwindowdump.h" + +#if QT_VERSION > 0x050000 +# include +# include +# include +# include +#endif +#include +#include +#include +#include + +namespace QtDiag { + +void indentStream(QTextStream &s, int indent) +{ + for (int i = 0; i < indent; ++i) + s << ' '; +} + +void formatObject(QTextStream &str, const QObject *o) +{ + str << o->metaObject()->className(); + const QString on = o->objectName(); + if (!on.isEmpty()) + str << "/\"" << on << '"'; +} + +void formatRect(QTextStream &str, const QRect &geom) +{ + str << geom.width() << 'x' << geom.height() + << forcesign << geom.x() << geom.y() << noforcesign; +} + +#define debugType(s, type, typeConstant) \ +if ((type & typeConstant) == typeConstant) \ + s << ' ' << #typeConstant; + +#define debugFlag(s, flags, flagConstant) \ +if (flags & flagConstant) \ + s << ' ' << #flagConstant; + +void formatWindowFlags(QTextStream &str, const Qt::WindowFlags flags) +{ + str << showbase << hex << unsigned(flags) << dec << noshowbase; + const Qt::WindowFlags windowType = flags & Qt::WindowType_Mask; + debugFlag(str, flags, Qt::Window) + debugType(str, windowType, Qt::Dialog) + debugType(str, windowType, Qt::Sheet) + debugType(str, windowType, Qt::Drawer) + debugType(str, windowType, Qt::Popup) + debugType(str, windowType, Qt::Tool) + debugType(str, windowType, Qt::ToolTip) + debugType(str, windowType, Qt::SplashScreen) + debugType(str, windowType, Qt::Desktop) + debugType(str, windowType, Qt::SubWindow) +#if QT_VERSION > 0x050000 + debugType(str, windowType, Qt::ForeignWindow) + debugType(str, windowType, Qt::CoverWindow) +#endif + debugFlag(str, flags, Qt::MSWindowsFixedSizeDialogHint) + debugFlag(str, flags, Qt::MSWindowsOwnDC) + debugFlag(str, flags, Qt::X11BypassWindowManagerHint) + debugFlag(str, flags, Qt::FramelessWindowHint) + debugFlag(str, flags, Qt::WindowTitleHint) + debugFlag(str, flags, Qt::WindowSystemMenuHint) + debugFlag(str, flags, Qt::WindowMinimizeButtonHint) + debugFlag(str, flags, Qt::WindowMaximizeButtonHint) + debugFlag(str, flags, Qt::WindowContextHelpButtonHint) + debugFlag(str, flags, Qt::WindowShadeButtonHint) + debugFlag(str, flags, Qt::WindowStaysOnTopHint) + debugFlag(str, flags, Qt::CustomizeWindowHint) +#if QT_VERSION > 0x050000 + debugFlag(str, flags, Qt::WindowTransparentForInput) + debugFlag(str, flags, Qt::WindowOverridesSystemGestures) + debugFlag(str, flags, Qt::WindowDoesNotAcceptFocus) + debugFlag(str, flags, Qt::NoDropShadowWindowHint) + debugFlag(str, flags, Qt::WindowFullscreenButtonHint) +#endif + debugFlag(str, flags, Qt::WindowStaysOnBottomHint) + debugFlag(str, flags, Qt::MacWindowToolBarButtonHint) + debugFlag(str, flags, Qt::BypassGraphicsProxyWidget) + debugFlag(str, flags, Qt::WindowOkButtonHint) + debugFlag(str, flags, Qt::WindowCancelButtonHint) +} + +#if QT_VERSION > 0x050000 + +void formatWindow(QTextStream &str, const QWindow *w, FormatWindowOptions options) +{ + const QPlatformWindow *pw = w->handle(); + formatObject(str, w); + str << ' ' << (w->isVisible() ? "[visible] " : "[hidden] "); + if (const WId nativeWinId = pw ? pw->winId() : WId(0)) + str << "[native: " << hex << showbase << nativeWinId << dec << noshowbase << "] "; + if (w->isTopLevel()) + str << "[top] "; + if (w->isExposed()) + str << "[exposed] "; + formatRect(str, w->geometry()); + if (!(options & DontPrintWindowFlags)) { + str << ' '; + formatWindowFlags(str, w->flags()); + } + str << '\n'; +} + +static void dumpWindowRecursion(QTextStream &str, const QWindow *w, + FormatWindowOptions options = 0, int depth = 0) +{ + indentStream(str, 2 * depth); + formatWindow(str, w); + foreach (const QObject *co, w->children()) { + if (co->isWindowType()) + dumpWindowRecursion(str, static_cast(co), options, depth + 1); + } +} + +void dumpAllWindows(FormatWindowOptions options) +{ + QString d; + QTextStream str(&d); + str << "### QWindows:\n"; + foreach (QWindow *w, QGuiApplication::topLevelWindows()) + dumpWindowRecursion(str, w, options); + qDebug().noquote() << d; +} + +#else // Qt 5 +class QWindow {}; + +void formatWindow(QTextStream &, const QWindow *, FormatWindowOptions) +{ +} + +void dumpAllWindows(FormatWindowOptions options) +{ +} + +#endif // Qt 4 + +} // namespace QtDiag diff --git a/src/plugins/bearer/networkmanager/qnmdbushelper.h b/tests/manual/diaglib/qwindowdump.h similarity index 58% rename from src/plugins/bearer/networkmanager/qnmdbushelper.h rename to tests/manual/diaglib/qwindowdump.h index e224af87f1d..ab7c0243e96 100644 --- a/src/plugins/bearer/networkmanager/qnmdbushelper.h +++ b/tests/manual/diaglib/qwindowdump.h @@ -3,7 +3,7 @@ ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** -** This file is part of the plugins of the Qt Toolkit. +** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage @@ -31,43 +31,33 @@ ** ****************************************************************************/ -#ifndef QNMDBUSHELPERPRIVATE_H -#define QNMDBUSHELPERPRIVATE_H +#ifndef _WINDOWDUMP_ +#define _WINDOWDUMP_ -#include -#include -#include +#include -#ifndef QT_NO_DBUS +QT_FORWARD_DECLARE_CLASS(QRect) +QT_FORWARD_DECLARE_CLASS(QObject) +QT_FORWARD_DECLARE_CLASS(QWindow) +QT_FORWARD_DECLARE_CLASS(QTextStream) -QT_BEGIN_NAMESPACE +namespace QtDiag { -class QNmDBusHelper: public QObject, protected QDBusContext - { - Q_OBJECT - public: - QNmDBusHelper(QObject *parent = 0); - ~QNmDBusHelper(); - - public slots: - void deviceStateChanged(quint32); - void slotAccessPointAdded(QDBusObjectPath); - void slotAccessPointRemoved(QDBusObjectPath); - void slotPropertiesChanged(QMap); - void slotSettingsRemoved(); - void activeConnectionPropertiesChanged(QMap); - -Q_SIGNALS: - void pathForStateChanged(const QString &, quint32); - void pathForAccessPointAdded(const QString &); - void pathForAccessPointRemoved(const QString &); - void pathForPropertiesChanged(const QString &, QMap); - void pathForSettingsRemoved(const QString &); - void pathForConnectionsChanged(const QStringList &pathsList); +enum FormatWindowOption { + DontPrintWindowFlags = 0x001 }; -QT_END_NAMESPACE +Q_DECLARE_FLAGS(FormatWindowOptions, FormatWindowOption) +Q_DECLARE_OPERATORS_FOR_FLAGS(FormatWindowOptions) -#endif // QT_NO_DBUS +void indentStream(QTextStream &s, int indent); +void formatObject(QTextStream &str, const QObject *o); +void formatRect(QTextStream &str, const QRect &geom); +void formatWindowFlags(QTextStream &str, const Qt::WindowFlags flags); -#endif// QNMDBUSHELPERPRIVATE_H +void formatWindow(QTextStream &str, const QWindow *w, FormatWindowOptions options = 0); +void dumpAllWindows(FormatWindowOptions options = 0); + +} // namespace QtDiag + +#endif diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro index e593756a7df..fe3e624bfea 100644 --- a/tests/manual/manual.pro +++ b/tests/manual/manual.pro @@ -29,6 +29,7 @@ qtabletevent \ qtexteditlist \ qtbug-8933 \ qtouchevent \ +touch \ qwidget_zorder \ repaint \ socketengine \ diff --git a/tests/manual/touch/main.cpp b/tests/manual/touch/main.cpp new file mode 100644 index 00000000000..6b06db614c2 --- /dev/null +++ b/tests/manual/touch/main.cpp @@ -0,0 +1,209 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** 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. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QDebug operator<<(QDebug debug, const QTouchDevice *d) +{ + QDebugStateSaver saver(debug); + debug.nospace(); + debug << "QTouchDevice(" << d->name() << ','; + switch (d->type()) { + case QTouchDevice::TouchScreen: + debug << "TouchScreen"; + break; + case QTouchDevice::TouchPad: + debug << "TouchPad"; + break; + } + debug << ", capabilities=" << d->capabilities() + << ", maximumTouchPoints=" << d->maximumTouchPoints() << ')'; + return debug; +} + +typedef QVector EventTypeVector; + +class EventFilter : public QObject { + Q_OBJECT +public: + explicit EventFilter(const EventTypeVector &types, QObject *p) : QObject(p), m_types(types) {} + + bool eventFilter(QObject *, QEvent *) Q_DECL_OVERRIDE; + +signals: + void eventReceived(const QString &); + +private: + const EventTypeVector m_types; +}; + +bool EventFilter::eventFilter(QObject *o, QEvent *e) +{ + static int n = 0; + if (m_types.contains(e->type())) { + QString message; + QDebug(&message) << '#' << n++ << ' ' << o->objectName() << ' ' << e; + emit eventReceived(message); + } + return false; +} + +class TouchTestWidget : public QWidget { +public: + explicit TouchTestWidget(QWidget *parent = 0) : QWidget(parent) + { + setAttribute(Qt::WA_AcceptTouchEvents); + } + + bool event(QEvent *event) Q_DECL_OVERRIDE + { + switch (event->type()) { + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + event->accept(); + return true; + default: + break; + } + return QWidget::event(event); + } +}; + +class MainWindow : public QMainWindow +{ + Q_OBJECT +public: + MainWindow(); + QWidget *touchWidget() const { return m_touchWidget; } + +public slots: + void appendToLog(const QString &text) { m_logTextEdit->appendPlainText(text); } + void dumpTouchDevices(); + +private: + QWidget *m_touchWidget; + QPlainTextEdit *m_logTextEdit; +}; + +MainWindow::MainWindow() + : m_touchWidget(new TouchTestWidget) + , m_logTextEdit(new QPlainTextEdit) +{ + setWindowTitle(QStringLiteral("Touch Event Tester ") + QT_VERSION_STR); + + setObjectName("MainWin"); + QMenu *fileMenu = menuBar()->addMenu("File"); + QAction *da = fileMenu->addAction(QStringLiteral("Dump devices")); + da->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_D)); + connect(da, SIGNAL(triggered()), this, SLOT(dumpTouchDevices())); + QAction *qa = fileMenu->addAction(QStringLiteral("Quit")); + qa->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q)); + connect(qa, SIGNAL(triggered()), this, SLOT(close())); + + QSplitter *mainSplitter = new QSplitter(Qt::Vertical); + + m_touchWidget->setObjectName(QStringLiteral("TouchWidget")); + const QSize screenSize = QGuiApplication::primaryScreen()->availableGeometry().size(); + m_touchWidget->setMinimumSize(screenSize / 2); + mainSplitter->addWidget(m_touchWidget); + + m_logTextEdit->setObjectName(QStringLiteral("LogTextEdit")); + m_logTextEdit->setMinimumHeight(screenSize.height() / 4); + mainSplitter->addWidget(m_logTextEdit); + setCentralWidget(mainSplitter); + + dumpTouchDevices(); +} + +void MainWindow::dumpTouchDevices() +{ + QString message; + QDebug debug(&message); + const QList devices = QTouchDevice::devices(); + debug << devices.size() << "Device(s):\n"; + for (int i = 0; i < devices.size(); ++i) + debug << "Device #" << i << devices.at(i) << '\n'; + appendToLog(message); +} + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + QCommandLineParser parser; + parser.setApplicationDescription(QStringLiteral("Touch/Mouse tester")); + parser.addHelpOption(); + const QCommandLineOption mouseMoveOption(QStringLiteral("mousemove"), + QStringLiteral("Log mouse move events")); + parser.addOption(mouseMoveOption); + const QCommandLineOption globalFilterOption(QStringLiteral("global"), + QStringLiteral("Global event filter")); + parser.addOption(globalFilterOption); + parser.process(QApplication::arguments()); + + MainWindow w; + w.show(); + const QSize pos = QGuiApplication::primaryScreen()->availableGeometry().size() - w.size(); + w.move(pos.width() / 2, pos.height() / 2); + + EventTypeVector eventTypes; + eventTypes << QEvent::MouseButtonPress << QEvent::MouseButtonRelease + << QEvent::MouseButtonDblClick + << QEvent::TouchBegin << QEvent::TouchUpdate << QEvent::TouchEnd; + if (parser.isSet(mouseMoveOption)) + eventTypes << QEvent::MouseMove; + QObject *filterTarget = parser.isSet(globalFilterOption) + ? static_cast(&a) + : static_cast(w.touchWidget()); + EventFilter *filter = new EventFilter(eventTypes, filterTarget); + filterTarget->installEventFilter(filter); + QObject::connect(filter, SIGNAL(eventReceived(QString)), &w, SLOT(appendToLog(QString))); + + return a.exec(); +} + +#include "main.moc" diff --git a/tests/manual/touch/touch.pro b/tests/manual/touch/touch.pro new file mode 100644 index 00000000000..fcb3c47f436 --- /dev/null +++ b/tests/manual/touch/touch.pro @@ -0,0 +1,5 @@ +TEMPLATE = app +QT = core gui +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets +CONFIG -= app_bundle +SOURCES += main.cpp