From aceaa510c89a9226170de6c60dc7dd21505e50f7 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 23 Apr 2018 14:47:17 -0700 Subject: [PATCH 01/92] Added referral to physical memory Test. Added menu items - `close` and `about` --- tools/auto-tester/src/Test.cpp | 78 +++++++++++++++++-------- tools/auto-tester/src/Test.h | 2 + tools/auto-tester/src/ui/AutoTester.cpp | 10 ++++ tools/auto-tester/src/ui/AutoTester.h | 2 + tools/auto-tester/src/ui/AutoTester.ui | 24 ++++++++ 5 files changed, 91 insertions(+), 25 deletions(-) diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index 99f9025fdd..57806e80f6 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -498,6 +498,12 @@ ExtractedText Test::getTestScriptLines(QString testFileName) { const QString regexAssertGPU(ws + functionAssertGPU + ws + "\\(" + ws + quotedString + ".*"); const QRegularExpression lineAssertGPU = QRegularExpression(regexAssertGPU); + // Assert the correct amount of memory + const QString functionAssertPhysicalMemoryGB(ws + "autoTester" + ws + "\\." + ws + "assertPhysicalMemoryGB"); + const QString regexAssertPhysicalMemoryGB(ws + functionAssertPhysicalMemoryGB + ws + "\\(" + ws + quotedString + ".*"); + const QRegularExpression lineAssertPhysicalMemoryGB = QRegularExpression(regexAssertPhysicalMemoryGB); + + // Each step is either of the following forms: // autoTester.addStepSnapshot("Take snapshot"... // autoTester.addStep("Clean up after test"... @@ -514,18 +520,27 @@ ExtractedText Test::getTestScriptLines(QString testFileName) { if (lineContainingTitle.match(line).hasMatch()) { QStringList tokens = line.split('"'); relevantTextFromTest.title = tokens[1]; + } else if (lineAssertPlatform.match(line).hasMatch()) { QStringList platforms = line.split('"'); relevantTextFromTest.platform = platforms[1]; + } else if (lineAssertDisplay.match(line).hasMatch()) { QStringList displays = line.split('"'); relevantTextFromTest.display = displays[1]; + } else if (lineAssertCPU.match(line).hasMatch()) { QStringList cpus = line.split('"'); relevantTextFromTest.cpu = cpus[1]; + } else if (lineAssertGPU.match(line).hasMatch()) { QStringList gpus = line.split('"'); relevantTextFromTest.gpu = gpus[1]; + + } else if (lineAssertPhysicalMemoryGB.match(line).hasMatch()) { + QStringList physicalMemoryGB = line.split('"'); + relevantTextFromTest.physicalMemoryGB = physicalMemoryGB[1]; + } else if (lineStepSnapshot.match(line).hasMatch()) { QStringList tokens = line.split('"'); QString nameOfStep = tokens[1]; @@ -534,6 +549,7 @@ ExtractedText Test::getTestScriptLines(QString testFileName) { step->text = nameOfStep; step->takeSnapshot = true; relevantTextFromTest.stepList.emplace_back(step); + } else if (lineStep.match(line).hasMatch()) { QStringList tokens = line.split('"'); QString nameOfStep = tokens[1]; @@ -630,62 +646,74 @@ void Test::createMDFile(QString testDirectory) { // Platform QStringList platforms = testScriptLines.platform.split(" ");; - stream << "## Platforms\n"; - stream << "Run the test on each of the following platforms\n"; - for (int i = 0; i < platforms.size(); ++i) { - // Note that the platforms parameter may include extra spaces, these appear as empty strings in the list - if (platforms[i] != QString()) { - stream << " - " << platforms[i] << "\n"; + if (platforms.size() > 0) { + stream << "## Platforms\n"; + stream << "Run the test on each of the following platforms\n"; + for (int i = 0; i < platforms.size(); ++i) { + // Note that the platforms parameter may include extra spaces, these appear as empty strings in the list + if (platforms[i] != QString()) { + stream << " - " << platforms[i] << "\n"; + } } } // Display QStringList displays = testScriptLines.display.split(" "); - stream << "## Displays\n"; - stream << "Run the test on each of the following displays\n"; - for (int i = 0; i < displays.size(); ++i) { - // Note that the displays parameter may include extra spaces, these appear as empty strings in the list - if (displays[i] != QString()) { - stream << " - " << displays[i] << "\n"; + if (displays.size()) { + stream << "## Displays\n"; + stream << "Run the test on each of the following displays\n"; + for (int i = 0; i < displays.size(); ++i) { + // Note that the displays parameter may include extra spaces, these appear as empty strings in the list + if (displays[i] != QString()) { + stream << " - " << displays[i] << "\n"; + } } } // CPU QStringList cpus = testScriptLines.cpu.split(" "); - stream << "## Processors\n"; - stream << "Run the test on each of the following processors\n"; - for (int i = 0; i < cpus.size(); ++i) { - // Note that the cpus parameter may include extra spaces, these appear as empty strings in the list - if (cpus[i] != QString()) { - stream << " - " << cpus[i] << "\n"; + if (cpus.size() > 0) { + stream << "## Processors\n"; + stream << "Run the test on each of the following processors\n"; + for (int i = 0; i < cpus.size(); ++i) { + // Note that the cpus parameter may include extra spaces, these appear as empty strings in the list + if (cpus[i] != QString()) { + stream << " - " << cpus[i] << "\n"; + } } } // GPU QStringList gpus = testScriptLines.gpu.split(" "); - stream << "## Graphics Cards\n"; - stream << "Run the test on graphics cards from each of the following vendors\n"; - for (int i = 0; i < gpus.size(); ++i) { - // Note that the gpus parameter may include extra spaces, these appear as empty strings in the list - if (gpus[i] != QString()) { - stream << " - " << gpus[i] << "\n"; + if (gpus.size() > 0) { + stream << "## Graphics Cards\n"; + stream << "Run the test on graphics cards from each of the following vendors\n"; + for (int i = 0; i < gpus.size(); ++i) { + // Note that the gpus parameter may include extra spaces, these appear as empty strings in the list + if (gpus[i] != QString()) { + stream << " - " << gpus[i] << "\n"; + } } } stream << "## Steps\n"; stream << "Press space bar to advance step by step\n\n"; + // Note that snapshots of step n are taken in step n+1 + // (this implies that if the LAST step requests a snapshot then this will not work - caveat emptor) int snapShotIndex { 0 }; for (size_t i = 0; i < testScriptLines.stepList.size(); ++i) { stream << "### Step " << QString::number(i + 1) << "\n"; stream << "- " << testScriptLines.stepList[i]->text << "\n"; - if (testScriptLines.stepList[i]->takeSnapshot) { + if ((i + 1 < testScriptLines.stepList.size()) && testScriptLines.stepList[i + 1]->takeSnapshot) { stream << "- ![](./ExpectedImage_" << QString::number(snapShotIndex).rightJustified(5, '0') << ".png)\n"; ++snapShotIndex; } } mdFile.close(); + + messageBox.information(0, "Success", "Test MD file " + mdFilename + " has been created"); } void Test::createTestsOutline() { diff --git a/tools/auto-tester/src/Test.h b/tools/auto-tester/src/Test.h index e69459fef2..7f5553f9e3 100644 --- a/tools/auto-tester/src/Test.h +++ b/tools/auto-tester/src/Test.h @@ -34,6 +34,8 @@ public: QString display; QString cpu; QString gpu; + QString physicalMemoryGB; + StepList stepList; }; diff --git a/tools/auto-tester/src/ui/AutoTester.cpp b/tools/auto-tester/src/ui/AutoTester.cpp index 21acfe9569..3f7d2cba28 100644 --- a/tools/auto-tester/src/ui/AutoTester.cpp +++ b/tools/auto-tester/src/ui/AutoTester.cpp @@ -10,6 +10,8 @@ // #include "AutoTester.h" +#include + AutoTester::AutoTester(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); ui.checkBoxInteractiveMode->setChecked(true); @@ -18,6 +20,9 @@ AutoTester::AutoTester(QWidget *parent) : QMainWindow(parent) { test = new Test(); signalMapper = new QSignalMapper(); + + connect(ui.actionClose, &QAction::triggered, this, &AutoTester::on_closeButton_clicked); + connect(ui.actionAbout, &QAction::triggered, this, &AutoTester::about); } void AutoTester::on_evaluateTestsButton_clicked() { @@ -100,3 +105,8 @@ void AutoTester::saveImage(int index) { ui.progressBar->setValue(_numberOfImagesDownloaded); } } + +void AutoTester::about() { + QMessageBox messageBox; + messageBox.information(0, "About", QString("Built ") + __DATE__ + " : " + __TIME__); +} \ No newline at end of file diff --git a/tools/auto-tester/src/ui/AutoTester.h b/tools/auto-tester/src/ui/AutoTester.h index 1788e97177..03cb7fbcec 100644 --- a/tools/auto-tester/src/ui/AutoTester.h +++ b/tools/auto-tester/src/ui/AutoTester.h @@ -37,6 +37,8 @@ private slots: void saveImage(int index); + void about(); + private: Ui::AutoTesterClass ui; Test* test; diff --git a/tools/auto-tester/src/ui/AutoTester.ui b/tools/auto-tester/src/ui/AutoTester.ui index 2eb1314481..c5115d69b2 100644 --- a/tools/auto-tester/src/ui/AutoTester.ui +++ b/tools/auto-tester/src/ui/AutoTester.ui @@ -157,6 +157,20 @@ 21 + + + File + + + + + + Help + + + + + @@ -167,6 +181,16 @@ + + + Close + + + + + About + + From 99ad51189c66ed5e6c2f425c55d39be9953df464 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Tue, 24 Apr 2018 23:03:56 +0100 Subject: [PATCH 02/92] fix browse asset filtering added support for list of filters using formatting consistent with other implementations, e.g: (*.png *.wav) --- .../assetDialog/AssetDialogContent.qml | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/interface/resources/qml/dialogs/assetDialog/AssetDialogContent.qml b/interface/resources/qml/dialogs/assetDialog/AssetDialogContent.qml index 84f4c694ff..7c8a735ead 100644 --- a/interface/resources/qml/dialogs/assetDialog/AssetDialogContent.qml +++ b/interface/resources/qml/dialogs/assetDialog/AssetDialogContent.qml @@ -19,14 +19,14 @@ import "../fileDialog" Item { // Set from OffscreenUi::assetDialog() property alias dir: assetTableModel.folder - property alias filter: selectionType.filtersString // FIXME: Currently only supports simple filters, "*.xxx". + property alias filter: selectionType.filtersString property int options // Not used. property bool selectDirectory: false // Not implemented. - //property bool saveDialog: false; - //property bool multiSelect: false; + // property bool saveDialog: false; + // property bool multiSelect: false; property bool singleClickNavigate: false @@ -84,7 +84,7 @@ Item { size: 28 width: height enabled: destination !== "" - //onClicked: d.navigateHome(); + // onClicked: d.navigateHome(); onClicked: assetTableModel.folder = destination; } } @@ -227,7 +227,9 @@ Item { function onGetAllMappings(error, map) { var mappings, - fileTypeFilter, + fileTypeFilters = [], + filterListStart, + filterListEnd, index, path, fileName, @@ -248,7 +250,14 @@ Item { if (error === "") { mappings = Object.keys(map); - fileTypeFilter = filter.replace("*", "").toLowerCase(); + filter = filter.replace(/\s/g, ''); + filterListStart = filter.indexOf("("); + filterListEnd = filter.indexOf(")"); + if (filterListStart !== -1 && filterListEnd !== -1) { + fileTypeFilters = filter.substring(filterListStart + 2, filterListEnd).toLowerCase().split("*"); + } else if (filter !== "") { + fileTypeFilters[0] = filter.replace("*", "").toLowerCase(); + } for (i = 0, length = mappings.length; i < length; i++) { index = mappings[i].lastIndexOf("/"); @@ -259,7 +268,24 @@ Item { fileIsDir = false; isValid = false; - if (fileType.toLowerCase() === fileTypeFilter) { + if (fileTypeFilters.length > 1) { + if (fileTypeFilters.indexOf(fileType.toLowerCase()) !== -1) { + if (path === folder) { + isValid = !selectDirectory; + } else if (path.length > folder.length) { + subDirectory = path.slice(folder.length); + index = subDirectory.indexOf("/"); + if (index === subDirectory.lastIndexOf("/")) { + fileName = subDirectory.slice(0, index); + if (subDirectories.indexOf(fileName) === -1) { + fileIsDir = true; + isValid = true; + subDirectories.push(fileName); + } + } + } + } + } else if (fileType.toLowerCase() === fileTypeFilters[0] || fileTypeFilters.length === 0) { if (path === folder) { isValid = !selectDirectory; } else if (path.length > folder.length) { From 21a9525a737e3db268cabdd82c0c60504a54444f Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Tue, 24 Apr 2018 17:52:12 -0700 Subject: [PATCH 03/92] Version of HMACAuth with exposed lock Client is responsible for locking between adding and retrieving. Fixes a likely race. --- libraries/networking/src/HMACAuth.cpp | 11 ++++++----- libraries/networking/src/HMACAuth.h | 2 ++ libraries/networking/src/LimitedNodeList.cpp | 5 +++-- libraries/networking/src/NLPacket.cpp | 1 + 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/libraries/networking/src/HMACAuth.cpp b/libraries/networking/src/HMACAuth.cpp index 42b5c48d93..e276e64b40 100644 --- a/libraries/networking/src/HMACAuth.cpp +++ b/libraries/networking/src/HMACAuth.cpp @@ -68,7 +68,7 @@ bool HMACAuth::setKey(const char* keyValue, int keyLen) { return false; } - QMutexLocker lock(&_lock); + //QMutexLocker lock(&_lock); return (bool) HMAC_Init_ex(_hmacContext, keyValue, keyLen, sslStruct, nullptr); } @@ -78,16 +78,17 @@ bool HMACAuth::setKey(const QUuid& uidKey) { } bool HMACAuth::addData(const char* data, int dataLen) { - QMutexLocker lock(&_lock); + //QMutexLocker lock(&_lock); return (bool) HMAC_Update(_hmacContext, reinterpret_cast(data), dataLen); } HMACAuth::HMACHash HMACAuth::result() { HMACHash hashValue(EVP_MAX_MD_SIZE); unsigned int hashLen; - QMutexLocker lock(&_lock); - HMAC_Final(_hmacContext, &hashValue[0], &hashLen); - hashValue.resize((size_t) hashLen); + //QMutexLocker lock(&_lock); + if (HMAC_Final(_hmacContext, &hashValue[0], &hashLen)) { + hashValue.resize((size_t)hashLen); + } // Clear state for possible reuse. HMAC_Init_ex(_hmacContext, nullptr, 0, nullptr, nullptr); return hashValue; diff --git a/libraries/networking/src/HMACAuth.h b/libraries/networking/src/HMACAuth.h index 0bf7a86ec1..ba1ec78214 100644 --- a/libraries/networking/src/HMACAuth.h +++ b/libraries/networking/src/HMACAuth.h @@ -26,6 +26,8 @@ public: explicit HMACAuth(AuthMethod authMethod = MD5); ~HMACAuth(); + QMutex& getLock() { return _lock; } + bool setKey(const char* keyValue, int keyLen); bool setKey(const QUuid& uidKey); bool addData(const char* data, int dataLen); diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 8d177ca534..d66dd644d5 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -333,13 +333,14 @@ bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packe QByteArray packetHeaderHash = NLPacket::verificationHashInHeader(packet); QByteArray expectedHash = NLPacket::hashForPacketAndHMAC(packet, sourceNode->getAuthenticateHash()); - // check if the md5 hash in the header matches the hash we would expect + // check if the HMAC-md5 hash in the header matches the hash we would expect if (packetHeaderHash != expectedHash) { static QMultiMap hashDebugSuppressMap; if (!hashDebugSuppressMap.contains(sourceID, headerType)) { - qCDebug(networking) << packetHeaderHash << expectedHash; qCDebug(networking) << "Packet hash mismatch on" << headerType << "- Sender" << sourceID; + qCDebug(networking) << "Packet len:" << packet.getDataSize() << "Expected hash:" << + expectedHash.toHex() << "Actual:" << packetHeaderHash.toHex(); hashDebugSuppressMap.insert(sourceID, headerType); } diff --git a/libraries/networking/src/NLPacket.cpp b/libraries/networking/src/NLPacket.cpp index 3355e1cd6b..09a7b78840 100644 --- a/libraries/networking/src/NLPacket.cpp +++ b/libraries/networking/src/NLPacket.cpp @@ -157,6 +157,7 @@ QByteArray NLPacket::hashForPacketAndHMAC(const udt::Packet& packet, HMACAuth& h + NUM_BYTES_LOCALID + NUM_BYTES_MD5_HASH; // add the packet payload and the connection UUID + QMutexLocker hashLock(&hash.getLock()); hash.addData(packet.getData() + offset, packet.getDataSize() - offset); auto hashResult { hash.result() }; return QByteArray((const char*) hashResult.data(), (int) hashResult.size()); From bd72350287c31a12edc65094e05febcf2343f132 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Wed, 25 Apr 2018 12:47:55 +0100 Subject: [PATCH 04/92] describe magic number --- .../resources/qml/dialogs/assetDialog/AssetDialogContent.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/dialogs/assetDialog/AssetDialogContent.qml b/interface/resources/qml/dialogs/assetDialog/AssetDialogContent.qml index 7c8a735ead..cd9ce226c0 100644 --- a/interface/resources/qml/dialogs/assetDialog/AssetDialogContent.qml +++ b/interface/resources/qml/dialogs/assetDialog/AssetDialogContent.qml @@ -254,7 +254,8 @@ Item { filterListStart = filter.indexOf("("); filterListEnd = filter.indexOf(")"); if (filterListStart !== -1 && filterListEnd !== -1) { - fileTypeFilters = filter.substring(filterListStart + 2, filterListEnd).toLowerCase().split("*"); + var FIRST_EXTENSION_OFFSET = 2; + fileTypeFilters = filter.substring(filterListStart + FIRST_EXTENSION_OFFSET, filterListEnd).toLowerCase().split("*"); } else if (filter !== "") { fileTypeFilters[0] = filter.replace("*", "").toLowerCase(); } From bd6b6c94232d7308842df7bddbff68a9b5e7b1b6 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Wed, 25 Apr 2018 12:57:46 +0100 Subject: [PATCH 05/92] fix content within 128 columns --- .../resources/qml/dialogs/assetDialog/AssetDialogContent.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/dialogs/assetDialog/AssetDialogContent.qml b/interface/resources/qml/dialogs/assetDialog/AssetDialogContent.qml index cd9ce226c0..ed442aa191 100644 --- a/interface/resources/qml/dialogs/assetDialog/AssetDialogContent.qml +++ b/interface/resources/qml/dialogs/assetDialog/AssetDialogContent.qml @@ -255,7 +255,8 @@ Item { filterListEnd = filter.indexOf(")"); if (filterListStart !== -1 && filterListEnd !== -1) { var FIRST_EXTENSION_OFFSET = 2; - fileTypeFilters = filter.substring(filterListStart + FIRST_EXTENSION_OFFSET, filterListEnd).toLowerCase().split("*"); + fileTypeFilters = filter.substring(filterListStart + FIRST_EXTENSION_OFFSET + , filterListEnd).toLowerCase().split("*"); } else if (filter !== "") { fileTypeFilters[0] = filter.replace("*", "").toLowerCase(); } From 3233cc43ac8d12a48e500130c6b7a91fbcff448c Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Wed, 25 Apr 2018 10:30:50 -0700 Subject: [PATCH 06/92] Revert "Merge pull request #12981 from birarda/bug/revert-hmac" This reverts commit 91b93db0c5f27a5b5c0282780ee56102078224be, reversing changes made to 6062f21da114f34164ba80db7e31bf45b959626e. --- libraries/networking/src/HMACAuth.cpp | 94 +++++++++++++++++++ libraries/networking/src/HMACAuth.h | 40 ++++++++ libraries/networking/src/LimitedNodeList.cpp | 36 +++---- libraries/networking/src/LimitedNodeList.h | 10 +- libraries/networking/src/NLPacket.cpp | 16 ++-- libraries/networking/src/NLPacket.h | 8 +- libraries/networking/src/Node.cpp | 14 ++- libraries/networking/src/Node.h | 5 +- .../networking/src/udt/PacketHeaders.cpp | 2 +- 9 files changed, 186 insertions(+), 39 deletions(-) create mode 100644 libraries/networking/src/HMACAuth.cpp create mode 100644 libraries/networking/src/HMACAuth.h diff --git a/libraries/networking/src/HMACAuth.cpp b/libraries/networking/src/HMACAuth.cpp new file mode 100644 index 0000000000..42b5c48d93 --- /dev/null +++ b/libraries/networking/src/HMACAuth.cpp @@ -0,0 +1,94 @@ +// +// HMACAuth.cpp +// libraries/networking/src +// +// Created by Simon Walton on 3/19/2018. +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include +#include + +#include "HMACAuth.h" + +#include + +#if OPENSSL_VERSION_NUMBER >= 0x10100000 +HMACAuth::HMACAuth(AuthMethod authMethod) + : _hmacContext(HMAC_CTX_new()) + , _authMethod(authMethod) { } + +HMACAuth::~HMACAuth() +{ + HMAC_CTX_free(_hmacContext); +} + +#else + +HMACAuth::HMACAuth(AuthMethod authMethod) + : _hmacContext(new HMAC_CTX()) + , _authMethod(authMethod) { + HMAC_CTX_init(_hmacContext); +} + +HMACAuth::~HMACAuth() { + HMAC_CTX_cleanup(_hmacContext); + delete _hmacContext; +} +#endif + +bool HMACAuth::setKey(const char* keyValue, int keyLen) { + const EVP_MD* sslStruct = nullptr; + + switch (_authMethod) { + case MD5: + sslStruct = EVP_md5(); + break; + + case SHA1: + sslStruct = EVP_sha1(); + break; + + case SHA224: + sslStruct = EVP_sha224(); + break; + + case SHA256: + sslStruct = EVP_sha256(); + break; + + case RIPEMD160: + sslStruct = EVP_ripemd160(); + break; + + default: + return false; + } + + QMutexLocker lock(&_lock); + return (bool) HMAC_Init_ex(_hmacContext, keyValue, keyLen, sslStruct, nullptr); +} + +bool HMACAuth::setKey(const QUuid& uidKey) { + const QByteArray rfcBytes(uidKey.toRfc4122()); + return setKey(rfcBytes.constData(), rfcBytes.length()); +} + +bool HMACAuth::addData(const char* data, int dataLen) { + QMutexLocker lock(&_lock); + return (bool) HMAC_Update(_hmacContext, reinterpret_cast(data), dataLen); +} + +HMACAuth::HMACHash HMACAuth::result() { + HMACHash hashValue(EVP_MAX_MD_SIZE); + unsigned int hashLen; + QMutexLocker lock(&_lock); + HMAC_Final(_hmacContext, &hashValue[0], &hashLen); + hashValue.resize((size_t) hashLen); + // Clear state for possible reuse. + HMAC_Init_ex(_hmacContext, nullptr, 0, nullptr, nullptr); + return hashValue; +} diff --git a/libraries/networking/src/HMACAuth.h b/libraries/networking/src/HMACAuth.h new file mode 100644 index 0000000000..0bf7a86ec1 --- /dev/null +++ b/libraries/networking/src/HMACAuth.h @@ -0,0 +1,40 @@ +// +// HMACAuth.h +// libraries/networking/src +// +// Created by Simon Walton on 3/19/2018. +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_HMACAuth_h +#define hifi_HMACAuth_h + +#include +#include +#include + +class QUuid; + +class HMACAuth { +public: + enum AuthMethod { MD5, SHA1, SHA224, SHA256, RIPEMD160 }; + using HMACHash = std::vector; + + explicit HMACAuth(AuthMethod authMethod = MD5); + ~HMACAuth(); + + bool setKey(const char* keyValue, int keyLen); + bool setKey(const QUuid& uidKey); + bool addData(const char* data, int dataLen); + HMACHash result(); + +private: + QMutex _lock; + struct hmac_ctx_st* _hmacContext; + AuthMethod _authMethod; +}; + +#endif // hifi_HMACAuth_h diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 92385e99b0..8d177ca534 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -36,6 +36,7 @@ #include "HifiSockAddr.h" #include "NetworkLogging.h" #include "udt/Packet.h" +#include "HMACAuth.h" static Setting::Handle LIMITED_NODELIST_LOCAL_PORT("LimitedNodeList.LocalPort", 0); @@ -330,7 +331,7 @@ bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packe if (verifiedPacket && !ignoreVerification) { QByteArray packetHeaderHash = NLPacket::verificationHashInHeader(packet); - QByteArray expectedHash = NLPacket::hashForPacketAndSecret(packet, sourceNode->getConnectionSecret()); + QByteArray expectedHash = NLPacket::hashForPacketAndHMAC(packet, sourceNode->getAuthenticateHash()); // check if the md5 hash in the header matches the hash we would expect if (packetHeaderHash != expectedHash) { @@ -370,15 +371,15 @@ void LimitedNodeList::collectPacketStats(const NLPacket& packet) { _numCollectedBytes += packet.getDataSize(); } -void LimitedNodeList::fillPacketHeader(const NLPacket& packet, const QUuid& connectionSecret) { +void LimitedNodeList::fillPacketHeader(const NLPacket& packet, HMACAuth* hmacAuth) { if (!PacketTypeEnum::getNonSourcedPackets().contains(packet.getType())) { packet.writeSourceID(getSessionLocalID()); } - if (!connectionSecret.isNull() + if (hmacAuth && !PacketTypeEnum::getNonSourcedPackets().contains(packet.getType()) && !PacketTypeEnum::getNonVerifiedPackets().contains(packet.getType())) { - packet.writeVerificationHashGivenSecret(connectionSecret); + packet.writeVerificationHash(*hmacAuth); } } @@ -394,17 +395,17 @@ qint64 LimitedNodeList::sendUnreliablePacket(const NLPacket& packet, const Node& emit dataSent(destinationNode.getType(), packet.getDataSize()); destinationNode.recordBytesSent(packet.getDataSize()); - return sendUnreliablePacket(packet, *destinationNode.getActiveSocket(), destinationNode.getConnectionSecret()); + return sendUnreliablePacket(packet, *destinationNode.getActiveSocket(), &destinationNode.getAuthenticateHash()); } qint64 LimitedNodeList::sendUnreliablePacket(const NLPacket& packet, const HifiSockAddr& sockAddr, - const QUuid& connectionSecret) { + HMACAuth* hmacAuth) { Q_ASSERT(!packet.isPartOfMessage()); Q_ASSERT_X(!packet.isReliable(), "LimitedNodeList::sendUnreliablePacket", "Trying to send a reliable packet unreliably."); collectPacketStats(packet); - fillPacketHeader(packet, connectionSecret); + fillPacketHeader(packet, hmacAuth); return _nodeSocket.writePacket(packet, sockAddr); } @@ -417,7 +418,7 @@ qint64 LimitedNodeList::sendPacket(std::unique_ptr packet, const Node& emit dataSent(destinationNode.getType(), packet->getDataSize()); destinationNode.recordBytesSent(packet->getDataSize()); - return sendPacket(std::move(packet), *activeSocket, destinationNode.getConnectionSecret()); + return sendPacket(std::move(packet), *activeSocket, &destinationNode.getAuthenticateHash()); } else { qCDebug(networking) << "LimitedNodeList::sendPacket called without active socket for node" << destinationNode << "- not sending"; return ERROR_SENDING_PACKET_BYTES; @@ -425,18 +426,18 @@ qint64 LimitedNodeList::sendPacket(std::unique_ptr packet, const Node& } qint64 LimitedNodeList::sendPacket(std::unique_ptr packet, const HifiSockAddr& sockAddr, - const QUuid& connectionSecret) { + HMACAuth* hmacAuth) { Q_ASSERT(!packet->isPartOfMessage()); if (packet->isReliable()) { collectPacketStats(*packet); - fillPacketHeader(*packet, connectionSecret); + fillPacketHeader(*packet, hmacAuth); auto size = packet->getDataSize(); _nodeSocket.writePacket(std::move(packet), sockAddr); return size; } else { - return sendUnreliablePacket(*packet, sockAddr, connectionSecret); + return sendUnreliablePacket(*packet, sockAddr, hmacAuth); } } @@ -445,13 +446,14 @@ qint64 LimitedNodeList::sendUnreliableUnorderedPacketList(NLPacketList& packetLi if (activeSocket) { qint64 bytesSent = 0; - auto connectionSecret = destinationNode.getConnectionSecret(); + auto& connectionHash = destinationNode.getAuthenticateHash(); // close the last packet in the list packetList.closeCurrentPacket(); while (!packetList._packets.empty()) { - bytesSent += sendPacket(packetList.takeFront(), *activeSocket, connectionSecret); + bytesSent += sendPacket(packetList.takeFront(), *activeSocket, + &connectionHash); } emit dataSent(destinationNode.getType(), bytesSent); @@ -464,14 +466,14 @@ qint64 LimitedNodeList::sendUnreliableUnorderedPacketList(NLPacketList& packetLi } qint64 LimitedNodeList::sendUnreliableUnorderedPacketList(NLPacketList& packetList, const HifiSockAddr& sockAddr, - const QUuid& connectionSecret) { + HMACAuth* hmacAuth) { qint64 bytesSent = 0; // close the last packet in the list packetList.closeCurrentPacket(); while (!packetList._packets.empty()) { - bytesSent += sendPacket(packetList.takeFront(), sockAddr, connectionSecret); + bytesSent += sendPacket(packetList.takeFront(), sockAddr, hmacAuth); } return bytesSent; @@ -499,7 +501,7 @@ qint64 LimitedNodeList::sendPacketList(std::unique_ptr packetList, for (std::unique_ptr& packet : packetList->_packets) { NLPacket* nlPacket = static_cast(packet.get()); collectPacketStats(*nlPacket); - fillPacketHeader(*nlPacket, destinationNode.getConnectionSecret()); + fillPacketHeader(*nlPacket, &destinationNode.getAuthenticateHash()); } return _nodeSocket.writePacketList(std::move(packetList), *activeSocket); @@ -522,7 +524,7 @@ qint64 LimitedNodeList::sendPacket(std::unique_ptr packet, const Node& auto& destinationSockAddr = (overridenSockAddr.isNull()) ? *destinationNode.getActiveSocket() : overridenSockAddr; - return sendPacket(std::move(packet), destinationSockAddr, destinationNode.getConnectionSecret()); + return sendPacket(std::move(packet), destinationSockAddr, &destinationNode.getAuthenticateHash()); } int LimitedNodeList::updateNodeWithDataFromPacket(QSharedPointer message, SharedNodePointer sendingNode) { diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 3d6fd0cd91..05374bbfbb 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -138,19 +138,17 @@ public: // use sendUnreliablePacket to send an unreliable packet (that you do not need to move) // either to a node (via its active socket) or to a manual sockaddr qint64 sendUnreliablePacket(const NLPacket& packet, const Node& destinationNode); - qint64 sendUnreliablePacket(const NLPacket& packet, const HifiSockAddr& sockAddr, - const QUuid& connectionSecret = QUuid()); + qint64 sendUnreliablePacket(const NLPacket& packet, const HifiSockAddr& sockAddr, HMACAuth* hmacAuth = nullptr); // use sendPacket to send a moved unreliable or reliable NL packet to a node's active socket or manual sockaddr qint64 sendPacket(std::unique_ptr packet, const Node& destinationNode); - qint64 sendPacket(std::unique_ptr packet, const HifiSockAddr& sockAddr, - const QUuid& connectionSecret = QUuid()); + qint64 sendPacket(std::unique_ptr packet, const HifiSockAddr& sockAddr, HMACAuth* hmacAuth = nullptr); // use sendUnreliableUnorderedPacketList to unreliably send separate packets from the packet list // either to a node's active socket or to a manual sockaddr qint64 sendUnreliableUnorderedPacketList(NLPacketList& packetList, const Node& destinationNode); qint64 sendUnreliableUnorderedPacketList(NLPacketList& packetList, const HifiSockAddr& sockAddr, - const QUuid& connectionSecret = QUuid()); + HMACAuth* hmacAuth = nullptr); // use sendPacketList to send reliable packet lists (ordered or unordered) to a node's active socket // or to a manual sock addr @@ -372,7 +370,7 @@ protected: qint64 writePacket(const NLPacket& packet, const HifiSockAddr& destinationSockAddr, const QUuid& connectionSecret = QUuid()); void collectPacketStats(const NLPacket& packet); - void fillPacketHeader(const NLPacket& packet, const QUuid& connectionSecret = QUuid()); + void fillPacketHeader(const NLPacket& packet, HMACAuth* hmacAuth = nullptr); void setLocalSocket(const HifiSockAddr& sockAddr); diff --git a/libraries/networking/src/NLPacket.cpp b/libraries/networking/src/NLPacket.cpp index ac3fbc966b..3355e1cd6b 100644 --- a/libraries/networking/src/NLPacket.cpp +++ b/libraries/networking/src/NLPacket.cpp @@ -11,6 +11,8 @@ #include "NLPacket.h" +#include "HMACAuth.h" + int NLPacket::localHeaderSize(PacketType type) { bool nonSourced = PacketTypeEnum::getNonSourcedPackets().contains(type); bool nonVerified = PacketTypeEnum::getNonVerifiedPackets().contains(type); @@ -150,18 +152,14 @@ QByteArray NLPacket::verificationHashInHeader(const udt::Packet& packet) { return QByteArray(packet.getData() + offset, NUM_BYTES_MD5_HASH); } -QByteArray NLPacket::hashForPacketAndSecret(const udt::Packet& packet, const QUuid& connectionSecret) { - QCryptographicHash hash(QCryptographicHash::Md5); - +QByteArray NLPacket::hashForPacketAndHMAC(const udt::Packet& packet, HMACAuth& hash) { int offset = Packet::totalHeaderSize(packet.isPartOfMessage()) + sizeof(PacketType) + sizeof(PacketVersion) + NUM_BYTES_LOCALID + NUM_BYTES_MD5_HASH; // add the packet payload and the connection UUID hash.addData(packet.getData() + offset, packet.getDataSize() - offset); - hash.addData(connectionSecret.toRfc4122()); - - // return the hash - return hash.result(); + auto hashResult { hash.result() }; + return QByteArray((const char*) hashResult.data(), (int) hashResult.size()); } void NLPacket::writeTypeAndVersion() { @@ -214,14 +212,14 @@ void NLPacket::writeSourceID(LocalID sourceID) const { _sourceID = sourceID; } -void NLPacket::writeVerificationHashGivenSecret(const QUuid& connectionSecret) const { +void NLPacket::writeVerificationHash(HMACAuth& hmacAuth) const { Q_ASSERT(!PacketTypeEnum::getNonSourcedPackets().contains(_type) && !PacketTypeEnum::getNonVerifiedPackets().contains(_type)); auto offset = Packet::totalHeaderSize(isPartOfMessage()) + sizeof(PacketType) + sizeof(PacketVersion) + NUM_BYTES_LOCALID; - QByteArray verificationHash = hashForPacketAndSecret(*this, connectionSecret); + QByteArray verificationHash = hashForPacketAndHMAC(*this, hmacAuth); memcpy(_packet.get() + offset, verificationHash.data(), verificationHash.size()); } diff --git a/libraries/networking/src/NLPacket.h b/libraries/networking/src/NLPacket.h index 9b07bc6581..4103f2068e 100644 --- a/libraries/networking/src/NLPacket.h +++ b/libraries/networking/src/NLPacket.h @@ -18,6 +18,8 @@ #include "udt/Packet.h" +class HMACAuth; + class NLPacket : public udt::Packet { Q_OBJECT public: @@ -69,7 +71,7 @@ public: static LocalID sourceIDInHeader(const udt::Packet& packet); static QByteArray verificationHashInHeader(const udt::Packet& packet); - static QByteArray hashForPacketAndSecret(const udt::Packet& packet, const QUuid& connectionSecret); + static QByteArray hashForPacketAndHMAC(const udt::Packet& packet, HMACAuth& hash); PacketType getType() const { return _type; } void setType(PacketType type); @@ -78,9 +80,9 @@ public: void setVersion(PacketVersion version); LocalID getSourceID() const { return _sourceID; } - + void writeSourceID(LocalID sourceID) const; - void writeVerificationHashGivenSecret(const QUuid& connectionSecret) const; + void writeVerificationHash(HMACAuth& hmacAuth) const; protected: diff --git a/libraries/networking/src/Node.cpp b/libraries/networking/src/Node.cpp index 73b7c44e7e..7979b36e30 100644 --- a/libraries/networking/src/Node.cpp +++ b/libraries/networking/src/Node.cpp @@ -86,10 +86,10 @@ NodeType_t NodeType::fromString(QString type) { Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket, - const HifiSockAddr& localSocket, QObject* parent) : + const HifiSockAddr& localSocket, QObject* parent) : NetworkPeer(uuid, publicSocket, localSocket, parent), _type(type), - _pingMs(-1), // "Uninitialized" + _authenticateHash(new HMACAuth), _pingMs(-1), // "Uninitialized" _clockSkewUsec(0), _mutex(), _clockSkewMovingPercentile(30, 0.8f) // moving 80th percentile of 30 samples @@ -108,6 +108,7 @@ void Node::setType(char type) { _symmetricSocket.setObjectName(typeString); } + void Node::updateClockSkewUsec(qint64 clockSkewSample) { _clockSkewMovingPercentile.updatePercentile(clockSkewSample); _clockSkewUsec = (quint64)_clockSkewMovingPercentile.getValueAtPercentile(); @@ -194,3 +195,12 @@ QDebug operator<<(QDebug debug, const Node& node) { debug.nospace() << node.getPublicSocket() << "/" << node.getLocalSocket(); return debug.nospace(); } + +void Node::setConnectionSecret(const QUuid& connectionSecret) { + if (_connectionSecret == connectionSecret) { + return; + } + + _connectionSecret = connectionSecret; + _authenticateHash->setKey(_connectionSecret); +} diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index 93b6a649d4..5b3b559582 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -33,6 +33,7 @@ #include "SimpleMovingAverage.h" #include "MovingPercentile.h" #include "NodePermissions.h" +#include "HMACAuth.h" class Node : public NetworkPeer { Q_OBJECT @@ -55,7 +56,8 @@ public: void setIsUpstream(bool isUpstream) { _isUpstream = isUpstream; } const QUuid& getConnectionSecret() const { return _connectionSecret; } - void setConnectionSecret(const QUuid& connectionSecret) { _connectionSecret = connectionSecret; } + void setConnectionSecret(const QUuid& connectionSecret); + HMACAuth& getAuthenticateHash() const { return *_authenticateHash; } NodeData* getLinkedData() const { return _linkedData.get(); } void setLinkedData(std::unique_ptr linkedData) { _linkedData = std::move(linkedData); } @@ -97,6 +99,7 @@ private: NodeType_t _type; QUuid _connectionSecret; + std::unique_ptr _authenticateHash; std::unique_ptr _linkedData; bool _isReplicated { false }; int _pingMs; diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 98b0e1d892..db466a0403 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -91,7 +91,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::Ping: return static_cast(PingVersion::IncludeConnectionID); default: - return 20; + return 19; } } From 4fa11f116fb17847c5bdcee167301f16d94cc2ce Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Wed, 25 Apr 2018 14:41:16 -0700 Subject: [PATCH 07/92] Add & use HMACAuth method that calculates hash atomically To avoid issues with race conditions involving separate addData() and result() calls use a method that does both in the lock. --- libraries/networking/src/HMACAuth.cpp | 25 +++++++++++++++++++++---- libraries/networking/src/HMACAuth.h | 5 +++-- libraries/networking/src/NLPacket.cpp | 7 ++++--- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/libraries/networking/src/HMACAuth.cpp b/libraries/networking/src/HMACAuth.cpp index e276e64b40..8aa2fea6a9 100644 --- a/libraries/networking/src/HMACAuth.cpp +++ b/libraries/networking/src/HMACAuth.cpp @@ -68,7 +68,7 @@ bool HMACAuth::setKey(const char* keyValue, int keyLen) { return false; } - //QMutexLocker lock(&_lock); + QMutexLocker lock(&_lock); return (bool) HMAC_Init_ex(_hmacContext, keyValue, keyLen, sslStruct, nullptr); } @@ -78,14 +78,14 @@ bool HMACAuth::setKey(const QUuid& uidKey) { } bool HMACAuth::addData(const char* data, int dataLen) { - //QMutexLocker lock(&_lock); + QMutexLocker lock(&_lock); return (bool) HMAC_Update(_hmacContext, reinterpret_cast(data), dataLen); } HMACAuth::HMACHash HMACAuth::result() { HMACHash hashValue(EVP_MAX_MD_SIZE); - unsigned int hashLen; - //QMutexLocker lock(&_lock); + unsigned int hashLen; + QMutexLocker lock(&_lock); if (HMAC_Final(_hmacContext, &hashValue[0], &hashLen)) { hashValue.resize((size_t)hashLen); } @@ -93,3 +93,20 @@ HMACAuth::HMACHash HMACAuth::result() { HMAC_Init_ex(_hmacContext, nullptr, 0, nullptr, nullptr); return hashValue; } + +bool HMACAuth::calculateHash(HMACHash& hashResult, const char* data, int dataLen) { + QMutexLocker lock(&_lock); + if (!HMAC_Update(_hmacContext, reinterpret_cast(data), dataLen)) { + return false; + } + + hashResult.resize(EVP_MAX_MD_SIZE); + unsigned int hashLen; + if (HMAC_Final(_hmacContext, &hashResult[0], &hashLen)) { + hashResult.resize((size_t)hashLen); + // Clear state for possible reuse. + HMAC_Init_ex(_hmacContext, nullptr, 0, nullptr, nullptr); + return true; + } + return false; +} diff --git a/libraries/networking/src/HMACAuth.h b/libraries/networking/src/HMACAuth.h index ba1ec78214..ec06bfbda2 100644 --- a/libraries/networking/src/HMACAuth.h +++ b/libraries/networking/src/HMACAuth.h @@ -26,10 +26,11 @@ public: explicit HMACAuth(AuthMethod authMethod = MD5); ~HMACAuth(); - QMutex& getLock() { return _lock; } - bool setKey(const char* keyValue, int keyLen); bool setKey(const QUuid& uidKey); + // Calculate complete hash in one. + bool calculateHash(HMACHash& hashResult, const char* data, int dataLen); + // Append data to be hashed. bool addData(const char* data, int dataLen); HMACHash result(); diff --git a/libraries/networking/src/NLPacket.cpp b/libraries/networking/src/NLPacket.cpp index 09a7b78840..f946e97bf4 100644 --- a/libraries/networking/src/NLPacket.cpp +++ b/libraries/networking/src/NLPacket.cpp @@ -157,9 +157,10 @@ QByteArray NLPacket::hashForPacketAndHMAC(const udt::Packet& packet, HMACAuth& h + NUM_BYTES_LOCALID + NUM_BYTES_MD5_HASH; // add the packet payload and the connection UUID - QMutexLocker hashLock(&hash.getLock()); - hash.addData(packet.getData() + offset, packet.getDataSize() - offset); - auto hashResult { hash.result() }; + HMACAuth::HMACHash hashResult; + if (!hash.calculateHash(hashResult, packet.getData() + offset, packet.getDataSize() - offset)) { + return QByteArray(); + } return QByteArray((const char*) hashResult.data(), (int) hashResult.size()); } From 66bd424ae4002a75cd3003f4e97df1322dd2143f Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Wed, 25 Apr 2018 14:51:11 -0700 Subject: [PATCH 08/92] Bump default packet version for new HMAC --- libraries/networking/src/udt/PacketHeaders.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index db466a0403..98b0e1d892 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -91,7 +91,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::Ping: return static_cast(PingVersion::IncludeConnectionID); default: - return 19; + return 20; } } From 9ef56c44a3da38161741cf4dc62f49e786c8e5b1 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Wed, 25 Apr 2018 17:08:08 -0700 Subject: [PATCH 09/92] Merge PR12964 to not use verification if not keyed https://github.com/highfidelity/hifi/pull/12964 --- libraries/networking/src/HMACAuth.cpp | 20 +++++++++++++++++--- libraries/networking/src/LimitedNodeList.cpp | 20 ++++++++++++-------- libraries/networking/src/Node.cpp | 6 +++++- libraries/networking/src/Node.h | 4 ++-- 4 files changed, 36 insertions(+), 14 deletions(-) diff --git a/libraries/networking/src/HMACAuth.cpp b/libraries/networking/src/HMACAuth.cpp index 8aa2fea6a9..8e57978b5a 100644 --- a/libraries/networking/src/HMACAuth.cpp +++ b/libraries/networking/src/HMACAuth.cpp @@ -9,12 +9,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "HMACAuth.h" + #include #include -#include "HMACAuth.h" - #include +#include "NetworkLogging.h" +#include #if OPENSSL_VERSION_NUMBER >= 0x10100000 HMACAuth::HMACAuth(AuthMethod authMethod) @@ -86,9 +88,17 @@ HMACAuth::HMACHash HMACAuth::result() { HMACHash hashValue(EVP_MAX_MD_SIZE); unsigned int hashLen; QMutexLocker lock(&_lock); - if (HMAC_Final(_hmacContext, &hashValue[0], &hashLen)) { + + auto hmacResult = HMAC_Final(_hmacContext, &hashValue[0], &hashLen); + + if (hmacResult) { hashValue.resize((size_t)hashLen); + } else { + // the HMAC_FINAL call failed - should not be possible to get into this state + qCWarning(networking) << "Error occured calling HMAC_Final"; + assert(hmacResult); } + // Clear state for possible reuse. HMAC_Init_ex(_hmacContext, nullptr, 0, nullptr, nullptr); return hashValue; @@ -97,6 +107,8 @@ HMACAuth::HMACHash HMACAuth::result() { bool HMACAuth::calculateHash(HMACHash& hashResult, const char* data, int dataLen) { QMutexLocker lock(&_lock); if (!HMAC_Update(_hmacContext, reinterpret_cast(data), dataLen)) { + qCWarning(networking) << "Error occured calling HMAC_Update"; + assert(false); return false; } @@ -108,5 +120,7 @@ bool HMACAuth::calculateHash(HMACHash& hashResult, const char* data, int dataLen HMAC_Init_ex(_hmacContext, nullptr, 0, nullptr, nullptr); return true; } + qCWarning(networking) << "Error occured calling HMAC_Final"; + assert(false); return false; } diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index d66dd644d5..5457e206f5 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -331,10 +331,14 @@ bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packe if (verifiedPacket && !ignoreVerification) { QByteArray packetHeaderHash = NLPacket::verificationHashInHeader(packet); - QByteArray expectedHash = NLPacket::hashForPacketAndHMAC(packet, sourceNode->getAuthenticateHash()); + QByteArray expectedHash; + auto sourceNodeHMACAuth = sourceNode->getAuthenticateHash(); + if (sourceNode->getAuthenticateHash()) { + expectedHash = NLPacket::hashForPacketAndHMAC(packet, *sourceNodeHMACAuth); + } // check if the HMAC-md5 hash in the header matches the hash we would expect - if (packetHeaderHash != expectedHash) { + if (!sourceNodeHMACAuth || packetHeaderHash != expectedHash) { static QMultiMap hashDebugSuppressMap; if (!hashDebugSuppressMap.contains(sourceID, headerType)) { @@ -396,7 +400,7 @@ qint64 LimitedNodeList::sendUnreliablePacket(const NLPacket& packet, const Node& emit dataSent(destinationNode.getType(), packet.getDataSize()); destinationNode.recordBytesSent(packet.getDataSize()); - return sendUnreliablePacket(packet, *destinationNode.getActiveSocket(), &destinationNode.getAuthenticateHash()); + return sendUnreliablePacket(packet, *destinationNode.getActiveSocket(), destinationNode.getAuthenticateHash()); } qint64 LimitedNodeList::sendUnreliablePacket(const NLPacket& packet, const HifiSockAddr& sockAddr, @@ -419,7 +423,7 @@ qint64 LimitedNodeList::sendPacket(std::unique_ptr packet, const Node& emit dataSent(destinationNode.getType(), packet->getDataSize()); destinationNode.recordBytesSent(packet->getDataSize()); - return sendPacket(std::move(packet), *activeSocket, &destinationNode.getAuthenticateHash()); + return sendPacket(std::move(packet), *activeSocket, destinationNode.getAuthenticateHash()); } else { qCDebug(networking) << "LimitedNodeList::sendPacket called without active socket for node" << destinationNode << "- not sending"; return ERROR_SENDING_PACKET_BYTES; @@ -447,14 +451,14 @@ qint64 LimitedNodeList::sendUnreliableUnorderedPacketList(NLPacketList& packetLi if (activeSocket) { qint64 bytesSent = 0; - auto& connectionHash = destinationNode.getAuthenticateHash(); + auto connectionHash = destinationNode.getAuthenticateHash(); // close the last packet in the list packetList.closeCurrentPacket(); while (!packetList._packets.empty()) { bytesSent += sendPacket(packetList.takeFront(), *activeSocket, - &connectionHash); + connectionHash); } emit dataSent(destinationNode.getType(), bytesSent); @@ -502,7 +506,7 @@ qint64 LimitedNodeList::sendPacketList(std::unique_ptr packetList, for (std::unique_ptr& packet : packetList->_packets) { NLPacket* nlPacket = static_cast(packet.get()); collectPacketStats(*nlPacket); - fillPacketHeader(*nlPacket, &destinationNode.getAuthenticateHash()); + fillPacketHeader(*nlPacket, destinationNode.getAuthenticateHash()); } return _nodeSocket.writePacketList(std::move(packetList), *activeSocket); @@ -525,7 +529,7 @@ qint64 LimitedNodeList::sendPacket(std::unique_ptr packet, const Node& auto& destinationSockAddr = (overridenSockAddr.isNull()) ? *destinationNode.getActiveSocket() : overridenSockAddr; - return sendPacket(std::move(packet), destinationSockAddr, &destinationNode.getAuthenticateHash()); + return sendPacket(std::move(packet), destinationSockAddr, destinationNode.getAuthenticateHash()); } int LimitedNodeList::updateNodeWithDataFromPacket(QSharedPointer message, SharedNodePointer sendingNode) { diff --git a/libraries/networking/src/Node.cpp b/libraries/networking/src/Node.cpp index 7979b36e30..8fd8131b10 100644 --- a/libraries/networking/src/Node.cpp +++ b/libraries/networking/src/Node.cpp @@ -89,7 +89,7 @@ Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, QObject* parent) : NetworkPeer(uuid, publicSocket, localSocket, parent), _type(type), - _authenticateHash(new HMACAuth), _pingMs(-1), // "Uninitialized" + _pingMs(-1), // "Uninitialized" _clockSkewUsec(0), _mutex(), _clockSkewMovingPercentile(30, 0.8f) // moving 80th percentile of 30 samples @@ -201,6 +201,10 @@ void Node::setConnectionSecret(const QUuid& connectionSecret) { return; } + if (!_authenticateHash) { + _authenticateHash.reset(new HMACAuth()); + } + _connectionSecret = connectionSecret; _authenticateHash->setKey(_connectionSecret); } diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index 5b3b559582..bcfe525aa8 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -57,7 +57,7 @@ public: const QUuid& getConnectionSecret() const { return _connectionSecret; } void setConnectionSecret(const QUuid& connectionSecret); - HMACAuth& getAuthenticateHash() const { return *_authenticateHash; } + HMACAuth* getAuthenticateHash() const { return _authenticateHash.get(); } NodeData* getLinkedData() const { return _linkedData.get(); } void setLinkedData(std::unique_ptr linkedData) { _linkedData = std::move(linkedData); } @@ -99,7 +99,7 @@ private: NodeType_t _type; QUuid _connectionSecret; - std::unique_ptr _authenticateHash; + std::unique_ptr _authenticateHash { nullptr }; std::unique_ptr _linkedData; bool _isReplicated { false }; int _pingMs; From bfbded7beca85e58c1b87801f715d3cee678f027 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Fri, 27 Apr 2018 16:57:24 -0700 Subject: [PATCH 10/92] Reset pending domain checkins in more locations --- libraries/networking/src/DomainHandler.cpp | 3 +++ libraries/networking/src/DomainHandler.h | 2 +- libraries/networking/src/NodeList.cpp | 6 +++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index cd8064c4c0..84af21004d 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -239,6 +239,7 @@ void DomainHandler::activateICELocalSocket() { _domainURL.setHost(_sockAddr.getAddress().toString()); emit domainURLChanged(_domainURL); emit completedSocketDiscovery(); + clearPendingCheckins(); // Clear outstanding count. } void DomainHandler::activateICEPublicSocket() { @@ -248,6 +249,7 @@ void DomainHandler::activateICEPublicSocket() { _domainURL.setHost(_sockAddr.getAddress().toString()); emit domainURLChanged(_domainURL); emit completedSocketDiscovery(); + clearPendingCheckins(); // Clear outstanding count. } QString DomainHandler::getViewPointFromNamedPath(QString namedPath) { @@ -339,6 +341,7 @@ void DomainHandler::processSettingsPacketList(QSharedPointer pa qCDebug(networking) << "Received domain settings: \n" << _settingsObject; } + clearPendingCheckins(); // Reset outstanding check-ins. emit settingsReceived(_settingsObject); } diff --git a/libraries/networking/src/DomainHandler.h b/libraries/networking/src/DomainHandler.h index 2d4712209d..08908dbaf6 100644 --- a/libraries/networking/src/DomainHandler.h +++ b/libraries/networking/src/DomainHandler.h @@ -97,7 +97,7 @@ public: int getCheckInPacketsSinceLastReply() const { return _checkInPacketsSinceLastReply; } void sentCheckInPacket(); - void domainListReceived() { _checkInPacketsSinceLastReply = 0; } + void clearPendingCheckins() { _checkInPacketsSinceLastReply = 0; } /**jsdoc *

The reasons that you may be refused connection to a domain are defined by numeric values:

diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 04e32f50cb..9d3e5f0e91 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -534,6 +534,8 @@ void NodeList::processDomainServerPathResponse(QSharedPointer m qCDebug(networking) << "Could not go to viewpoint" << viewpoint << "which was the lookup result for path" << pathQuery; } + + _domainHandler.clearPendingCheckins(); } void NodeList::handleICEConnectionToDomainServer() { @@ -594,6 +596,8 @@ void NodeList::processDomainServerConnectionTokenPacket(QSharedPointerreadWithoutCopy(NUM_BYTES_RFC4122_UUID))); + + _domainHandler.clearPendingCheckins(); sendDomainServerCheckIn(); } @@ -605,7 +609,7 @@ void NodeList::processDomainServerList(QSharedPointer message) } // this is a packet from the domain server, reset the count of un-replied check-ins - _domainHandler.domainListReceived(); + _domainHandler.clearPendingCheckins(); // emit our signal so listeners know we just heard from the DS emit receivedDomainServerList(); From cf9b089a3c523c26fbe0a60ee142702ee5969971 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Fri, 27 Apr 2018 17:18:16 -0700 Subject: [PATCH 11/92] Added option to set snapshot location (for this execution only) from the command line. --- interface/src/Application.cpp | 15 ++++++++++++--- interface/src/Application.h | 2 ++ interface/src/ui/Snapshot.cpp | 12 +++++++++--- interface/src/ui/Snapshot.h | 4 ++-- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c38caca090..c0fe84894d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -986,13 +986,22 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning())); setProperty(hifi::properties::CRASHED, _previousSessionCrashed); { - const QString TEST_SCRIPT = "--testScript"; + const QString TEST_SCRIPT { "--testScript" }; + const QString TEST_SNAPSHOT_LOCATION { "--testSnapshotLocation" }; + const QStringList args = arguments(); for (int i = 0; i < args.size() - 1; ++i) { if (args.at(i) == TEST_SCRIPT) { QString testScriptPath = args.at(i + 1); if (QFileInfo(testScriptPath).exists()) { setProperty(hifi::properties::TEST, QUrl::fromLocalFile(testScriptPath)); + } + } else if (args.at(i) == TEST_SNAPSHOT_LOCATION) { + // Set test snapshot location only if it is a writeable directory + QString pathname(args.at(i + 1)); + QFileInfo fileInfo(pathname); + if (fileInfo.isDir() && fileInfo.isWritable()) { + testSnapshotLocation = pathname; } } } @@ -7259,7 +7268,7 @@ void Application::loadAvatarBrowser() const { void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio, const QString& filename) { postLambdaEvent([notify, includeAnimated, aspectRatio, filename, this] { // Get a screenshot and save it - QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio), filename); + QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio), filename, QString()); // If we're not doing an animated snapshot as well... if (!includeAnimated) { // Tell the dependency manager that the capture of the still snapshot has taken place. @@ -7273,7 +7282,7 @@ void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRa void Application::takeSecondaryCameraSnapshot(const QString& filename) { postLambdaEvent([filename, this] { - QString snapshotPath = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getSecondaryCameraScreenshot(), filename); + QString snapshotPath = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getSecondaryCameraScreenshot(), filename, testSnapshotLocation); emit DependencyManager::get()->stillSnapshotTaken(snapshotPath, true); }); } diff --git a/interface/src/Application.h b/interface/src/Application.h index 74b0e5a110..341560bc5b 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -719,5 +719,7 @@ private: std::atomic _pendingIdleEvent { true }; std::atomic _pendingRenderEvent { true }; + + QString testSnapshotLocation { QString() }; }; #endif // hifi_Application_h diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 69103a40b5..9eb64dcb14 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -89,10 +89,10 @@ QString Snapshot::saveSnapshot(QImage image, const QString& filename) { QTemporaryFile* Snapshot::saveTempSnapshot(QImage image) { // return whatever we get back from saved file for snapshot - return static_cast(savedFileForSnapshot(image, true)); + return static_cast(savedFileForSnapshot(image, true, QString(), QString())); } -QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QString& userSelectedFilename) { +QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QString& userSelectedFilename, QString userSelectedPathname) { // adding URL to snapshot QUrl currentURL = DependencyManager::get()->currentPublicAddress(); @@ -117,7 +117,13 @@ QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QSt const int IMAGE_QUALITY = 100; if (!isTemporary) { - QString snapshotFullPath = snapshotsLocation.get(); + // If user has requested specific path then use it, else use the application value + QString snapshotFullPath; + if (!userSelectedPathname.isNull()) { + snapshotFullPath = userSelectedPathname; + } else { + snapshotFullPath = snapshotsLocation.get(); + } if (snapshotFullPath.isEmpty()) { snapshotFullPath = OffscreenUi::getExistingDirectory(nullptr, "Choose Snapshots Directory", QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)); diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index 62d3ed3db8..20e9e8339f 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -37,7 +37,7 @@ class Snapshot : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY public: - static QString saveSnapshot(QImage image, const QString& filename); + static QString saveSnapshot(QImage image, const QString& filename, const QString& pathname); static QTemporaryFile* saveTempSnapshot(QImage image); static SnapshotMetaData* parseSnapshotData(QString snapshotPath); @@ -51,7 +51,7 @@ public slots: Q_INVOKABLE QString getSnapshotsLocation(); Q_INVOKABLE void setSnapshotsLocation(const QString& location); private: - static QFile* savedFileForSnapshot(QImage & image, bool isTemporary, const QString& userSelectedFilename = QString()); + static QFile* savedFileForSnapshot(QImage & image, bool isTemporary, const QString& userSelectedFilename, QString userSelectedPathname); }; #endif // hifi_Snapshot_h From b994776ebd98314025ecdc86fdffc91ebb42eba1 Mon Sep 17 00:00:00 2001 From: Liv Erickson Date: Mon, 30 Apr 2018 12:01:37 -0700 Subject: [PATCH 12/92] do not open help on first run --- interface/src/Application.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cd4562da54..6c11286d03 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3166,9 +3166,6 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { // If this is a first run we short-circuit the address passed in if (firstRun.get()) { -#if !defined(Q_OS_ANDROID) - showHelp(); -#endif DependencyManager::get()->goToEntry(); sentTo = SENT_TO_ENTRY; firstRun.set(false); From cfc5892d63f342949bf886dc45e99e07809aa0db Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Mon, 30 Apr 2018 13:41:56 -0700 Subject: [PATCH 13/92] Only clear check-in count on Domain Query related responses --- libraries/networking/src/DomainHandler.cpp | 3 --- libraries/networking/src/NodeList.cpp | 2 -- 2 files changed, 5 deletions(-) diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index 84af21004d..cd8064c4c0 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -239,7 +239,6 @@ void DomainHandler::activateICELocalSocket() { _domainURL.setHost(_sockAddr.getAddress().toString()); emit domainURLChanged(_domainURL); emit completedSocketDiscovery(); - clearPendingCheckins(); // Clear outstanding count. } void DomainHandler::activateICEPublicSocket() { @@ -249,7 +248,6 @@ void DomainHandler::activateICEPublicSocket() { _domainURL.setHost(_sockAddr.getAddress().toString()); emit domainURLChanged(_domainURL); emit completedSocketDiscovery(); - clearPendingCheckins(); // Clear outstanding count. } QString DomainHandler::getViewPointFromNamedPath(QString namedPath) { @@ -341,7 +339,6 @@ void DomainHandler::processSettingsPacketList(QSharedPointer pa qCDebug(networking) << "Received domain settings: \n" << _settingsObject; } - clearPendingCheckins(); // Reset outstanding check-ins. emit settingsReceived(_settingsObject); } diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 9d3e5f0e91..4920ea97c7 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -534,8 +534,6 @@ void NodeList::processDomainServerPathResponse(QSharedPointer m qCDebug(networking) << "Could not go to viewpoint" << viewpoint << "which was the lookup result for path" << pathQuery; } - - _domainHandler.clearPendingCheckins(); } void NodeList::handleICEConnectionToDomainServer() { From c01fd02de2c5f427e56d75b29b57fcd4122e6d0c Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 30 Apr 2018 17:23:49 -0700 Subject: [PATCH 14/92] Corrected parameter type. --- interface/src/ui/Snapshot.cpp | 2 +- interface/src/ui/Snapshot.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 9eb64dcb14..1af7086933 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -92,7 +92,7 @@ QTemporaryFile* Snapshot::saveTempSnapshot(QImage image) { return static_cast(savedFileForSnapshot(image, true, QString(), QString())); } -QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QString& userSelectedFilename, QString userSelectedPathname) { +QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QString& userSelectedFilename, const QString& userSelectedPathname) { // adding URL to snapshot QUrl currentURL = DependencyManager::get()->currentPublicAddress(); diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index 20e9e8339f..86c860cfcb 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -51,7 +51,7 @@ public slots: Q_INVOKABLE QString getSnapshotsLocation(); Q_INVOKABLE void setSnapshotsLocation(const QString& location); private: - static QFile* savedFileForSnapshot(QImage & image, bool isTemporary, const QString& userSelectedFilename, QString userSelectedPathname); + static QFile* savedFileForSnapshot(QImage & image, bool isTemporary, const QString& userSelectedFilename, const QString& userSelectedPathname); }; #endif // hifi_Snapshot_h From d5610a2f37885a0748129bc3de9dd77261ad12b0 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 30 Apr 2018 17:52:44 -0700 Subject: [PATCH 15/92] WTF... --- interface/src/ui/Snapshot.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 1af7086933..d52f01223c 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -73,9 +73,9 @@ SnapshotMetaData* Snapshot::parseSnapshotData(QString snapshotPath) { return data; } -QString Snapshot::saveSnapshot(QImage image, const QString& filename) { +QString Snapshot::saveSnapshot(QImage image, const QString& filename, const QString& pathname) { - QFile* snapshotFile = savedFileForSnapshot(image, false, filename); + QFile* snapshotFile = savedFileForSnapshot(image, false, filename, pathname); // we don't need the snapshot file, so close it, grab its filename and delete it snapshotFile->close(); From b722c80b3f9f367fdc5758064c4110ecc8216221 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 1 May 2018 14:25:33 -0700 Subject: [PATCH 16/92] WIP --- tools/auto-tester/src/ui/AutoTester.cpp | 12 ++++++++---- tools/auto-tester/src/ui/AutoTester.h | 6 +++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/tools/auto-tester/src/ui/AutoTester.cpp b/tools/auto-tester/src/ui/AutoTester.cpp index 3f7d2cba28..860868565a 100644 --- a/tools/auto-tester/src/ui/AutoTester.cpp +++ b/tools/auto-tester/src/ui/AutoTester.cpp @@ -10,8 +10,6 @@ // #include "AutoTester.h" -#include - AutoTester::AutoTester(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); ui.checkBoxInteractiveMode->setChecked(true); @@ -91,11 +89,17 @@ void AutoTester::saveImage(int index) { QPixmap pixmap; pixmap.loadFromData(downloaders[index]->downloadedData()); + int sdf = pixmap.width(); QImage image = pixmap.toImage(); image = image.convertToFormat(QImage::Format_ARGB32); QString fullPathname = _directoryName + "/" + _filenames[index]; - image.save(fullPathname, 0, 100); + if (!image.save(fullPathname, 0, 100)) { + QMessageBox messageBox; + messageBox.information(0, "Test Aborted", "Failed to save image: " + _filenames[index]); + ui.progressBar->setVisible(false); + return; + } ++_numberOfImagesDownloaded; @@ -109,4 +113,4 @@ void AutoTester::saveImage(int index) { void AutoTester::about() { QMessageBox messageBox; messageBox.information(0, "About", QString("Built ") + __DATE__ + " : " + __TIME__); -} \ No newline at end of file +} diff --git a/tools/auto-tester/src/ui/AutoTester.h b/tools/auto-tester/src/ui/AutoTester.h index 03cb7fbcec..d911b6aaff 100644 --- a/tools/auto-tester/src/ui/AutoTester.h +++ b/tools/auto-tester/src/ui/AutoTester.h @@ -52,9 +52,9 @@ private: // Used to enable passing a parameter to slots QSignalMapper* signalMapper; - int _numberOfImagesToDownload; - int _numberOfImagesDownloaded; - int _index; + int _numberOfImagesToDownload { 0 }; + int _numberOfImagesDownloaded { 0 }; + int _index { 0 }; }; #endif // hifi_AutoTester_h \ No newline at end of file From d1bb37874d0ca832fea0d3d78472ce14b3115ef8 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 30 Apr 2018 17:13:44 -0700 Subject: [PATCH 17/92] Prevent crash in ImageProvider when tablet isn't yet initialized --- interface/src/commerce/Wallet.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 3e0e4adf18..42c8b9973d 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -615,9 +615,12 @@ void Wallet::updateImageProvider() { securityImageProvider->setSecurityImage(_securityImage); // inform tablet security image provider - QQmlEngine* tabletEngine = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system")->getTabletSurface()->getSurfaceContext()->engine(); - securityImageProvider = reinterpret_cast(tabletEngine->imageProvider(SecurityImageProvider::PROVIDER_NAME)); - securityImageProvider->setSecurityImage(_securityImage); + auto tablet = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system"); + if (tablet) { + QQmlEngine* tabletEngine = tablet->getTabletSurface()->getSurfaceContext()->engine(); + securityImageProvider = reinterpret_cast(tabletEngine->imageProvider(SecurityImageProvider::PROVIDER_NAME)); + securityImageProvider->setSecurityImage(_securityImage); + } } void Wallet::chooseSecurityImage(const QString& filename) { From d5f809c3c08730a3016c772a4b710fd8e7b10d85 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 1 May 2018 09:54:23 -0700 Subject: [PATCH 18/92] Actually fix --- interface/src/commerce/Wallet.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 42c8b9973d..35e6ca1c92 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -615,11 +615,14 @@ void Wallet::updateImageProvider() { securityImageProvider->setSecurityImage(_securityImage); // inform tablet security image provider - auto tablet = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system"); + TabletProxy* tablet = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system"); if (tablet) { - QQmlEngine* tabletEngine = tablet->getTabletSurface()->getSurfaceContext()->engine(); - securityImageProvider = reinterpret_cast(tabletEngine->imageProvider(SecurityImageProvider::PROVIDER_NAME)); - securityImageProvider->setSecurityImage(_securityImage); + OffscreenQmlSurface* tabletSurface = tablet->getTabletSurface(); + if (tabletSurface) { + QQmlEngine* tabletEngine = tabletSurface->getSurfaceContext()->engine(); + securityImageProvider = reinterpret_cast(tabletEngine->imageProvider(SecurityImageProvider::PROVIDER_NAME)); + securityImageProvider->setSecurityImage(_securityImage); + } } } From a3e4fa84292ab1607ed6cca3a10003ed75825595 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 1 May 2018 15:27:29 -0700 Subject: [PATCH 19/92] Corrected download of images. --- tools/auto-tester/src/Downloader.cpp | 9 +++++++++ tools/auto-tester/src/Test.cpp | 7 +++++-- tools/auto-tester/src/ui/AutoTester.cpp | 1 + 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/tools/auto-tester/src/Downloader.cpp b/tools/auto-tester/src/Downloader.cpp index 030aa95a19..e66b498bd5 100644 --- a/tools/auto-tester/src/Downloader.cpp +++ b/tools/auto-tester/src/Downloader.cpp @@ -9,6 +9,8 @@ // #include "Downloader.h" +#include + Downloader::Downloader(QUrl imageUrl, QObject *parent) : QObject(parent) { connect( &_networkAccessManager, SIGNAL (finished(QNetworkReply*)), @@ -20,6 +22,13 @@ Downloader::Downloader(QUrl imageUrl, QObject *parent) : QObject(parent) { } void Downloader::fileDownloaded(QNetworkReply* reply) { + QNetworkReply::NetworkError error = reply->error(); + if (error != QNetworkReply::NetworkError::NoError) { + QMessageBox messageBox; + messageBox.information(0, "Test Aborted", "Failed to download image: " + reply->errorString()); + return; + } + _downloadedData = reply->readAll(); //emit a signal diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index 57806e80f6..d0a1606cd8 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -221,8 +221,11 @@ void Test::startTestsEvaluation() { QString expectedImageFilenameTail = currentFilename.left(currentFilename.length() - 4).right(NUM_DIGITS); QString expectedImageStoredFilename = EXPECTED_IMAGE_PREFIX + expectedImageFilenameTail + ".png"; - QString imageURLString("https://github.com/" + githubUser + "/hifi_tests/blob/" + gitHubBranch + "/" + - expectedImagePartialSourceDirectory + "/" + expectedImageStoredFilename + "?raw=true"); + //https://raw.githubusercontent.com/highfidelity/hifi_tests/master/tests/content/entity/zone/zoneOrientation/ExpectedImage_00001.png + + + QString imageURLString("https://raw.githubusercontent.com/" + githubUser + "/hifi_tests/" + gitHubBranch + "/" + + expectedImagePartialSourceDirectory + "/" + expectedImageStoredFilename); expectedImagesURLs << imageURLString; diff --git a/tools/auto-tester/src/ui/AutoTester.cpp b/tools/auto-tester/src/ui/AutoTester.cpp index 860868565a..17b1513467 100644 --- a/tools/auto-tester/src/ui/AutoTester.cpp +++ b/tools/auto-tester/src/ui/AutoTester.cpp @@ -86,6 +86,7 @@ void AutoTester::downloadImages(const QStringList& URLs, const QString& director } void AutoTester::saveImage(int index) { + QByteArray q = downloaders[index]->downloadedData(); QPixmap pixmap; pixmap.loadFromData(downloaders[index]->downloadedData()); From 521ae36cbf9fb2f8dc197e150e2b28c1a78e1f40 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 1 May 2018 15:29:22 -0700 Subject: [PATCH 20/92] Make resource swapchains immutable, fix for 14638 --- .../src/gpu/gl/GLBackendOutput.cpp | 4 ++-- .../src/gpu/gl/GLBackendPipeline.cpp | 9 ++++---- libraries/gpu/src/gpu/ResourceSwapChain.h | 19 +++++++---------- .../render-utils/src/AntialiasingEffect.cpp | 21 +++++++++---------- 4 files changed, 24 insertions(+), 29 deletions(-) diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp index 2285b0e486..d1ab34da90 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp @@ -46,10 +46,10 @@ void GLBackend::do_setFramebuffer(const Batch& batch, size_t paramOffset) { } void GLBackend::do_setFramebufferSwapChain(const Batch& batch, size_t paramOffset) { - auto swapChain = batch._swapChains.get(batch._params[paramOffset]._uint); + auto swapChain = std::static_pointer_cast(batch._swapChains.get(batch._params[paramOffset]._uint)); if (swapChain) { auto index = batch._params[paramOffset + 1]._uint; - FramebufferPointer framebuffer = static_cast(swapChain.get())->get(index); + const auto& framebuffer = swapChain->get(index); setFramebuffer(framebuffer); } } diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp index 237b8bc1e9..d5cb331a4a 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp @@ -1,4 +1,4 @@ -// +// // GLBackendPipeline.cpp // libraries/gpu/src/gpu // @@ -263,7 +263,7 @@ void GLBackend::do_setResourceFramebufferSwapChainTexture(const Batch& batch, si return; } - SwapChainPointer swapChain = batch._swapChains.get(batch._params[paramOffset + 0]._uint); + auto swapChain = std::static_pointer_cast(batch._swapChains.get(batch._params[paramOffset + 0]._uint)); if (!swapChain) { releaseResourceTexture(slot); @@ -271,9 +271,8 @@ void GLBackend::do_setResourceFramebufferSwapChainTexture(const Batch& batch, si } auto index = batch._params[paramOffset + 2]._uint; auto renderBufferSlot = batch._params[paramOffset + 3]._uint; - FramebufferPointer resourceFramebuffer = static_cast(swapChain.get())->get(index); - TexturePointer resourceTexture = resourceFramebuffer->getRenderBuffer(renderBufferSlot); - + auto resourceFramebuffer = swapChain->get(index); + auto resourceTexture = resourceFramebuffer->getRenderBuffer(renderBufferSlot); setResourceTexture(slot, resourceTexture); } diff --git a/libraries/gpu/src/gpu/ResourceSwapChain.h b/libraries/gpu/src/gpu/ResourceSwapChain.h index 7b46b35521..84e8ec7c74 100644 --- a/libraries/gpu/src/gpu/ResourceSwapChain.h +++ b/libraries/gpu/src/gpu/ResourceSwapChain.h @@ -15,18 +15,18 @@ namespace gpu { class SwapChain { public: - SwapChain(unsigned int size = 2U) : _size{ size } {} + SwapChain(size_t size = 2U) : _size{ size } {} virtual ~SwapChain() {} void advance() { _frontIndex = (_frontIndex + 1) % _size; } - unsigned int getSize() const { return _size; } + size_t getSize() const { return _size; } protected: - unsigned int _size; - unsigned int _frontIndex{ 0U }; + const size_t _size; + size_t _frontIndex{ 0U }; }; typedef std::shared_ptr SwapChainPointer; @@ -41,16 +41,13 @@ namespace gpu { using Type = R; using TypePointer = std::shared_ptr; + using TypeConstPointer = std::shared_ptr; - ResourceSwapChain(unsigned int size = 2U) : SwapChain{ size } {} - - void reset() { - for (auto& ptr : _resources) { - ptr.reset(); + ResourceSwapChain(const std::vector& v) : SwapChain{ std::min(v.size(), MAX_SIZE) } { + for (size_t i = 0; i < _size; ++i) { + _resources[i] = v[i]; } } - - TypePointer& edit(unsigned int index) { return _resources[(index + _frontIndex) % _size]; } const TypePointer& get(unsigned int index) const { return _resources[(index + _frontIndex) % _size]; } private: diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp index ba5036ad68..357782a321 100644 --- a/libraries/render-utils/src/AntialiasingEffect.cpp +++ b/libraries/render-utils/src/AntialiasingEffect.cpp @@ -188,7 +188,6 @@ const int AntialiasingPass_NextMapSlot = 4; Antialiasing::Antialiasing() { - _antialiasingBuffers = std::make_shared(2U); } Antialiasing::~Antialiasing() { @@ -317,25 +316,25 @@ void Antialiasing::run(const render::RenderContextPointer& renderContext, const int width = sourceBuffer->getWidth(); int height = sourceBuffer->getHeight(); - if (_antialiasingBuffers->get(0)) { - if (_antialiasingBuffers->get(0)->getSize() != uvec2(width, height)) {// || (sourceBuffer && (_antialiasingBuffer->getRenderBuffer(1) != sourceBuffer->getRenderBuffer(0)))) { - _antialiasingBuffers->edit(0).reset(); - _antialiasingBuffers->edit(1).reset(); - _antialiasingTextures[0].reset(); - _antialiasingTextures[1].reset(); - } + if (_antialiasingBuffers && _antialiasingBuffers->get(0) && _antialiasingBuffers->get(0)->getSize() != uvec2(width, height)) { + _antialiasingBuffers.reset(); + _antialiasingTextures[0].reset(); + _antialiasingTextures[1].reset(); } - if (!_antialiasingBuffers->get(0)) { + + if (!_antialiasingBuffers) { + std::vector antiAliasingBuffers; // Link the antialiasing FBO to texture for (int i = 0; i < 2; i++) { - auto& antiAliasingBuffer = _antialiasingBuffers->edit(i); - antiAliasingBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("antialiasing")); + antiAliasingBuffers.emplace_back(gpu::Framebuffer::create("antialiasing")); + const auto& antiAliasingBuffer = antiAliasingBuffers.back(); auto format = gpu::Element::COLOR_SRGBA_32; // DependencyManager::get()->getLightingTexture()->getTexelFormat(); auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR); _antialiasingTextures[i] = gpu::Texture::createRenderBuffer(format, width, height, gpu::Texture::SINGLE_MIP, defaultSampler); antiAliasingBuffer->setRenderBuffer(0, _antialiasingTextures[i]); } + _antialiasingBuffers = std::make_shared(antiAliasingBuffers); } gpu::doInBatch("Antialiasing::run", args->_context, [&](gpu::Batch& batch) { From fb929da2280ad3a45c32a41130a5ebeeb31e6160 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 1 May 2018 16:54:26 -0700 Subject: [PATCH 21/92] Change type used for swap chain count --- libraries/gpu/src/gpu/ResourceSwapChain.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/gpu/src/gpu/ResourceSwapChain.h b/libraries/gpu/src/gpu/ResourceSwapChain.h index 84e8ec7c74..28c5ff2ed3 100644 --- a/libraries/gpu/src/gpu/ResourceSwapChain.h +++ b/libraries/gpu/src/gpu/ResourceSwapChain.h @@ -15,18 +15,18 @@ namespace gpu { class SwapChain { public: - SwapChain(size_t size = 2U) : _size{ size } {} + SwapChain(uint8_t size = 2U) : _size{ size } {} virtual ~SwapChain() {} void advance() { _frontIndex = (_frontIndex + 1) % _size; } - size_t getSize() const { return _size; } + uint8_t getSize() const { return _size; } protected: - const size_t _size; - size_t _frontIndex{ 0U }; + const uint8_t _size; + uint8_t _frontIndex{ 0U }; }; typedef std::shared_ptr SwapChainPointer; @@ -43,7 +43,7 @@ namespace gpu { using TypePointer = std::shared_ptr; using TypeConstPointer = std::shared_ptr; - ResourceSwapChain(const std::vector& v) : SwapChain{ std::min(v.size(), MAX_SIZE) } { + ResourceSwapChain(const std::vector& v) : SwapChain{ std::min((uint8_t)v.size(), MAX_SIZE) } { for (size_t i = 0; i < _size; ++i) { _resources[i] = v[i]; } From 93afbcdc08f42f68e4c0f9417279bd012f69643f Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 1 May 2018 17:59:07 -0700 Subject: [PATCH 22/92] First success with running from command line. --- tools/auto-tester/src/Test.cpp | 53 ++++++++++++++----------- tools/auto-tester/src/Test.h | 29 +++++++------- tools/auto-tester/src/main.cpp | 15 ++++++- tools/auto-tester/src/ui/AutoTester.cpp | 12 ++++-- tools/auto-tester/src/ui/AutoTester.h | 5 +++ 5 files changed, 70 insertions(+), 44 deletions(-) diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index d0a1606cd8..7139f0a43c 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -27,7 +27,7 @@ Test::Test() { mismatchWindow.setModal(true); } -bool Test::createTestResultsFolderPath(QString directory) { +bool Test::createTestResultsFolderPath(const QString& directory) { QDateTime now = QDateTime::currentDateTime(); testResultsFolderPath = directory + "/" + TEST_RESULTS_FOLDER + "--" + now.toString(DATETIME_FORMAT); QDir testResultsFolder(testResultsFolderPath); @@ -125,7 +125,7 @@ bool Test::compareImageLists(bool isInteractiveMode, QProgressBar* progressBar) return success; } -void Test::appendTestResultsToFile(QString testResultsFolderPath, TestFailure testFailure, QPixmap comparisonImage) { +void Test::appendTestResultsToFile(const QString& testResultsFolderPath, TestFailure testFailure, QPixmap comparisonImage) { if (!QDir().exists(testResultsFolderPath)) { messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Folder " + testResultsFolderPath + " not found"); exit(-1); @@ -174,10 +174,16 @@ void Test::appendTestResultsToFile(QString testResultsFolderPath, TestFailure te comparisonImage.save(failureFolderPath + "/" + "Difference Image.jpg"); } -void Test::startTestsEvaluation() { - // Get list of JPEG images in folder, sorted by name - pathToTestResultsDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test images", ".", QFileDialog::ShowDirsOnly); - if (pathToTestResultsDirectory == "") { +void Test::startTestsEvaluation(const QString& testFolder) { + QString pathToTestResultsDirectory; + if (testFolder.isNull()) { + // Get list of JPEG images in folder, sorted by name + pathToTestResultsDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test images", ".", QFileDialog::ShowDirsOnly); + } else { + pathToTestResultsDirectory = testFolder; + } + + if (pathToTestResultsDirectory == QString()) { return; } @@ -221,9 +227,6 @@ void Test::startTestsEvaluation() { QString expectedImageFilenameTail = currentFilename.left(currentFilename.length() - 4).right(NUM_DIGITS); QString expectedImageStoredFilename = EXPECTED_IMAGE_PREFIX + expectedImageFilenameTail + ".png"; - //https://raw.githubusercontent.com/highfidelity/hifi_tests/master/tests/content/entity/zone/zoneOrientation/ExpectedImage_00001.png - - QString imageURLString("https://raw.githubusercontent.com/" + githubUser + "/hifi_tests/" + gitHubBranch + "/" + expectedImagePartialSourceDirectory + "/" + expectedImageStoredFilename); @@ -240,19 +243,21 @@ void Test::startTestsEvaluation() { autoTester->downloadImages(expectedImagesURLs, pathToTestResultsDirectory, expectedImagesFilenames); } -void Test::finishTestsEvaluation(bool interactiveMode, QProgressBar* progressBar) { - bool success = compareImageLists(interactiveMode, progressBar); +void Test::finishTestsEvaluation(bool isRunningFromCommandline, bool interactiveMode, QProgressBar* progressBar) { + bool success = compareImageLists((!isRunningFromCommandline && interactiveMode), progressBar); - if (success) { - messageBox.information(0, "Success", "All images are as expected"); - } else { - messageBox.information(0, "Failure", "One or more images are not as expected"); + if (!isRunningFromCommandline) { + if (success) { + messageBox.information(0, "Success", "All images are as expected"); + } else { + messageBox.information(0, "Failure", "One or more images are not as expected"); + } } zipAndDeleteTestResultsFolder(); } -bool Test::isAValidDirectory(QString pathname) { +bool Test::isAValidDirectory(const QString& pathname) { // Only process directories QDir dir(pathname); if (!dir.exists()) { @@ -267,7 +272,7 @@ bool Test::isAValidDirectory(QString pathname) { return true; } -QString Test::extractPathFromTestsDown(QString fullPath) { +QString Test::extractPathFromTestsDown(const QString& fullPath) { // `fullPath` includes the full path to the test. We need the portion below (and including) `tests` QStringList pathParts = fullPath.split('/'); int i{ 0 }; @@ -348,7 +353,7 @@ void Test::createAllRecursiveScripts() { messageBox.information(0, "Success", "Scripts have been created"); } -void Test::createRecursiveScript(QString topLevelDirectory, bool interactiveMode) { +void Test::createRecursiveScript(const QString& topLevelDirectory, bool interactiveMode) { const QString recursiveTestsFilename("testRecursive.js"); QFile allTestsFilename(topLevelDirectory + "/" + recursiveTestsFilename); if (!allTestsFilename.open(QIODevice::WriteOnly | QIODevice::Text)) { @@ -615,7 +620,7 @@ void Test::createAllMDFiles() { messageBox.information(0, "Success", "MD files have been created"); } -void Test::createMDFile(QString testDirectory) { +void Test::createMDFile(const QString& testDirectory) { // Verify folder contains test.js file QString testFileName(testDirectory + "/" + TEST_FILENAME); QFileInfo testFileInfo(testFileName); @@ -790,7 +795,7 @@ void Test::createTestsOutline() { messageBox.information(0, "Success", "Test outline file " + testsOutlineFilename + " has been created"); } -void Test::copyJPGtoPNG(QString sourceJPGFullFilename, QString destinationPNGFullFilename) { +void Test::copyJPGtoPNG(const QString& sourceJPGFullFilename, const QString& destinationPNGFullFilename) { QFile::remove(destinationPNGFullFilename); QImageReader reader; @@ -803,7 +808,7 @@ void Test::copyJPGtoPNG(QString sourceJPGFullFilename, QString destinationPNGFul writer.write(image); } -QStringList Test::createListOfAll_imagesInDirectory(QString imageFormat, QString pathToImageDirectory) { +QStringList Test::createListOfAll_imagesInDirectory(const QString& imageFormat, const QString& pathToImageDirectory) { imageDirectory = QDir(pathToImageDirectory); QStringList nameFilters; nameFilters << "*." + imageFormat; @@ -816,7 +821,7 @@ QStringList Test::createListOfAll_imagesInDirectory(QString imageFormat, QString // Filename (i.e. without extension) contains _tests_ (this is based on all test scripts being within the tests folder // Last 5 characters in filename are digits // Extension is jpg -bool Test::isInSnapshotFilenameFormat(QString imageFormat, QString filename) { +bool Test::isInSnapshotFilenameFormat(const QString& imageFormat, const QString& filename) { QStringList filenameParts = filename.split("."); bool filnameHasNoPeriods = (filenameParts.size() == 2); @@ -833,7 +838,7 @@ bool Test::isInSnapshotFilenameFormat(QString imageFormat, QString filename) { // For a file named "D_GitHub_hifi-tests_tests_content_entity_zone_create_0.jpg", the test directory is // D:/GitHub/hifi-tests/tests/content/entity/zone/create // This method assumes the filename is in the correct format -QString Test::getExpectedImageDestinationDirectory(QString filename) { +QString Test::getExpectedImageDestinationDirectory(const QString& filename) { QString filenameWithoutExtension = filename.split(".")[0]; QStringList filenameParts = filenameWithoutExtension.split("_"); @@ -850,7 +855,7 @@ QString Test::getExpectedImageDestinationDirectory(QString filename) { // is ...tests/content/entity/zone/create // This is used to create the full URL // This method assumes the filename is in the correct format -QString Test::getExpectedImagePartialSourceDirectory(QString filename) { +QString Test::getExpectedImagePartialSourceDirectory(const QString& filename) { QString filenameWithoutExtension = filename.split(".")[0]; QStringList filenameParts = filenameWithoutExtension.split("_"); diff --git a/tools/auto-tester/src/Test.h b/tools/auto-tester/src/Test.h index 7f5553f9e3..02cab53381 100644 --- a/tools/auto-tester/src/Test.h +++ b/tools/auto-tester/src/Test.h @@ -43,39 +43,39 @@ class Test { public: Test(); - void startTestsEvaluation(); - void finishTestsEvaluation(bool interactiveMode, QProgressBar* progressBar); + void startTestsEvaluation(const QString& testFolder = QString()); + void finishTestsEvaluation(bool isRunningFromCommandline, bool interactiveMode, QProgressBar* progressBar); void createRecursiveScript(); void createAllRecursiveScripts(); - void createRecursiveScript(QString topLevelDirectory, bool interactiveMode); + void createRecursiveScript(const QString& topLevelDirectory, bool interactiveMode); void createTest(); void createMDFile(); void createAllMDFiles(); - void createMDFile(QString topLevelDirectory); + void createMDFile(const QString& topLevelDirectory); void createTestsOutline(); bool compareImageLists(bool isInteractiveMode, QProgressBar* progressBar); - QStringList createListOfAll_imagesInDirectory(QString imageFormat, QString pathToImageDirectory); + QStringList createListOfAll_imagesInDirectory(const QString& imageFormat, const QString& pathToImageDirectory); - bool isInSnapshotFilenameFormat(QString imageFormat, QString filename); + bool isInSnapshotFilenameFormat(const QString& imageFormat, const QString& filename); void importTest(QTextStream& textStream, const QString& testPathname); - void appendTestResultsToFile(QString testResultsFolderPath, TestFailure testFailure, QPixmap comparisonImage); + void appendTestResultsToFile(const QString& testResultsFolderPath, TestFailure testFailure, QPixmap comparisonImage); - bool createTestResultsFolderPath(QString directory); + bool createTestResultsFolderPath(const QString& directory); void zipAndDeleteTestResultsFolder(); - bool isAValidDirectory(QString pathname); - QString extractPathFromTestsDown(QString fullPath); - QString getExpectedImageDestinationDirectory(QString filename); - QString getExpectedImagePartialSourceDirectory(QString filename); + bool isAValidDirectory(const QString& pathname); + QString extractPathFromTestsDown(const QString& fullPath); + QString getExpectedImageDestinationDirectory(const QString& filename); + QString getExpectedImagePartialSourceDirectory(const QString& filename); - void copyJPGtoPNG(QString sourceJPGFullFilename, QString destinationPNGFullFilename); + void copyJPGtoPNG(const QString& sourceJPGFullFilename, const QString& destinationPNGFullFilename); private: const QString TEST_FILENAME { "test.js" }; @@ -90,14 +90,13 @@ private: ImageComparer imageComparer; - QString testResultsFolderPath { "" }; + QString testResultsFolderPath; int index { 1 }; // Expected images are in the format ExpectedImage_dddd.jpg (d == decimal digit) const int NUM_DIGITS { 5 }; const QString EXPECTED_IMAGE_PREFIX { "ExpectedImage_" }; - QString pathToTestResultsDirectory; QStringList expectedImagesFilenames; QStringList expectedImagesFullFilenames; QStringList resultImagesFullFilenames; diff --git a/tools/auto-tester/src/main.cpp b/tools/auto-tester/src/main.cpp index cd0ce22b13..ffa7a0b237 100644 --- a/tools/auto-tester/src/main.cpp +++ b/tools/auto-tester/src/main.cpp @@ -13,10 +13,23 @@ AutoTester* autoTester; int main(int argc, char *argv[]) { + // Only parameter is "--testFolder" + QString testFolder; + if (argc == 3) { + if (QString(argv[1]) == "--testFolder") { + testFolder = QString(argv[2]); + } + } + QApplication application(argc, argv); autoTester = new AutoTester(); - autoTester->show(); + + if (!testFolder.isNull()) { + autoTester->runFromCommandLine(testFolder); + } else { + autoTester->show(); + } return application.exec(); } diff --git a/tools/auto-tester/src/ui/AutoTester.cpp b/tools/auto-tester/src/ui/AutoTester.cpp index 17b1513467..e0f92664ef 100644 --- a/tools/auto-tester/src/ui/AutoTester.cpp +++ b/tools/auto-tester/src/ui/AutoTester.cpp @@ -15,12 +15,17 @@ AutoTester::AutoTester(QWidget *parent) : QMainWindow(parent) { ui.checkBoxInteractiveMode->setChecked(true); ui.progressBar->setVisible(false); - test = new Test(); - signalMapper = new QSignalMapper(); connect(ui.actionClose, &QAction::triggered, this, &AutoTester::on_closeButton_clicked); connect(ui.actionAbout, &QAction::triggered, this, &AutoTester::about); + + test = new Test(); +} + +void AutoTester::runFromCommandLine(const QString& testFolder) { + isRunningFromCommandline = true; + test->startTestsEvaluation(testFolder); } void AutoTester::on_evaluateTestsButton_clicked() { @@ -86,7 +91,6 @@ void AutoTester::downloadImages(const QStringList& URLs, const QString& director } void AutoTester::saveImage(int index) { - QByteArray q = downloaders[index]->downloadedData(); QPixmap pixmap; pixmap.loadFromData(downloaders[index]->downloadedData()); @@ -105,7 +109,7 @@ void AutoTester::saveImage(int index) { ++_numberOfImagesDownloaded; if (_numberOfImagesDownloaded == _numberOfImagesToDownload) { - test->finishTestsEvaluation(ui.checkBoxInteractiveMode->isChecked(), ui.progressBar); + test->finishTestsEvaluation(isRunningFromCommandline, ui.checkBoxInteractiveMode->isChecked(), ui.progressBar); } else { ui.progressBar->setValue(_numberOfImagesDownloaded); } diff --git a/tools/auto-tester/src/ui/AutoTester.h b/tools/auto-tester/src/ui/AutoTester.h index d911b6aaff..fe37f2298d 100644 --- a/tools/auto-tester/src/ui/AutoTester.h +++ b/tools/auto-tester/src/ui/AutoTester.h @@ -22,6 +22,9 @@ class AutoTester : public QMainWindow { public: AutoTester(QWidget *parent = Q_NULLPTR); + + void runFromCommandLine(const QString& testFolder); + void downloadImage(const QUrl& url); void downloadImages(const QStringList& URLs, const QString& directoryName, const QStringList& filenames); @@ -55,6 +58,8 @@ private: int _numberOfImagesToDownload { 0 }; int _numberOfImagesDownloaded { 0 }; int _index { 0 }; + + bool isRunningFromCommandline { false }; }; #endif // hifi_AutoTester_h \ No newline at end of file From 7bad849e67e4ff2ccefb90f3d1c149b06eedacfb Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 1 May 2018 15:29:22 -0700 Subject: [PATCH 23/92] Make resource swapchains immutable, fix for 14638 --- .../src/gpu/gl/GLBackendOutput.cpp | 4 ++-- .../src/gpu/gl/GLBackendPipeline.cpp | 7 +++---- libraries/gpu/src/gpu/ResourceSwapChain.h | 19 +++++++---------- .../render-utils/src/AntialiasingEffect.cpp | 21 +++++++++---------- 4 files changed, 23 insertions(+), 28 deletions(-) diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp index 2285b0e486..d1ab34da90 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp @@ -46,10 +46,10 @@ void GLBackend::do_setFramebuffer(const Batch& batch, size_t paramOffset) { } void GLBackend::do_setFramebufferSwapChain(const Batch& batch, size_t paramOffset) { - auto swapChain = batch._swapChains.get(batch._params[paramOffset]._uint); + auto swapChain = std::static_pointer_cast(batch._swapChains.get(batch._params[paramOffset]._uint)); if (swapChain) { auto index = batch._params[paramOffset + 1]._uint; - FramebufferPointer framebuffer = static_cast(swapChain.get())->get(index); + const auto& framebuffer = swapChain->get(index); setFramebuffer(framebuffer); } } diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp index 58fcc51605..91f1d8bb8c 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp @@ -268,7 +268,7 @@ void GLBackend::do_setResourceFramebufferSwapChainTexture(const Batch& batch, si return; } - SwapChainPointer swapChain = batch._swapChains.get(batch._params[paramOffset + 0]._uint); + auto swapChain = std::static_pointer_cast(batch._swapChains.get(batch._params[paramOffset + 0]._uint)); if (!swapChain) { releaseResourceTexture(slot); @@ -276,9 +276,8 @@ void GLBackend::do_setResourceFramebufferSwapChainTexture(const Batch& batch, si } auto index = batch._params[paramOffset + 2]._uint; auto renderBufferSlot = batch._params[paramOffset + 3]._uint; - FramebufferPointer resourceFramebuffer = static_cast(swapChain.get())->get(index); - TexturePointer resourceTexture = resourceFramebuffer->getRenderBuffer(renderBufferSlot); - + auto resourceFramebuffer = swapChain->get(index); + auto resourceTexture = resourceFramebuffer->getRenderBuffer(renderBufferSlot); setResourceTexture(slot, resourceTexture); } diff --git a/libraries/gpu/src/gpu/ResourceSwapChain.h b/libraries/gpu/src/gpu/ResourceSwapChain.h index 7b46b35521..84e8ec7c74 100644 --- a/libraries/gpu/src/gpu/ResourceSwapChain.h +++ b/libraries/gpu/src/gpu/ResourceSwapChain.h @@ -15,18 +15,18 @@ namespace gpu { class SwapChain { public: - SwapChain(unsigned int size = 2U) : _size{ size } {} + SwapChain(size_t size = 2U) : _size{ size } {} virtual ~SwapChain() {} void advance() { _frontIndex = (_frontIndex + 1) % _size; } - unsigned int getSize() const { return _size; } + size_t getSize() const { return _size; } protected: - unsigned int _size; - unsigned int _frontIndex{ 0U }; + const size_t _size; + size_t _frontIndex{ 0U }; }; typedef std::shared_ptr SwapChainPointer; @@ -41,16 +41,13 @@ namespace gpu { using Type = R; using TypePointer = std::shared_ptr; + using TypeConstPointer = std::shared_ptr; - ResourceSwapChain(unsigned int size = 2U) : SwapChain{ size } {} - - void reset() { - for (auto& ptr : _resources) { - ptr.reset(); + ResourceSwapChain(const std::vector& v) : SwapChain{ std::min(v.size(), MAX_SIZE) } { + for (size_t i = 0; i < _size; ++i) { + _resources[i] = v[i]; } } - - TypePointer& edit(unsigned int index) { return _resources[(index + _frontIndex) % _size]; } const TypePointer& get(unsigned int index) const { return _resources[(index + _frontIndex) % _size]; } private: diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp index e620fc2d61..f77b4fc68b 100644 --- a/libraries/render-utils/src/AntialiasingEffect.cpp +++ b/libraries/render-utils/src/AntialiasingEffect.cpp @@ -189,7 +189,6 @@ const int AntialiasingPass_NextMapSlot = 4; Antialiasing::Antialiasing(bool isSharpenEnabled) : _isSharpenEnabled{ isSharpenEnabled } { - _antialiasingBuffers = std::make_shared(2U); } Antialiasing::~Antialiasing() { @@ -321,25 +320,25 @@ void Antialiasing::run(const render::RenderContextPointer& renderContext, const int width = sourceBuffer->getWidth(); int height = sourceBuffer->getHeight(); - if (_antialiasingBuffers->get(0)) { - if (_antialiasingBuffers->get(0)->getSize() != uvec2(width, height)) {// || (sourceBuffer && (_antialiasingBuffer->getRenderBuffer(1) != sourceBuffer->getRenderBuffer(0)))) { - _antialiasingBuffers->edit(0).reset(); - _antialiasingBuffers->edit(1).reset(); - _antialiasingTextures[0].reset(); - _antialiasingTextures[1].reset(); - } + if (_antialiasingBuffers && _antialiasingBuffers->get(0) && _antialiasingBuffers->get(0)->getSize() != uvec2(width, height)) { + _antialiasingBuffers.reset(); + _antialiasingTextures[0].reset(); + _antialiasingTextures[1].reset(); } - if (!_antialiasingBuffers->get(0)) { + + if (!_antialiasingBuffers) { + std::vector antiAliasingBuffers; // Link the antialiasing FBO to texture auto format = sourceBuffer->getRenderBuffer(0)->getTexelFormat(); auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP); for (int i = 0; i < 2; i++) { - auto& antiAliasingBuffer = _antialiasingBuffers->edit(i); - antiAliasingBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("antialiasing")); + antiAliasingBuffers.emplace_back(gpu::Framebuffer::create("antialiasing")); + const auto& antiAliasingBuffer = antiAliasingBuffers.back(); _antialiasingTextures[i] = gpu::Texture::createRenderBuffer(format, width, height, gpu::Texture::SINGLE_MIP, defaultSampler); antiAliasingBuffer->setRenderBuffer(0, _antialiasingTextures[i]); } + _antialiasingBuffers = std::make_shared(antiAliasingBuffers); } gpu::doInBatch("Antialiasing::run", args->_context, [&](gpu::Batch& batch) { From 233c60a5063573cb55770b382013deeefadfba6f Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 1 May 2018 16:54:26 -0700 Subject: [PATCH 24/92] Change type used for swap chain count --- libraries/gpu/src/gpu/ResourceSwapChain.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/gpu/src/gpu/ResourceSwapChain.h b/libraries/gpu/src/gpu/ResourceSwapChain.h index 84e8ec7c74..28c5ff2ed3 100644 --- a/libraries/gpu/src/gpu/ResourceSwapChain.h +++ b/libraries/gpu/src/gpu/ResourceSwapChain.h @@ -15,18 +15,18 @@ namespace gpu { class SwapChain { public: - SwapChain(size_t size = 2U) : _size{ size } {} + SwapChain(uint8_t size = 2U) : _size{ size } {} virtual ~SwapChain() {} void advance() { _frontIndex = (_frontIndex + 1) % _size; } - size_t getSize() const { return _size; } + uint8_t getSize() const { return _size; } protected: - const size_t _size; - size_t _frontIndex{ 0U }; + const uint8_t _size; + uint8_t _frontIndex{ 0U }; }; typedef std::shared_ptr SwapChainPointer; @@ -43,7 +43,7 @@ namespace gpu { using TypePointer = std::shared_ptr; using TypeConstPointer = std::shared_ptr; - ResourceSwapChain(const std::vector& v) : SwapChain{ std::min(v.size(), MAX_SIZE) } { + ResourceSwapChain(const std::vector& v) : SwapChain{ std::min((uint8_t)v.size(), MAX_SIZE) } { for (size_t i = 0; i < _size; ++i) { _resources[i] = v[i]; } From e0b16dfe03493caf8f8aae8cbe02393b21d66df5 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 2 May 2018 14:17:01 -0700 Subject: [PATCH 25/92] Allow use of `--url` command line argument in test mode. --- interface/src/Application.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index eb59576cc0..3c9e244da6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2143,6 +2143,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto scriptEngines = DependencyManager::get(); const auto testScript = property(hifi::properties::TEST).toUrl(); scriptEngines->loadScript(testScript, false); + + // This is done so we don't get a "connection time-out" message when we haven't passed in a URL. + if (arguments().contains("--url")) { + auto reply = SandboxUtils::getStatus(); + connect(reply, &QNetworkReply::finished, this, [=] { + handleSandboxStatus(reply); + }); + } } else { PROFILE_RANGE(render, "GetSandboxStatus"); auto reply = SandboxUtils::getStatus(); From 5cbb8674ec2c001302cdcc43085b2ea7cf62157c Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 2 May 2018 14:45:28 -0700 Subject: [PATCH 26/92] Use default parameter for saveSnapshot(). --- interface/src/Application.cpp | 2 +- interface/src/Application.h | 2 +- interface/src/ui/Snapshot.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 22a77b9bf1..bd306948bb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -7387,7 +7387,7 @@ void Application::loadAvatarBrowser() const { void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio, const QString& filename) { postLambdaEvent([notify, includeAnimated, aspectRatio, filename, this] { // Get a screenshot and save it - QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio), filename, QString()); + QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio), filename); // If we're not doing an animated snapshot as well... if (!includeAnimated) { // Tell the dependency manager that the capture of the still snapshot has taken place. diff --git a/interface/src/Application.h b/interface/src/Application.h index f1276bca34..fe31f55dcb 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -732,6 +732,6 @@ private: std::atomic _pendingIdleEvent { true }; std::atomic _pendingRenderEvent { true }; - QString testSnapshotLocation { QString() }; + QString testSnapshotLocation; }; #endif // hifi_Application_h diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index 86c860cfcb..a3454bcba5 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -37,7 +37,7 @@ class Snapshot : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY public: - static QString saveSnapshot(QImage image, const QString& filename, const QString& pathname); + static QString saveSnapshot(QImage image, const QString& filename, const QString& pathname = QString()); static QTemporaryFile* saveTempSnapshot(QImage image); static SnapshotMetaData* parseSnapshotData(QString snapshotPath); From 56e5b0e7b434c6375207c0f4cf14fbaea03666cb Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 2 May 2018 15:25:31 -0700 Subject: [PATCH 27/92] Added `autoTester.enableAuto();` to the recursive tests. --- tools/auto-tester/src/Test.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index 7139f0a43c..18d1350402 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -371,7 +371,8 @@ void Test::createRecursiveScript(const QString& topLevelDirectory, bool interact textStream << "var autoTester = Script.require(\"https://github.com/" + githubUser + "/hifi_tests/blob/" + gitHubBranch + "/tests/utils/autoTester.js?raw=true\");" << endl; - textStream << "autoTester.enableRecursive();" << endl << endl; + textStream << "autoTester.enableRecursive();" << endl; + textStream << "autoTester.enableAuto();" << endl << endl; QVector testPathnames; From b9cdaf31a07b0346aa5e3a1005c106687097e1ef Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 2 May 2018 15:26:03 -0700 Subject: [PATCH 28/92] Corrected name of create all recursive tests call. --- tools/auto-tester/src/ui/AutoTester.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/auto-tester/src/ui/AutoTester.ui b/tools/auto-tester/src/ui/AutoTester.ui index c5115d69b2..8c534eb7c7 100644 --- a/tools/auto-tester/src/ui/AutoTester.ui +++ b/tools/auto-tester/src/ui/AutoTester.ui @@ -95,7 +95,7 @@ 24 - + 360 From 9776e1d15d42313d845ac532a4c77d807c1ae9fa Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 2 May 2018 23:38:30 -0700 Subject: [PATCH 29/92] Exposing larger number of ubo because we can and moving the ubo slot using 11 to 12 to avoid collision --- .../src/RenderableParticleEffectEntityItem.cpp | 4 ++-- .../entities-renderer/src/RenderablePolyLineEntityItem.cpp | 4 ++-- libraries/gpu-gl-common/src/gpu/gl/GLBackend.h | 2 +- libraries/gpu/src/gpu/Batch.cpp | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index b3a4a1a1ab..ee77646920 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -23,8 +23,8 @@ using namespace render::entities; static uint8_t CUSTOM_PIPELINE_NUMBER = 0; static gpu::Stream::FormatPointer _vertexFormat; static std::weak_ptr _texturedPipeline; -// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 11 to avoid collisions -static int32_t PARTICLE_UNIFORM_SLOT { 11 }; +// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 12 to avoid collisions +static int32_t PARTICLE_UNIFORM_SLOT { 12 }; static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, gpu::Batch& batch) { auto texturedPipeline = _texturedPipeline.lock(); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 394ab08dfb..d571eac35c 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -34,8 +34,8 @@ using namespace render::entities; static uint8_t CUSTOM_PIPELINE_NUMBER { 0 }; static const int32_t PAINTSTROKE_TEXTURE_SLOT { 0 }; -// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 11 to avoid collisions -static const int32_t PAINTSTROKE_UNIFORM_SLOT { 11 }; +// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 12 to avoid collisions +static const int32_t PAINTSTROKE_UNIFORM_SLOT { 12 }; static gpu::Stream::FormatPointer polylineFormat; static gpu::PipelinePointer polylinePipeline; #ifdef POLYLINE_ENTITY_USE_FADE_EFFECT diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h index f2e2271552..53a147fb27 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h @@ -92,7 +92,7 @@ public: // this is the maximum per shader stage on the low end apple // TODO make it platform dependant at init time - static const int MAX_NUM_UNIFORM_BUFFERS = 12; + static const int MAX_NUM_UNIFORM_BUFFERS = 15; size_t getMaxNumUniformBuffers() const { return MAX_NUM_UNIFORM_BUFFERS; } // this is the maximum per shader stage on the low end apple diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 31bbfdd708..7725ee7bce 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -34,7 +34,7 @@ ProfileRangeBatch::~ProfileRangeBatch() { using namespace gpu; // FIXME make these backend / pipeline dependent. -static const int MAX_NUM_UNIFORM_BUFFERS = 12; +static const int MAX_NUM_UNIFORM_BUFFERS = 15; static const int MAX_NUM_RESOURCE_BUFFERS = 16; static const int MAX_NUM_RESOURCE_TEXTURES = 16; From 6579e3c3d23a9117e7f64bcc4a320bebf3498c7b Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 3 May 2018 09:09:58 -0700 Subject: [PATCH 30/92] Adjusting the number to 14 max UBO per shader stage after checking on opengl.glinfo.org --- libraries/gpu-gl-common/src/gpu/gl/GLBackend.h | 2 +- libraries/gpu/src/gpu/Batch.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h index 53a147fb27..f0b79fb23e 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h @@ -92,7 +92,7 @@ public: // this is the maximum per shader stage on the low end apple // TODO make it platform dependant at init time - static const int MAX_NUM_UNIFORM_BUFFERS = 15; + static const int MAX_NUM_UNIFORM_BUFFERS = 14; size_t getMaxNumUniformBuffers() const { return MAX_NUM_UNIFORM_BUFFERS; } // this is the maximum per shader stage on the low end apple diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 7725ee7bce..4b965af7bc 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -34,7 +34,7 @@ ProfileRangeBatch::~ProfileRangeBatch() { using namespace gpu; // FIXME make these backend / pipeline dependent. -static const int MAX_NUM_UNIFORM_BUFFERS = 15; +static const int MAX_NUM_UNIFORM_BUFFERS = 14; static const int MAX_NUM_RESOURCE_BUFFERS = 16; static const int MAX_NUM_RESOURCE_TEXTURES = 16; From 60a49c3f7c630f03666e04cc67f3c4558c7816cf Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 3 May 2018 10:37:29 -0700 Subject: [PATCH 31/92] applying the local lights on translucent fix --- .../src/RenderableParticleEffectEntityItem.cpp | 4 ++-- .../entities-renderer/src/RenderablePolyLineEntityItem.cpp | 4 ++-- libraries/gpu-gl-common/src/gpu/gl/GLBackend.h | 2 +- libraries/gpu/src/gpu/Batch.cpp | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index b3a4a1a1ab..ee77646920 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -23,8 +23,8 @@ using namespace render::entities; static uint8_t CUSTOM_PIPELINE_NUMBER = 0; static gpu::Stream::FormatPointer _vertexFormat; static std::weak_ptr _texturedPipeline; -// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 11 to avoid collisions -static int32_t PARTICLE_UNIFORM_SLOT { 11 }; +// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 12 to avoid collisions +static int32_t PARTICLE_UNIFORM_SLOT { 12 }; static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, gpu::Batch& batch) { auto texturedPipeline = _texturedPipeline.lock(); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 394ab08dfb..d571eac35c 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -34,8 +34,8 @@ using namespace render::entities; static uint8_t CUSTOM_PIPELINE_NUMBER { 0 }; static const int32_t PAINTSTROKE_TEXTURE_SLOT { 0 }; -// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 11 to avoid collisions -static const int32_t PAINTSTROKE_UNIFORM_SLOT { 11 }; +// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 12 to avoid collisions +static const int32_t PAINTSTROKE_UNIFORM_SLOT { 12 }; static gpu::Stream::FormatPointer polylineFormat; static gpu::PipelinePointer polylinePipeline; #ifdef POLYLINE_ENTITY_USE_FADE_EFFECT diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h index 5bbb44f9e1..314bbee387 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h @@ -91,7 +91,7 @@ public: // this is the maximum per shader stage on the low end apple // TODO make it platform dependant at init time - static const int MAX_NUM_UNIFORM_BUFFERS = 12; + static const int MAX_NUM_UNIFORM_BUFFERS = 14; size_t getMaxNumUniformBuffers() const { return MAX_NUM_UNIFORM_BUFFERS; } // this is the maximum per shader stage on the low end apple diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 84a7c275f0..90115806b4 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -34,7 +34,7 @@ ProfileRangeBatch::~ProfileRangeBatch() { using namespace gpu; // FIXME make these backend / pipeline dependent. -static const int MAX_NUM_UNIFORM_BUFFERS = 12; +static const int MAX_NUM_UNIFORM_BUFFERS = 14; static const int MAX_NUM_RESOURCE_BUFFERS = 16; static const int MAX_NUM_RESOURCE_TEXTURES = 16; From 46f461dcdbdcf40095ef4e152fc082ae27d952e3 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 3 May 2018 11:20:37 -0700 Subject: [PATCH 32/92] Don't display crash message if running from command line with a test script. --- interface/src/Application.cpp | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2abac520fb..45a1a34f1a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -743,6 +743,9 @@ extern DisplayPluginList getDisplayPlugins(); extern InputPluginList getInputPlugins(); extern void saveInputPluginSettings(const InputPluginList& plugins); +const QString TEST_SCRIPT { "--testScript" }; +const QString TEST_SNAPSHOT_LOCATION { "--testSnapshotLocation" }; + bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { const char** constArgv = const_cast(argv); @@ -777,7 +780,22 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { static const auto SUPPRESS_SETTINGS_RESET = "--suppress-settings-reset"; bool suppressPrompt = cmdOptionExists(argc, const_cast(argv), SUPPRESS_SETTINGS_RESET); - bool previousSessionCrashed = CrashHandler::checkForResetSettings(runningMarkerExisted, suppressPrompt); + + // Ignore any previous crashes if running from command line with a test script. + bool inTestMode { false }; + for (int i = 0; i < argc; ++i) { + QString parameter(argv[i]); + if (parameter == TEST_SCRIPT) { + inTestMode = true; + break; + } + } + + bool previousSessionCrashed { false }; + if (!inTestMode) { + previousSessionCrashed = CrashHandler::checkForResetSettings(runningMarkerExisted, suppressPrompt); + } + // get dir to use for cache static const auto CACHE_SWITCH = "--cache"; QString cacheDir = getCmdOption(argc, const_cast(argv), CACHE_SWITCH); @@ -997,10 +1015,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning())); setProperty(hifi::properties::CRASHED, _previousSessionCrashed); { - const QString TEST_SCRIPT { "--testScript" }; - const QString TEST_SNAPSHOT_LOCATION { "--testSnapshotLocation" }; - const QStringList args = arguments(); + for (int i = 0; i < args.size() - 1; ++i) { if (args.at(i) == TEST_SCRIPT) { QString testScriptPath = args.at(i + 1); From 4793cddde6a4e1eb12281df57b0cb722e9e66f68 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 3 May 2018 11:27:07 -0700 Subject: [PATCH 33/92] fix highlighting issues --- .../highlightNearbyEntities.js | 4 ++- .../mouseHighlightEntities.js | 31 +++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js index a66f7bd144..32e1b4300d 100644 --- a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js +++ b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js @@ -89,7 +89,9 @@ } if (this.isGrabable(controllerData, props) || this.hasHyperLink(props)) { dispatcherUtils.highlightTargetEntity(props.id); - newHighlightedEntities.push(props.id); + if (newHighlightedEntities.indexOf(props.id) < 0) { + newHighlightedEntities.push(props.id); + } } } diff --git a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js b/scripts/system/controllers/controllerModules/mouseHighlightEntities.js index 6af1055a69..86c96fcf6b 100644 --- a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js +++ b/scripts/system/controllers/controllerModules/mouseHighlightEntities.js @@ -12,7 +12,7 @@ /* jslint bitwise: true */ -/* global Script, print, Entities, Picks, HMD */ +/* global Script, print, Entities, Picks, HMD, Controller, MyAvatar*/ (function() { @@ -20,6 +20,7 @@ function MouseHighlightEntities() { this.highlightedEntity = null; + this.grabbedEntity = null; this.parameters = dispatcherUtils.makeDispatcherModuleParameters( 5, @@ -27,13 +28,18 @@ [], 100); + this.setGrabbedEntity = function(entity) { + this.grabbedEntity = entity; + this.highlightedEntity = null; + }; + this.isReady = function(controllerData) { if (HMD.active) { if (this.highlightedEntity) { dispatcherUtils.unhighlightTargetEntity(this.highlightedEntity); this.highlightedEntity = null; } - } else { + } else if (!this.grabbedEntity) { var pickResult = controllerData.mouseRayPick; if (pickResult.type === Picks.INTERSECTED_ENTITY) { var targetEntityID = pickResult.objectID; @@ -70,8 +76,29 @@ var mouseHighlightEntities = new MouseHighlightEntities(); dispatcherUtils.enableDispatcherModule("MouseHighlightEntities", mouseHighlightEntities); + var handleMessage = function(channel, message, sender) { + var data; + if (sender === MyAvatar.sessionUUID) { + if (channel === 'Hifi-Object-Manipulation') { + try { + data = JSON.parse(message); + if (data.action === 'grab') { + var grabbedEntity = data.grabbedEntity; + mouseHighlightEntities.setGrabbedEntity(grabbedEntity); + } else if (data.action === 'release') { + mouseHighlightEntities.setGrabbedEntity(null); + } + } catch (e) { + print("Warning: mouseHighlightEntities -- error parsing Hifi-Object-Manipulation: " + message); + } + } + } + }; + function cleanup() { dispatcherUtils.disableDispatcherModule("MouseHighlightEntities"); } + Messages.subscribe('Hifi-Object-Manipulation'); + Messages.messageReceived.connect(handleMessage); Script.scriptEnding.connect(cleanup); })(); From cffb008c3113b3871533d0e4b4aa1448dd99b604 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 3 May 2018 13:07:32 -0700 Subject: [PATCH 34/92] fixing edge case --- scripts/system/controllers/grab.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js index 8ae94a4caa..a835373e4d 100644 --- a/scripts/system/controllers/grab.js +++ b/scripts/system/controllers/grab.js @@ -409,7 +409,7 @@ Grabber.prototype.pressEvent = function(event) { var args = "mouse"; Entities.callEntityMethod(this.entityID, "startDistanceGrab", args); - Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({ + Messages.sendLocalMessage('Hifi-Object-Manipulation', JSON.stringify({ action: 'grab', grabbedEntity: this.entityID })); @@ -450,7 +450,7 @@ Grabber.prototype.releaseEvent = function(event) { var args = "mouse"; Entities.callEntityMethod(this.entityID, "releaseGrab", args); - Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({ + Messages.sendLocalMessage('Hifi-Object-Manipulation', JSON.stringify({ action: 'release', grabbedEntity: this.entityID, joint: "mouse" From 3a5425122bcba2a91525c457ef92ca752a4dd782 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 3 May 2018 14:31:01 -0700 Subject: [PATCH 35/92] Shutdown interface when test script finishes. --- interface/src/Application.cpp | 4 +++- libraries/script-engine/src/ScriptEngines.cpp | 11 ++++++++++- libraries/script-engine/src/ScriptEngines.h | 3 ++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 45a1a34f1a..d8c162a79c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2160,7 +2160,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo if (testProperty.isValid()) { auto scriptEngines = DependencyManager::get(); const auto testScript = property(hifi::properties::TEST).toUrl(); - scriptEngines->loadScript(testScript, false); + + // Set last parameter to exit interface when the test script finishes + scriptEngines->loadScript(testScript, false, false, false, false, true); // This is done so we don't get a "connection time-out" message when we haven't passed in a URL. if (arguments().contains("--url")) { diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index f2ed296b63..ef4eddbf39 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -456,7 +456,7 @@ void ScriptEngines::reloadAllScripts() { } ScriptEnginePointer ScriptEngines::loadScript(const QUrl& scriptFilename, bool isUserLoaded, bool loadScriptFromEditor, - bool activateMainWindow, bool reload) { + bool activateMainWindow, bool reload, bool exitWhenFinished) { if (thread() != QThread::currentThread()) { ScriptEnginePointer result { nullptr }; BLOCKING_INVOKE_METHOD(this, "loadScript", Q_RETURN_ARG(ScriptEnginePointer, result), @@ -496,6 +496,11 @@ ScriptEnginePointer ScriptEngines::loadScript(const QUrl& scriptFilename, bool i connect(scriptEngine.data(), &ScriptEngine::scriptLoaded, this, &ScriptEngines::onScriptEngineLoaded); connect(scriptEngine.data(), &ScriptEngine::errorLoadingScript, this, &ScriptEngines::onScriptEngineError); + // Shutdown interface when script finishes, if requested + if (exitWhenFinished) { + connect(scriptEngine.data(), &ScriptEngine::finished, this, &ScriptEngines::exitWhenFinished); + } + // get the script engine object to load the script at the designated script URL scriptEngine->loadURL(scriptUrl, reload); } @@ -536,6 +541,10 @@ void ScriptEngines::onScriptEngineLoaded(const QString& rawScriptURL) { emit scriptCountChanged(); } +void ScriptEngines::exitWhenFinished() { + qApp->quit(); +} + int ScriptEngines::runScriptInitializers(ScriptEnginePointer scriptEngine) { int ii=0; for (auto initializer : _scriptInitializers) { diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index 376bae4827..6f88e8978d 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -91,7 +91,7 @@ public: * @returns {boolean} */ Q_INVOKABLE ScriptEnginePointer loadScript(const QUrl& scriptFilename = QString(), - bool isUserLoaded = true, bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false); + bool isUserLoaded = true, bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false, bool exitWhenFinished = false); /**jsdoc * @function ScriptDiscoveryService.stopScript @@ -266,6 +266,7 @@ protected: ScriptEnginePointer reloadScript(const QString& scriptName, bool isUserLoaded = true) { return loadScript(scriptName, isUserLoaded, false, false, true); } void removeScriptEngine(ScriptEnginePointer); void onScriptEngineLoaded(const QString& scriptFilename); + void exitWhenFinished(); void onScriptEngineError(const QString& scriptFilename); void launchScriptEngine(ScriptEnginePointer); From 3b566332c6d6fe3413b0bf6b3293dd75b46a8e01 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 3 May 2018 14:34:12 -0700 Subject: [PATCH 36/92] Shutdown interface when test script finishes. --- libraries/script-engine/src/ScriptEngines.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index ef4eddbf39..d2834e8c4a 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -456,7 +456,7 @@ void ScriptEngines::reloadAllScripts() { } ScriptEnginePointer ScriptEngines::loadScript(const QUrl& scriptFilename, bool isUserLoaded, bool loadScriptFromEditor, - bool activateMainWindow, bool reload, bool exitWhenFinished) { + bool activateMainWindow, bool reload, bool exitWhenFinished) { if (thread() != QThread::currentThread()) { ScriptEnginePointer result { nullptr }; BLOCKING_INVOKE_METHOD(this, "loadScript", Q_RETURN_ARG(ScriptEnginePointer, result), @@ -496,7 +496,7 @@ ScriptEnginePointer ScriptEngines::loadScript(const QUrl& scriptFilename, bool i connect(scriptEngine.data(), &ScriptEngine::scriptLoaded, this, &ScriptEngines::onScriptEngineLoaded); connect(scriptEngine.data(), &ScriptEngine::errorLoadingScript, this, &ScriptEngines::onScriptEngineError); - // Shutdown interface when script finishes, if requested + // Shutdown Interface when script finishes, if requested if (exitWhenFinished) { connect(scriptEngine.data(), &ScriptEngine::finished, this, &ScriptEngines::exitWhenFinished); } From beb19c53faa18ff57bb0f12b147b2ca5292354e6 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 3 May 2018 15:00:14 -0700 Subject: [PATCH 37/92] Added date and time to auto-generated scripts. --- tools/auto-tester/src/Test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index 18d1350402..e9dcad6c72 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -366,10 +366,10 @@ void Test::createRecursiveScript(const QString& topLevelDirectory, bool interact } QTextStream textStream(&allTestsFilename); - textStream << "// This is an automatically generated file, created by auto-tester" << endl << endl; + textStream << "// This is an automatically generated file, created by auto-tester on " << __DATE__ << ", " << __TIME__ << endl << endl; textStream << "var autoTester = Script.require(\"https://github.com/" + githubUser + "/hifi_tests/blob/" - + gitHubBranch + "/tests/utils/autoTester.js?raw=true\");" << endl; + + gitHubBranch + "/tests/utils/autoTester.js?raw=true\");" << endl << endl; textStream << "autoTester.enableRecursive();" << endl; textStream << "autoTester.enableAuto();" << endl << endl; From fe9c6052f73a55aa1873485fa6ae6a7c1d6bf580 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 3 May 2018 15:02:11 -0700 Subject: [PATCH 38/92] Added `quitWhenFinished` parameter to the command line. --- interface/src/Application.cpp | 15 +++++++++++---- interface/src/Application.h | 1 + interface/src/ui/Snapshot.cpp | 2 ++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d8c162a79c..fed6caab89 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -743,7 +743,9 @@ extern DisplayPluginList getDisplayPlugins(); extern InputPluginList getInputPlugins(); extern void saveInputPluginSettings(const InputPluginList& plugins); +// Parameters used for running tests from teh command line const QString TEST_SCRIPT { "--testScript" }; +const QString TEST_QUIT_WHEN_FINISHED { "--quitWhenFinished" }; const QString TEST_SNAPSHOT_LOCATION { "--testSnapshotLocation" }; bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { @@ -1018,11 +1020,16 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo const QStringList args = arguments(); for (int i = 0; i < args.size() - 1; ++i) { - if (args.at(i) == TEST_SCRIPT) { + if (args.at(i) == TEST_SCRIPT && (i + 1) < args.size()) { QString testScriptPath = args.at(i + 1); if (QFileInfo(testScriptPath).exists()) { setProperty(hifi::properties::TEST, QUrl::fromLocalFile(testScriptPath)); - } + } + + // quite when finished parameter must directly follow the test script + if ((i + 2) < args.size() && args.at(i + 2) == TEST_QUIT_WHEN_FINISHED) { + quitWhenFinished = true; + } } else if (args.at(i) == TEST_SNAPSHOT_LOCATION) { // Set test snapshot location only if it is a writeable directory QString pathname(args.at(i + 1)); @@ -2161,8 +2168,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto scriptEngines = DependencyManager::get(); const auto testScript = property(hifi::properties::TEST).toUrl(); - // Set last parameter to exit interface when the test script finishes - scriptEngines->loadScript(testScript, false, false, false, false, true); + // Set last parameter to exit interface when the test script finishes, if so requested + scriptEngines->loadScript(testScript, false, false, false, false, quitWhenFinished); // This is done so we don't get a "connection time-out" message when we haven't passed in a URL. if (arguments().contains("--url")) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 088b74aa9b..cc366c74fe 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -740,5 +740,6 @@ private: std::atomic _pendingRenderEvent { true }; QString testSnapshotLocation; + bool quitWhenFinished { false }; }; #endif // hifi_Application_h diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index d52f01223c..5616b35ac0 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -73,6 +73,7 @@ SnapshotMetaData* Snapshot::parseSnapshotData(QString snapshotPath) { return data; } +#pragma optimize("", off) QString Snapshot::saveSnapshot(QImage image, const QString& filename, const QString& pathname) { QFile* snapshotFile = savedFileForSnapshot(image, false, filename, pathname); @@ -92,6 +93,7 @@ QTemporaryFile* Snapshot::saveTempSnapshot(QImage image) { return static_cast(savedFileForSnapshot(image, true, QString(), QString())); } +#pragma optimize("", off) QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QString& userSelectedFilename, const QString& userSelectedPathname) { // adding URL to snapshot From 2c6c0a25fcc95b0ba37a356ae460d3da8b796036 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 3 May 2018 15:15:30 -0700 Subject: [PATCH 39/92] Add testSnapshotLocation parameter to `takeSnapshot`. --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fed6caab89..54f1ba2606 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -7412,7 +7412,7 @@ void Application::loadAvatarBrowser() const { void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio, const QString& filename) { postLambdaEvent([notify, includeAnimated, aspectRatio, filename, this] { // Get a screenshot and save it - QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio), filename); + QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio), filename, testSnapshotLocation); // If we're not doing an animated snapshot as well... if (!includeAnimated) { // Tell the dependency manager that the capture of the still snapshot has taken place. From 887b8285cdc03dce6c9ab369e6f8200ed16668bf Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 3 May 2018 16:44:04 -0700 Subject: [PATCH 40/92] Removed unneeded pragma. --- interface/src/ui/Snapshot.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 5616b35ac0..a84e19154b 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -73,7 +73,6 @@ SnapshotMetaData* Snapshot::parseSnapshotData(QString snapshotPath) { return data; } -#pragma optimize("", off) QString Snapshot::saveSnapshot(QImage image, const QString& filename, const QString& pathname) { QFile* snapshotFile = savedFileForSnapshot(image, false, filename, pathname); From da621d99d35c55fae647d2f4510b985f21b218d1 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 3 May 2018 16:52:03 -0700 Subject: [PATCH 41/92] Removed unneeded pragma. --- interface/src/ui/Snapshot.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index a84e19154b..d52f01223c 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -92,7 +92,6 @@ QTemporaryFile* Snapshot::saveTempSnapshot(QImage image) { return static_cast(savedFileForSnapshot(image, true, QString(), QString())); } -#pragma optimize("", off) QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QString& userSelectedFilename, const QString& userSelectedPathname) { // adding URL to snapshot From 1f691edf0d7a731a692757844748c62a9e62a088 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 3 May 2018 17:04:17 -0700 Subject: [PATCH 42/92] Removed platform code (was used for MD files). --- tools/auto-tester/src/Test.cpp | 72 ---------------------------------- tools/auto-tester/src/Test.h | 6 --- 2 files changed, 78 deletions(-) diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index e9dcad6c72..e00bc920e5 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -530,26 +530,6 @@ ExtractedText Test::getTestScriptLines(QString testFileName) { QStringList tokens = line.split('"'); relevantTextFromTest.title = tokens[1]; - } else if (lineAssertPlatform.match(line).hasMatch()) { - QStringList platforms = line.split('"'); - relevantTextFromTest.platform = platforms[1]; - - } else if (lineAssertDisplay.match(line).hasMatch()) { - QStringList displays = line.split('"'); - relevantTextFromTest.display = displays[1]; - - } else if (lineAssertCPU.match(line).hasMatch()) { - QStringList cpus = line.split('"'); - relevantTextFromTest.cpu = cpus[1]; - - } else if (lineAssertGPU.match(line).hasMatch()) { - QStringList gpus = line.split('"'); - relevantTextFromTest.gpu = gpus[1]; - - } else if (lineAssertPhysicalMemoryGB.match(line).hasMatch()) { - QStringList physicalMemoryGB = line.split('"'); - relevantTextFromTest.physicalMemoryGB = physicalMemoryGB[1]; - } else if (lineStepSnapshot.match(line).hasMatch()) { QStringList tokens = line.split('"'); QString nameOfStep = tokens[1]; @@ -653,58 +633,6 @@ void Test::createMDFile(const QString& testDirectory) { stream << "## Preconditions" << "\n"; stream << "- In an empty region of a domain with editing rights." << "\n\n"; - // Platform - QStringList platforms = testScriptLines.platform.split(" ");; - if (platforms.size() > 0) { - stream << "## Platforms\n"; - stream << "Run the test on each of the following platforms\n"; - for (int i = 0; i < platforms.size(); ++i) { - // Note that the platforms parameter may include extra spaces, these appear as empty strings in the list - if (platforms[i] != QString()) { - stream << " - " << platforms[i] << "\n"; - } - } - } - - // Display - QStringList displays = testScriptLines.display.split(" "); - if (displays.size()) { - stream << "## Displays\n"; - stream << "Run the test on each of the following displays\n"; - for (int i = 0; i < displays.size(); ++i) { - // Note that the displays parameter may include extra spaces, these appear as empty strings in the list - if (displays[i] != QString()) { - stream << " - " << displays[i] << "\n"; - } - } - } - - // CPU - QStringList cpus = testScriptLines.cpu.split(" "); - if (cpus.size() > 0) { - stream << "## Processors\n"; - stream << "Run the test on each of the following processors\n"; - for (int i = 0; i < cpus.size(); ++i) { - // Note that the cpus parameter may include extra spaces, these appear as empty strings in the list - if (cpus[i] != QString()) { - stream << " - " << cpus[i] << "\n"; - } - } - } - - // GPU - QStringList gpus = testScriptLines.gpu.split(" "); - if (gpus.size() > 0) { - stream << "## Graphics Cards\n"; - stream << "Run the test on graphics cards from each of the following vendors\n"; - for (int i = 0; i < gpus.size(); ++i) { - // Note that the gpus parameter may include extra spaces, these appear as empty strings in the list - if (gpus[i] != QString()) { - stream << " - " << gpus[i] << "\n"; - } - } - } - stream << "## Steps\n"; stream << "Press space bar to advance step by step\n\n"; diff --git a/tools/auto-tester/src/Test.h b/tools/auto-tester/src/Test.h index 02cab53381..b341c1d00f 100644 --- a/tools/auto-tester/src/Test.h +++ b/tools/auto-tester/src/Test.h @@ -30,12 +30,6 @@ using StepList = std::vector; class ExtractedText { public: QString title; - QString platform; - QString display; - QString cpu; - QString gpu; - QString physicalMemoryGB; - StepList stepList; }; From a57c72df6e4754e497f38827bfa888f954325212 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 4 May 2018 08:53:49 -0700 Subject: [PATCH 43/92] fix entity highlighting during edit mode --- .../controllers/controllerModules/mouseHighlightEntities.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js b/scripts/system/controllers/controllerModules/mouseHighlightEntities.js index 86c96fcf6b..3180e58e2c 100644 --- a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js +++ b/scripts/system/controllers/controllerModules/mouseHighlightEntities.js @@ -12,10 +12,11 @@ /* jslint bitwise: true */ -/* global Script, print, Entities, Picks, HMD, Controller, MyAvatar*/ +/* global Script, print, Entities, Picks, HMD, Controller, MyAvatar, isInEditMode*/ (function() { + Script.include("/~/system/libraries/utils.js"); var dispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js"); function MouseHighlightEntities() { @@ -39,7 +40,7 @@ dispatcherUtils.unhighlightTargetEntity(this.highlightedEntity); this.highlightedEntity = null; } - } else if (!this.grabbedEntity) { + } else if (!this.grabbedEntity && !isInEditMode()) { var pickResult = controllerData.mouseRayPick; if (pickResult.type === Picks.INTERSECTED_ENTITY) { var targetEntityID = pickResult.objectID; From a35517d9851aad3ea1c324840912670a3c54bcd0 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 5 May 2018 07:05:10 +1200 Subject: [PATCH 44/92] Fix JSDoc for Users.requestUsernameFromID --- .../script-engine/src/UsersScriptingInterface.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index f214c3f11c..e80d38239f 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -106,10 +106,11 @@ public slots: void mute(const QUuid& nodeID); /**jsdoc - * Get the user name and machine fingerprint associated with the given UUID. This will only do anything if you're an admin - * of the domain you're in. - * @function Users.getUsernameFromID - * @param {Uuid} nodeID The node or session ID of the user whose username you want. + * Request the user name and machine fingerprint associated with the given UUID. The user name will be returned in a + * {@link Users.usernameFromIDReply|usernameFromIDReply} signal. This will only do anything if you're an admin of the domain + * you're in. + * @function Users.requestUsernameFromID + * @param {Uuid} nodeID The node or session ID of the user whose user name you want. */ void requestUsernameFromID(const QUuid& nodeID); @@ -170,7 +171,8 @@ signals: void enteredIgnoreRadius(); /**jsdoc - * Notifies scripts of the user name and machine fingerprint associated with a UUID. + * Triggered in response to a {@link Users.requestUsernameFromID|requestUsernameFromID} call. Provides the user name and + * machine fingerprint associated with a UUID. * Username and machineFingerprint will be their default constructor output if the requesting user isn't an admin. * @function Users.usernameFromIDReply * @param {Uuid} nodeID From aef5ea093604bc2685f319a9e835ba915323f6be Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Fri, 4 May 2018 12:30:13 -0700 Subject: [PATCH 45/92] Correct usage of the test script URL. --- interface/src/Application.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 54f1ba2606..fc1602e2e3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1022,7 +1022,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo for (int i = 0; i < args.size() - 1; ++i) { if (args.at(i) == TEST_SCRIPT && (i + 1) < args.size()) { QString testScriptPath = args.at(i + 1); - if (QFileInfo(testScriptPath).exists()) { + + // If the URL scheme is "http(s)" then use as is, else - treat it as a local file + // This is done so as not break previous command line scripts + if (testScriptPath.left(4) == "http") { + setProperty(hifi::properties::TEST, QUrl::fromUserInput(testScriptPath)); + } else if (QFileInfo(testScriptPath).exists()) { setProperty(hifi::properties::TEST, QUrl::fromLocalFile(testScriptPath)); } From 2c2b74f4c8a965ee7f0171f9d9685d09b9c75a4e Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Fri, 4 May 2018 14:13:14 -0700 Subject: [PATCH 46/92] Removed unused variable. --- tools/auto-tester/src/ui/AutoTester.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/auto-tester/src/ui/AutoTester.cpp b/tools/auto-tester/src/ui/AutoTester.cpp index e0f92664ef..59fe5d9de2 100644 --- a/tools/auto-tester/src/ui/AutoTester.cpp +++ b/tools/auto-tester/src/ui/AutoTester.cpp @@ -94,7 +94,6 @@ void AutoTester::saveImage(int index) { QPixmap pixmap; pixmap.loadFromData(downloaders[index]->downloadedData()); - int sdf = pixmap.width(); QImage image = pixmap.toImage(); image = image.convertToFormat(QImage::Format_ARGB32); From 6414fcaae568b31e43c89b72bbc7405d4eb5e88a Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 4 May 2018 14:20:17 -0700 Subject: [PATCH 47/92] fix-another-highlighting-issue --- .../controllerModules/highlightNearbyEntities.js | 11 ++++++++++- .../controllers/controllerModules/inEditMode.js | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js index 32e1b4300d..bc09ebee7a 100644 --- a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js +++ b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js @@ -56,6 +56,12 @@ return canGrabEntity; }; + this.clearAll = function() { + this.highlightedEntities.forEach(function(entity) { + dispatcherUtils.unhighlightTargetEntity(entity); + }); + }; + this.hasHyperLink = function(props) { return (props.href !== "" && props.href !== undefined); }; @@ -121,7 +127,6 @@ if (channel === 'Hifi-unhighlight-entity') { try { data = JSON.parse(message); - var hand = data.hand; if (hand === dispatcherUtils.LEFT_HAND) { leftHighlightNearbyEntities.removeEntityFromHighlightList(data.entityID); @@ -131,6 +136,9 @@ } catch (e) { print("Failed to parse message"); } + } else if (channel === 'Hifi-unhighlight-all') { + leftHighlightNearbyEntities.clearAll(); + rightHighlightNearbyEntities.clearAll(); } } }; @@ -145,6 +153,7 @@ dispatcherUtils.disableDispatcherModule("RightHighlightNearbyEntities"); } Messages.subscribe('Hifi-unhighlight-entity'); + Messages.subscribe('Hifi-unhighlight-all'); Messages.messageReceived.connect(handleMessage); Script.scriptEnding.connect(cleanup); }()); diff --git a/scripts/system/controllers/controllerModules/inEditMode.js b/scripts/system/controllers/controllerModules/inEditMode.js index f7e86f9042..3ad7902d71 100644 --- a/scripts/system/controllers/controllerModules/inEditMode.js +++ b/scripts/system/controllers/controllerModules/inEditMode.js @@ -78,6 +78,7 @@ Script.include("/~/system/libraries/utils.js"); if (controllerData.triggerValues[this.hand] < TRIGGER_ON_VALUE) { this.triggerClicked = false; } + Messages.sendLocalMessage('Hifi-unhighlight-all', ''); return makeRunningValues(true, [], []); } this.triggerClicked = false; From 176d69444f461cdb16d3d26b9ae0f06e17db0476 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 4 May 2018 14:20:17 -0700 Subject: [PATCH 48/92] fix-another-highlighting-issue --- .../controllerModules/highlightNearbyEntities.js | 11 ++++++++++- .../controllers/controllerModules/inEditMode.js | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js index 32e1b4300d..bc09ebee7a 100644 --- a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js +++ b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js @@ -56,6 +56,12 @@ return canGrabEntity; }; + this.clearAll = function() { + this.highlightedEntities.forEach(function(entity) { + dispatcherUtils.unhighlightTargetEntity(entity); + }); + }; + this.hasHyperLink = function(props) { return (props.href !== "" && props.href !== undefined); }; @@ -121,7 +127,6 @@ if (channel === 'Hifi-unhighlight-entity') { try { data = JSON.parse(message); - var hand = data.hand; if (hand === dispatcherUtils.LEFT_HAND) { leftHighlightNearbyEntities.removeEntityFromHighlightList(data.entityID); @@ -131,6 +136,9 @@ } catch (e) { print("Failed to parse message"); } + } else if (channel === 'Hifi-unhighlight-all') { + leftHighlightNearbyEntities.clearAll(); + rightHighlightNearbyEntities.clearAll(); } } }; @@ -145,6 +153,7 @@ dispatcherUtils.disableDispatcherModule("RightHighlightNearbyEntities"); } Messages.subscribe('Hifi-unhighlight-entity'); + Messages.subscribe('Hifi-unhighlight-all'); Messages.messageReceived.connect(handleMessage); Script.scriptEnding.connect(cleanup); }()); diff --git a/scripts/system/controllers/controllerModules/inEditMode.js b/scripts/system/controllers/controllerModules/inEditMode.js index f7e86f9042..3ad7902d71 100644 --- a/scripts/system/controllers/controllerModules/inEditMode.js +++ b/scripts/system/controllers/controllerModules/inEditMode.js @@ -78,6 +78,7 @@ Script.include("/~/system/libraries/utils.js"); if (controllerData.triggerValues[this.hand] < TRIGGER_ON_VALUE) { this.triggerClicked = false; } + Messages.sendLocalMessage('Hifi-unhighlight-all', ''); return makeRunningValues(true, [], []); } this.triggerClicked = false; From 00d2f9494bbc493a8efad13ea2cbe29a1983339c Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Fri, 4 May 2018 15:07:20 -0700 Subject: [PATCH 49/92] Change HMACAuth::calculateHash to just call existing methods --- libraries/networking/src/HMACAuth.cpp | 17 ++++------------- libraries/networking/src/HMACAuth.h | 2 +- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/libraries/networking/src/HMACAuth.cpp b/libraries/networking/src/HMACAuth.cpp index 8e57978b5a..515af9a070 100644 --- a/libraries/networking/src/HMACAuth.cpp +++ b/libraries/networking/src/HMACAuth.cpp @@ -106,21 +106,12 @@ HMACAuth::HMACHash HMACAuth::result() { bool HMACAuth::calculateHash(HMACHash& hashResult, const char* data, int dataLen) { QMutexLocker lock(&_lock); - if (!HMAC_Update(_hmacContext, reinterpret_cast(data), dataLen)) { - qCWarning(networking) << "Error occured calling HMAC_Update"; + if (!addData(data, dataLen)) { + qCWarning(networking) << "Error occured calling HMACAuth::addData()"; assert(false); return false; } - hashResult.resize(EVP_MAX_MD_SIZE); - unsigned int hashLen; - if (HMAC_Final(_hmacContext, &hashResult[0], &hashLen)) { - hashResult.resize((size_t)hashLen); - // Clear state for possible reuse. - HMAC_Init_ex(_hmacContext, nullptr, 0, nullptr, nullptr); - return true; - } - qCWarning(networking) << "Error occured calling HMAC_Final"; - assert(false); - return false; + hashResult = result(); + return true; } diff --git a/libraries/networking/src/HMACAuth.h b/libraries/networking/src/HMACAuth.h index ec06bfbda2..59870bb7b6 100644 --- a/libraries/networking/src/HMACAuth.h +++ b/libraries/networking/src/HMACAuth.h @@ -35,7 +35,7 @@ public: HMACHash result(); private: - QMutex _lock; + QMutex _lock { QMutex::Recursive }; struct hmac_ctx_st* _hmacContext; AuthMethod _authMethod; }; From 4ebed7605c979eed603a1d7738730537708e3359 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 4 May 2018 10:10:48 -0700 Subject: [PATCH 50/92] MS14758: Fix avatar reset when gifting worn avatar --- interface/resources/qml/hifi/commerce/purchases/Purchases.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index 08e3e7a552..b54a931c51 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -582,7 +582,7 @@ Rectangle { } lightboxPopup.button2text = "CONFIRM"; lightboxPopup.button2method = function() { - MyAvatar.skeletonModelURL = ''; + MyAvatar.useFullAvatarURL(''); root.activeView = "giftAsset"; lightboxPopup.visible = false; }; From 8480bb962b99bdcf2a5b3e457d9cd36106889b68 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 3 May 2018 13:51:50 -0700 Subject: [PATCH 51/92] Fix for crash deep in QML after useFullAvatarURL Here we avoid calling FSTReader::downloadMapping() from within MyAvatar::useFullAvatarURL(). This prevents the error case where a QEventLoop is entered during QML execution. --- interface/src/avatar/MyAvatar.cpp | 18 +++++++++++------- .../src/model-networking/ModelCache.cpp | 14 +++++++++----- .../src/model-networking/ModelCache.h | 2 ++ 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 249a765d92..3eef1dac3c 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1473,6 +1473,15 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { std::shared_ptr skeletonConnection = std::make_shared(); *skeletonConnection = QObject::connect(_skeletonModel.get(), &SkeletonModel::skeletonLoaded, [this, skeletonModelChangeCount, skeletonConnection]() { if (skeletonModelChangeCount == _skeletonModelChangeCount) { + + if (_fullAvatarModelName.isEmpty()) { + // Store the FST file name into preferences + const auto& mapping = _skeletonModel->getGeometry()->getMapping(); + if (mapping.value("name").isValid()) { + _fullAvatarModelName = mapping.value("name").toString(); + } + } + initHeadBones(); _skeletonModel->setCauterizeBoneSet(_headBoneSet); _fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl(); @@ -1535,12 +1544,7 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN if (_fullAvatarURLFromPreferences != fullAvatarURL) { _fullAvatarURLFromPreferences = fullAvatarURL; - if (modelName.isEmpty()) { - QVariantHash fullAvatarFST = FSTReader::downloadMapping(_fullAvatarURLFromPreferences.toString()); - _fullAvatarModelName = fullAvatarFST["name"].toString(); - } else { - _fullAvatarModelName = modelName; - } + _fullAvatarModelName = modelName; } const QString& urlString = fullAvatarURL.toString(); @@ -1548,8 +1552,8 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN setSkeletonModelURL(fullAvatarURL); UserActivityLogger::getInstance().changedModel("skeleton", urlString); } + markIdentityDataChanged(); - } void MyAvatar::setAttachmentData(const QVector& attachmentData) { diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index f17cdbb7e8..939168f1b1 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -63,16 +63,18 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) { PROFILE_ASYNC_BEGIN(resource_parse_geometry, "GeometryMappingResource::downloadFinished", _url.toString(), { { "url", _url.toString() } }); - auto mapping = FSTReader::readMapping(data); + // store parsed contents of FST file + _mapping = FSTReader::readMapping(data); + + QString filename = _mapping.value("filename").toString(); - QString filename = mapping.value("filename").toString(); if (filename.isNull()) { qCDebug(modelnetworking) << "Mapping file" << _url << "has no \"filename\" field"; finishedLoading(false); } else { QUrl url = _url.resolved(filename); - QString texdir = mapping.value(TEXDIR_FIELD).toString(); + QString texdir = _mapping.value(TEXDIR_FIELD).toString(); if (!texdir.isNull()) { if (!texdir.endsWith('/')) { texdir += '/'; @@ -82,7 +84,8 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) { _textureBaseUrl = url.resolved(QUrl(".")); } - auto animGraphVariant = mapping.value("animGraphUrl"); + auto animGraphVariant = _mapping.value("animGraphUrl"); + if (animGraphVariant.isValid()) { QUrl fstUrl(animGraphVariant.toString()); if (fstUrl.isValid()) { @@ -95,7 +98,7 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) { } auto modelCache = DependencyManager::get(); - GeometryExtra extra{ mapping, _textureBaseUrl, false }; + GeometryExtra extra{ _mapping, _textureBaseUrl, false }; // Get the raw GeometryResource _geometryResource = modelCache->getResource(url, QUrl(), &extra).staticCast(); @@ -362,6 +365,7 @@ Geometry::Geometry(const Geometry& geometry) { } _animGraphOverrideUrl = geometry._animGraphOverrideUrl; + _mapping = geometry._mapping; } void Geometry::setTextures(const QVariantMap& textureMap) { diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index 9532f39ce0..6978e0077e 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -55,6 +55,7 @@ public: virtual bool areTexturesLoaded() const; const QUrl& getAnimGraphOverrideUrl() const { return _animGraphOverrideUrl; } + const QVariantHash& getMapping() const { return _mapping; } protected: friend class GeometryMappingResource; @@ -68,6 +69,7 @@ protected: NetworkMaterials _materials; QUrl _animGraphOverrideUrl; + QVariantHash _mapping; // parsed contents of FST file. private: mutable bool _areTexturesLoaded { false }; From 72526781d9b1fabaeede002d972c48d76e1f631b Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 19 Apr 2018 16:15:22 -0700 Subject: [PATCH 52/92] Additional work on splash screen --- interface/resources/shaders/splashSkybox.frag | 37 +++ interface/src/Application.cpp | 258 +++++++++++------- interface/src/Application.h | 2 + interface/src/Application_render.cpp | 4 +- interface/src/avatar/MyAvatar.cpp | 2 +- interface/src/avatar/MyAvatar.h | 2 +- .../display-plugins/OpenGLDisplayPlugin.cpp | 3 +- .../procedural/src/procedural/Procedural.cpp | 4 +- .../src/ui-plugins/PluginContainer.h | 6 + .../oculus/src/OculusBaseDisplayPlugin.cpp | 11 +- 10 files changed, 221 insertions(+), 108 deletions(-) create mode 100644 interface/resources/shaders/splashSkybox.frag diff --git a/interface/resources/shaders/splashSkybox.frag b/interface/resources/shaders/splashSkybox.frag new file mode 100644 index 0000000000..8088b745bc --- /dev/null +++ b/interface/resources/shaders/splashSkybox.frag @@ -0,0 +1,37 @@ + +float noise3D(vec3 p) +{ + return fract(sin(dot(p ,vec3(12.9898,78.233,126.7235))) * 43758.5453); +} + +float worley3D(vec3 p) +{ + float r = 3.0; + vec3 f = floor(p); + vec3 x = fract(p); + for(int i = -1; i<=1; i++) + { + for(int j = -1; j<=1; j++) + { + for(int k = -1; k<=1; k++) + { + vec3 q = vec3(float(i),float(j),float(k)); + vec3 v = q + vec3(noise3D((q+f)*1.11), noise3D((q+f)*1.14), noise3D((q+f)*1.17)) - x; + float d = dot(v, v); + r = min(r, d); + } + } + } + return sqrt(r); +} + + +vec3 getSkyboxColor() { + vec3 color = abs(normalize(_normal)); +// vec2 uv; +// uv.x = 0.5 + atan(_normal.z, _normal.x); +// uv.y = 0.5 - asin(_normal.y); +// uv *= 20.0; +// color.r = worley3D(vec3(uv, iGlobalTime)); + return color; +} \ No newline at end of file diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 59541a3182..4a59cf3549 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -144,6 +144,7 @@ #include #include #include +#include #include #include @@ -385,7 +386,7 @@ Setting::Handle maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTRE static const QString MARKETPLACE_CDN_HOSTNAME = "mpassets.highfidelity.com"; static const int INTERVAL_TO_CHECK_HMD_WORN_STATUS = 500; // milliseconds static const QString DESKTOP_DISPLAY_PLUGIN_NAME = "Desktop"; - +static const QString ACTIVE_DISPLAY_PLUGIN_SETTING_NAME = "activeDisplayPlugin"; static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system"; const std::vector> Application::_acceptedExtensions { @@ -1322,10 +1323,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo QCoreApplication::processEvents(); _glWidget->createContext(); - // Create the main thread context, the GPU backend, and the display plugins + // Create the main thread context, the GPU backend initializeGL(); - DependencyManager::get()->setGPUContext(_gpuContext); - qCDebug(interfaceapp, "Initialized Display."); + qCDebug(interfaceapp, "Initialized GL"); + + // Initialize the display plugin architecture + initializeDisplayPlugins(); + qCDebug(interfaceapp, "Initialized Display"); + // Create the rendering engine. This can be slow on some machines due to lots of // GPU pipeline creation. initializeRenderEngine(); @@ -2359,6 +2364,10 @@ void Application::onAboutToQuit() { } } + // The active display plugin needs to be loaded before the menu system is active, + // so its persisted explicitly here + Setting::Handle{ ACTIVE_DISPLAY_PLUGIN_SETTING_NAME }.set(getActiveDisplayPlugin()->getName()); + getActiveDisplayPlugin()->deactivate(); if (_autoSwitchDisplayModeSupportedHMDPlugin && _autoSwitchDisplayModeSupportedHMDPlugin->isSessionActive()) { @@ -2598,10 +2607,81 @@ void Application::initializeGL() { _glWidget->makeCurrent(); _gpuContext = std::make_shared(); + DependencyManager::get()->setGPUContext(_gpuContext); + // Restore the default main thread context _offscreenContext->makeCurrent(); +} - updateDisplayMode(); +static const QString SPLASH_SKYBOX{ "{\"ProceduralEntity\":{ \"version\":2, \"shaderUrl\":\"qrc:///shaders/splashSkybox.frag\" } }" }; + +void Application::initializeDisplayPlugins() { + auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); + Setting::Handle activeDisplayPluginSetting{ ACTIVE_DISPLAY_PLUGIN_SETTING_NAME, displayPlugins.at(0)->getName() }; + auto lastActiveDisplayPluginName = activeDisplayPluginSetting.get(); + + auto defaultDisplayPlugin = displayPlugins.at(0); + // Once time initialization code + DisplayPluginPointer targetDisplayPlugin; + foreach(auto displayPlugin, displayPlugins) { + displayPlugin->setContext(_gpuContext); + if (displayPlugin->getName() == lastActiveDisplayPluginName) { + targetDisplayPlugin = displayPlugin; + } + QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged, + [this](const QSize& size) { resizeGL(); }); + QObject::connect(displayPlugin.get(), &DisplayPlugin::resetSensorsRequested, this, &Application::requestReset); + } + + // The default display plugin needs to be activated first, otherwise the display plugin thread + // may be launched by an external plugin, which is bad + setDisplayPlugin(defaultDisplayPlugin); + + // Now set the desired plugin if it's not the same as the default plugin + if (targetDisplayPlugin != defaultDisplayPlugin) { + setDisplayPlugin(targetDisplayPlugin); + } + + // Submit a default frame to render until the engine starts up + updateRenderArgs(0.0f); + + _offscreenContext->makeCurrent(); + { + QMutexLocker viewLocker(&_renderArgsMutex); + + if (_appRenderArgs._isStereo) { + _gpuContext->enableStereo(true); + _gpuContext->setStereoProjections(_appRenderArgs._eyeProjections); + _gpuContext->setStereoViews(_appRenderArgs._eyeOffsets); + } + + // Frame resources + auto framebufferCache = DependencyManager::get(); + gpu::FramebufferPointer finalFramebuffer = framebufferCache->getFramebuffer(); + std::shared_ptr procedural = std::make_shared(); + procedural->parse(SPLASH_SKYBOX); + + _gpuContext->beginFrame(_appRenderArgs._view, _appRenderArgs._headPose); + gpu::doInBatch("splashFrame", _gpuContext, [&](gpu::Batch& batch) { + batch.resetStages(); + batch.enableStereo(false); + batch.setFramebuffer(finalFramebuffer); + batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, { 0, 1, 1, 1 }); + + batch.enableSkybox(true); + batch.enableStereo(_appRenderArgs._isStereo); + batch.setViewportTransform({ 0, 0, finalFramebuffer->getSize() }); + procedural->render(batch, _appRenderArgs._renderArgs.getViewFrustum()); + }); + auto frame = _gpuContext->endFrame(); + frame->frameIndex = 0; + frame->framebuffer = finalFramebuffer; + frame->pose = _appRenderArgs._headPose; + frame->framebufferRecycler = [framebufferCache, procedural](const gpu::FramebufferPointer& framebuffer) { + framebufferCache->releaseFramebuffer(framebuffer); + }; + _displayPlugin->submitFrame(frame); + } } void Application::initializeRenderEngine() { @@ -2625,6 +2705,7 @@ void Application::initializeRenderEngine() { } extern void setupPreferences(); +static void addDisplayPluginToMenu(const DisplayPluginPointer& displayPlugin, bool active); void Application::initializeUi() { // Build a shared canvas / context for the Chromium processes @@ -2766,10 +2847,25 @@ void Application::initializeUi() { offscreenSurfaceCache->reserve(TabletScriptingInterface::QML, 1); offscreenSurfaceCache->reserve(Web3DOverlay::QML, 2); - // Now that the menu is instantiated, ensure the display plugin menu is properly updated - updateDisplayMode(); flushMenuUpdates(); + // Now that the menu is instantiated, ensure the display plugin menu is properly updated + { + auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); + // first sort the plugins into groupings: standard, advanced, developer + std::stable_sort(displayPlugins.begin(), displayPlugins.end(), + [](const DisplayPluginPointer& a, const DisplayPluginPointer& b)->bool { return a->getGrouping() < b->getGrouping(); }); + + // concatenate the groupings into a single list in the order: standard, advanced, developer + for(const auto& displayPlugin : displayPlugins) { + addDisplayPluginToMenu(displayPlugin, _displayPlugin == displayPlugin); + } + + // after all plugins have been added to the menu, add a separator to the menu + auto parent = getPrimaryMenu()->getMenu(MenuOption::OutputMenu); + parent->addSeparator(); + } + // The display plugins are created before the menu now, so we need to do this here to hide the menu bar // now that it exists if (_window && _window->isFullScreen()) { @@ -5723,6 +5819,32 @@ void Application::update(float deltaTime) { } + updateRenderArgs(deltaTime); + + // HACK + // load the view frustum + // FIXME: This preDisplayRender call is temporary until we create a separate render::scene for the mirror rendering. + // Then we can move this logic into the Avatar::simulate call. + myAvatar->preDisplaySide(&_appRenderArgs._renderArgs); + + + { + PerformanceTimer perfTimer("limitless"); + AnimDebugDraw::getInstance().update(); + } + + { + PerformanceTimer perfTimer("limitless"); + DependencyManager::get()->update(); + } + + { // Game loop is done, mark the end of the frame for the scene transactions and the render loop to take over + PerformanceTimer perfTimer("enqueueFrame"); + getMain3DScene()->enqueueFrame(); + } +} + +void Application::updateRenderArgs(float deltaTime) { editRenderArgs([this, deltaTime](AppRenderArgs& appRenderArgs) { PerformanceTimer perfTimer("editRenderArgs"); appRenderArgs._headPose = getHMDSensorPose(); @@ -5746,9 +5868,9 @@ void Application::update(float deltaTime) { QMutexLocker viewLocker(&_viewMutex); // adjust near clip plane to account for sensor scaling. auto adjustedProjection = glm::perspective(glm::radians(_fieldOfView.get()), - getActiveDisplayPlugin()->getRecommendedAspectRatio(), - DEFAULT_NEAR_CLIP * sensorToWorldScale, - DEFAULT_FAR_CLIP); + getActiveDisplayPlugin()->getRecommendedAspectRatio(), + DEFAULT_NEAR_CLIP * sensorToWorldScale, + DEFAULT_FAR_CLIP); _viewFrustum.setProjection(adjustedProjection); _viewFrustum.calculate(); } @@ -5764,8 +5886,14 @@ void Application::update(float deltaTime) { } { PROFILE_RANGE(render, "/resizeGL"); - PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings)); - bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); + bool showWarnings = false; + bool suppressShortTimings = false; + auto menu = Menu::getInstance(); + if (menu) { + suppressShortTimings = menu->isOptionChecked(MenuOption::SuppressShortTimings); + showWarnings = menu->isOptionChecked(MenuOption::PipelineWarnings); + } + PerformanceWarning::setSuppressShortTimings(suppressShortTimings); PerformanceWarning warn(showWarnings, "Application::paintGL()"); resizeGL(); } @@ -5821,12 +5949,6 @@ void Application::update(float deltaTime) { } } - // HACK - // load the view frustum - // FIXME: This preDisplayRender call is temporary until we create a separate render::scene for the mirror rendering. - // Then we can move this logic into the Avatar::simulate call. - myAvatar->preDisplaySide(&appRenderArgs._renderArgs); - { QMutexLocker viewLocker(&_viewMutex); _myCamera.loadViewFrustum(_displayViewFrustum); @@ -5838,21 +5960,6 @@ void Application::update(float deltaTime) { appRenderArgs._renderArgs.setViewFrustum(_displayViewFrustum); } }); - - { - PerformanceTimer perfTimer("limitless"); - AnimDebugDraw::getInstance().update(); - } - - { - PerformanceTimer perfTimer("limitless"); - DependencyManager::get()->update(); - } - - { // Game loop is done, mark the end of the frame for the scene transactions and the render loop to take over - PerformanceTimer perfTimer("enqueueFrame"); - getMain3DScene()->enqueueFrame(); - } } void Application::queryAvatars() { @@ -7493,15 +7600,19 @@ void Application::shareSnapshot(const QString& path, const QUrl& href) { } float Application::getRenderResolutionScale() const { - if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionOne)) { + auto menu = Menu::getInstance(); + if (!menu) { return 1.0f; - } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionTwoThird)) { + } + if (menu->isOptionChecked(MenuOption::RenderResolutionOne)) { + return 1.0f; + } else if (menu->isOptionChecked(MenuOption::RenderResolutionTwoThird)) { return 0.666f; - } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionHalf)) { + } else if (menu->isOptionChecked(MenuOption::RenderResolutionHalf)) { return 0.5f; - } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionThird)) { + } else if (menu->isOptionChecked(MenuOption::RenderResolutionThird)) { return 0.333f; - } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionQuarter)) { + } else if (menu->isOptionChecked(MenuOption::RenderResolutionQuarter)) { return 0.25f; } else { return 1.0f; @@ -7725,7 +7836,7 @@ DisplayPluginPointer Application::getActiveDisplayPlugin() const { static const char* EXCLUSION_GROUP_KEY = "exclusionGroup"; -static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool active = false) { +static void addDisplayPluginToMenu(const DisplayPluginPointer& displayPlugin, bool active) { auto menu = Menu::getInstance(); QString name = displayPlugin->getName(); auto grouping = displayPlugin->getGrouping(); @@ -7770,65 +7881,12 @@ void Application::updateDisplayMode() { qFatal("Attempted to switch display plugins from a non-main thread"); } - auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); - - // Once time initialization code - static std::once_flag once; - std::call_once(once, [&] { - foreach(auto displayPlugin, displayPlugins) { - displayPlugin->setContext(_gpuContext); - QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged, - [this](const QSize& size) { resizeGL(); }); - QObject::connect(displayPlugin.get(), &DisplayPlugin::resetSensorsRequested, this, &Application::requestReset); - } - }); - // Once time initialization code that depends on the UI being available - auto menu = Menu::getInstance(); - if (menu) { - static std::once_flag onceUi; - std::call_once(onceUi, [&] { - bool first = true; - - // first sort the plugins into groupings: standard, advanced, developer - DisplayPluginList standard; - DisplayPluginList advanced; - DisplayPluginList developer; - foreach(auto displayPlugin, displayPlugins) { - displayPlugin->setContext(_gpuContext); - auto grouping = displayPlugin->getGrouping(); - switch (grouping) { - case Plugin::ADVANCED: - advanced.push_back(displayPlugin); - break; - case Plugin::DEVELOPER: - developer.push_back(displayPlugin); - break; - default: - standard.push_back(displayPlugin); - break; - } - } - - // concatenate the groupings into a single list in the order: standard, advanced, developer - standard.insert(std::end(standard), std::begin(advanced), std::end(advanced)); - standard.insert(std::end(standard), std::begin(developer), std::end(developer)); - - foreach(auto displayPlugin, standard) { - addDisplayPluginToMenu(displayPlugin, first); - first = false; - } - - // after all plugins have been added to the menu, add a separator to the menu - auto parent = menu->getMenu(MenuOption::OutputMenu); - parent->addSeparator(); - }); - - } - + auto displayPlugins = getDisplayPlugins(); // Default to the first item on the list, in case none of the menu items match DisplayPluginPointer newDisplayPlugin = displayPlugins.at(0); + auto menu = getPrimaryMenu(); if (menu) { foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) { QString name = displayPlugin->getName(); @@ -7852,6 +7910,14 @@ void Application::updateDisplayMode() { } void Application::setDisplayPlugin(DisplayPluginPointer newDisplayPlugin) { + if (newDisplayPlugin == _displayPlugin) { + return; + } + + // FIXME don't have the application directly set the state of the UI, + // instead emit a signal that the display plugin is changing and let + // the desktop lock itself. Reduces coupling between the UI and display + // plugins auto offscreenUi = DependencyManager::get(); auto desktop = offscreenUi->getDesktop(); auto menu = Menu::getInstance(); @@ -7862,8 +7928,8 @@ void Application::setDisplayPlugin(DisplayPluginPointer newDisplayPlugin) { bool wasRepositionLocked = false; if (desktop) { // Tell the desktop to no reposition (which requires plugin info), until we have set the new plugin, below. - wasRepositionLocked = offscreenUi->getDesktop()->property("repositionLocked").toBool(); - offscreenUi->getDesktop()->setProperty("repositionLocked", true); + wasRepositionLocked = desktop->property("repositionLocked").toBool(); + desktop->setProperty("repositionLocked", true); } if (_displayPlugin) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 654b5c797b..b801ec6d34 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -148,6 +148,7 @@ public: Q_INVOKABLE QString getUserAgent(); void initializeGL(); + void initializeDisplayPlugins(); void initializeRenderEngine(); void initializeUi(); @@ -671,6 +672,7 @@ private: using RenderArgsEditor = std::function ; void editRenderArgs(RenderArgsEditor editor); + void updateRenderArgs(float deltaTime); Overlays _overlays; diff --git a/interface/src/Application_render.cpp b/interface/src/Application_render.cpp index e1015ca5d1..76babe3682 100644 --- a/interface/src/Application_render.cpp +++ b/interface/src/Application_render.cpp @@ -13,8 +13,9 @@ #include #include -#include "ui/Stats.h" +#include #include +#include "ui/Stats.h" #include "Util.h" @@ -233,3 +234,4 @@ void Application::runRenderFrame(RenderArgs* renderArgs) { _renderEngine->run(); } } + diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 15b220c63b..6c6f6d4d41 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2039,7 +2039,7 @@ void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) { } } -void MyAvatar::preDisplaySide(RenderArgs* renderArgs) { +void MyAvatar::preDisplaySide(const RenderArgs* renderArgs) { // toggle using the cauterizedBones depending on where the camera is and the rendering pass type. const bool shouldDrawHead = shouldRenderHead(renderArgs); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index ac3d3cd2f4..154e2e4d09 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -272,7 +272,7 @@ public: void update(float deltaTime); virtual void postUpdate(float deltaTime, const render::ScenePointer& scene) override; - void preDisplaySide(RenderArgs* renderArgs); + void preDisplaySide(const RenderArgs* renderArgs); const glm::mat4& getHMDSensorMatrix() const { return _hmdSensorMatrix; } const glm::vec3& getHMDSensorPosition() const { return _hmdSensorPosition; } diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 4b33565bfd..3cfc0651d8 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -336,9 +336,8 @@ void OpenGLDisplayPlugin::deactivate() { _container->showDisplayPluginsTools(false); if (!_container->currentDisplayActions().isEmpty()) { - auto menu = _container->getPrimaryMenu(); foreach(auto itemInfo, _container->currentDisplayActions()) { - menu->removeMenuItem(itemInfo.first, itemInfo.second); + _container->removeMenuItem(itemInfo.first, itemInfo.second); } _container->currentDisplayActions().clear(); } diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index c155d5bd7f..19c4a62443 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -19,7 +19,7 @@ #include #include #include - +#include #include "ProceduralCommon_frag.h" #include "Logging.h" @@ -178,6 +178,8 @@ void Procedural::setProceduralData(const ProceduralData& proceduralData) { return; } _shaderPath = shaderUrl.toLocalFile(); + } else if (shaderUrl.scheme() == URL_SCHEME_QRC) { + _shaderPath = ":" + shaderUrl.path(); } else { _networkShader = ShaderCache::instance().getShader(shaderUrl); } diff --git a/libraries/ui-plugins/src/ui-plugins/PluginContainer.h b/libraries/ui-plugins/src/ui-plugins/PluginContainer.h index da9ea46cf4..5df20ff30c 100644 --- a/libraries/ui-plugins/src/ui-plugins/PluginContainer.h +++ b/libraries/ui-plugins/src/ui-plugins/PluginContainer.h @@ -54,6 +54,12 @@ public: void setFullscreen(const QScreen* targetScreen, bool hideMenu = false); void unsetFullscreen(const QScreen* avoidScreen = nullptr); + // FIXME remove access tot he menu from the plugin container + // Instead let display plugins expose a structure about the kinds + // of actions and menu items they want to have appear when they are + // active and allow the application to act on that when the display + // plugin becomes active (or when the UI is initialized, and a + // display plugin is already active) virtual ui::Menu* getPrimaryMenu() = 0; virtual void showDisplayPluginsTools(bool show = true) = 0; virtual void requestReset() = 0; diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp index d8f2db75c9..7e337070d3 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp @@ -166,12 +166,11 @@ void OculusBaseDisplayPlugin::deactivateSession() { //_session = nullptr; } void OculusBaseDisplayPlugin::updatePresentPose() { - //mat4 sensorResetMat; - //_currentPresentFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds(); - //_currentPresentFrameInfo.predictedDisplayTime = ovr_GetPredictedDisplayTime(_session, _currentFrame->frameIndex); - //auto trackingState = ovr_GetTrackingState(_session, _currentRenderFrameInfo.predictedDisplayTime, ovrFalse); - //_currentPresentFrameInfo.presentPose = toGlm(trackingState.HeadPose.ThePose); - _currentPresentFrameInfo.presentPose = _currentPresentFrameInfo.renderPose; + _currentPresentFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds(); + _currentPresentFrameInfo.predictedDisplayTime = ovr_GetPredictedDisplayTime(_session, 0); + auto trackingState = ovr_GetTrackingState(_session, _currentRenderFrameInfo.predictedDisplayTime, ovrFalse); + _currentPresentFrameInfo.presentPose = toGlm(trackingState.HeadPose.ThePose); + _currentPresentFrameInfo.renderPose = _currentPresentFrameInfo.presentPose; } OculusBaseDisplayPlugin::~OculusBaseDisplayPlugin() { From 803bd284a644366e315138fa3c80a98e51ec17ae Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 1 May 2018 14:41:23 -0700 Subject: [PATCH 53/92] Alternate shader --- interface/resources/shaders/splashSkybox.frag | 70 +++++++++++-------- interface/src/Application.cpp | 5 +- 2 files changed, 44 insertions(+), 31 deletions(-) diff --git a/interface/resources/shaders/splashSkybox.frag b/interface/resources/shaders/splashSkybox.frag index 8088b745bc..38c89b4d26 100644 --- a/interface/resources/shaders/splashSkybox.frag +++ b/interface/resources/shaders/splashSkybox.frag @@ -1,37 +1,47 @@ +const vec3 COLOR = vec3(0x00, 0xD8, 0x02) / vec3(0xFF); +const float CUTOFF = 0.65; +const float NOISE_MULT = 8.0; +const float NOISE_POWER = 1.0; -float noise3D(vec3 p) -{ - return fract(sin(dot(p ,vec3(12.9898,78.233,126.7235))) * 43758.5453); +float noise4D(vec4 p) { + return fract(sin(dot(p ,vec4(12.9898,78.233,126.7235, 593.2241))) * 43758.5453); } -float worley3D(vec3 p) -{ - float r = 3.0; - vec3 f = floor(p); - vec3 x = fract(p); - for(int i = -1; i<=1; i++) - { - for(int j = -1; j<=1; j++) - { - for(int k = -1; k<=1; k++) - { - vec3 q = vec3(float(i),float(j),float(k)); - vec3 v = q + vec3(noise3D((q+f)*1.11), noise3D((q+f)*1.14), noise3D((q+f)*1.17)) - x; - float d = dot(v, v); - r = min(r, d); - } - } - } +float worley4D(vec4 p) { + float r = 3.0; + vec4 f = floor(p); + vec4 x = fract(p); + for(int i = -1; i<=1; i++) + { + for(int j = -1; j<=1; j++) + { + for(int k = -1; k<=1; k++) + { + for (int l = -1; l <= 1; l++) { + vec4 q = vec4(float(i),float(j),float(k), float(l)); + vec4 v = q + vec4(noise4D((q+f)*1.11), noise4D((q+f)*1.14), noise4D((q+f)*1.17), noise4D((q+f)*1.20)) - x; + float d = dot(v, v); + r = min(r, d); + } + } + } + } return sqrt(r); -} +} +vec3 mainColor(vec3 direction) { + float n = worley4D(vec4(direction * NOISE_MULT, iGlobalTime / 3.0)); + n = 1.0 - n; + n = pow(n, NOISE_POWER); + if (n < CUTOFF) { + return vec3(0.0); + } + + n = (n - CUTOFF) / (1.0 - CUTOFF); + return COLOR * (1.0 - n); +} + vec3 getSkyboxColor() { - vec3 color = abs(normalize(_normal)); -// vec2 uv; -// uv.x = 0.5 + atan(_normal.z, _normal.x); -// uv.y = 0.5 - asin(_normal.y); -// uv *= 20.0; -// color.r = worley3D(vec3(uv, iGlobalTime)); - return color; -} \ No newline at end of file + return mainColor(normalize(_normal)); +} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4a59cf3549..e6830a04c8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2671,6 +2671,9 @@ void Application::initializeDisplayPlugins() { batch.enableSkybox(true); batch.enableStereo(_appRenderArgs._isStereo); batch.setViewportTransform({ 0, 0, finalFramebuffer->getSize() }); + batch.runLambda([] { + // update uniform values + }); procedural->render(batch, _appRenderArgs._renderArgs.getViewFrustum()); }); auto frame = _gpuContext->endFrame(); @@ -3016,7 +3019,7 @@ void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) { _thirdPersonHMDCameraBoomValid = false; _myCamera.setOrientation(myAvatar->getHead()->getOrientation()); - if (Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) { + if (isOptionChecked(MenuOption::CenterPlayerInView)) { _myCamera.setPosition(myAvatar->getDefaultEyePosition() + _myCamera.getOrientation() * boomOffset); } From 38f43bdc6802e695cb78470eb65a75c62fd027de Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 1 May 2018 16:49:00 -0700 Subject: [PATCH 54/92] Disable current splash frame implementaton --- interface/src/Application.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e6830a04c8..ea487c2239 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2646,6 +2646,9 @@ void Application::initializeDisplayPlugins() { updateRenderArgs(0.0f); _offscreenContext->makeCurrent(); + +#define ENABLE_SPLASH_FRAME 0 +#if ENABLE_SPLASH_FRAME { QMutexLocker viewLocker(&_renderArgsMutex); @@ -2666,14 +2669,10 @@ void Application::initializeDisplayPlugins() { batch.resetStages(); batch.enableStereo(false); batch.setFramebuffer(finalFramebuffer); - batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, { 0, 1, 1, 1 }); - + batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, { 0, 0, 0, 1 }); batch.enableSkybox(true); batch.enableStereo(_appRenderArgs._isStereo); batch.setViewportTransform({ 0, 0, finalFramebuffer->getSize() }); - batch.runLambda([] { - // update uniform values - }); procedural->render(batch, _appRenderArgs._renderArgs.getViewFrustum()); }); auto frame = _gpuContext->endFrame(); @@ -2685,6 +2684,7 @@ void Application::initializeDisplayPlugins() { }; _displayPlugin->submitFrame(frame); } +#endif } void Application::initializeRenderEngine() { From 6a55e67ce9cd01ed29825d14889a1d0d2ad902c6 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 5 May 2018 16:39:03 -0700 Subject: [PATCH 55/92] avoid misaligned pointer deref --- libraries/gpu/src/gpu/Texture_ktx.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index 0822af3cfb..bb081637be 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -46,13 +46,14 @@ struct GPUKTXPayload { memcpy(data, &_samplerDesc, sizeof(Sampler::Desc)); data += sizeof(Sampler::Desc); - + // We can't copy the bitset in Texture::Usage in a crossplateform manner // So serialize it manually - *(uint32*)data = _usage._flags.to_ulong(); + uint32 usageData = _usage._flags.to_ulong(); + memcpy(data, &usageData, sizeof(uint32)); data += sizeof(uint32); - *(TextureUsageType*)data = _usageType; + memcpy(data, &_usageType, sizeof(TextureUsageType)); data += sizeof(TextureUsageType); return data + PADDING; @@ -77,10 +78,12 @@ struct GPUKTXPayload { memcpy(&_samplerDesc, data, sizeof(Sampler::Desc)); data += sizeof(Sampler::Desc); - + // We can't copy the bitset in Texture::Usage in a crossplateform manner // So unserialize it manually - _usage = Texture::Usage(*(const uint32*)data); + uint32 usageData; + memcpy(&usageData, data, sizeof(uint32)); + _usage = Texture::Usage(usageData); data += sizeof(uint32); _usageType = *(const TextureUsageType*)data; @@ -710,4 +713,4 @@ bool Texture::evalTextureFormat(const ktx::Header& header, Element& mipFormat, E return false; } return true; -} \ No newline at end of file +} From 677c99abd46e429090a4ebd3d85b2f7145e9ea6e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 5 May 2018 20:50:54 -0700 Subject: [PATCH 56/92] use memcpy on _usageType as well --- libraries/gpu/src/gpu/Texture_ktx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index bb081637be..129c125411 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -86,7 +86,7 @@ struct GPUKTXPayload { _usage = Texture::Usage(usageData); data += sizeof(uint32); - _usageType = *(const TextureUsageType*)data; + memcpy(&_usageType, data, sizeof(TextureUsageType)); return true; } From b4cfea2fbc4793bc9f3fddcf8949ab67cf826c19 Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Sun, 6 May 2018 17:17:06 +0300 Subject: [PATCH 57/92] FB14818 Login page for steam is blank --- interface/resources/qml/LoginDialog/SignInBody.qml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/interface/resources/qml/LoginDialog/SignInBody.qml b/interface/resources/qml/LoginDialog/SignInBody.qml index c4b6c2aee1..9cb1add704 100644 --- a/interface/resources/qml/LoginDialog/SignInBody.qml +++ b/interface/resources/qml/LoginDialog/SignInBody.qml @@ -84,11 +84,9 @@ Item { height: undefined // invalidate so that the image's size sets the height focus: true - style: OriginalStyles.ButtonStyle { - background: Image { - id: buttonImage - source: "../../images/steam-sign-in.png" - } + background: Image { + id: buttonImage + source: "../../images/steam-sign-in.png" } onClicked: signInBody.login() } From c2004debd57921c6d2f3658ea05e0b0e2232b94a Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 7 May 2018 11:41:19 -0700 Subject: [PATCH 58/92] test using highp floats everywhere for android --- .../gpu-gl/src/gpu/gl41/GL41BackendShader.cpp | 1 - .../gpu-gl/src/gpu/gl45/GL45BackendShader.cpp | 1 - .../src/gpu/gles/GLESBackendShader.cpp | 7 +++---- libraries/graphics/src/graphics/Light.slh | 2 +- .../src/graphics/LightIrradiance.shared.slh | 4 ++-- .../src/graphics/LightVolume.shared.slh | 4 ++-- libraries/graphics/src/graphics/Material.slh | 11 ++++------- .../src/graphics/SphericalHarmonics.shared.slh | 18 +++++++++--------- libraries/render-utils/src/LightingModel.slh | 8 ++++---- 9 files changed, 25 insertions(+), 31 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendShader.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendShader.cpp index 151b5bd1f9..64c9033cf7 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendShader.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendShader.cpp @@ -17,7 +17,6 @@ std::string GL41Backend::getBackendShaderHeader() const { static const std::string header( R"SHADER(#version 410 core #define GPU_GL410 - #define PRECISIONQ #define BITFIELD int )SHADER"); return header; diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendShader.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendShader.cpp index 6f6ded518f..44e439df55 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendShader.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendShader.cpp @@ -18,7 +18,6 @@ std::string GL45Backend::getBackendShaderHeader() const { static const std::string header( R"SHADER(#version 450 core #define GPU_GL450 - #define PRECISIONQ #define BITFIELD int )SHADER" #ifdef GPU_SSBO_TRANSFORM_OBJECT diff --git a/libraries/gpu-gles/src/gpu/gles/GLESBackendShader.cpp b/libraries/gpu-gles/src/gpu/gles/GLESBackendShader.cpp index 4278d732c8..7e8056ba79 100644 --- a/libraries/gpu-gles/src/gpu/gles/GLESBackendShader.cpp +++ b/libraries/gpu-gles/src/gpu/gles/GLESBackendShader.cpp @@ -17,10 +17,9 @@ std::string GLESBackend::getBackendShaderHeader() const { static const std::string header( R"SHADER(#version 310 es #extension GL_EXT_texture_buffer : enable - precision lowp float; // check precision 2 - precision lowp samplerBuffer; - precision lowp sampler2DShadow; - #define PRECISIONQ highp + precision highp float; + precision highp samplerBuffer; + precision highp sampler2DShadow; #define BITFIELD highp int )SHADER"); return header; diff --git a/libraries/graphics/src/graphics/Light.slh b/libraries/graphics/src/graphics/Light.slh index c8992730f0..53b840f5fb 100644 --- a/libraries/graphics/src/graphics/Light.slh +++ b/libraries/graphics/src/graphics/Light.slh @@ -34,7 +34,7 @@ vec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradi // Light Ambient struct LightAmbient { - PRECISIONQ vec4 _ambient; + vec4 _ambient; SphericalHarmonics _ambientSphere; mat4 transform; }; diff --git a/libraries/graphics/src/graphics/LightIrradiance.shared.slh b/libraries/graphics/src/graphics/LightIrradiance.shared.slh index 4ae7967bf5..13d6cf4b93 100644 --- a/libraries/graphics/src/graphics/LightIrradiance.shared.slh +++ b/libraries/graphics/src/graphics/LightIrradiance.shared.slh @@ -14,9 +14,9 @@ #define LightIrradianceConstRef LightIrradiance struct LightIrradiance { - PRECISIONQ vec4 colorIntensity; + vec4 colorIntensity; // falloffRadius, cutoffRadius, falloffSpot, spare - PRECISIONQ vec4 attenuation; + vec4 attenuation; }; diff --git a/libraries/graphics/src/graphics/LightVolume.shared.slh b/libraries/graphics/src/graphics/LightVolume.shared.slh index 4e4359eac0..3f0cb135f5 100644 --- a/libraries/graphics/src/graphics/LightVolume.shared.slh +++ b/libraries/graphics/src/graphics/LightVolume.shared.slh @@ -16,8 +16,8 @@ #define LightVolumeConstRef LightVolume struct LightVolume { - PRECISIONQ vec4 positionRadius; - PRECISIONQ vec4 directionSpotCos; + vec4 positionRadius; + vec4 directionSpotCos; }; bool lightVolume_isPoint(LightVolume lv) { return bool(lv.directionSpotCos.w < 0.f); } diff --git a/libraries/graphics/src/graphics/Material.slh b/libraries/graphics/src/graphics/Material.slh index ecf3c18a0e..dd2985b4da 100644 --- a/libraries/graphics/src/graphics/Material.slh +++ b/libraries/graphics/src/graphics/Material.slh @@ -15,10 +15,10 @@ // to what is provided by the uniform buffer, or the material key has the wrong bits struct Material { - PRECISIONQ vec4 _emissiveOpacity; - PRECISIONQ vec4 _albedoRoughness; - PRECISIONQ vec4 _fresnelMetallic; - PRECISIONQ vec4 _scatteringSpare2Key; + vec4 _emissiveOpacity; + vec4 _albedoRoughness; + vec4 _fresnelMetallic; + vec4 _scatteringSpare2Key; }; uniform materialBuffer { @@ -64,7 +64,4 @@ const BITFIELD OCCLUSION_MAP_BIT = 0x00004000; const BITFIELD LIGHTMAP_MAP_BIT = 0x00008000; const BITFIELD SCATTERING_MAP_BIT = 0x00010000; -#ifdef GL_ES -precision lowp float; -#endif <@endif@> diff --git a/libraries/graphics/src/graphics/SphericalHarmonics.shared.slh b/libraries/graphics/src/graphics/SphericalHarmonics.shared.slh index 6e1763dcba..312824c5a3 100644 --- a/libraries/graphics/src/graphics/SphericalHarmonics.shared.slh +++ b/libraries/graphics/src/graphics/SphericalHarmonics.shared.slh @@ -16,15 +16,15 @@ #define SphericalHarmonicsConstRef SphericalHarmonics struct SphericalHarmonics { - PRECISIONQ vec4 L00; - PRECISIONQ vec4 L1m1; - PRECISIONQ vec4 L10; - PRECISIONQ vec4 L11; - PRECISIONQ vec4 L2m2; - PRECISIONQ vec4 L2m1; - PRECISIONQ vec4 L20; - PRECISIONQ vec4 L21; - PRECISIONQ vec4 L22; + vec4 L00; + vec4 L1m1; + vec4 L10; + vec4 L11; + vec4 L2m2; + vec4 L2m1; + vec4 L20; + vec4 L21; + vec4 L22; }; vec4 sphericalHarmonics_evalSphericalLight(SphericalHarmonicsConstRef sh, vec3 direction) { diff --git a/libraries/render-utils/src/LightingModel.slh b/libraries/render-utils/src/LightingModel.slh index 6a5982f1e8..8abdb5cbf9 100644 --- a/libraries/render-utils/src/LightingModel.slh +++ b/libraries/render-utils/src/LightingModel.slh @@ -14,10 +14,10 @@ <@func declareLightingModel()@> struct LightingModel { - PRECISIONQ vec4 _UnlitEmissiveLightmapBackground; - PRECISIONQ vec4 _ScatteringDiffuseSpecularAlbedo; - PRECISIONQ vec4 _AmbientDirectionalPointSpot; - PRECISIONQ vec4 _ShowContourObscuranceWireframe; + vec4 _UnlitEmissiveLightmapBackground; + vec4 _ScatteringDiffuseSpecularAlbedo; + vec4 _AmbientDirectionalPointSpot; + vec4 _ShowContourObscuranceWireframe; }; uniform lightingModelBuffer{ From 646c0ec987eb285e641ef1ca9a75bfc45f888136 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 7 May 2018 11:56:47 -0700 Subject: [PATCH 59/92] MS14878: Prevent wallet passphrase leak in specific case --- scripts/system/marketplaces/marketplaces.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index a05778e2dd..c3edee264f 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -789,10 +789,14 @@ var selectionDisplay = null; // for gridTool.js to ignore var savedDisablePreviewOptionLocked = false; var savedDisablePreviewOption = Menu.isOptionChecked("Disable Preview");; function maybeEnableHMDPreview() { - setTabletVisibleInSecondaryCamera(true); - DesktopPreviewProvider.setPreviewDisabledReason("USER"); - Menu.setIsOptionChecked("Disable Preview", savedDisablePreviewOption); - savedDisablePreviewOptionLocked = false; + // Set a small timeout to prevent sensitive data from being shown during + // UI fade + Script.setTimeout(function () { + setTabletVisibleInSecondaryCamera(true); + DesktopPreviewProvider.setPreviewDisabledReason("USER"); + Menu.setIsOptionChecked("Disable Preview", savedDisablePreviewOption); + savedDisablePreviewOptionLocked = false; + }, 150); } // Function Name: fromQml() From c3ef6aab1c96158ea4edb67f188da9e39c2f69be Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 7 May 2018 12:51:41 -0700 Subject: [PATCH 60/92] Don't save test scripts --- libraries/script-engine/src/ScriptEngine.h | 5 +++++ libraries/script-engine/src/ScriptEngines.cpp | 15 ++++----------- libraries/script-engine/src/ScriptEngines.h | 4 ++-- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 7a9af2278c..3001666b5d 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -526,6 +526,9 @@ public: void setUserLoaded(bool isUserLoaded) { _isUserLoaded = isUserLoaded; } bool isUserLoaded() const { return _isUserLoaded; } + void setQuitWhenFinished(const bool quitWhenFinished) { _quitWhenFinished = quitWhenFinished; } + bool isQuitWhenFinished() const { return _quitWhenFinished; } + // NOTE - this is used by the TypedArray implementation. we need to review this for thread safety ArrayBufferClass* getArrayBufferClass() { return _arrayBufferClass; } @@ -768,6 +771,8 @@ protected: std::atomic _isUserLoaded { false }; bool _isReloading { false }; + std::atomic _quitWhenFinished; + ArrayBufferClass* _arrayBufferClass; AssetScriptingInterface* _assetScriptingInterface; diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index d2834e8c4a..b5a7cff0ab 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -347,7 +347,8 @@ void ScriptEngines::saveScripts() { { QReadLocker lock(&_scriptEnginesHashLock); for (auto it = _scriptEnginesHash.begin(); it != _scriptEnginesHash.end(); ++it) { - if (it.value() && it.value()->isUserLoaded()) { + // Save user-loaded scripts, only if they are set to quit when finished + if (it.value() && it.value()->isUserLoaded() && !it.value()->isQuitWhenFinished()) { auto normalizedUrl = normalizeScriptURL(it.key()); list.append(normalizedUrl.toString()); } @@ -456,7 +457,7 @@ void ScriptEngines::reloadAllScripts() { } ScriptEnginePointer ScriptEngines::loadScript(const QUrl& scriptFilename, bool isUserLoaded, bool loadScriptFromEditor, - bool activateMainWindow, bool reload, bool exitWhenFinished) { + bool activateMainWindow, bool reload, bool quitWhenFinished) { if (thread() != QThread::currentThread()) { ScriptEnginePointer result { nullptr }; BLOCKING_INVOKE_METHOD(this, "loadScript", Q_RETURN_ARG(ScriptEnginePointer, result), @@ -488,6 +489,7 @@ ScriptEnginePointer ScriptEngines::loadScript(const QUrl& scriptFilename, bool i scriptEngine = ScriptEnginePointer(new ScriptEngine(_context, NO_SCRIPT, "about:" + scriptFilename.fileName())); addScriptEngine(scriptEngine); scriptEngine->setUserLoaded(isUserLoaded); + scriptEngine->setQuitWhenFinished(quitWhenFinished); if (scriptFilename.isEmpty() || !scriptUrl.isValid()) { launchScriptEngine(scriptEngine); @@ -496,11 +498,6 @@ ScriptEnginePointer ScriptEngines::loadScript(const QUrl& scriptFilename, bool i connect(scriptEngine.data(), &ScriptEngine::scriptLoaded, this, &ScriptEngines::onScriptEngineLoaded); connect(scriptEngine.data(), &ScriptEngine::errorLoadingScript, this, &ScriptEngines::onScriptEngineError); - // Shutdown Interface when script finishes, if requested - if (exitWhenFinished) { - connect(scriptEngine.data(), &ScriptEngine::finished, this, &ScriptEngines::exitWhenFinished); - } - // get the script engine object to load the script at the designated script URL scriptEngine->loadURL(scriptUrl, reload); } @@ -541,10 +538,6 @@ void ScriptEngines::onScriptEngineLoaded(const QString& rawScriptURL) { emit scriptCountChanged(); } -void ScriptEngines::exitWhenFinished() { - qApp->quit(); -} - int ScriptEngines::runScriptInitializers(ScriptEnginePointer scriptEngine) { int ii=0; for (auto initializer : _scriptInitializers) { diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index 6f88e8978d..51eec8ab3e 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -88,10 +88,11 @@ public: * @param {boolean} [loadScriptFromEditor=false] * @param {boolean} [activateMainWindow=false] * @param {boolean} [reload=false] + * @param {boolean} [quitWhenFinished=false] * @returns {boolean} */ Q_INVOKABLE ScriptEnginePointer loadScript(const QUrl& scriptFilename = QString(), - bool isUserLoaded = true, bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false, bool exitWhenFinished = false); + bool isUserLoaded = true, bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false, bool quitWhenFinished = false); /**jsdoc * @function ScriptDiscoveryService.stopScript @@ -266,7 +267,6 @@ protected: ScriptEnginePointer reloadScript(const QString& scriptName, bool isUserLoaded = true) { return loadScript(scriptName, isUserLoaded, false, false, true); } void removeScriptEngine(ScriptEnginePointer); void onScriptEngineLoaded(const QString& scriptFilename); - void exitWhenFinished(); void onScriptEngineError(const QString& scriptFilename); void launchScriptEngine(ScriptEnginePointer); From 2e51a66441cc89e21337b7c38774b234b094872c Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 7 May 2018 13:01:18 -0700 Subject: [PATCH 61/92] Use 'standard' format for command line parameter with multiple options. --- interface/src/Application.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8ee577c282..bb04c3bf40 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -744,9 +744,9 @@ extern InputPluginList getInputPlugins(); extern void saveInputPluginSettings(const InputPluginList& plugins); // Parameters used for running tests from teh command line -const QString TEST_SCRIPT { "--testScript" }; -const QString TEST_QUIT_WHEN_FINISHED { "--quitWhenFinished" }; -const QString TEST_SNAPSHOT_LOCATION { "--testSnapshotLocation" }; +const QString TEST_SCRIPT_COMMAND { "--testScript" }; +const QString TEST_QUIT_WHEN_FINISHED_OPTION { "quitWhenFinished" }; +const QString TEST_SNAPSHOT_LOCATION_COMMAND { "--testSnapshotLocation" }; bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { const char** constArgv = const_cast(argv); @@ -787,7 +787,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { bool inTestMode { false }; for (int i = 0; i < argc; ++i) { QString parameter(argv[i]); - if (parameter == TEST_SCRIPT) { + if (parameter == TEST_SCRIPT_COMMAND) { inTestMode = true; break; } @@ -1019,7 +1019,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo const QStringList args = arguments(); for (int i = 0; i < args.size() - 1; ++i) { - if (args.at(i) == TEST_SCRIPT && (i + 1) < args.size()) { + if (args.at(i) == TEST_SCRIPT_COMMAND && (i + 1) < args.size()) { QString testScriptPath = args.at(i + 1); // If the URL scheme is "http(s)" then use as is, else - treat it as a local file @@ -1031,10 +1031,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo } // quite when finished parameter must directly follow the test script - if ((i + 2) < args.size() && args.at(i + 2) == TEST_QUIT_WHEN_FINISHED) { + if ((i + 2) < args.size() && args.at(i + 2) == TEST_QUIT_WHEN_FINISHED_OPTION) { quitWhenFinished = true; } - } else if (args.at(i) == TEST_SNAPSHOT_LOCATION) { + } else if (args.at(i) == TEST_SNAPSHOT_LOCATION_COMMAND) { // Set test snapshot location only if it is a writeable directory QString pathname(args.at(i + 1)); QFileInfo fileInfo(pathname); From fd4530e671b96d17af052ef7882fc674800a66f6 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 7 May 2018 14:39:31 -0700 Subject: [PATCH 62/92] MS3128: Remove vestigal Edit menu item --- scripts/system/edit.js | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 6bb815a597..523582836f 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1165,17 +1165,11 @@ function setupModelMenus() { }); modelMenuAddedDelete = true; } - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Entity List...", - afterItem: "Entities", - grouping: "Advanced" - }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Parent Entity to Last", - afterItem: "Entity List...", + afterItem: "Entities", grouping: "Advanced" }); @@ -1297,7 +1291,6 @@ function cleanupModelMenus() { Menu.removeMenuItem("Edit", "Parent Entity to Last"); Menu.removeMenuItem("Edit", "Unparent Entity"); - Menu.removeMenuItem("Edit", "Entity List..."); Menu.removeMenuItem("Edit", "Allow Selecting of Large Models"); Menu.removeMenuItem("Edit", "Allow Selecting of Small Models"); Menu.removeMenuItem("Edit", "Allow Selecting of Lights"); @@ -1659,8 +1652,6 @@ function handeMenuEvent(menuItem) { Window.promptTextChanged.connect(onPromptTextChanged); Window.promptAsync("URL of SVO to import", ""); } - } else if (menuItem === "Entity List...") { - entityListTool.toggleVisible(); } else if (menuItem === "Select All Entities In Box") { selectAllEtitiesInCurrentSelectionBox(false); } else if (menuItem === "Select All Entities Touching Box") { From a593209ec132ee828f454d6f505ee7ee9cc0ea38 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 7 May 2018 15:30:17 -0700 Subject: [PATCH 63/92] remove highlight when point to the sky --- .../controllers/controllerModules/farActionGrabEntity.js | 3 +++ .../controllers/controllerModules/mouseHighlightEntities.js | 3 +++ 2 files changed, 6 insertions(+) diff --git a/scripts/system/controllers/controllerModules/farActionGrabEntity.js b/scripts/system/controllers/controllerModules/farActionGrabEntity.js index cc884cdbc7..66cd197abd 100644 --- a/scripts/system/controllers/controllerModules/farActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farActionGrabEntity.js @@ -564,6 +564,9 @@ Script.include("/~/system/libraries/Xform.js"); } } else if (this.distanceRotating) { this.distanceRotate(otherFarGrabModule); + } else if (this.highlightedEntity) { + Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", this.highlightedEntity); + this.highlightedEntity = null; } } return this.exitIfDisabled(controllerData); diff --git a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js b/scripts/system/controllers/controllerModules/mouseHighlightEntities.js index 3180e58e2c..ac57c8691f 100644 --- a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js +++ b/scripts/system/controllers/controllerModules/mouseHighlightEntities.js @@ -63,6 +63,9 @@ this.highlightedEntity = targetEntityID; } } + } else if (this.highlightedEntity) { + dispatcherUtils.unhighlightTargetEntity(this.highlightedEntity); + this.highlightedEntity = null; } } From eb14658bc554c58e72e40474bbb7bdc328570d83 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 8 May 2018 11:13:06 -0700 Subject: [PATCH 64/92] Per Austin's comments. --- interface/src/Application.cpp | 4 +- tools/auto-tester/src/Downloader.cpp | 5 +-- tools/auto-tester/src/Test.cpp | 54 +++++++++++++------------ tools/auto-tester/src/Test.h | 2 - tools/auto-tester/src/ui/AutoTester.cpp | 3 +- 5 files changed, 33 insertions(+), 35 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8d1db32cdd..544d767370 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1022,9 +1022,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo if (args.at(i) == TEST_SCRIPT_COMMAND && (i + 1) < args.size()) { QString testScriptPath = args.at(i + 1); - // If the URL scheme is "http(s)" then use as is, else - treat it as a local file + // If the URL scheme is http(s) or ftp, then use as is, else - treat it as a local file // This is done so as not break previous command line scripts - if (testScriptPath.left(4) == "http") { + if (testScriptPath.left(URL_SCHEME_HTTP.length()) == URL_SCHEME_HTTP || testScriptPath.left(URL_SCHEME_FTP.length()) == URL_SCHEME_FTP) { setProperty(hifi::properties::TEST, QUrl::fromUserInput(testScriptPath)); } else if (QFileInfo(testScriptPath).exists()) { setProperty(hifi::properties::TEST, QUrl::fromLocalFile(testScriptPath)); diff --git a/tools/auto-tester/src/Downloader.cpp b/tools/auto-tester/src/Downloader.cpp index e66b498bd5..530a3b61bd 100644 --- a/tools/auto-tester/src/Downloader.cpp +++ b/tools/auto-tester/src/Downloader.cpp @@ -9,7 +9,7 @@ // #include "Downloader.h" -#include +#include Downloader::Downloader(QUrl imageUrl, QObject *parent) : QObject(parent) { connect( @@ -24,8 +24,7 @@ Downloader::Downloader(QUrl imageUrl, QObject *parent) : QObject(parent) { void Downloader::fileDownloaded(QNetworkReply* reply) { QNetworkReply::NetworkError error = reply->error(); if (error != QNetworkReply::NetworkError::NoError) { - QMessageBox messageBox; - messageBox.information(0, "Test Aborted", "Failed to download image: " + reply->errorString()); + QMessageBox::information(0, "Test Aborted", "Failed to download image: " + reply->errorString()); return; } diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index e00bc920e5..0eec03a782 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -72,7 +72,7 @@ bool Test::compareImageLists(bool isInteractiveMode, QProgressBar* progressBar) QImage expectedImage(expectedImagesFullFilenames[i]); if (resultImage.width() != expectedImage.width() || resultImage.height() != expectedImage.height()) { - messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Images are not the same size"); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Images are not the same size"); exit(-1); } @@ -80,7 +80,7 @@ bool Test::compareImageLists(bool isInteractiveMode, QProgressBar* progressBar) try { similarityIndex = imageComparer.compareImages(resultImage, expectedImage); } catch (...) { - messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Image not in expected format"); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Image not in expected format"); exit(-1); } @@ -127,20 +127,20 @@ bool Test::compareImageLists(bool isInteractiveMode, QProgressBar* progressBar) void Test::appendTestResultsToFile(const QString& testResultsFolderPath, TestFailure testFailure, QPixmap comparisonImage) { if (!QDir().exists(testResultsFolderPath)) { - messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Folder " + testResultsFolderPath + " not found"); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Folder " + testResultsFolderPath + " not found"); exit(-1); } QString failureFolderPath { testResultsFolderPath + "/" + "Failure_" + QString::number(index) }; if (!QDir().mkdir(failureFolderPath)) { - messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create folder " + failureFolderPath); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create folder " + failureFolderPath); exit(-1); } ++index; QFile descriptionFile(failureFolderPath + "/" + TEST_RESULTS_FILENAME); if (!descriptionFile.open(QIODevice::ReadWrite)) { - messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create file " + TEST_RESULTS_FILENAME); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create file " + TEST_RESULTS_FILENAME); exit(-1); } @@ -160,14 +160,14 @@ void Test::appendTestResultsToFile(const QString& testResultsFolderPath, TestFai sourceFile = testFailure._pathname + testFailure._expectedImageFilename; destinationFile = failureFolderPath + "/" + "Expected Image.jpg"; if (!QFile::copy(sourceFile, destinationFile)) { - messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to copy " + sourceFile + " to " + destinationFile); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to copy " + sourceFile + " to " + destinationFile); exit(-1); } sourceFile = testFailure._pathname + testFailure._actualImageFilename; destinationFile = failureFolderPath + "/" + "Actual Image.jpg"; if (!QFile::copy(sourceFile, destinationFile)) { - messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to copy " + sourceFile + " to " + destinationFile); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to copy " + sourceFile + " to " + destinationFile); exit(-1); } @@ -248,9 +248,9 @@ void Test::finishTestsEvaluation(bool isRunningFromCommandline, bool interactive if (!isRunningFromCommandline) { if (success) { - messageBox.information(0, "Success", "All images are as expected"); + QMessageBox::information(0, "Success", "All images are as expected"); } else { - messageBox.information(0, "Failure", "One or more images are not as expected"); + QMessageBox::information(0, "Failure", "One or more images are not as expected"); } } @@ -281,7 +281,7 @@ QString Test::extractPathFromTestsDown(const QString& fullPath) { } if (i == pathParts.length()) { - messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Bad testPathname"); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Bad testPathname"); exit(-1); } @@ -350,14 +350,14 @@ void Test::createAllRecursiveScripts() { } } - messageBox.information(0, "Success", "Scripts have been created"); + QMessageBox::information(0, "Success", "Scripts have been created"); } void Test::createRecursiveScript(const QString& topLevelDirectory, bool interactiveMode) { const QString recursiveTestsFilename("testRecursive.js"); QFile allTestsFilename(topLevelDirectory + "/" + recursiveTestsFilename); if (!allTestsFilename.open(QIODevice::WriteOnly | QIODevice::Text)) { - messageBox.critical(0, + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create \"" + recursiveTestsFilename + "\" in directory \"" + topLevelDirectory + "\"" ); @@ -366,7 +366,9 @@ void Test::createRecursiveScript(const QString& topLevelDirectory, bool interact } QTextStream textStream(&allTestsFilename); - textStream << "// This is an automatically generated file, created by auto-tester on " << __DATE__ << ", " << __TIME__ << endl << endl; + + const QString DATE_TIME_FORMAT("MMM d yyyy, h:mm"); + textStream << "// This is an automatically generated file, created by auto-tester on " << QDateTime::currentDateTime().toString(DATE_TIME_FORMAT) << endl << endl; textStream << "var autoTester = Script.require(\"https://github.com/" + githubUser + "/hifi_tests/blob/" + gitHubBranch + "/tests/utils/autoTester.js?raw=true\");" << endl << endl; @@ -407,7 +409,7 @@ void Test::createRecursiveScript(const QString& topLevelDirectory, bool interact } if (interactiveMode && testPathnames.length() <= 0) { - messageBox.information(0, "Failure", "No \"" + TEST_FILENAME + "\" files found"); + QMessageBox::information(0, "Failure", "No \"" + TEST_FILENAME + "\" files found"); allTestsFilename.close(); return; } @@ -418,7 +420,7 @@ void Test::createRecursiveScript(const QString& topLevelDirectory, bool interact allTestsFilename.close(); if (interactiveMode) { - messageBox.information(0, "Success", "Script has been created"); + QMessageBox::information(0, "Success", "Script has been created"); } } @@ -443,7 +445,7 @@ void Test::createTest() { QString fullCurrentFilename = imageSourceDirectory + "/" + currentFilename; if (isInSnapshotFilenameFormat("jpg", currentFilename)) { if (i >= maxImages) { - messageBox.critical(0, "Error", "More than " + QString::number(maxImages) + " images not supported"); + QMessageBox::critical(0, "Error", "More than " + QString::number(maxImages) + " images not supported"); exit(-1); } QString newFilename = "ExpectedImage_" + QString::number(i - 1).rightJustified(5, '0') + ".png"; @@ -452,14 +454,14 @@ void Test::createTest() { try { copyJPGtoPNG(fullCurrentFilename, fullNewFileName); } catch (...) { - messageBox.critical(0, "Error", "Could not delete existing file: " + currentFilename + "\nTest creation aborted"); + QMessageBox::critical(0, "Error", "Could not delete existing file: " + currentFilename + "\nTest creation aborted"); exit(-1); } ++i; } } - messageBox.information(0, "Success", "Test images have been created"); + QMessageBox::information(0, "Success", "Test images have been created"); } ExtractedText Test::getTestScriptLines(QString testFileName) { @@ -468,7 +470,7 @@ ExtractedText Test::getTestScriptLines(QString testFileName) { QFile inputFile(testFileName); inputFile.open(QIODevice::ReadOnly); if (!inputFile.isOpen()) { - messageBox.critical(0, + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to open \"" + testFileName ); @@ -598,7 +600,7 @@ void Test::createAllMDFiles() { } } - messageBox.information(0, "Success", "MD files have been created"); + QMessageBox::information(0, "Success", "MD files have been created"); } void Test::createMDFile(const QString& testDirectory) { @@ -606,7 +608,7 @@ void Test::createMDFile(const QString& testDirectory) { QString testFileName(testDirectory + "/" + TEST_FILENAME); QFileInfo testFileInfo(testFileName); if (!testFileInfo.exists()) { - messageBox.critical(0, "Error", "Could not find file: " + TEST_FILENAME); + QMessageBox::critical(0, "Error", "Could not find file: " + TEST_FILENAME); return; } @@ -615,7 +617,7 @@ void Test::createMDFile(const QString& testDirectory) { QString mdFilename(testDirectory + "/" + "test.md"); QFile mdFile(mdFilename); if (!mdFile.open(QIODevice::WriteOnly)) { - messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create file " + mdFilename); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create file " + mdFilename); exit(-1); } @@ -650,7 +652,7 @@ void Test::createMDFile(const QString& testDirectory) { mdFile.close(); - messageBox.information(0, "Success", "Test MD file " + mdFilename + " has been created"); + QMessageBox::information(0, "Success", "Test MD file " + mdFilename + " has been created"); } void Test::createTestsOutline() { @@ -663,7 +665,7 @@ void Test::createTestsOutline() { QString mdFilename(testsRootDirectory + "/" + testsOutlineFilename); QFile mdFile(mdFilename); if (!mdFile.open(QIODevice::WriteOnly)) { - messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create file " + mdFilename); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create file " + mdFilename); exit(-1); } @@ -721,7 +723,7 @@ void Test::createTestsOutline() { mdFile.close(); - messageBox.information(0, "Success", "Test outline file " + testsOutlineFilename + " has been created"); + QMessageBox::information(0, "Success", "Test outline file " + testsOutlineFilename + " has been created"); } void Test::copyJPGtoPNG(const QString& sourceJPGFullFilename, const QString& destinationPNGFullFilename) { @@ -796,7 +798,7 @@ QString Test::getExpectedImagePartialSourceDirectory(const QString& filename) { } if (i < 0) { - messageBox.critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Bad filename"); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Bad filename"); exit(-1); } diff --git a/tools/auto-tester/src/Test.h b/tools/auto-tester/src/Test.h index b341c1d00f..bc28d6ad0a 100644 --- a/tools/auto-tester/src/Test.h +++ b/tools/auto-tester/src/Test.h @@ -76,8 +76,6 @@ private: const QString TEST_RESULTS_FOLDER { "TestResults" }; const QString TEST_RESULTS_FILENAME { "TestResults.txt" }; - QMessageBox messageBox; - QDir imageDirectory; MismatchWindow mismatchWindow; diff --git a/tools/auto-tester/src/ui/AutoTester.cpp b/tools/auto-tester/src/ui/AutoTester.cpp index 59fe5d9de2..8fd81efc1f 100644 --- a/tools/auto-tester/src/ui/AutoTester.cpp +++ b/tools/auto-tester/src/ui/AutoTester.cpp @@ -115,6 +115,5 @@ void AutoTester::saveImage(int index) { } void AutoTester::about() { - QMessageBox messageBox; - messageBox.information(0, "About", QString("Built ") + __DATE__ + " : " + __TIME__); + QMessageBox::information(0, "About", QString("Built ") + __DATE__ + " : " + __TIME__); } From d5bb582811dd8f73d68e06add7b4589c766b25b7 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 8 May 2018 11:40:56 -0700 Subject: [PATCH 65/92] Per Austin's comments. --- interface/src/ui/Snapshot.cpp | 2 +- interface/src/ui/Snapshot.h | 5 ++++- tools/auto-tester/src/ui/AutoTester.cpp | 3 +-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 73ea8398e7..39fef1d742 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -90,7 +90,7 @@ QString Snapshot::saveSnapshot(QImage image, const QString& filename, const QStr QTemporaryFile* Snapshot::saveTempSnapshot(QImage image) { // return whatever we get back from saved file for snapshot - return static_cast(savedFileForSnapshot(image, true, QString(), QString())); + return static_cast(savedFileForSnapshot(image, true)); } QFile* Snapshot::savedFileForSnapshot(QImage & shot, bool isTemporary, const QString& userSelectedFilename, const QString& userSelectedPathname) { diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index aad63d1037..606313f3c3 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -52,7 +52,10 @@ public slots: Q_INVOKABLE QString getSnapshotsLocation(); Q_INVOKABLE void setSnapshotsLocation(const QString& location); private: - static QFile* savedFileForSnapshot(QImage & image, bool isTemporary, const QString& userSelectedFilename, const QString& userSelectedPathname); + static QFile* savedFileForSnapshot(QImage& image, + bool isTemporary, + const QString& userSelectedFilename = QString(), + const QString& userSelectedPathname = QString()); }; #endif // hifi_Snapshot_h diff --git a/tools/auto-tester/src/ui/AutoTester.cpp b/tools/auto-tester/src/ui/AutoTester.cpp index 8fd81efc1f..db9974a250 100644 --- a/tools/auto-tester/src/ui/AutoTester.cpp +++ b/tools/auto-tester/src/ui/AutoTester.cpp @@ -99,8 +99,7 @@ void AutoTester::saveImage(int index) { QString fullPathname = _directoryName + "/" + _filenames[index]; if (!image.save(fullPathname, 0, 100)) { - QMessageBox messageBox; - messageBox.information(0, "Test Aborted", "Failed to save image: " + _filenames[index]); + QMessageBox::information(0, "Test Aborted", "Failed to save image: " + _filenames[index]); ui.progressBar->setVisible(false); return; } From 0513204781cc4104faf3d0fd4d35b2c034d0a47f Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 8 May 2018 15:05:55 -0700 Subject: [PATCH 66/92] fix hmd.js --- scripts/system/hmd.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/hmd.js b/scripts/system/hmd.js index b9fd7f725c..bf1e048bc4 100644 --- a/scripts/system/hmd.js +++ b/scripts/system/hmd.js @@ -18,7 +18,7 @@ var headset; // The preferred headset. Default to the first one found in the following list. var displayMenuName = "Display"; var desktopMenuItemName = "Desktop"; -['OpenVR (Vive)', 'Oculus Rift'].forEach(function (name) { +['HTC Vive', 'Oculus Rift'].forEach(function (name) { if (!headset && Menu.menuItemExists(displayMenuName, name)) { headset = name; } From 1a0ded4526d7f37fd4ce25df4567b249c4859a65 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 8 May 2018 15:10:57 -0700 Subject: [PATCH 67/92] adding windows --- scripts/system/hmd.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/hmd.js b/scripts/system/hmd.js index bf1e048bc4..2d4a2d3e97 100644 --- a/scripts/system/hmd.js +++ b/scripts/system/hmd.js @@ -18,7 +18,7 @@ var headset; // The preferred headset. Default to the first one found in the following list. var displayMenuName = "Display"; var desktopMenuItemName = "Desktop"; -['HTC Vive', 'Oculus Rift'].forEach(function (name) { +['HTC Vive', 'Oculus Rift', 'WindowMS'].forEach(function (name) { if (!headset && Menu.menuItemExists(displayMenuName, name)) { headset = name; } From 7f9f9d769adfe5e96159ae1c836322dcb643acb7 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 8 May 2018 15:51:52 -0700 Subject: [PATCH 68/92] Corrected bug causing Interface not to exit at end of test. --- libraries/script-engine/src/ScriptEngines.cpp | 9 +++++++++ libraries/script-engine/src/ScriptEngines.h | 1 + 2 files changed, 10 insertions(+) diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index b5a7cff0ab..ad6e1debe9 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -498,6 +498,11 @@ ScriptEnginePointer ScriptEngines::loadScript(const QUrl& scriptFilename, bool i connect(scriptEngine.data(), &ScriptEngine::scriptLoaded, this, &ScriptEngines::onScriptEngineLoaded); connect(scriptEngine.data(), &ScriptEngine::errorLoadingScript, this, &ScriptEngines::onScriptEngineError); + // Shutdown Interface when script finishes, if requested + if (quitWhenFinished) { + connect(scriptEngine.data(), &ScriptEngine::finished, this, &ScriptEngines::quitWhenFinished); + } + // get the script engine object to load the script at the designated script URL scriptEngine->loadURL(scriptUrl, reload); } @@ -538,6 +543,10 @@ void ScriptEngines::onScriptEngineLoaded(const QString& rawScriptURL) { emit scriptCountChanged(); } +void ScriptEngines::quitWhenFinished() { + qApp->quit(); +} + int ScriptEngines::runScriptInitializers(ScriptEnginePointer scriptEngine) { int ii=0; for (auto initializer : _scriptInitializers) { diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index 51eec8ab3e..4d5964e462 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -267,6 +267,7 @@ protected: ScriptEnginePointer reloadScript(const QString& scriptName, bool isUserLoaded = true) { return loadScript(scriptName, isUserLoaded, false, false, true); } void removeScriptEngine(ScriptEnginePointer); void onScriptEngineLoaded(const QString& scriptFilename); + void quitWhenFinished(); void onScriptEngineError(const QString& scriptFilename); void launchScriptEngine(ScriptEnginePointer); From 44e7541888d203cd79ba2f06a079b3cdaf382ded Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 8 May 2018 15:57:27 -0700 Subject: [PATCH 69/92] Fixing the size evaluation for compressed texture and gpu::Element Type enum --- libraries/gpu/src/gpu/Format.h | 73 ++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index d4e4a89636..7a3e0a2f82 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -50,47 +50,50 @@ enum Type : uint8_t { }; // Array providing the size in bytes for a given scalar type static const int TYPE_SIZE[NUM_TYPES] = { - 4, - 4, - 4, - 2, - 2, - 2, - 1, - 1, + 4, // FLOAT + 4, // INT32 + 4, // UINT32 + 2, // HALF + 2, // INT16 + 2, // UINT16 + 1, // INT8 + 1, // UINT8 // normalized values - 4, - 4, - 2, - 2, - 1, - 1, - 4, + 4, // NINT32 + 4, // NUINT32 + 2, // NINT16 + 2, // NUINT16 + 1, // NINT8 + 1, // NUINT8 + 1, // NUINT2 + 1, // NINT2_10_10_10 - 1 + 1, // COMPRESSED }; + // Array answering the question Does this type is integer or not static const bool TYPE_IS_INTEGER[NUM_TYPES] = { - false, - true, - true, - false, - true, - true, - true, - true, + false, // FLOAT + true, // INT32 + true, // UINT32 + false, // HALF + true, // INT16 + true, // UINT16 + true, // INT8 + true, // UINT8 // Normalized values - false, - false, - false, - false, - false, - false, - false, + false, // NINT32 + false, // NUINT32 + false, // NINT16 + false, // NUINT16 + false, // NINT8 + false, // NUINT8 + false, // NUINT2 + false, // NINT2_10_10_10 - false, + false, // COMPRESSED }; // Dimension of an Element @@ -367,9 +370,9 @@ public: static const Element PART_DRAWCALL; protected: - uint8 _semantic; - uint8 _dimension : 4; - uint8 _type : 4; + uint16 _semantic : 7; + uint16 _dimension : 4; + uint16 _type : 5; }; From 540f200b99a6df817799bb9b1f29588985c939ef Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 8 May 2018 16:34:28 -0700 Subject: [PATCH 70/92] MS14937: Fix Replace button for content sets during Checkout --- interface/resources/qml/hifi/commerce/checkout/Checkout.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 1cfbcf9075..f25282c738 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -787,7 +787,7 @@ Rectangle { } lightboxPopup.button2text = "CONFIRM"; lightboxPopup.button2method = function() { - Commerce.replaceContentSet(root.itemHref); + Commerce.replaceContentSet(root.itemHref, root.certificateId); lightboxPopup.visible = false; rezzedNotifContainer.visible = true; rezzedNotifContainerTimer.start(); From 22c26c348dcf39d313a631ab2f52e80e33c7dee4 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 8 May 2018 16:34:28 -0700 Subject: [PATCH 71/92] MS14937: Fix Replace button for content sets during Checkout --- interface/resources/qml/hifi/commerce/checkout/Checkout.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 1cfbcf9075..f25282c738 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -787,7 +787,7 @@ Rectangle { } lightboxPopup.button2text = "CONFIRM"; lightboxPopup.button2method = function() { - Commerce.replaceContentSet(root.itemHref); + Commerce.replaceContentSet(root.itemHref, root.certificateId); lightboxPopup.visible = false; rezzedNotifContainer.visible = true; rezzedNotifContainerTimer.start(); From 0349847857fb2393c0894426b22011a60c2475a5 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Tue, 8 May 2018 17:46:25 -0700 Subject: [PATCH 72/92] Add comment re threading issues --- libraries/networking/src/HMACAuth.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/HMACAuth.h b/libraries/networking/src/HMACAuth.h index 59870bb7b6..1346bdee17 100644 --- a/libraries/networking/src/HMACAuth.h +++ b/libraries/networking/src/HMACAuth.h @@ -30,8 +30,12 @@ public: bool setKey(const QUuid& uidKey); // Calculate complete hash in one. bool calculateHash(HMACHash& hashResult, const char* data, int dataLen); - // Append data to be hashed. + + // Append to data to be hashed. bool addData(const char* data, int dataLen); + // Get the resulting hash from calls to addData(). + // Note that only one hash may be calculated at a time for each + // HMACAuth instance if this interface is used. HMACHash result(); private: From 06c6f5506904f964b8c77e99ca7b083e5546c468 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 9 May 2018 09:35:42 -0700 Subject: [PATCH 73/92] MS14951: Fix Snapshot hotkey sound playback --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 038180a60d..525f0f2ee7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2128,7 +2128,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo return entityServerNode && !isPhysicsEnabled(); }); - _snapshotSound = DependencyManager::get()->getSound(PathUtils::resourcesUrl("sounds/snap.wav")); + _snapshotSound = DependencyManager::get()->getSound(PathUtils::resourcesUrl("sounds/snapshot/snap.wav")); QVariant testProperty = property(hifi::properties::TEST); qDebug() << testProperty; From 542e707de8d6d1cacb0e6b3e05f4b5258bff9921 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 9 May 2018 09:35:42 -0700 Subject: [PATCH 74/92] MS14951: Fix Snapshot hotkey sound playback --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 789f60bdb1..6a063fb990 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2093,7 +2093,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo return entityServerNode && !isPhysicsEnabled(); }); - _snapshotSound = DependencyManager::get()->getSound(PathUtils::resourcesUrl("sounds/snap.wav")); + _snapshotSound = DependencyManager::get()->getSound(PathUtils::resourcesUrl("sounds/snapshot/snap.wav")); QVariant testProperty = property(hifi::properties::TEST); qDebug() << testProperty; From db03265a6b8e0f2fa4873929fc5ec3c932e71d71 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 8 May 2018 18:49:55 -0700 Subject: [PATCH 75/92] when in serverless mode, short-circuit simulation ownership bids --- .../entities/src/EntityEditPacketSender.cpp | 8 -------- libraries/octree/src/OctreeEditPacketSender.cpp | 9 --------- libraries/octree/src/OctreeEditPacketSender.h | 3 --- libraries/physics/src/EntityMotionState.cpp | 8 +++++++- libraries/physics/src/EntityMotionState.h | 2 ++ .../physics/src/PhysicalEntitySimulation.cpp | 16 ++++++++++++---- 6 files changed, 21 insertions(+), 25 deletions(-) diff --git a/libraries/entities/src/EntityEditPacketSender.cpp b/libraries/entities/src/EntityEditPacketSender.cpp index 5d7bd61854..c0a45936ac 100644 --- a/libraries/entities/src/EntityEditPacketSender.cpp +++ b/libraries/entities/src/EntityEditPacketSender.cpp @@ -73,7 +73,6 @@ void EntityEditPacketSender::queueEditAvatarEntityMessage(PacketType type, _myAvatar->updateAvatarEntity(entityItemID, binaryProperties); entity->setLastBroadcast(usecTimestampNow()); - return; } @@ -81,10 +80,6 @@ void EntityEditPacketSender::queueEditEntityMessage(PacketType type, EntityTreePointer entityTree, EntityItemID entityItemID, const EntityItemProperties& properties) { - if (!_shouldSend) { - return; // bail early - } - if (properties.getClientOnly() && properties.getOwningAvatarID() == _myAvatar->getID()) { // this is an avatar-based entity --> update our avatar-data rather than sending to the entity-server queueEditAvatarEntityMessage(type, entityTree, entityItemID, properties); @@ -143,9 +138,6 @@ void EntityEditPacketSender::queueEditEntityMessage(PacketType type, } void EntityEditPacketSender::queueEraseEntityMessage(const EntityItemID& entityItemID) { - if (!_shouldSend) { - return; // bail early - } // in case this was a clientOnly entity: if(_myAvatar) { diff --git a/libraries/octree/src/OctreeEditPacketSender.cpp b/libraries/octree/src/OctreeEditPacketSender.cpp index 4f10c9bf79..4bc20c80c6 100644 --- a/libraries/octree/src/OctreeEditPacketSender.cpp +++ b/libraries/octree/src/OctreeEditPacketSender.cpp @@ -22,7 +22,6 @@ const int OctreeEditPacketSender::DEFAULT_MAX_PENDING_MESSAGES = PacketSender::D OctreeEditPacketSender::OctreeEditPacketSender() : - _shouldSend(true), _maxPendingMessages(DEFAULT_MAX_PENDING_MESSAGES), _releaseQueuedMessagesPending(false) { @@ -145,10 +144,6 @@ void OctreeEditPacketSender::queuePendingPacketToNodes(std::unique_ptr } void OctreeEditPacketSender::queuePacketToNodes(std::unique_ptr packet) { - if (!_shouldSend) { - return; // bail early - } - assert(serversExist()); // we must have servers to be here!! auto node = DependencyManager::get()->soloNodeOfType(getMyNodeType()); @@ -161,10 +156,6 @@ void OctreeEditPacketSender::queuePacketToNodes(std::unique_ptr packet // NOTE: editMessage - is JUST the octcode/color and does not contain the packet header void OctreeEditPacketSender::queueOctreeEditMessage(PacketType type, QByteArray& editMessage) { - if (!_shouldSend) { - return; // bail early - } - // If we don't have servers, then we will simply queue up all of these packets and wait till we have // servers for processing if (!serversExist()) { diff --git a/libraries/octree/src/OctreeEditPacketSender.h b/libraries/octree/src/OctreeEditPacketSender.h index 8a33eb8b73..1dad5b74c7 100644 --- a/libraries/octree/src/OctreeEditPacketSender.h +++ b/libraries/octree/src/OctreeEditPacketSender.h @@ -41,12 +41,10 @@ public: /// are we in sending mode. If we're not in sending mode then all packets and messages will be ignored and /// not queued and not sent - bool getShouldSend() const { return _shouldSend; } /// set sending mode. By default we are set to shouldSend=TRUE and packets will be sent. If shouldSend=FALSE, then we'll /// switch to not sending mode, and all packets and messages will be ignored, not queued, and not sent. This might be used /// in an application like interface when all octree features are disabled. - void setShouldSend(bool shouldSend) { _shouldSend = shouldSend; } /// if you're running in non-threaded mode, you must call this method regularly virtual bool process() override; @@ -76,7 +74,6 @@ public slots: protected: using EditMessagePair = std::pair; - bool _shouldSend; void queuePacketToNode(const QUuid& nodeID, std::unique_ptr packet); void queuePacketListToNode(const QUuid& nodeUUID, std::unique_ptr packetList); diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index c2bacd4949..47297adef5 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -348,7 +348,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) { if (_numInactiveUpdates > 0) { const uint8_t MAX_NUM_INACTIVE_UPDATES = 20; - if (_numInactiveUpdates > MAX_NUM_INACTIVE_UPDATES) { + if (_numInactiveUpdates > MAX_NUM_INACTIVE_UPDATES || isServerlessMode()) { // clear local ownership (stop sending updates) and let the server clear itself _entity->clearSimulationOwnership(); return false; @@ -827,3 +827,9 @@ void EntityMotionState::clearObjectVelocities() const { } _entity->setAcceleration(glm::vec3(0.0f)); } + +bool EntityMotionState::isServerlessMode() { + EntityTreeElementPointer element = _entity->getElement(); + EntityTreePointer tree = element ? element->getTree() : nullptr; + return tree ? tree->isServerlessMode() : false; +} diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index a542c61d43..376cc5afe2 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -156,6 +156,8 @@ protected: uint8_t _numInactiveUpdates { 1 }; uint8_t _bidPriority { 0 }; bool _serverVariablesSet { false }; + + bool isServerlessMode(); }; #endif // hifi_EntityMotionState_h diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index ab7c2ec252..467de22591 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -327,10 +327,18 @@ void PhysicalEntitySimulation::handleChangedMotionStates(const VectorOfMotionSta } void PhysicalEntitySimulation::addOwnershipBid(EntityMotionState* motionState) { - motionState->initForBid(); - motionState->sendBid(_entityPacketSender, _physicsEngine->getNumSubsteps()); - _bids.push_back(motionState); - _nextBidExpiry = glm::min(_nextBidExpiry, motionState->getNextBidExpiry()); + if (getEntityTree()->isServerlessMode()) { + EntityItemPointer entity = motionState->getEntity(); + auto nodeList = DependencyManager::get(); + auto sessionID = nodeList->getSessionUUID(); + entity->setSimulationOwner(SimulationOwner(sessionID, SCRIPT_GRAB_SIMULATION_PRIORITY)); + _owned.push_back(motionState); + } else { + motionState->initForBid(); + motionState->sendBid(_entityPacketSender, _physicsEngine->getNumSubsteps()); + _bids.push_back(motionState); + _nextBidExpiry = glm::min(_nextBidExpiry, motionState->getNextBidExpiry()); + } } void PhysicalEntitySimulation::addOwnership(EntityMotionState* motionState) { From 7466d08f1f3c3d5ee500d4a499839c88469667a9 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 5 May 2018 16:42:44 -0700 Subject: [PATCH 76/92] more suppression of logging --- interface/src/Application.cpp | 43 +++++++++++++++++-- libraries/entities/src/EntityItem.cpp | 2 +- libraries/qml/src/qml/Logging.h | 4 +- libraries/script-engine/src/ScriptEngine.cpp | 6 +-- .../script-engine/src/ScriptEngineLogging.cpp | 1 + .../script-engine/src/ScriptEngineLogging.h | 1 + 6 files changed, 47 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ec28dcb3dd..c9055e92b2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -154,6 +154,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include "AudioClient.h" #include "audio/AudioScope.h" @@ -1372,8 +1379,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Needs to happen AFTER the render engine initialization to access its configuration initializeUi(); - updateVerboseLogging(); - init(); qCDebug(interfaceapp, "init() complete."); @@ -1713,6 +1718,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo loadSettings(); + updateVerboseLogging(); + // Now that we've loaded the menu and thus switched to the previous display plugin // we can unlock the desktop repositioning code, since all the positions will be // relative to the desktop size for this plugin @@ -2254,10 +2261,16 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _pendingRenderEvent = false; qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID()); + + updateVerboseLogging(); } void Application::updateVerboseLogging() { - bool enable = Menu::getInstance()->isOptionChecked(MenuOption::VerboseLogging); + auto menu = Menu::getInstance(); + if (!menu) { + return; + } + bool enable = menu->isOptionChecked(MenuOption::VerboseLogging); const_cast(&animation())->setEnabled(QtDebugMsg, enable); const_cast(&animation())->setEnabled(QtInfoMsg, enable); @@ -2268,6 +2281,12 @@ void Application::updateVerboseLogging() { const_cast(&scriptengine())->setEnabled(QtDebugMsg, enable); const_cast(&scriptengine())->setEnabled(QtInfoMsg, enable); + const_cast(&scriptengine_module())->setEnabled(QtDebugMsg, enable); + const_cast(&scriptengine_module())->setEnabled(QtInfoMsg, enable); + + const_cast(&scriptengine_script())->setEnabled(QtDebugMsg, enable); + const_cast(&scriptengine_script())->setEnabled(QtInfoMsg, enable); + const_cast(&modelformat())->setEnabled(QtDebugMsg, enable); const_cast(&modelformat())->setEnabled(QtInfoMsg, enable); @@ -2294,6 +2313,24 @@ void Application::updateVerboseLogging() { const_cast(&glLogging())->setEnabled(QtDebugMsg, enable); const_cast(&glLogging())->setEnabled(QtInfoMsg, enable); + + const_cast(&shared())->setEnabled(QtDebugMsg, enable); + const_cast(&shared())->setEnabled(QtInfoMsg, enable); + + const_cast(&plugins())->setEnabled(QtDebugMsg, enable); + const_cast(&plugins())->setEnabled(QtInfoMsg, enable); + + const_cast(&gpulogging())->setEnabled(QtDebugMsg, enable); + const_cast(&gpulogging())->setEnabled(QtInfoMsg, enable); + + const_cast(&gpugllogging())->setEnabled(QtDebugMsg, enable); + const_cast(&gpugllogging())->setEnabled(QtInfoMsg, enable); + + const_cast(&qmlLogging())->setEnabled(QtDebugMsg, enable); + const_cast(&qmlLogging())->setEnabled(QtInfoMsg, enable); + + const_cast(&entities())->setEnabled(QtDebugMsg, enable); + const_cast(&entities())->setEnabled(QtInfoMsg, enable); } void Application::domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo) { diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 1d81a6ae6d..d35c01a51b 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1070,7 +1070,7 @@ bool EntityItem::stepKinematicMotion(float timeElapsed) { const float MAX_TIME_ELAPSED = 1.0f; // seconds if (timeElapsed > MAX_TIME_ELAPSED) { - qCWarning(entities) << "kinematic timestep = " << timeElapsed << " truncated to " << MAX_TIME_ELAPSED; + qCDebug(entities) << "kinematic timestep = " << timeElapsed << " truncated to " << MAX_TIME_ELAPSED; } timeElapsed = glm::min(timeElapsed, MAX_TIME_ELAPSED); diff --git a/libraries/qml/src/qml/Logging.h b/libraries/qml/src/qml/Logging.h index 487566701d..48efdd1da9 100644 --- a/libraries/qml/src/qml/Logging.h +++ b/libraries/qml/src/qml/Logging.h @@ -6,8 +6,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_Controllers_Logging_h -#define hifi_Controllers_Logging_h +#ifndef hifi_QML_Logging_h +#define hifi_QML_Logging_h #include diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 9a383454d4..23ffbabe77 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -101,8 +101,6 @@ int functionSignatureMetaID = qRegisterMetaType(); -Q_LOGGING_CATEGORY(scriptengineScript, "hifi.scriptengine.script") - static QScriptValue debugPrint(QScriptContext* context, QScriptEngine* engine) { QString message = ""; for (int i = 0; i < context->argumentCount(); i++) { @@ -115,9 +113,9 @@ static QScriptValue debugPrint(QScriptContext* context, QScriptEngine* engine) { if (ScriptEngine *scriptEngine = qobject_cast(engine)) { scriptEngine->print(message); // prefix the script engine name to help disambiguate messages in the main debug log - qCDebug(scriptengineScript, "[%s] %s", qUtf8Printable(scriptEngine->getFilename()), qUtf8Printable(message)); + qCDebug(scriptengine_script, "[%s] %s", qUtf8Printable(scriptEngine->getFilename()), qUtf8Printable(message)); } else { - qCDebug(scriptengineScript, "%s", qUtf8Printable(message)); + qCDebug(scriptengine_script, "%s", qUtf8Printable(message)); } return QScriptValue(); diff --git a/libraries/script-engine/src/ScriptEngineLogging.cpp b/libraries/script-engine/src/ScriptEngineLogging.cpp index 392bc05129..b51d7c3780 100644 --- a/libraries/script-engine/src/ScriptEngineLogging.cpp +++ b/libraries/script-engine/src/ScriptEngineLogging.cpp @@ -13,3 +13,4 @@ Q_LOGGING_CATEGORY(scriptengine, "hifi.scriptengine") Q_LOGGING_CATEGORY(scriptengine_module, "hifi.scriptengine.module") +Q_LOGGING_CATEGORY(scriptengine_script, "hifi.scriptengine.script") diff --git a/libraries/script-engine/src/ScriptEngineLogging.h b/libraries/script-engine/src/ScriptEngineLogging.h index 62e46632a6..3096dd4927 100644 --- a/libraries/script-engine/src/ScriptEngineLogging.h +++ b/libraries/script-engine/src/ScriptEngineLogging.h @@ -16,6 +16,7 @@ Q_DECLARE_LOGGING_CATEGORY(scriptengine) Q_DECLARE_LOGGING_CATEGORY(scriptengine_module) +Q_DECLARE_LOGGING_CATEGORY(scriptengine_script) #endif // hifi_ScriptEngineLogging_h From 16e832ac0894a2c2413dbdc3328da148757c00d0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 9 May 2018 13:01:33 -0700 Subject: [PATCH 77/92] use setFilterRules rather than specifying each logging category to suppress --- interface/src/Application.cpp | 82 ++--------------------------------- 1 file changed, 4 insertions(+), 78 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c9055e92b2..20efe73f08 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -145,23 +145,6 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include "AudioClient.h" #include "audio/AudioScope.h" #include "avatar/AvatarManager.h" @@ -2261,8 +2244,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _pendingRenderEvent = false; qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID()); - - updateVerboseLogging(); } void Application::updateVerboseLogging() { @@ -2272,65 +2253,10 @@ void Application::updateVerboseLogging() { } bool enable = menu->isOptionChecked(MenuOption::VerboseLogging); - const_cast(&animation())->setEnabled(QtDebugMsg, enable); - const_cast(&animation())->setEnabled(QtInfoMsg, enable); - - const_cast(&avatars())->setEnabled(QtDebugMsg, enable); - const_cast(&avatars())->setEnabled(QtInfoMsg, enable); - - const_cast(&scriptengine())->setEnabled(QtDebugMsg, enable); - const_cast(&scriptengine())->setEnabled(QtInfoMsg, enable); - - const_cast(&scriptengine_module())->setEnabled(QtDebugMsg, enable); - const_cast(&scriptengine_module())->setEnabled(QtInfoMsg, enable); - - const_cast(&scriptengine_script())->setEnabled(QtDebugMsg, enable); - const_cast(&scriptengine_script())->setEnabled(QtInfoMsg, enable); - - const_cast(&modelformat())->setEnabled(QtDebugMsg, enable); - const_cast(&modelformat())->setEnabled(QtInfoMsg, enable); - - const_cast(&controllers())->setEnabled(QtDebugMsg, enable); - const_cast(&controllers())->setEnabled(QtInfoMsg, enable); - - const_cast(&resourceLog())->setEnabled(QtDebugMsg, enable); - const_cast(&resourceLog())->setEnabled(QtInfoMsg, enable); - - const_cast(&networking())->setEnabled(QtDebugMsg, enable); - const_cast(&networking())->setEnabled(QtInfoMsg, enable); - - const_cast(&asset_client())->setEnabled(QtDebugMsg, enable); - const_cast(&asset_client())->setEnabled(QtInfoMsg, enable); - - const_cast(&messages_client())->setEnabled(QtDebugMsg, enable); - const_cast(&messages_client())->setEnabled(QtInfoMsg, enable); - - const_cast(&storagelogging())->setEnabled(QtDebugMsg, enable); - const_cast(&storagelogging())->setEnabled(QtInfoMsg, enable); - - const_cast(&uiLogging())->setEnabled(QtDebugMsg, enable); - const_cast(&uiLogging())->setEnabled(QtInfoMsg, enable); - - const_cast(&glLogging())->setEnabled(QtDebugMsg, enable); - const_cast(&glLogging())->setEnabled(QtInfoMsg, enable); - - const_cast(&shared())->setEnabled(QtDebugMsg, enable); - const_cast(&shared())->setEnabled(QtInfoMsg, enable); - - const_cast(&plugins())->setEnabled(QtDebugMsg, enable); - const_cast(&plugins())->setEnabled(QtInfoMsg, enable); - - const_cast(&gpulogging())->setEnabled(QtDebugMsg, enable); - const_cast(&gpulogging())->setEnabled(QtInfoMsg, enable); - - const_cast(&gpugllogging())->setEnabled(QtDebugMsg, enable); - const_cast(&gpugllogging())->setEnabled(QtInfoMsg, enable); - - const_cast(&qmlLogging())->setEnabled(QtDebugMsg, enable); - const_cast(&qmlLogging())->setEnabled(QtInfoMsg, enable); - - const_cast(&entities())->setEnabled(QtDebugMsg, enable); - const_cast(&entities())->setEnabled(QtInfoMsg, enable); + QString rules = "*.debug=%1\n" + "*.info=%1"; + rules = rules.arg(enable ? "true" : "false"); + QLoggingCategory::setFilterRules(rules); } void Application::domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo) { From d5afb3a49b81d1b4d1070211b604e04f938a42d5 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 8 May 2018 09:04:59 -0700 Subject: [PATCH 78/92] Move non-automated tests into new folder --- .../controllers/CMakeLists.txt | 0 .../controllers/qml/main.qml | 0 .../controllers/src/main.cpp | 0 .../entities/CMakeLists.txt | 0 {tests => tests-manual}/entities/packet.bin | Bin {tests => tests-manual}/entities/src/main.cpp | 0 {tests => tests-manual}/gl/CMakeLists.txt | 0 {tests => tests-manual}/gl/src/main.cpp | 0 tests-manual/gpu-textures/CMakeLists.txt | 16 ++ .../gpu-textures/qml/textureStats.qml | 52 ++++++ tests-manual/gpu-textures/src/TestHelpers.cpp | 26 +++ tests-manual/gpu-textures/src/TestHelpers.h | 40 +++++ .../gpu-textures/src/TestTextures.cpp | 168 +++++++++++++++++ tests-manual/gpu-textures/src/TestTextures.h | 74 ++++++++ tests-manual/gpu-textures/src/TestWindow.cpp | 117 ++++++++++++ tests-manual/gpu-textures/src/TestWindow.h | 41 +++++ tests-manual/gpu-textures/src/main.cpp | 170 ++++++++++++++++++ .../gpu}/CMakeLists.txt | 0 .../gpu}/src/TestFbx.cpp | 0 .../gpu}/src/TestFbx.h | 0 .../gpu}/src/TestFloorGrid.cpp | 0 .../gpu}/src/TestFloorGrid.h | 0 .../gpu}/src/TestFloorTexture.cpp | 0 .../gpu}/src/TestFloorTexture.h | 0 .../gpu}/src/TestHelpers.cpp | 0 .../gpu}/src/TestHelpers.h | 0 .../gpu}/src/TestInstancedShapes.cpp | 0 .../gpu}/src/TestInstancedShapes.h | 0 .../gpu}/src/TestShapes.cpp | 0 .../gpu}/src/TestShapes.h | 0 .../gpu}/src/TestWindow.cpp | 0 .../gpu}/src/TestWindow.h | 0 .../gpu}/src/main.cpp | 0 {tests => tests-manual}/qml/CMakeLists.txt | 0 .../qml/qml/controls/WebEntityView.qml | 0 {tests => tests-manual}/qml/qml/main.qml | 0 .../qml/qml/qml/+android/UI.js | 0 .../qml/qml/qml/+ios/UI.js | 0 .../qml/qml/qml/+osx/UI.js | 0 .../qml/qml/qml/ButtonPage.qml | 0 .../qml/qml/qml/InputPage.qml | 0 .../qml/qml/qml/ProgressPage.qml | 0 {tests => tests-manual}/qml/qml/qml/UI.js | 0 {tests => tests-manual}/qml/src/main.cpp | 0 {tests => tests-manual}/qt59/CMakeLists.txt | 0 {tests => tests-manual}/qt59/src/main.cpp | 0 .../render-perf/CMakeLists.txt | 0 .../render-perf/src/Camera.hpp | 0 .../render-perf/src/main.cpp | 0 .../render-texture-load/CMakeLists.txt | 0 .../render-texture-load/src/GLIHelpers.cpp | 0 .../render-texture-load/src/GLIHelpers.h | 0 .../render-texture-load/src/main.cpp | 0 .../render-utils/CMakeLists.txt | 0 .../render-utils/src/main.cpp | 0 .../shaders/CMakeLists.txt | 0 {tests => tests-manual}/shaders/src/main.cpp | 0 {tests => tests-manual}/ui/CMakeLists.txt | 0 {tests => tests-manual}/ui/qml/Palettes.qml | 0 .../ui/qml/ScrollingGraph.qml | 0 {tests => tests-manual}/ui/qml/StubMenu.qml | 0 {tests => tests-manual}/ui/qml/Stubs.qml | 0 .../ui/qml/TestControllers.qml | 0 {tests => tests-manual}/ui/qml/TestDialog.qml | 0 {tests => tests-manual}/ui/qml/TestMenu.qml | 0 {tests => tests-manual}/ui/qml/TestRoot.qml | 0 .../ui/qml/controlDemo/ButtonPage.qml | 0 .../ui/qml/controlDemo/InputPage.qml | 0 .../ui/qml/controlDemo/ProgressPage.qml | 0 .../ui/qml/controlDemo/main.qml | 0 {tests => tests-manual}/ui/qml/main.qml | 0 {tests => tests-manual}/ui/qmlscratch.pro | 0 {tests => tests-manual}/ui/src/main.cpp | 0 73 files changed, 704 insertions(+) rename {tests => tests-manual}/controllers/CMakeLists.txt (100%) rename {tests => tests-manual}/controllers/qml/main.qml (100%) rename {tests => tests-manual}/controllers/src/main.cpp (100%) rename {tests => tests-manual}/entities/CMakeLists.txt (100%) rename {tests => tests-manual}/entities/packet.bin (100%) rename {tests => tests-manual}/entities/src/main.cpp (100%) rename {tests => tests-manual}/gl/CMakeLists.txt (100%) rename {tests => tests-manual}/gl/src/main.cpp (100%) create mode 100644 tests-manual/gpu-textures/CMakeLists.txt create mode 100644 tests-manual/gpu-textures/qml/textureStats.qml create mode 100644 tests-manual/gpu-textures/src/TestHelpers.cpp create mode 100644 tests-manual/gpu-textures/src/TestHelpers.h create mode 100644 tests-manual/gpu-textures/src/TestTextures.cpp create mode 100644 tests-manual/gpu-textures/src/TestTextures.h create mode 100644 tests-manual/gpu-textures/src/TestWindow.cpp create mode 100644 tests-manual/gpu-textures/src/TestWindow.h create mode 100644 tests-manual/gpu-textures/src/main.cpp rename {tests/gpu-test => tests-manual/gpu}/CMakeLists.txt (100%) rename {tests/gpu-test => tests-manual/gpu}/src/TestFbx.cpp (100%) rename {tests/gpu-test => tests-manual/gpu}/src/TestFbx.h (100%) rename {tests/gpu-test => tests-manual/gpu}/src/TestFloorGrid.cpp (100%) rename {tests/gpu-test => tests-manual/gpu}/src/TestFloorGrid.h (100%) rename {tests/gpu-test => tests-manual/gpu}/src/TestFloorTexture.cpp (100%) rename {tests/gpu-test => tests-manual/gpu}/src/TestFloorTexture.h (100%) rename {tests/gpu-test => tests-manual/gpu}/src/TestHelpers.cpp (100%) rename {tests/gpu-test => tests-manual/gpu}/src/TestHelpers.h (100%) rename {tests/gpu-test => tests-manual/gpu}/src/TestInstancedShapes.cpp (100%) rename {tests/gpu-test => tests-manual/gpu}/src/TestInstancedShapes.h (100%) rename {tests/gpu-test => tests-manual/gpu}/src/TestShapes.cpp (100%) rename {tests/gpu-test => tests-manual/gpu}/src/TestShapes.h (100%) rename {tests/gpu-test => tests-manual/gpu}/src/TestWindow.cpp (100%) rename {tests/gpu-test => tests-manual/gpu}/src/TestWindow.h (100%) rename {tests/gpu-test => tests-manual/gpu}/src/main.cpp (100%) rename {tests => tests-manual}/qml/CMakeLists.txt (100%) rename {tests => tests-manual}/qml/qml/controls/WebEntityView.qml (100%) rename {tests => tests-manual}/qml/qml/main.qml (100%) rename {tests => tests-manual}/qml/qml/qml/+android/UI.js (100%) rename {tests => tests-manual}/qml/qml/qml/+ios/UI.js (100%) rename {tests => tests-manual}/qml/qml/qml/+osx/UI.js (100%) rename {tests => tests-manual}/qml/qml/qml/ButtonPage.qml (100%) rename {tests => tests-manual}/qml/qml/qml/InputPage.qml (100%) rename {tests => tests-manual}/qml/qml/qml/ProgressPage.qml (100%) rename {tests => tests-manual}/qml/qml/qml/UI.js (100%) rename {tests => tests-manual}/qml/src/main.cpp (100%) rename {tests => tests-manual}/qt59/CMakeLists.txt (100%) rename {tests => tests-manual}/qt59/src/main.cpp (100%) rename {tests => tests-manual}/render-perf/CMakeLists.txt (100%) rename {tests => tests-manual}/render-perf/src/Camera.hpp (100%) rename {tests => tests-manual}/render-perf/src/main.cpp (100%) rename {tests => tests-manual}/render-texture-load/CMakeLists.txt (100%) rename {tests => tests-manual}/render-texture-load/src/GLIHelpers.cpp (100%) rename {tests => tests-manual}/render-texture-load/src/GLIHelpers.h (100%) rename {tests => tests-manual}/render-texture-load/src/main.cpp (100%) rename {tests => tests-manual}/render-utils/CMakeLists.txt (100%) rename {tests => tests-manual}/render-utils/src/main.cpp (100%) rename {tests => tests-manual}/shaders/CMakeLists.txt (100%) rename {tests => tests-manual}/shaders/src/main.cpp (100%) rename {tests => tests-manual}/ui/CMakeLists.txt (100%) rename {tests => tests-manual}/ui/qml/Palettes.qml (100%) rename {tests => tests-manual}/ui/qml/ScrollingGraph.qml (100%) rename {tests => tests-manual}/ui/qml/StubMenu.qml (100%) rename {tests => tests-manual}/ui/qml/Stubs.qml (100%) rename {tests => tests-manual}/ui/qml/TestControllers.qml (100%) rename {tests => tests-manual}/ui/qml/TestDialog.qml (100%) rename {tests => tests-manual}/ui/qml/TestMenu.qml (100%) rename {tests => tests-manual}/ui/qml/TestRoot.qml (100%) rename {tests => tests-manual}/ui/qml/controlDemo/ButtonPage.qml (100%) rename {tests => tests-manual}/ui/qml/controlDemo/InputPage.qml (100%) rename {tests => tests-manual}/ui/qml/controlDemo/ProgressPage.qml (100%) rename {tests => tests-manual}/ui/qml/controlDemo/main.qml (100%) rename {tests => tests-manual}/ui/qml/main.qml (100%) rename {tests => tests-manual}/ui/qmlscratch.pro (100%) rename {tests => tests-manual}/ui/src/main.cpp (100%) diff --git a/tests/controllers/CMakeLists.txt b/tests-manual/controllers/CMakeLists.txt similarity index 100% rename from tests/controllers/CMakeLists.txt rename to tests-manual/controllers/CMakeLists.txt diff --git a/tests/controllers/qml/main.qml b/tests-manual/controllers/qml/main.qml similarity index 100% rename from tests/controllers/qml/main.qml rename to tests-manual/controllers/qml/main.qml diff --git a/tests/controllers/src/main.cpp b/tests-manual/controllers/src/main.cpp similarity index 100% rename from tests/controllers/src/main.cpp rename to tests-manual/controllers/src/main.cpp diff --git a/tests/entities/CMakeLists.txt b/tests-manual/entities/CMakeLists.txt similarity index 100% rename from tests/entities/CMakeLists.txt rename to tests-manual/entities/CMakeLists.txt diff --git a/tests/entities/packet.bin b/tests-manual/entities/packet.bin similarity index 100% rename from tests/entities/packet.bin rename to tests-manual/entities/packet.bin diff --git a/tests/entities/src/main.cpp b/tests-manual/entities/src/main.cpp similarity index 100% rename from tests/entities/src/main.cpp rename to tests-manual/entities/src/main.cpp diff --git a/tests/gl/CMakeLists.txt b/tests-manual/gl/CMakeLists.txt similarity index 100% rename from tests/gl/CMakeLists.txt rename to tests-manual/gl/CMakeLists.txt diff --git a/tests/gl/src/main.cpp b/tests-manual/gl/src/main.cpp similarity index 100% rename from tests/gl/src/main.cpp rename to tests-manual/gl/src/main.cpp diff --git a/tests-manual/gpu-textures/CMakeLists.txt b/tests-manual/gpu-textures/CMakeLists.txt new file mode 100644 index 0000000000..c10f2eda3f --- /dev/null +++ b/tests-manual/gpu-textures/CMakeLists.txt @@ -0,0 +1,16 @@ +set(TARGET_NAME gpu-textures-tests) +AUTOSCRIBE_SHADER_LIB(gpu graphics render-utils) +# This is not a testcase -- just set it up as a regular hifi project +setup_hifi_project(Quick Gui Script) +setup_memory_debugger() +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") +link_hifi_libraries( + shared task networking gl + ktx gpu octree + ${PLATFORM_GL_BACKEND} +) + +set(EXTRA_DEPLOY_OPTIONS "--qmldir \"${PROJECT_SOURCE_DIR}/qml\"") +package_libraries_for_deployment() + +target_nsight() diff --git a/tests-manual/gpu-textures/qml/textureStats.qml b/tests-manual/gpu-textures/qml/textureStats.qml new file mode 100644 index 0000000000..d3700c3eac --- /dev/null +++ b/tests-manual/gpu-textures/qml/textureStats.qml @@ -0,0 +1,52 @@ +import QtQuick 2.5 +import QtQuick.Controls 2.3 + +Item { + width: 400 + height: 600 + + Column { + spacing: 10 + anchors.top: parent.top + anchors.left: parent.left + anchors.margins: 10 + + Text { text: qsTr("Total") } + Text { text: Stats.total + " MB" } + Text { text: qsTr("Allocated") } + Text { text: Stats.allocated } + Text { text: qsTr("Populated") } + Text { text: Stats.populated } + Text { text: qsTr("Pending") } + Text { text: Stats.pending } + Text { text: qsTr("Current Index") } + Text { text: Stats.index } + Text { text: qsTr("Current Source") } + Text { text: Stats.source } + Text { text: qsTr("Current Rez") } + Text { text: Stats.rez.width + " x " + Stats.rez.height } + } + + Row { + id: row1 + spacing: 10 + anchors.bottom: row2.top + anchors.left: parent.left + anchors.margins: 10 + Button { text: "1024"; onClicked: Stats.maxTextureMemory(1024); } + Button { text: "256"; onClicked: Stats.maxTextureMemory(256); } + } + + Row { + id: row2 + spacing: 10 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.margins: 10 + Button { text: "Change Textures"; onClicked: Stats.changeTextures(); } + Button { text: "Next"; onClicked: Stats.nextTexture(); } + Button { text: "Previous"; onClicked: Stats.prevTexture(); } + } + +} + diff --git a/tests-manual/gpu-textures/src/TestHelpers.cpp b/tests-manual/gpu-textures/src/TestHelpers.cpp new file mode 100644 index 0000000000..f952a4385f --- /dev/null +++ b/tests-manual/gpu-textures/src/TestHelpers.cpp @@ -0,0 +1,26 @@ +// +// Created by Bradley Austin Davis on 2016/05/16 +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "TestHelpers.h" +#include + +gpu::ShaderPointer makeShader(const std::string & vertexShaderSrc, const std::string & fragmentShaderSrc, const gpu::Shader::BindingSet & bindings) { + auto vs = gpu::Shader::createVertex(vertexShaderSrc); + auto fs = gpu::Shader::createPixel(fragmentShaderSrc); + auto shader = gpu::Shader::createProgram(vs, fs); + if (!gpu::Shader::makeProgram(*shader, bindings)) { + printf("Could not compile shader\n"); + exit(-1); + } + return shader; +} + +QString projectRootDir() { + static QString projectRootPath = QFileInfo(QFileInfo(__FILE__).absolutePath() + "/..").absoluteFilePath(); + return projectRootPath; +} diff --git a/tests-manual/gpu-textures/src/TestHelpers.h b/tests-manual/gpu-textures/src/TestHelpers.h new file mode 100644 index 0000000000..17730c3642 --- /dev/null +++ b/tests-manual/gpu-textures/src/TestHelpers.h @@ -0,0 +1,40 @@ +// +// Created by Bradley Austin Davis on 2016/05/16 +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#pragma once + +#include + +#include +#include +#include + +#include +#include +#include +#include + +struct RenderArgs { + gpu::ContextPointer _context; + ivec4 _viewport; + gpu::Batch* _batch; +}; + +class GpuTestBase : public QObject { +public: + virtual ~GpuTestBase() {} + virtual bool isReady() const { return true; } + virtual size_t getTestCount() const { return 1; } + virtual void renderTest(size_t test, const RenderArgs& args) = 0; + virtual QObject * statsObject() { return nullptr; } + virtual QUrl statUrl() { return QUrl(); } +}; + +uint32_t toCompactColor(const glm::vec4& color); +gpu::ShaderPointer makeShader(const std::string & vertexShaderSrc, const std::string & fragmentShaderSrc, const gpu::Shader::BindingSet & bindings); +QString projectRootDir(); diff --git a/tests-manual/gpu-textures/src/TestTextures.cpp b/tests-manual/gpu-textures/src/TestTextures.cpp new file mode 100644 index 0000000000..57cf1bccbf --- /dev/null +++ b/tests-manual/gpu-textures/src/TestTextures.cpp @@ -0,0 +1,168 @@ +// +// Created by Bradley Austin Davis on 2016/05/16 +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "TestTextures.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include "TestHelpers.h" + +#pragma optimize("", off) + +std::string vertexShaderSource = R"SHADER( +#line 14 +layout(location = 0) out vec2 outTexCoord0; + +const vec4 VERTICES[] = vec4[]( + vec4(-1.0, -1.0, 0.0, 1.0), + vec4( 1.0, -1.0, 0.0, 1.0), + vec4(-1.0, 1.0, 0.0, 1.0), + vec4( 1.0, 1.0, 0.0, 1.0) +); + +void main() { + outTexCoord0 = VERTICES[gl_VertexID].xy; + outTexCoord0 += 1.0; + outTexCoord0 /= 2.0; + gl_Position = VERTICES[gl_VertexID]; +} +)SHADER"; + +std::string fragmentShaderSource = R"SHADER( +#line 28 + +uniform sampler2D tex; + +layout(location = 0) in vec2 inTexCoord0; +layout(location = 0) out vec4 outFragColor; + +void main() { + outFragColor = texture(tex, inTexCoord0); + outFragColor.a = 1.0; + //outFragColor.rb = inTexCoord0; +} + +)SHADER"; + +#define STAT_UPDATE(name, src) \ + { \ + auto val = src; \ + if (_##name != val) { \ + _##name = val; \ + emit name##Changed(); \ + } \ + } + + +void TextureTestStats::update(int curIndex, const gpu::TexturePointer& texture) { + STAT_UPDATE(total, (int)BYTES_TO_MB(gpu::Context::getTextureGPUMemSize())); + STAT_UPDATE(allocated, (int)gpu::Context::getTextureResourceGPUMemSize()); + STAT_UPDATE(pending, (int)gpu::Context::getTexturePendingGPUTransferMemSize()); + STAT_UPDATE(populated, (int)gpu::Context::getTextureResourcePopulatedGPUMemSize()); + STAT_UPDATE(source, texture->source().c_str()); + STAT_UPDATE(index, curIndex); + auto dims = texture->getDimensions(); + STAT_UPDATE(rez, QSize(dims.x, dims.y)); +} + +TexturesTest::TexturesTest() { + connect(&stats, &TextureTestStats::changeTextures, this, &TexturesTest::onChangeTextures); + connect(&stats, &TextureTestStats::nextTexture, this, &TexturesTest::onNextTexture); + connect(&stats, &TextureTestStats::prevTexture, this, &TexturesTest::onPrevTexture); + connect(&stats, &TextureTestStats::maxTextureMemory, this, &TexturesTest::onMaxTextureMemory); + { + auto VS = gpu::Shader::createVertex(vertexShaderSource); + auto PS = gpu::Shader::createPixel(fragmentShaderSource); + auto program = gpu::Shader::createProgram(VS, PS); + gpu::Shader::BindingSet slotBindings; + gpu::Shader::makeProgram(*program, slotBindings); + // If the pipeline did not exist, make it + auto state = std::make_shared(); + state->setCullMode(gpu::State::CULL_NONE); + state->setDepthTest({}); + state->setBlendFunction({ false }); + pipeline = gpu::Pipeline::create(program, state); + } + + onChangeTextures(); +} + + +void TexturesTest::renderTest(size_t testId, const RenderArgs& args) { + stats.update((int)index, textures[index]); + gpu::Batch& batch = *(args._batch); + batch.setPipeline(pipeline); + batch.setInputFormat(vertexFormat); + for (const auto& texture : textures) { + batch.setResourceTexture(0, texture); + batch.draw(gpu::TRIANGLE_STRIP, 4, 0); + } + batch.setResourceTexture(0, textures[index]); + batch.draw(gpu::TRIANGLE_STRIP, 4, 0); +} + +#define LOAD_TEXTURE_COUNT 64 + +void TexturesTest::onChangeTextures() { + static const QDir TEST_DIR("D:/ktx_texture_test"); + static std::vector ALL_TEXTURE_FILES; + if (ALL_TEXTURE_FILES.empty()) { + auto entryList = TEST_DIR.entryList({ "*.ktx" }, QDir::Filter::Files); + ALL_TEXTURE_FILES.reserve(entryList.size()); + for (auto entry : entryList) { + auto textureFile = TEST_DIR.absoluteFilePath(entry).toStdString(); + ALL_TEXTURE_FILES.push_back(textureFile); + } + } + + oldTextures.clear(); + oldTextures.swap(textures); + +#if 0 + static const std::string bad = "D:/ktx_texture_test/b4beed38675dbc7a827ecd576399c1f4.ktx"; + auto texture = gpu::Texture::unserialize(bad); + auto texelFormat = texture->getTexelFormat(); + qDebug() << texture->getTexelFormat().getSemantic(); + qDebug() << texture->getTexelFormat().getScalarCount(); + textures.push_back(texture); +#else + std::shuffle(ALL_TEXTURE_FILES.begin(), ALL_TEXTURE_FILES.end(), std::default_random_engine()); + size_t newTextureCount = std::min(ALL_TEXTURE_FILES.size(), LOAD_TEXTURE_COUNT); + for (size_t i = 0; i < newTextureCount; ++i) { + const auto& textureFile = ALL_TEXTURE_FILES[i]; + auto texture = gpu::Texture::unserialize(textureFile); + qDebug() << textureFile.c_str(); + qDebug() << texture->getTexelFormat().getSemantic(); + qDebug() << texture->getTexelFormat().getScalarCount(); + textures.push_back(texture); + } +#endif + index = 0; + qDebug() << "Done"; +} + +void TexturesTest::onNextTexture() { + index += textures.size() + 1; + index %= textures.size(); +} + +void TexturesTest::onPrevTexture() { + index += textures.size() - 1; + index %= textures.size(); +} + +void TexturesTest::onMaxTextureMemory(int maxTextureMemory) { + gpu::Texture::setAllowedGPUMemoryUsage(MB_TO_BYTES(maxTextureMemory)); +} \ No newline at end of file diff --git a/tests-manual/gpu-textures/src/TestTextures.h b/tests-manual/gpu-textures/src/TestTextures.h new file mode 100644 index 0000000000..e446ce6132 --- /dev/null +++ b/tests-manual/gpu-textures/src/TestTextures.h @@ -0,0 +1,74 @@ +// +// Created by Bradley Austin Davis on 2016/05/16 +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#pragma once + +#include "TestHelpers.h" + +#define STATS_PROPERTY(type, name, initialValue) \ + Q_PROPERTY(type name READ name NOTIFY name##Changed) \ +public: \ + type name() { return _##name; }; \ +private: \ + type _##name{ initialValue }; + + +class TextureTestStats : public QObject { + Q_OBJECT; + STATS_PROPERTY(int, pending, 0) + STATS_PROPERTY(int, total, 0) + STATS_PROPERTY(int, populated, 0) + STATS_PROPERTY(int, allocated, 0) + STATS_PROPERTY(int, index, 0) + + STATS_PROPERTY(QString, source, QString()) + STATS_PROPERTY(QSize, rez, QSize(0, 0)) + +public: + void update(int index, const gpu::TexturePointer& texture); + +signals: + void pendingChanged(); + void totalChanged(); + void populatedChanged(); + void allocatedChanged(); + void changeTextures(); + void rezChanged(); + void indexChanged(); + void sourceChanged(); + void maxTextureMemory(int); + + void nextTexture(); + void prevTexture(); +}; + + +class TexturesTest : public GpuTestBase { + Q_OBJECT + + gpu::Stream::FormatPointer vertexFormat { std::make_shared() }; + std::vector textures; + std::vector oldTextures; + gpu::PipelinePointer pipeline; + TextureTestStats stats; + size_t index{ 0 }; + +public: + TexturesTest(); + QObject* statsObject() override { return &stats; } + QUrl statUrl() override { return QUrl::fromLocalFile(projectRootDir() + "/qml/textureStats.qml"); } + void renderTest(size_t testId, const RenderArgs& args) override; + +protected slots: + void onChangeTextures(); + void onMaxTextureMemory(int newValue); + void onNextTexture(); + void onPrevTexture(); + +}; + + diff --git a/tests-manual/gpu-textures/src/TestWindow.cpp b/tests-manual/gpu-textures/src/TestWindow.cpp new file mode 100644 index 0000000000..038b0b9b80 --- /dev/null +++ b/tests-manual/gpu-textures/src/TestWindow.cpp @@ -0,0 +1,117 @@ +// +// Created by Bradley Austin Davis on 2016/05/16 +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "TestWindow.h" + +#include +#include + +#include +#include + +#include + +#include + +TestWindow::TestWindow() { + + auto timer = new QTimer(this); + timer->setTimerType(Qt::PreciseTimer); + timer->setInterval(5); + connect(timer, &QTimer::timeout, [&] { draw(); }); + timer->start(); + + connect(qApp, &QCoreApplication::aboutToQuit, [this, timer] { + timer->stop(); + _aboutToQuit = true; + }); + + setSurfaceType(QSurface::OpenGLSurface); + + QSurfaceFormat format = getDefaultOpenGLSurfaceFormat(); + format.setOption(QSurfaceFormat::DebugContext); + setFormat(format); + _glContext.setFormat(format); + _glContext.create(); + _glContext.makeCurrent(this); + + show(); +} + +void TestWindow::initGl() { + _glContext.makeCurrent(this); + gl::initModuleGl(); + gpu::Context::init(); + _renderArgs->_context = std::make_shared(); + _glContext.makeCurrent(this); + resize(QSize(800, 600)); +} + +void TestWindow::resizeWindow(const QSize& size) { + _size = size; + _renderArgs->_viewport = ivec4(0, 0, _size.width(), _size.height()); +} + +void TestWindow::beginFrame() { + _renderArgs->_context->recycle(); + _renderArgs->_context->beginFrame(); + gpu::doInBatch("TestWindow::beginFrame", _renderArgs->_context, [&](gpu::Batch& batch) { + batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLORS, { 0.0f, 0.1f, 0.2f, 1.0f }); + batch.clearDepthFramebuffer(1e4); + batch.setViewportTransform({ 0, 0, _size.width() * devicePixelRatio(), _size.height() * devicePixelRatio() }); + }); + + gpu::doInBatch("TestWindow::beginFrame", _renderArgs->_context, [&](gpu::Batch& batch) { + batch.setViewportTransform(_renderArgs->_viewport); + batch.setStateScissorRect(_renderArgs->_viewport); + batch.setProjectionTransform(_projectionMatrix); + }); +} + +void TestWindow::endFrame() { + gpu::doInBatch("TestWindow::endFrame::finish", _renderArgs->_context, [&](gpu::Batch& batch) { + batch.resetStages(); + }); + auto framePointer = _renderArgs->_context->endFrame(); + _renderArgs->_context->consumeFrameUpdates(framePointer); + _renderArgs->_context->executeFrame(framePointer); + _glContext.swapBuffers(this); +} + +void TestWindow::draw() { + if (_aboutToQuit) { + return; + } + + // Attempting to draw before we're visible and have a valid size will + // produce GL errors. + if (!isVisible() || _size.width() <= 0 || _size.height() <= 0) { + return; + } + + if (!_glContext.makeCurrent(this)) { + return; + } + + static std::once_flag once; + std::call_once(once, [&] { initGl(); }); + beginFrame(); + + renderFrame(); + + endFrame(); +} + +void TestWindow::resizeEvent(QResizeEvent* ev) { + resizeWindow(ev->size()); + float fov_degrees = 60.0f; + float aspect_ratio = (float)_size.width() / _size.height(); + float near_clip = 0.1f; + float far_clip = 1000.0f; + _projectionMatrix = glm::perspective(glm::radians(fov_degrees), aspect_ratio, near_clip, far_clip); +} diff --git a/tests-manual/gpu-textures/src/TestWindow.h b/tests-manual/gpu-textures/src/TestWindow.h new file mode 100644 index 0000000000..00bbf03836 --- /dev/null +++ b/tests-manual/gpu-textures/src/TestWindow.h @@ -0,0 +1,41 @@ +// +// Created by Bradley Austin Davis on 2016/05/16 +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#pragma once + +#include +#include + +#include +#include +#include +#include "TestHelpers.h" + +#define DEFERRED_LIGHTING + +class TestWindow : public QWindow { +protected: + QOpenGLContextWrapper _glContext; + QSize _size; + glm::mat4 _projectionMatrix; + bool _aboutToQuit { false }; + std::shared_ptr _renderArgs{ std::make_shared() }; + + TestWindow(); + virtual void initGl(); + virtual void renderFrame() = 0; + +private: + void resizeWindow(const QSize& size); + + void beginFrame(); + void endFrame(); + void draw(); + void resizeEvent(QResizeEvent* ev) override; +}; + diff --git a/tests-manual/gpu-textures/src/main.cpp b/tests-manual/gpu-textures/src/main.cpp new file mode 100644 index 0000000000..3d0051dc1d --- /dev/null +++ b/tests-manual/gpu-textures/src/main.cpp @@ -0,0 +1,170 @@ +// +// main.cpp +// tests/gpu-test/src +// +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "TestWindow.h" +#include "TestTextures.h" + +using TestBuilder = std::function; +using TestBuilders = std::list; + +#define INTERACTIVE + +class MyTestWindow : public TestWindow { + using Parent = TestWindow; + TestBuilders _testBuilders; + GpuTestBase* _currentTest{ nullptr }; + size_t _currentTestId{ 0 }; + size_t _currentMaxTests{ 0 }; + glm::mat4 _camera; + QTime _time; + + void initGl() override { + Parent::initGl(); + _time.start(); + updateCamera(); + _testBuilders = TestBuilders({ + [] { return new TexturesTest(); }, + }); + } + + void updateCamera() { + float t = _time.elapsed() * 1e-3f; + glm::vec3 unitscale{ 1.0f }; + glm::vec3 up{ 0.0f, 1.0f, 0.0f }; + + float distance = 3.0f; + glm::vec3 camera_position{ distance * sinf(t), 0.5f, distance * cosf(t) }; + + static const vec3 camera_focus(0); + static const vec3 camera_up(0, 1, 0); + _camera = glm::inverse(glm::lookAt(camera_position, camera_focus, up)); + + ViewFrustum frustum; + frustum.setPosition(camera_position); + frustum.setOrientation(glm::quat_cast(_camera)); + frustum.setProjection(_projectionMatrix); + } + + void renderFrame() override { + updateCamera(); + + while ((!_currentTest || (_currentTestId >= _currentMaxTests)) && !_testBuilders.empty()) { + if (_currentTest) { + delete _currentTest; + _currentTest = nullptr; + } + + _currentTest = _testBuilders.front()(); + _testBuilders.pop_front(); + + if (_currentTest) { + auto statsObject = _currentTest->statsObject(); + QUrl url = _currentTest->statUrl(); + if (statsObject) { + auto screens = qApp->screens(); + auto primaryScreen = qApp->primaryScreen(); + auto targetScreen = primaryScreen; + for (const auto& screen : screens) { + if (screen == primaryScreen) { + continue; + } + targetScreen = screen; + break; + } + + auto destPoint = targetScreen->availableGeometry().topLeft(); + QQuickView* view = new QQuickView(); + view->rootContext()->setContextProperty("Stats", statsObject); + view->setSource(url); + view->show(); + view->setPosition({ destPoint.x() + 100, destPoint.y() + 100 }); + } + _currentMaxTests = _currentTest->getTestCount(); + _currentTestId = 0; + } + } + + if (!_currentTest && _testBuilders.empty()) { + qApp->quit(); + return; + } + + // Tests might need to wait for resources to download + if (!_currentTest->isReady()) { + return; + } + + gpu::doInBatch("main::renderFrame", _renderArgs->_context, [&](gpu::Batch& batch) { + batch.setViewTransform(_camera); + _renderArgs->_batch = &batch; + _currentTest->renderTest(_currentTestId, *_renderArgs); + _renderArgs->_batch = nullptr; + }); + } +}; + +int main(int argc, char** argv) { + setupHifiApplication("GPU Test"); + qputenv("HIFI_DEBUG_OPENGL", QByteArray("1")); + QApplication app(argc, argv); + MyTestWindow window; + app.exec(); + + return 0; +} diff --git a/tests/gpu-test/CMakeLists.txt b/tests-manual/gpu/CMakeLists.txt similarity index 100% rename from tests/gpu-test/CMakeLists.txt rename to tests-manual/gpu/CMakeLists.txt diff --git a/tests/gpu-test/src/TestFbx.cpp b/tests-manual/gpu/src/TestFbx.cpp similarity index 100% rename from tests/gpu-test/src/TestFbx.cpp rename to tests-manual/gpu/src/TestFbx.cpp diff --git a/tests/gpu-test/src/TestFbx.h b/tests-manual/gpu/src/TestFbx.h similarity index 100% rename from tests/gpu-test/src/TestFbx.h rename to tests-manual/gpu/src/TestFbx.h diff --git a/tests/gpu-test/src/TestFloorGrid.cpp b/tests-manual/gpu/src/TestFloorGrid.cpp similarity index 100% rename from tests/gpu-test/src/TestFloorGrid.cpp rename to tests-manual/gpu/src/TestFloorGrid.cpp diff --git a/tests/gpu-test/src/TestFloorGrid.h b/tests-manual/gpu/src/TestFloorGrid.h similarity index 100% rename from tests/gpu-test/src/TestFloorGrid.h rename to tests-manual/gpu/src/TestFloorGrid.h diff --git a/tests/gpu-test/src/TestFloorTexture.cpp b/tests-manual/gpu/src/TestFloorTexture.cpp similarity index 100% rename from tests/gpu-test/src/TestFloorTexture.cpp rename to tests-manual/gpu/src/TestFloorTexture.cpp diff --git a/tests/gpu-test/src/TestFloorTexture.h b/tests-manual/gpu/src/TestFloorTexture.h similarity index 100% rename from tests/gpu-test/src/TestFloorTexture.h rename to tests-manual/gpu/src/TestFloorTexture.h diff --git a/tests/gpu-test/src/TestHelpers.cpp b/tests-manual/gpu/src/TestHelpers.cpp similarity index 100% rename from tests/gpu-test/src/TestHelpers.cpp rename to tests-manual/gpu/src/TestHelpers.cpp diff --git a/tests/gpu-test/src/TestHelpers.h b/tests-manual/gpu/src/TestHelpers.h similarity index 100% rename from tests/gpu-test/src/TestHelpers.h rename to tests-manual/gpu/src/TestHelpers.h diff --git a/tests/gpu-test/src/TestInstancedShapes.cpp b/tests-manual/gpu/src/TestInstancedShapes.cpp similarity index 100% rename from tests/gpu-test/src/TestInstancedShapes.cpp rename to tests-manual/gpu/src/TestInstancedShapes.cpp diff --git a/tests/gpu-test/src/TestInstancedShapes.h b/tests-manual/gpu/src/TestInstancedShapes.h similarity index 100% rename from tests/gpu-test/src/TestInstancedShapes.h rename to tests-manual/gpu/src/TestInstancedShapes.h diff --git a/tests/gpu-test/src/TestShapes.cpp b/tests-manual/gpu/src/TestShapes.cpp similarity index 100% rename from tests/gpu-test/src/TestShapes.cpp rename to tests-manual/gpu/src/TestShapes.cpp diff --git a/tests/gpu-test/src/TestShapes.h b/tests-manual/gpu/src/TestShapes.h similarity index 100% rename from tests/gpu-test/src/TestShapes.h rename to tests-manual/gpu/src/TestShapes.h diff --git a/tests/gpu-test/src/TestWindow.cpp b/tests-manual/gpu/src/TestWindow.cpp similarity index 100% rename from tests/gpu-test/src/TestWindow.cpp rename to tests-manual/gpu/src/TestWindow.cpp diff --git a/tests/gpu-test/src/TestWindow.h b/tests-manual/gpu/src/TestWindow.h similarity index 100% rename from tests/gpu-test/src/TestWindow.h rename to tests-manual/gpu/src/TestWindow.h diff --git a/tests/gpu-test/src/main.cpp b/tests-manual/gpu/src/main.cpp similarity index 100% rename from tests/gpu-test/src/main.cpp rename to tests-manual/gpu/src/main.cpp diff --git a/tests/qml/CMakeLists.txt b/tests-manual/qml/CMakeLists.txt similarity index 100% rename from tests/qml/CMakeLists.txt rename to tests-manual/qml/CMakeLists.txt diff --git a/tests/qml/qml/controls/WebEntityView.qml b/tests-manual/qml/qml/controls/WebEntityView.qml similarity index 100% rename from tests/qml/qml/controls/WebEntityView.qml rename to tests-manual/qml/qml/controls/WebEntityView.qml diff --git a/tests/qml/qml/main.qml b/tests-manual/qml/qml/main.qml similarity index 100% rename from tests/qml/qml/main.qml rename to tests-manual/qml/qml/main.qml diff --git a/tests/qml/qml/qml/+android/UI.js b/tests-manual/qml/qml/qml/+android/UI.js similarity index 100% rename from tests/qml/qml/qml/+android/UI.js rename to tests-manual/qml/qml/qml/+android/UI.js diff --git a/tests/qml/qml/qml/+ios/UI.js b/tests-manual/qml/qml/qml/+ios/UI.js similarity index 100% rename from tests/qml/qml/qml/+ios/UI.js rename to tests-manual/qml/qml/qml/+ios/UI.js diff --git a/tests/qml/qml/qml/+osx/UI.js b/tests-manual/qml/qml/qml/+osx/UI.js similarity index 100% rename from tests/qml/qml/qml/+osx/UI.js rename to tests-manual/qml/qml/qml/+osx/UI.js diff --git a/tests/qml/qml/qml/ButtonPage.qml b/tests-manual/qml/qml/qml/ButtonPage.qml similarity index 100% rename from tests/qml/qml/qml/ButtonPage.qml rename to tests-manual/qml/qml/qml/ButtonPage.qml diff --git a/tests/qml/qml/qml/InputPage.qml b/tests-manual/qml/qml/qml/InputPage.qml similarity index 100% rename from tests/qml/qml/qml/InputPage.qml rename to tests-manual/qml/qml/qml/InputPage.qml diff --git a/tests/qml/qml/qml/ProgressPage.qml b/tests-manual/qml/qml/qml/ProgressPage.qml similarity index 100% rename from tests/qml/qml/qml/ProgressPage.qml rename to tests-manual/qml/qml/qml/ProgressPage.qml diff --git a/tests/qml/qml/qml/UI.js b/tests-manual/qml/qml/qml/UI.js similarity index 100% rename from tests/qml/qml/qml/UI.js rename to tests-manual/qml/qml/qml/UI.js diff --git a/tests/qml/src/main.cpp b/tests-manual/qml/src/main.cpp similarity index 100% rename from tests/qml/src/main.cpp rename to tests-manual/qml/src/main.cpp diff --git a/tests/qt59/CMakeLists.txt b/tests-manual/qt59/CMakeLists.txt similarity index 100% rename from tests/qt59/CMakeLists.txt rename to tests-manual/qt59/CMakeLists.txt diff --git a/tests/qt59/src/main.cpp b/tests-manual/qt59/src/main.cpp similarity index 100% rename from tests/qt59/src/main.cpp rename to tests-manual/qt59/src/main.cpp diff --git a/tests/render-perf/CMakeLists.txt b/tests-manual/render-perf/CMakeLists.txt similarity index 100% rename from tests/render-perf/CMakeLists.txt rename to tests-manual/render-perf/CMakeLists.txt diff --git a/tests/render-perf/src/Camera.hpp b/tests-manual/render-perf/src/Camera.hpp similarity index 100% rename from tests/render-perf/src/Camera.hpp rename to tests-manual/render-perf/src/Camera.hpp diff --git a/tests/render-perf/src/main.cpp b/tests-manual/render-perf/src/main.cpp similarity index 100% rename from tests/render-perf/src/main.cpp rename to tests-manual/render-perf/src/main.cpp diff --git a/tests/render-texture-load/CMakeLists.txt b/tests-manual/render-texture-load/CMakeLists.txt similarity index 100% rename from tests/render-texture-load/CMakeLists.txt rename to tests-manual/render-texture-load/CMakeLists.txt diff --git a/tests/render-texture-load/src/GLIHelpers.cpp b/tests-manual/render-texture-load/src/GLIHelpers.cpp similarity index 100% rename from tests/render-texture-load/src/GLIHelpers.cpp rename to tests-manual/render-texture-load/src/GLIHelpers.cpp diff --git a/tests/render-texture-load/src/GLIHelpers.h b/tests-manual/render-texture-load/src/GLIHelpers.h similarity index 100% rename from tests/render-texture-load/src/GLIHelpers.h rename to tests-manual/render-texture-load/src/GLIHelpers.h diff --git a/tests/render-texture-load/src/main.cpp b/tests-manual/render-texture-load/src/main.cpp similarity index 100% rename from tests/render-texture-load/src/main.cpp rename to tests-manual/render-texture-load/src/main.cpp diff --git a/tests/render-utils/CMakeLists.txt b/tests-manual/render-utils/CMakeLists.txt similarity index 100% rename from tests/render-utils/CMakeLists.txt rename to tests-manual/render-utils/CMakeLists.txt diff --git a/tests/render-utils/src/main.cpp b/tests-manual/render-utils/src/main.cpp similarity index 100% rename from tests/render-utils/src/main.cpp rename to tests-manual/render-utils/src/main.cpp diff --git a/tests/shaders/CMakeLists.txt b/tests-manual/shaders/CMakeLists.txt similarity index 100% rename from tests/shaders/CMakeLists.txt rename to tests-manual/shaders/CMakeLists.txt diff --git a/tests/shaders/src/main.cpp b/tests-manual/shaders/src/main.cpp similarity index 100% rename from tests/shaders/src/main.cpp rename to tests-manual/shaders/src/main.cpp diff --git a/tests/ui/CMakeLists.txt b/tests-manual/ui/CMakeLists.txt similarity index 100% rename from tests/ui/CMakeLists.txt rename to tests-manual/ui/CMakeLists.txt diff --git a/tests/ui/qml/Palettes.qml b/tests-manual/ui/qml/Palettes.qml similarity index 100% rename from tests/ui/qml/Palettes.qml rename to tests-manual/ui/qml/Palettes.qml diff --git a/tests/ui/qml/ScrollingGraph.qml b/tests-manual/ui/qml/ScrollingGraph.qml similarity index 100% rename from tests/ui/qml/ScrollingGraph.qml rename to tests-manual/ui/qml/ScrollingGraph.qml diff --git a/tests/ui/qml/StubMenu.qml b/tests-manual/ui/qml/StubMenu.qml similarity index 100% rename from tests/ui/qml/StubMenu.qml rename to tests-manual/ui/qml/StubMenu.qml diff --git a/tests/ui/qml/Stubs.qml b/tests-manual/ui/qml/Stubs.qml similarity index 100% rename from tests/ui/qml/Stubs.qml rename to tests-manual/ui/qml/Stubs.qml diff --git a/tests/ui/qml/TestControllers.qml b/tests-manual/ui/qml/TestControllers.qml similarity index 100% rename from tests/ui/qml/TestControllers.qml rename to tests-manual/ui/qml/TestControllers.qml diff --git a/tests/ui/qml/TestDialog.qml b/tests-manual/ui/qml/TestDialog.qml similarity index 100% rename from tests/ui/qml/TestDialog.qml rename to tests-manual/ui/qml/TestDialog.qml diff --git a/tests/ui/qml/TestMenu.qml b/tests-manual/ui/qml/TestMenu.qml similarity index 100% rename from tests/ui/qml/TestMenu.qml rename to tests-manual/ui/qml/TestMenu.qml diff --git a/tests/ui/qml/TestRoot.qml b/tests-manual/ui/qml/TestRoot.qml similarity index 100% rename from tests/ui/qml/TestRoot.qml rename to tests-manual/ui/qml/TestRoot.qml diff --git a/tests/ui/qml/controlDemo/ButtonPage.qml b/tests-manual/ui/qml/controlDemo/ButtonPage.qml similarity index 100% rename from tests/ui/qml/controlDemo/ButtonPage.qml rename to tests-manual/ui/qml/controlDemo/ButtonPage.qml diff --git a/tests/ui/qml/controlDemo/InputPage.qml b/tests-manual/ui/qml/controlDemo/InputPage.qml similarity index 100% rename from tests/ui/qml/controlDemo/InputPage.qml rename to tests-manual/ui/qml/controlDemo/InputPage.qml diff --git a/tests/ui/qml/controlDemo/ProgressPage.qml b/tests-manual/ui/qml/controlDemo/ProgressPage.qml similarity index 100% rename from tests/ui/qml/controlDemo/ProgressPage.qml rename to tests-manual/ui/qml/controlDemo/ProgressPage.qml diff --git a/tests/ui/qml/controlDemo/main.qml b/tests-manual/ui/qml/controlDemo/main.qml similarity index 100% rename from tests/ui/qml/controlDemo/main.qml rename to tests-manual/ui/qml/controlDemo/main.qml diff --git a/tests/ui/qml/main.qml b/tests-manual/ui/qml/main.qml similarity index 100% rename from tests/ui/qml/main.qml rename to tests-manual/ui/qml/main.qml diff --git a/tests/ui/qmlscratch.pro b/tests-manual/ui/qmlscratch.pro similarity index 100% rename from tests/ui/qmlscratch.pro rename to tests-manual/ui/qmlscratch.pro diff --git a/tests/ui/src/main.cpp b/tests-manual/ui/src/main.cpp similarity index 100% rename from tests/ui/src/main.cpp rename to tests-manual/ui/src/main.cpp From 6e16109fa45dfc5821bc59d9dac624ebab478321 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 8 May 2018 09:11:13 -0700 Subject: [PATCH 79/92] Fix unit test compile failures and crashes --- tests/animation/src/AnimTests.cpp | 1 + tests/ktx/src/KtxTests.cpp | 4 +++- tests/networking/src/ResourceTests.cpp | 21 ++++++++++++++++----- tests/networking/src/ResourceTests.h | 1 + 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/tests/animation/src/AnimTests.cpp b/tests/animation/src/AnimTests.cpp index fe54ac3781..432129594a 100644 --- a/tests/animation/src/AnimTests.cpp +++ b/tests/animation/src/AnimTests.cpp @@ -39,6 +39,7 @@ void AnimTests::initTestCase() { void AnimTests::cleanupTestCase() { //DependencyManager::destroy(); + DependencyManager::get()->cleanup(); } void AnimTests::testClipInternalState() { diff --git a/tests/ktx/src/KtxTests.cpp b/tests/ktx/src/KtxTests.cpp index 65d9cbec3d..5158ad2fd4 100644 --- a/tests/ktx/src/KtxTests.cpp +++ b/tests/ktx/src/KtxTests.cpp @@ -76,7 +76,9 @@ void KtxTests::testKtxEvalFunctions() { void KtxTests::testKtxSerialization() { const QString TEST_IMAGE = getRootPath() + "/scripts/developer/tests/cube_texture.png"; QImage image(TEST_IMAGE); - gpu::TexturePointer testTexture = image::TextureUsage::process2DTextureColorFromImage(image, TEST_IMAGE.toStdString(), true); + std::atomic abortSignal; + gpu::TexturePointer testTexture = + image::TextureUsage::process2DTextureColorFromImage(std::move(image), TEST_IMAGE.toStdString(), true, abortSignal); auto ktxMemory = gpu::Texture::serialize(*testTexture); QVERIFY(ktxMemory.get()); diff --git a/tests/networking/src/ResourceTests.cpp b/tests/networking/src/ResourceTests.cpp index 864d7c9939..6af3629bc7 100644 --- a/tests/networking/src/ResourceTests.cpp +++ b/tests/networking/src/ResourceTests.cpp @@ -11,16 +11,23 @@ #include -#include "ResourceCache.h" -#include "NetworkAccessManager.h" -#include "DependencyManager.h" +#include +#include +#include +#include +#include +#include QTEST_MAIN(ResourceTests) void ResourceTests::initTestCase() { - auto resourceCacheSharedItems = DependencyManager::set(); - + //DependencyManager::set(); + DependencyManager::set(); + DependencyManager::registerInheritance(); + DependencyManager::set(NodeType::Agent, INVALID_PORT); + DependencyManager::set(); + DependencyManager::set(); const qint64 MAXIMUM_CACHE_SIZE = 1024 * 1024 * 1024; // 1GB // set up the file cache @@ -34,6 +41,10 @@ void ResourceTests::initTestCase() { networkAccessManager.setCache(cache); } +void ResourceTests::cleanupTestCase() { + DependencyManager::get()->cleanup(); +} + static QSharedPointer resource; diff --git a/tests/networking/src/ResourceTests.h b/tests/networking/src/ResourceTests.h index 32fc151982..59675816ba 100644 --- a/tests/networking/src/ResourceTests.h +++ b/tests/networking/src/ResourceTests.h @@ -18,6 +18,7 @@ private slots: void initTestCase(); void downloadFirst(); void downloadAgain(); + void cleanupTestCase(); }; #endif // hifi_ResourceTests_h From f206456cddfd93f063632ed0e1c2e92dddcfa419 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 8 May 2018 10:18:08 -0700 Subject: [PATCH 80/92] Restoring manual tests to solution, removing dead tests --- CMakeLists.txt | 1 + tests-manual/CMakeLists.txt | 8 ++++ tests-manual/qt59/CMakeLists.txt | 22 ---------- tests-manual/qt59/src/main.cpp | 73 -------------------------------- tests-manual/ui/CMakeLists.txt | 1 - 5 files changed, 9 insertions(+), 96 deletions(-) create mode 100644 tests-manual/CMakeLists.txt delete mode 100644 tests-manual/qt59/CMakeLists.txt delete mode 100644 tests-manual/qt59/src/main.cpp delete mode 100644 tests-manual/ui/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 93b784b462..69ea0b7fd8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -180,6 +180,7 @@ add_subdirectory(tools) if (BUILD_TESTS) add_subdirectory(tests) + add_subdirectory(tests-manual) endif() if (BUILD_INSTALLER) diff --git a/tests-manual/CMakeLists.txt b/tests-manual/CMakeLists.txt new file mode 100644 index 0000000000..bc64183298 --- /dev/null +++ b/tests-manual/CMakeLists.txt @@ -0,0 +1,8 @@ +# add the manual test directories +file(GLOB TEST_SUBDIRS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/*") +foreach(DIR ${TEST_SUBDIRS}) + if((IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${DIR}") AND (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${DIR}/CMakeLists.txt")) + set(TEST_PROJ_NAME ${DIR}) + add_subdirectory(${DIR}) + endif() +endforeach() diff --git a/tests-manual/qt59/CMakeLists.txt b/tests-manual/qt59/CMakeLists.txt deleted file mode 100644 index e3450ae069..0000000000 --- a/tests-manual/qt59/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ - -set(TARGET_NAME qt59) - -if (WIN32) - SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ignore:4049 /ignore:4217") -endif() - -setup_memory_debugger() - -# This is not a testcase -- just set it up as a regular hifi project -setup_hifi_project(Gui) -set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") - - -# link in the shared libraries -link_hifi_libraries(shared networking) - -if (WIN32) - add_dependency_external_projects(wasapi) -endif() - -package_libraries_for_deployment() diff --git a/tests-manual/qt59/src/main.cpp b/tests-manual/qt59/src/main.cpp deleted file mode 100644 index 19b922de9f..0000000000 --- a/tests-manual/qt59/src/main.cpp +++ /dev/null @@ -1,73 +0,0 @@ -// -// Created by Bradley Austin Davis on 2017/06/06 -// Copyright 2013-2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -#include - -#include -#include -#include -#include - -#include - - -class Qt59TestApp : public QCoreApplication { - Q_OBJECT -public: - Qt59TestApp(int argc, char* argv[]); - ~Qt59TestApp(); - -private: - void finish(int exitCode); -}; - - - -Qt59TestApp::Qt59TestApp(int argc, char* argv[]) : - QCoreApplication(argc, argv) -{ - DependencyManager::registerInheritance(); - DependencyManager::set([&] { return QString("Mozilla/5.0 (HighFidelityACClient)"); }); - DependencyManager::set(); - DependencyManager::set(NodeType::Agent, 0); - auto nodeList = DependencyManager::get(); - nodeList->startThread(); - auto messagesClient = DependencyManager::set(); - messagesClient->startThread(); - QTimer::singleShot(1000, [this] { finish(0); }); -} - -Qt59TestApp::~Qt59TestApp() { -} - - -void Qt59TestApp::finish(int exitCode) { - auto nodeList = DependencyManager::get(); - - // send the domain a disconnect packet, force stoppage of domain-server check-ins - nodeList->getDomainHandler().disconnect(); - nodeList->setIsShuttingDown(true); - nodeList->getPacketReceiver().setShouldDropPackets(true); - - // remove the NodeList from the DependencyManager - DependencyManager::destroy(); - QCoreApplication::exit(exitCode); -} - - -int main(int argc, char * argv[]) { - setupHifiApplication("Qt59Test"); - - Qt59TestApp app(argc, argv); - - return app.exec(); -} - -#include "main.moc" diff --git a/tests-manual/ui/CMakeLists.txt b/tests-manual/ui/CMakeLists.txt deleted file mode 100644 index 0a5d6796e0..0000000000 --- a/tests-manual/ui/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -# This folder contains code for testing the QML UI using Qt Creator. It is not intended to be included in the CMake project From e9dc3c650b57e1610e95b4e7d72b2c022c5e7cbb Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 8 May 2018 15:31:17 -0700 Subject: [PATCH 81/92] Breakup building and testing --- cmake/macros/SetupHifiTestCase.cmake | 5 ++--- tests/CMakeLists.txt | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/cmake/macros/SetupHifiTestCase.cmake b/cmake/macros/SetupHifiTestCase.cmake index 6c7d38e19c..b0edb41e36 100644 --- a/cmake/macros/SetupHifiTestCase.cmake +++ b/cmake/macros/SetupHifiTestCase.cmake @@ -124,15 +124,14 @@ macro(SETUP_HIFI_TESTCASE) # This target will also build + run the other test targets using ctest when built. add_custom_target(${TEST_TARGET} - COMMAND ctest . SOURCES ${TEST_PROJ_SRC_FILES} # display source files under the testcase target DEPENDS ${${TEST_PROJ_NAME}_TARGETS}) + set_target_properties(${TEST_TARGET} PROPERTIES + FOLDER "Tests" EXCLUDE_FROM_DEFAULT_BUILD TRUE EXCLUDE_FROM_ALL TRUE) - set_target_properties(${TEST_TARGET} PROPERTIES FOLDER "Tests") - list (APPEND ALL_TEST_TARGETS ${TEST_TARGET}) set(ALL_TEST_TARGETS "${ALL_TEST_TARGETS}" PARENT_SCOPE) else () diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a8b0727e3d..bc11580979 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -27,9 +27,9 @@ set_target_properties("test-extensions" PROPERTIES FOLDER "Tests") # set (ALL_TEST_TARGETS "${ALL_TEST_TARGETS}" PARENT_SCOPE) # copies this back to parent scope # add_custom_target("all-tests" - COMMAND ctest . DEPENDS "${ALL_TEST_TARGETS}") -set_target_properties("all-tests" PROPERTIES FOLDER "hidden/test-targets") + set_target_properties("all-tests" PROPERTIES + FOLDER "hidden/test-targets" EXCLUDE_FROM_DEFAULT_BUILD TRUE EXCLUDE_FROM_ALL TRUE) From 12ae44c14f4424503ab5562a2b0706431173cc68 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 8 May 2018 15:34:51 -0700 Subject: [PATCH 82/92] Remove debugging pragma --- tests-manual/gpu-textures/src/TestTextures.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests-manual/gpu-textures/src/TestTextures.cpp b/tests-manual/gpu-textures/src/TestTextures.cpp index 57cf1bccbf..7aedb506da 100644 --- a/tests-manual/gpu-textures/src/TestTextures.cpp +++ b/tests-manual/gpu-textures/src/TestTextures.cpp @@ -19,8 +19,6 @@ #include "TestHelpers.h" -#pragma optimize("", off) - std::string vertexShaderSource = R"SHADER( #line 14 layout(location = 0) out vec2 outTexCoord0; @@ -165,4 +163,4 @@ void TexturesTest::onPrevTexture() { void TexturesTest::onMaxTextureMemory(int maxTextureMemory) { gpu::Texture::setAllowedGPUMemoryUsage(MB_TO_BYTES(maxTextureMemory)); -} \ No newline at end of file +} From 1d403b4d6781b5c728d29fb46d8634c10f714d0f Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 8 May 2018 19:41:07 -0700 Subject: [PATCH 83/92] Add texture transfer testing --- libraries/gl/src/gl/OffscreenGLCanvas.cpp | 15 +- tests/gpu/CMakeLists.txt | 9 + tests/gpu/src/TextureTest.cpp | 208 ++++++++++++++++++++++ tests/gpu/src/TextureTest.h | 37 ++++ 4 files changed, 263 insertions(+), 6 deletions(-) create mode 100644 tests/gpu/CMakeLists.txt create mode 100644 tests/gpu/src/TextureTest.cpp create mode 100644 tests/gpu/src/TextureTest.h diff --git a/libraries/gl/src/gl/OffscreenGLCanvas.cpp b/libraries/gl/src/gl/OffscreenGLCanvas.cpp index 91f7954943..6598a26c99 100644 --- a/libraries/gl/src/gl/OffscreenGLCanvas.cpp +++ b/libraries/gl/src/gl/OffscreenGLCanvas.cpp @@ -103,12 +103,15 @@ void OffscreenGLCanvas::onMessageLogged(const QOpenGLDebugMessage& debugMessage) bool OffscreenGLCanvas::makeCurrent() { bool result = _context->makeCurrent(_offscreenSurface); - std::call_once(_reportOnce, []{ - qCDebug(glLogging) << "GL Version: " << QString((const char*) glGetString(GL_VERSION)); - qCDebug(glLogging) << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION)); - qCDebug(glLogging) << "GL Vendor: " << QString((const char*) glGetString(GL_VENDOR)); - qCDebug(glLogging) << "GL Renderer: " << QString((const char*) glGetString(GL_RENDERER)); - }); + if (glGetString) { + std::call_once(_reportOnce, [] { + qCDebug(glLogging) << "GL Version: " << QString((const char*)glGetString(GL_VERSION)); + qCDebug(glLogging) << "GL Shader Language Version: " + << QString((const char*)glGetString(GL_SHADING_LANGUAGE_VERSION)); + qCDebug(glLogging) << "GL Vendor: " << QString((const char*)glGetString(GL_VENDOR)); + qCDebug(glLogging) << "GL Renderer: " << QString((const char*)glGetString(GL_RENDERER)); + }); + } return result; } diff --git a/tests/gpu/CMakeLists.txt b/tests/gpu/CMakeLists.txt new file mode 100644 index 0000000000..6974953b40 --- /dev/null +++ b/tests/gpu/CMakeLists.txt @@ -0,0 +1,9 @@ +# Declare dependencies +macro (setup_testcase_dependencies) + # link in the shared libraries + link_hifi_libraries(shared ktx gpu gl ${PLATFORM_GL_BACKEND}) + package_libraries_for_deployment() + target_opengl() +endmacro () + +setup_hifi_testcase() diff --git a/tests/gpu/src/TextureTest.cpp b/tests/gpu/src/TextureTest.cpp new file mode 100644 index 0000000000..9377a18244 --- /dev/null +++ b/tests/gpu/src/TextureTest.cpp @@ -0,0 +1,208 @@ +// +// Created by Bradley Austin Davis on 2018/01/11 +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "TextureTest.h" + +#include +#include +#include +#include +#include + +QTEST_MAIN(TextureTest) +#pragma optimize("", off) +#define LOAD_TEXTURE_COUNT 40 +static const QDir TEST_DIR("D:/ktx_texture_test"); + +std::string vertexShaderSource = R"SHADER( +#line 14 +layout(location = 0) out vec2 outTexCoord0; + +const vec4 VERTICES[] = vec4[]( + vec4(-1.0, -1.0, 0.0, 1.0), + vec4( 1.0, -1.0, 0.0, 1.0), + vec4(-1.0, 1.0, 0.0, 1.0), + vec4( 1.0, 1.0, 0.0, 1.0) +); + +void main() { + outTexCoord0 = VERTICES[gl_VertexID].xy; + outTexCoord0 += 1.0; + outTexCoord0 /= 2.0; + gl_Position = VERTICES[gl_VertexID]; +} +)SHADER"; + +std::string fragmentShaderSource = R"SHADER( +#line 28 + +uniform sampler2D tex; + +layout(location = 0) in vec2 inTexCoord0; +layout(location = 0) out vec4 outFragColor; + +void main() { + outFragColor = texture(tex, inTexCoord0); + outFragColor.a = 1.0; + //outFragColor.rb = inTexCoord0; +} + +)SHADER"; + +void TextureTest::initTestCase() { + getDefaultOpenGLSurfaceFormat(); + _canvas.create(); + if (!_canvas.makeCurrent()) { + qFatal("Unable to make test GL context current"); + } + gl::initModuleGl(); + gpu::Context::init(); + _gpuContext = std::make_shared(); + gpu::Texture::setAllowedGPUMemoryUsage(MB_TO_BYTES(4096)); + + _canvas.makeCurrent(); + { + auto VS = gpu::Shader::createVertex(vertexShaderSource); + auto PS = gpu::Shader::createPixel(fragmentShaderSource); + auto program = gpu::Shader::createProgram(VS, PS); + gpu::Shader::BindingSet slotBindings; + gpu::Shader::makeProgram(*program, slotBindings); + // If the pipeline did not exist, make it + auto state = std::make_shared(); + state->setCullMode(gpu::State::CULL_NONE); + state->setDepthTest({}); + state->setBlendFunction({ false }); + _pipeline = gpu::Pipeline::create(program, state); + } + + { _framebuffer.reset(gpu::Framebuffer::create("cached", gpu::Element::COLOR_SRGBA_32, _size.x, _size.y)); } + + { + auto entryList = TEST_DIR.entryList({ "*.ktx" }, QDir::Filter::Files); + _textureFiles.reserve(entryList.size()); + for (auto entry : entryList) { + auto textureFile = TEST_DIR.absoluteFilePath(entry).toStdString(); + _textureFiles.push_back(textureFile); + } + } + + { + std::shuffle(_textureFiles.begin(), _textureFiles.end(), std::default_random_engine()); + size_t newTextureCount = std::min(_textureFiles.size(), LOAD_TEXTURE_COUNT); + for (size_t i = 0; i < newTextureCount; ++i) { + const auto& textureFile = _textureFiles[i]; + auto texture = gpu::Texture::unserialize(textureFile); + _textures.push_back(texture); + } + } +} + +void TextureTest::cleanupTestCase() { + _gpuContext.reset(); +} + +void TextureTest::beginFrame() { + _gpuContext->recycle(); + _gpuContext->beginFrame(); + gpu::doInBatch("TestWindow::beginFrame", _gpuContext, [&](gpu::Batch& batch) { + batch.setFramebuffer(_framebuffer); + batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLORS, { 0.0f, 0.1f, 0.2f, 1.0f }); + batch.clearDepthFramebuffer(1e4); + batch.setViewportTransform({ 0, 0, _size.x, _size.y }); + }); +} + +void TextureTest::endFrame() { + gpu::doInBatch("TestWindow::endFrame::finish", _gpuContext, [&](gpu::Batch& batch) { batch.resetStages(); }); + auto framePointer = _gpuContext->endFrame(); + _gpuContext->consumeFrameUpdates(framePointer); + _gpuContext->executeFrame(framePointer); + // Simulate swapbuffers with a finish + glFinish(); + QThread::msleep(10); +} + +void TextureTest::renderFrame(const std::function& renderLambda) { + beginFrame(); + gpu::doInBatch("Test::body", _gpuContext, renderLambda); + endFrame(); +} + + +inline bool afterUsecs(uint64_t& startUsecs, uint64_t maxIntervalUecs) { + auto now = usecTimestampNow(); + auto interval = now - startUsecs; + if (interval > maxIntervalUecs) { + startUsecs = now; + return true; + } + return false; +} + +inline bool afterSecs(uint64_t& startUsecs, uint64_t maxIntervalSecs) { + return afterUsecs(startUsecs, maxIntervalSecs * USECS_PER_SECOND); +} + +template +void reportEvery(uint64_t& lastReportUsecs, uint64_t secs, F lamdba) { + if (afterSecs(lastReportUsecs, secs)) { + lamdba(); + } +} + +inline void failAfter(uint64_t startUsecs, uint64_t secs, const char* message) { + if (afterSecs(startUsecs, secs)) { + qFatal(message); + } +} + +void TextureTest::testTextureLoading() { + auto renderTexturesLamdba = [this](gpu::Batch& batch) { + batch.setPipeline(_pipeline); + for (const auto& texture : _textures) { + batch.setResourceTexture(0, texture); + batch.draw(gpu::TRIANGLE_STRIP, 4, 0); + } + }; + + size_t totalSize = 0; + for (const auto& texture : _textures) { + totalSize += texture->evalTotalSize(); + } + + auto reportLambda = [=] { + qDebug() << "Expected" << totalSize; + qDebug() << "Allowed " << gpu::Texture::getAllowedGPUMemoryUsage(); + qDebug() << "Allocated " << gpu::Context::getTextureResourceGPUMemSize(); + qDebug() << "Populated " << gpu::Context::getTextureResourcePopulatedGPUMemSize(); + qDebug() << "Pending " << gpu::Context::getTexturePendingGPUTransferMemSize(); + }; + + auto lastReport = usecTimestampNow(); + auto start = usecTimestampNow(); + while (totalSize != gpu::Context::getTextureResourceGPUMemSize()) { + reportEvery(lastReport, 4, reportLambda); + failAfter(start, 10, "Failed to allocate texture memory after 10 seconds"); + renderFrame(renderTexturesLamdba); + } + + // Restart the timer + start = usecTimestampNow(); + auto allocatedMemory = gpu::Context::getTextureResourceGPUMemSize(); + auto populatedMemory = gpu::Context::getTextureResourcePopulatedGPUMemSize(); + while (allocatedMemory != populatedMemory && 0 != gpu::Context::getTexturePendingGPUTransferMemSize()) { + reportEvery(lastReport, 4, reportLambda); + failAfter(start, 10, "Failed to populate texture memory after 10 seconds"); + renderFrame(); + allocatedMemory = gpu::Context::getTextureResourceGPUMemSize(); + populatedMemory = gpu::Context::getTextureResourcePopulatedGPUMemSize(); + } + QCOMPARE(allocatedMemory, totalSize); + QCOMPARE(populatedMemory, totalSize); +} + diff --git a/tests/gpu/src/TextureTest.h b/tests/gpu/src/TextureTest.h new file mode 100644 index 0000000000..f3753f5e9b --- /dev/null +++ b/tests/gpu/src/TextureTest.h @@ -0,0 +1,37 @@ +// +// Created by Bradley Austin Davis on 2018/05/08 +// Copyright 2013-2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#pragma once + +#include +#include +#include + +class TextureTest : public QObject { + Q_OBJECT + +private: + void beginFrame(); + void endFrame(); + void renderFrame(const std::function& = [](gpu::Batch&){}); + +private slots: + void initTestCase(); + void cleanupTestCase(); + void testTextureLoading(); + +private: + OffscreenGLCanvas _canvas; + gpu::ContextPointer _gpuContext; + gpu::PipelinePointer _pipeline; + gpu::FramebufferPointer _framebuffer; + gpu::TexturePointer _colorBuffer, _depthBuffer; + const glm::uvec2 _size{ 640, 480 }; + std::vector _textureFiles; + std::vector _textures; +}; From 7fbad47351f472c65030a59c128069eef8cf06a0 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 9 May 2018 09:52:00 -0700 Subject: [PATCH 84/92] Working on texture test --- libraries/test-utils/CMakeLists.txt | 3 + .../src/test-utils/FileDownloader.cpp | 21 +++ .../src/test-utils/FileDownloader.h | 23 +++ tests/QTestExtensions.h | 43 ++++- tests/gpu/CMakeLists.txt | 10 +- tests/gpu/src/TextureTest.cpp | 157 +++++++++++++----- tests/gpu/src/TextureTest.h | 6 +- 7 files changed, 214 insertions(+), 49 deletions(-) create mode 100644 libraries/test-utils/CMakeLists.txt create mode 100644 libraries/test-utils/src/test-utils/FileDownloader.cpp create mode 100644 libraries/test-utils/src/test-utils/FileDownloader.h diff --git a/libraries/test-utils/CMakeLists.txt b/libraries/test-utils/CMakeLists.txt new file mode 100644 index 0000000000..2c23e96c1e --- /dev/null +++ b/libraries/test-utils/CMakeLists.txt @@ -0,0 +1,3 @@ +set(TARGET_NAME test-utils) +setup_hifi_library(Network Gui) + diff --git a/libraries/test-utils/src/test-utils/FileDownloader.cpp b/libraries/test-utils/src/test-utils/FileDownloader.cpp new file mode 100644 index 0000000000..09049e3e0c --- /dev/null +++ b/libraries/test-utils/src/test-utils/FileDownloader.cpp @@ -0,0 +1,21 @@ +#include "FileDownloader.h" + +#include +#include + +FileDownloader::FileDownloader(QUrl url, const Handler& handler, QObject* parent) : QObject(parent), _handler(handler) { + connect(&_accessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(fileDownloaded(QNetworkReply*))); + _accessManager.get(QNetworkRequest(url)); +} + +void FileDownloader::waitForDownload() { + while (!_complete) { + QCoreApplication::processEvents(); + } +} + +void FileDownloader::fileDownloaded(QNetworkReply* pReply) { + _handler(pReply->readAll()); + pReply->deleteLater(); + _complete = true; +} diff --git a/libraries/test-utils/src/test-utils/FileDownloader.h b/libraries/test-utils/src/test-utils/FileDownloader.h new file mode 100644 index 0000000000..5a618fcf45 --- /dev/null +++ b/libraries/test-utils/src/test-utils/FileDownloader.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +class FileDownloader : public QObject { + Q_OBJECT + +public: + using Handler = std::function; + + FileDownloader(QUrl url, const Handler& handler, QObject* parent = 0); + + void waitForDownload(); + +private slots: + void fileDownloaded(QNetworkReply* pReply); + +private: + QNetworkAccessManager _accessManager; + Handler _handler; + bool _complete { false }; +}; diff --git a/tests/QTestExtensions.h b/tests/QTestExtensions.h index b7b9795a9a..c43ef3f73e 100644 --- a/tests/QTestExtensions.h +++ b/tests/QTestExtensions.h @@ -13,8 +13,9 @@ #define hifi_QTestExtensions_hpp #include +#include #include - +#include #include "GLMTestUtils.h" // Implements several extensions to QtTest. @@ -302,3 +303,43 @@ inline auto errorTest (float actual, float expected, float acceptableRelativeErr QCOMPARE_WITH_LAMBDA(actual, expected, errorTest(actual, expected, relativeError)) + +inline QString getTestResource(const QString& relativePath) { + static QDir dir; + static std::once_flag once; + std::call_once(once, []{ + QFileInfo fileInfo(__FILE__); + auto parentDir = fileInfo.absoluteDir(); + auto rootDir = parentDir.absoluteFilePath(".."); + dir = QDir::cleanPath(rootDir); + }); + + return QDir::cleanPath(dir.absoluteFilePath(relativePath)); +} + +inline bool afterUsecs(uint64_t& startUsecs, uint64_t maxIntervalUecs) { + auto now = usecTimestampNow(); + auto interval = now - startUsecs; + if (interval > maxIntervalUecs) { + startUsecs = now; + return true; + } + return false; +} + +inline bool afterSecs(uint64_t& startUsecs, uint64_t maxIntervalSecs) { + return afterUsecs(startUsecs, maxIntervalSecs * USECS_PER_SECOND); +} + +template +void reportEvery(uint64_t& lastReportUsecs, uint64_t secs, F lamdba) { + if (afterSecs(lastReportUsecs, secs)) { + lamdba(); + } +} + +inline void failAfter(uint64_t startUsecs, uint64_t secs, const char* message) { + if (afterSecs(startUsecs, secs)) { + QFAIL(message); + } +} diff --git a/tests/gpu/CMakeLists.txt b/tests/gpu/CMakeLists.txt index 6974953b40..ad0eac5822 100644 --- a/tests/gpu/CMakeLists.txt +++ b/tests/gpu/CMakeLists.txt @@ -1,9 +1,17 @@ # Declare dependencies macro (setup_testcase_dependencies) # link in the shared libraries - link_hifi_libraries(shared ktx gpu gl ${PLATFORM_GL_BACKEND}) + link_hifi_libraries(shared test-utils ktx gpu gl ${PLATFORM_GL_BACKEND}) package_libraries_for_deployment() target_opengl() + target_zlib() + find_package(QuaZip REQUIRED) + target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${QUAZIP_INCLUDE_DIRS}) + target_link_libraries(${TARGET_NAME} ${QUAZIP_LIBRARIES}) + if (WIN32) + add_paths_to_fixup_libs(${QUAZIP_DLL_PATH}) + add_dependency_external_projects(wasapi) + endif () endmacro () setup_hifi_testcase() diff --git a/tests/gpu/src/TextureTest.cpp b/tests/gpu/src/TextureTest.cpp index 9377a18244..f896914579 100644 --- a/tests/gpu/src/TextureTest.cpp +++ b/tests/gpu/src/TextureTest.cpp @@ -8,16 +8,27 @@ #include "TextureTest.h" +#include + #include #include #include #include #include +#include + +#include +#include + +#include "../../QTestExtensions.h" + +#pragma optimize("", off) QTEST_MAIN(TextureTest) -#pragma optimize("", off) + #define LOAD_TEXTURE_COUNT 40 -static const QDir TEST_DIR("D:/ktx_texture_test"); + +static const QString TEST_DATA("https://hifi-public.s3.amazonaws.com/austin/test_data/test_ktx.zip"); std::string vertexShaderSource = R"SHADER( #line 14 @@ -54,7 +65,10 @@ void main() { )SHADER"; +#define USE_SERVER_DATA 1 + void TextureTest::initTestCase() { + _resourcesPath = getTestResource("interface/resources"); getDefaultOpenGLSurfaceFormat(); _canvas.create(); if (!_canvas.makeCurrent()) { @@ -63,7 +77,32 @@ void TextureTest::initTestCase() { gl::initModuleGl(); gpu::Context::init(); _gpuContext = std::make_shared(); - gpu::Texture::setAllowedGPUMemoryUsage(MB_TO_BYTES(4096)); +#if USE_SERVER_DATA + if (!_testDataDir.isValid()) { + qFatal("Unable to create temp directory"); + } + + QString path = _testDataDir.path(); + FileDownloader(TEST_DATA, + [&](const QByteArray& data) { + QTemporaryFile zipFile; + if (zipFile.open()) { + zipFile.write(data); + zipFile.close(); + } + if (!_testDataDir.isValid()) { + qFatal("Unable to create temp dir"); + } + auto files = JlCompress::extractDir(zipFile.fileName(), _testDataDir.path()); + for (const auto& file : files) { + qDebug() << file; + } + }) + .waitForDownload(); + _resourcesPath = _testDataDir.path(); +#else + _resourcesPath = "D:/test_ktx"; +#endif _canvas.makeCurrent(); { @@ -80,19 +119,21 @@ void TextureTest::initTestCase() { _pipeline = gpu::Pipeline::create(program, state); } - { _framebuffer.reset(gpu::Framebuffer::create("cached", gpu::Element::COLOR_SRGBA_32, _size.x, _size.y)); } + _framebuffer.reset(gpu::Framebuffer::create("cached", gpu::Element::COLOR_SRGBA_32, _size.x, _size.y)); + // Find the test textures { - auto entryList = TEST_DIR.entryList({ "*.ktx" }, QDir::Filter::Files); + QDir resourcesDir(_resourcesPath); + auto entryList = resourcesDir.entryList({ "*.ktx" }, QDir::Filter::Files); _textureFiles.reserve(entryList.size()); for (auto entry : entryList) { - auto textureFile = TEST_DIR.absoluteFilePath(entry).toStdString(); + auto textureFile = resourcesDir.absoluteFilePath(entry).toStdString(); _textureFiles.push_back(textureFile); } } + // Load the test textures { - std::shuffle(_textureFiles.begin(), _textureFiles.end(), std::default_random_engine()); size_t newTextureCount = std::min(_textureFiles.size(), LOAD_TEXTURE_COUNT); for (size_t i = 0; i < newTextureCount; ++i) { const auto& textureFile = _textureFiles[i]; @@ -103,6 +144,9 @@ void TextureTest::initTestCase() { } void TextureTest::cleanupTestCase() { + _framebuffer.reset(); + _pipeline.reset(); + _gpuContext->recycle(); _gpuContext.reset(); } @@ -133,35 +177,8 @@ void TextureTest::renderFrame(const std::function& renderLamb endFrame(); } - -inline bool afterUsecs(uint64_t& startUsecs, uint64_t maxIntervalUecs) { - auto now = usecTimestampNow(); - auto interval = now - startUsecs; - if (interval > maxIntervalUecs) { - startUsecs = now; - return true; - } - return false; -} - -inline bool afterSecs(uint64_t& startUsecs, uint64_t maxIntervalSecs) { - return afterUsecs(startUsecs, maxIntervalSecs * USECS_PER_SECOND); -} - -template -void reportEvery(uint64_t& lastReportUsecs, uint64_t secs, F lamdba) { - if (afterSecs(lastReportUsecs, secs)) { - lamdba(); - } -} - -inline void failAfter(uint64_t startUsecs, uint64_t secs, const char* message) { - if (afterSecs(startUsecs, secs)) { - qFatal(message); - } -} - void TextureTest::testTextureLoading() { + QVERIFY(_textures.size() > 0); auto renderTexturesLamdba = [this](gpu::Batch& batch) { batch.setPipeline(_pipeline); for (const auto& texture : _textures) { @@ -170,39 +187,87 @@ void TextureTest::testTextureLoading() { } }; - size_t totalSize = 0; + size_t expectedAllocation = 0; for (const auto& texture : _textures) { - totalSize += texture->evalTotalSize(); + expectedAllocation += texture->evalTotalSize(); } + QVERIFY(_textures.size() > 0); auto reportLambda = [=] { - qDebug() << "Expected" << totalSize; - qDebug() << "Allowed " << gpu::Texture::getAllowedGPUMemoryUsage(); + qDebug() << "Allowed " << gpu::Texture::getAllowedGPUMemoryUsage(); qDebug() << "Allocated " << gpu::Context::getTextureResourceGPUMemSize(); qDebug() << "Populated " << gpu::Context::getTextureResourcePopulatedGPUMemSize(); qDebug() << "Pending " << gpu::Context::getTexturePendingGPUTransferMemSize(); }; + auto allocatedMemory = gpu::Context::getTextureResourceGPUMemSize(); + auto populatedMemory = gpu::Context::getTextureResourcePopulatedGPUMemSize(); + + // Cycle frames we're fully allocated + // We need to use the texture rendering lambda auto lastReport = usecTimestampNow(); auto start = usecTimestampNow(); - while (totalSize != gpu::Context::getTextureResourceGPUMemSize()) { + while (expectedAllocation != allocatedMemory) { reportEvery(lastReport, 4, reportLambda); failAfter(start, 10, "Failed to allocate texture memory after 10 seconds"); renderFrame(renderTexturesLamdba); + allocatedMemory = gpu::Context::getTextureResourceGPUMemSize(); + populatedMemory = gpu::Context::getTextureResourcePopulatedGPUMemSize(); } + QCOMPARE(allocatedMemory, expectedAllocation); // Restart the timer start = usecTimestampNow(); - auto allocatedMemory = gpu::Context::getTextureResourceGPUMemSize(); - auto populatedMemory = gpu::Context::getTextureResourcePopulatedGPUMemSize(); - while (allocatedMemory != populatedMemory && 0 != gpu::Context::getTexturePendingGPUTransferMemSize()) { + // Cycle frames we're fully populated + while (allocatedMemory != populatedMemory || 0 != gpu::Context::getTexturePendingGPUTransferMemSize()) { reportEvery(lastReport, 4, reportLambda); failAfter(start, 10, "Failed to populate texture memory after 10 seconds"); renderFrame(); allocatedMemory = gpu::Context::getTextureResourceGPUMemSize(); populatedMemory = gpu::Context::getTextureResourcePopulatedGPUMemSize(); } - QCOMPARE(allocatedMemory, totalSize); - QCOMPARE(populatedMemory, totalSize); -} + reportLambda(); + QCOMPARE(populatedMemory, allocatedMemory); + // FIXME workaround a race condition in the difference between populated size and the actual _populatedMip value in the texture + for (size_t i = 0; i < _textures.size(); ++i) { + renderFrame(); + } + + // Test on-demand deallocation of memory + auto maxMemory = allocatedMemory / 2; + gpu::Texture::setAllowedGPUMemoryUsage(maxMemory); + + // Restart the timer + start = usecTimestampNow(); + // Cycle frames until the allocated memory is below the max memory + while (allocatedMemory > maxMemory || allocatedMemory != populatedMemory) { + reportEvery(lastReport, 4, reportLambda); + failAfter(start, 10, "Failed to deallocate texture memory after 10 seconds"); + renderFrame(renderTexturesLamdba); + allocatedMemory = gpu::Context::getTextureResourceGPUMemSize(); + populatedMemory = gpu::Context::getTextureResourcePopulatedGPUMemSize(); + } + reportLambda(); + + // Verify that the allocation is now below the target + QVERIFY(allocatedMemory <= maxMemory); + // Verify that populated memory is the same as allocated memory + QCOMPARE(populatedMemory, allocatedMemory); + + // Restart the timer + start = usecTimestampNow(); + // Reset the max memory to automatic + gpu::Texture::setAllowedGPUMemoryUsage(0); + // Cycle frames we're fully populated + while (allocatedMemory != expectedAllocation || allocatedMemory != populatedMemory) { + reportEvery(lastReport, 4, reportLambda); + failAfter(start, 10, "Failed to populate texture memory after 10 seconds"); + renderFrame(); + allocatedMemory = gpu::Context::getTextureResourceGPUMemSize(); + populatedMemory = gpu::Context::getTextureResourcePopulatedGPUMemSize(); + } + reportLambda(); + QCOMPARE(allocatedMemory, expectedAllocation); + QCOMPARE(populatedMemory, allocatedMemory); +} diff --git a/tests/gpu/src/TextureTest.h b/tests/gpu/src/TextureTest.h index f3753f5e9b..9d3dc4ab81 100644 --- a/tests/gpu/src/TextureTest.h +++ b/tests/gpu/src/TextureTest.h @@ -9,6 +9,8 @@ #pragma once #include +#include + #include #include @@ -18,7 +20,7 @@ class TextureTest : public QObject { private: void beginFrame(); void endFrame(); - void renderFrame(const std::function& = [](gpu::Batch&){}); + void renderFrame(const std::function& = [](gpu::Batch&) {}); private slots: void initTestCase(); @@ -26,6 +28,8 @@ private slots: void testTextureLoading(); private: + QString _resourcesPath; + QTemporaryDir _testDataDir; OffscreenGLCanvas _canvas; gpu::ContextPointer _gpuContext; gpu::PipelinePointer _pipeline; From 57691d5d66cafb7cf55216f96f3b32426fee3a20 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 9 May 2018 12:36:26 -0700 Subject: [PATCH 85/92] Cache downloaded assets --- tests/gpu/src/TextureTest.cpp | 54 +++++++++++++++++------------------ tests/gpu/src/TextureTest.h | 1 - 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/tests/gpu/src/TextureTest.cpp b/tests/gpu/src/TextureTest.cpp index f896914579..65d0933302 100644 --- a/tests/gpu/src/TextureTest.cpp +++ b/tests/gpu/src/TextureTest.cpp @@ -8,6 +8,7 @@ #include "TextureTest.h" +#include #include #include @@ -22,13 +23,12 @@ #include "../../QTestExtensions.h" -#pragma optimize("", off) - QTEST_MAIN(TextureTest) #define LOAD_TEXTURE_COUNT 40 static const QString TEST_DATA("https://hifi-public.s3.amazonaws.com/austin/test_data/test_ktx.zip"); +static const QString TEST_DIR_NAME("{630b8f02-52af-4cdf-a896-24e472b94b28}"); std::string vertexShaderSource = R"SHADER( #line 14 @@ -65,9 +65,18 @@ void main() { )SHADER"; -#define USE_SERVER_DATA 1 +QtMessageHandler originalHandler; + +void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { +#if defined(Q_OS_WIN) + OutputDebugStringA(message.toStdString().c_str()); + OutputDebugStringA("\n"); +#endif + originalHandler(type, context, message); +} void TextureTest::initTestCase() { + originalHandler = qInstallMessageHandler(messageHandler); _resourcesPath = getTestResource("interface/resources"); getDefaultOpenGLSurfaceFormat(); _canvas.create(); @@ -77,32 +86,21 @@ void TextureTest::initTestCase() { gl::initModuleGl(); gpu::Context::init(); _gpuContext = std::make_shared(); -#if USE_SERVER_DATA - if (!_testDataDir.isValid()) { - qFatal("Unable to create temp directory"); - } - QString path = _testDataDir.path(); - FileDownloader(TEST_DATA, - [&](const QByteArray& data) { - QTemporaryFile zipFile; - if (zipFile.open()) { - zipFile.write(data); - zipFile.close(); - } - if (!_testDataDir.isValid()) { - qFatal("Unable to create temp dir"); - } - auto files = JlCompress::extractDir(zipFile.fileName(), _testDataDir.path()); - for (const auto& file : files) { - qDebug() << file; - } - }) - .waitForDownload(); - _resourcesPath = _testDataDir.path(); -#else - _resourcesPath = "D:/test_ktx"; -#endif + _resourcesPath = QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/" + TEST_DIR_NAME; + if (!QFileInfo(_resourcesPath).exists()) { + QDir(_resourcesPath).mkpath("."); + FileDownloader(TEST_DATA, + [&](const QByteArray& data) { + QTemporaryFile zipFile; + if (zipFile.open()) { + zipFile.write(data); + zipFile.close(); + } + JlCompress::extractDir(zipFile.fileName(), _resourcesPath); + }) + .waitForDownload(); + } _canvas.makeCurrent(); { diff --git a/tests/gpu/src/TextureTest.h b/tests/gpu/src/TextureTest.h index 9d3dc4ab81..91f8a358ea 100644 --- a/tests/gpu/src/TextureTest.h +++ b/tests/gpu/src/TextureTest.h @@ -29,7 +29,6 @@ private slots: private: QString _resourcesPath; - QTemporaryDir _testDataDir; OffscreenGLCanvas _canvas; gpu::ContextPointer _gpuContext; gpu::PipelinePointer _pipeline; From e0b57a22286207c86c31f24cfc4582c212d26139 Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Wed, 9 May 2018 18:20:19 -0300 Subject: [PATCH 86/92] Code review in radar.js --- scripts/system/+android/radar.js | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/scripts/system/+android/radar.js b/scripts/system/+android/radar.js index 67ba896207..5d93ed4db1 100644 --- a/scripts/system/+android/radar.js +++ b/scripts/system/+android/radar.js @@ -346,9 +346,9 @@ function pinchUpdate(event) { } Camera.position = { - x: Camera.position.x, - y:radarHeight, - z:Camera.position.z + x : Camera.position.x, + y : radarHeight, + z : Camera.position.z }; if (!draggingCamera) { @@ -360,7 +360,7 @@ function pinchUpdate(event) { } function isInsideSquare(coords0, coords1, halfside) { - return coords0 != undefined && coords1!= undefined && + return coords0 != undefined && coords1 != undefined && Math.abs(coords0.x - coords1.x) <= halfside && Math.abs(coords0.y - coords1.y) <= halfside; } @@ -372,7 +372,7 @@ function dragScrollUpdate(event) { // drag management var pickRay = Camera.computePickRay(event.x, event.y); var dragAt = Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction, - radarHeight-MyAvatar.position.y)); + radarHeight - MyAvatar.position.y)); if (lastDragAt === undefined || lastDragAt === null) { lastDragAt = dragAt; @@ -1082,29 +1082,20 @@ function renderAllOthersAvatarIcons() { } } -/******************************************************************************* - * Entities (to remark) cache structure for showing entities markers - ******************************************************************************/ - var ICON_ENTITY_DEFAULT_DIMENSIONS = { x : 0.10, y : 0.00001, z : 0.10 }; -var entityIconModelDimensionsVal = { - x : 0, - y : 0.00001, - z : 0 -}; + function teleportIconModelDimensions(y) { - // given the current height, give a size - // TODO: receive entity.position.y and substract to radarHeight + var teleportModelDimensions = ICON_ENTITY_DEFAULT_DIMENSIONS; var xz = -0.002831 * (radarHeight - y) + 0.1; - entityIconModelDimensionsVal.x = xz; - entityIconModelDimensionsVal.z = xz; + teleportModelDimensions.x = xz; + teleportModelDimensions.z = xz; // reuse object - return entityIconModelDimensionsVal; + return teleportModelDimensions; } /******************************************************************************* From 9b6225db40bfa1f69707e2a1507a007f2eed9b4f Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Wed, 9 May 2018 14:29:10 -0700 Subject: [PATCH 87/92] Bump default packet version 20 -> 21 --- libraries/networking/src/udt/PacketHeaders.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 98b0e1d892..e7a793d267 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -91,7 +91,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::Ping: return static_cast(PingVersion::IncludeConnectionID); default: - return 20; + return 21; } } From cb336bdeab4b0400af37fdf62073566f8106bd35 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 10 May 2018 10:55:50 -0700 Subject: [PATCH 88/92] Fix linux build problems --- tests/QTestExtensions.h | 8 ++++---- tests/gpu/src/TextureTest.cpp | 21 +++++++++++++++++---- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/tests/QTestExtensions.h b/tests/QTestExtensions.h index c43ef3f73e..ac037d831b 100644 --- a/tests/QTestExtensions.h +++ b/tests/QTestExtensions.h @@ -317,7 +317,7 @@ inline QString getTestResource(const QString& relativePath) { return QDir::cleanPath(dir.absoluteFilePath(relativePath)); } -inline bool afterUsecs(uint64_t& startUsecs, uint64_t maxIntervalUecs) { +inline bool afterUsecs(quint64& startUsecs, quint64 maxIntervalUecs) { auto now = usecTimestampNow(); auto interval = now - startUsecs; if (interval > maxIntervalUecs) { @@ -327,18 +327,18 @@ inline bool afterUsecs(uint64_t& startUsecs, uint64_t maxIntervalUecs) { return false; } -inline bool afterSecs(uint64_t& startUsecs, uint64_t maxIntervalSecs) { +inline bool afterSecs(quint64& startUsecs, quint64 maxIntervalSecs) { return afterUsecs(startUsecs, maxIntervalSecs * USECS_PER_SECOND); } template -void reportEvery(uint64_t& lastReportUsecs, uint64_t secs, F lamdba) { +void doEvery(quint64& lastReportUsecs, quint64 secs, F lamdba) { if (afterSecs(lastReportUsecs, secs)) { lamdba(); } } -inline void failAfter(uint64_t startUsecs, uint64_t secs, const char* message) { +inline void failAfter(quint64 startUsecs, quint64 secs, const char* message) { if (afterSecs(startUsecs, secs)) { QFAIL(message); } diff --git a/tests/gpu/src/TextureTest.cpp b/tests/gpu/src/TextureTest.cpp index 65d0933302..18361af791 100644 --- a/tests/gpu/src/TextureTest.cpp +++ b/tests/gpu/src/TextureTest.cpp @@ -206,7 +206,7 @@ void TextureTest::testTextureLoading() { auto lastReport = usecTimestampNow(); auto start = usecTimestampNow(); while (expectedAllocation != allocatedMemory) { - reportEvery(lastReport, 4, reportLambda); + doEvery(lastReport, 4, reportLambda); failAfter(start, 10, "Failed to allocate texture memory after 10 seconds"); renderFrame(renderTexturesLamdba); allocatedMemory = gpu::Context::getTextureResourceGPUMemSize(); @@ -218,7 +218,7 @@ void TextureTest::testTextureLoading() { start = usecTimestampNow(); // Cycle frames we're fully populated while (allocatedMemory != populatedMemory || 0 != gpu::Context::getTexturePendingGPUTransferMemSize()) { - reportEvery(lastReport, 4, reportLambda); + doEvery(lastReport, 4, reportLambda); failAfter(start, 10, "Failed to populate texture memory after 10 seconds"); renderFrame(); allocatedMemory = gpu::Context::getTextureResourceGPUMemSize(); @@ -240,7 +240,7 @@ void TextureTest::testTextureLoading() { start = usecTimestampNow(); // Cycle frames until the allocated memory is below the max memory while (allocatedMemory > maxMemory || allocatedMemory != populatedMemory) { - reportEvery(lastReport, 4, reportLambda); + doEvery(lastReport, 4, reportLambda); failAfter(start, 10, "Failed to deallocate texture memory after 10 seconds"); renderFrame(renderTexturesLamdba); allocatedMemory = gpu::Context::getTextureResourceGPUMemSize(); @@ -259,7 +259,7 @@ void TextureTest::testTextureLoading() { gpu::Texture::setAllowedGPUMemoryUsage(0); // Cycle frames we're fully populated while (allocatedMemory != expectedAllocation || allocatedMemory != populatedMemory) { - reportEvery(lastReport, 4, reportLambda); + doEvery(lastReport, 4, reportLambda); failAfter(start, 10, "Failed to populate texture memory after 10 seconds"); renderFrame(); allocatedMemory = gpu::Context::getTextureResourceGPUMemSize(); @@ -268,4 +268,17 @@ void TextureTest::testTextureLoading() { reportLambda(); QCOMPARE(allocatedMemory, expectedAllocation); QCOMPARE(populatedMemory, allocatedMemory); + + _textures.clear(); + // Cycle frames we're fully populated + while (allocatedMemory != 0) { + failAfter(start, 10, "Failed to clear texture memory after 10 seconds"); + renderFrame(); + allocatedMemory = gpu::Context::getTextureResourceGPUMemSize(); + populatedMemory = gpu::Context::getTextureResourcePopulatedGPUMemSize(); + } + QCOMPARE(allocatedMemory, 0); + QCOMPARE(populatedMemory, 0); + qDebug() << "Done"; + } From a061e84ad7028d59dc7a8db72c070df6a9fba999 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Thu, 10 May 2018 19:40:02 +0100 Subject: [PATCH 89/92] remove unused commented code --- .../qml/dialogs/assetDialog/AssetDialogContent.qml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/interface/resources/qml/dialogs/assetDialog/AssetDialogContent.qml b/interface/resources/qml/dialogs/assetDialog/AssetDialogContent.qml index ed442aa191..914fe139ab 100644 --- a/interface/resources/qml/dialogs/assetDialog/AssetDialogContent.qml +++ b/interface/resources/qml/dialogs/assetDialog/AssetDialogContent.qml @@ -20,14 +20,8 @@ Item { // Set from OffscreenUi::assetDialog() property alias dir: assetTableModel.folder property alias filter: selectionType.filtersString - property int options // Not used. property bool selectDirectory: false - - // Not implemented. - // property bool saveDialog: false; - // property bool multiSelect: false; - property bool singleClickNavigate: false HifiConstants { id: hifi } @@ -84,7 +78,6 @@ Item { size: 28 width: height enabled: destination !== "" - // onClicked: d.navigateHome(); onClicked: assetTableModel.folder = destination; } } From 32d10641dc44861e9c22b3505cc579ce02648845 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 10 May 2018 14:41:35 -0700 Subject: [PATCH 90/92] don't enable so much logging when 'verbose logging' is turned on --- interface/src/Application.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 20efe73f08..6810621093 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2253,8 +2253,12 @@ void Application::updateVerboseLogging() { } bool enable = menu->isOptionChecked(MenuOption::VerboseLogging); - QString rules = "*.debug=%1\n" - "*.info=%1"; + QString rules = + "hifi.*.debug=%1\n" + "hifi.*.info=%1\n" + "hifi.audio-stream.warning=false\n" + "hifi.audio-stream.debug=false\n" + "hifi.audio-stream.info=false"; rules = rules.arg(enable ? "true" : "false"); QLoggingCategory::setFilterRules(rules); } From 826c427e2a0d12bfd2e72dc166a7e66b6db33c61 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 10 May 2018 15:42:59 -0700 Subject: [PATCH 91/92] trying to sort-out audio-stream logging --- interface/src/Application.cpp | 1 - libraries/audio/src/AudioLogging.cpp | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6810621093..ff8b545c57 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2256,7 +2256,6 @@ void Application::updateVerboseLogging() { QString rules = "hifi.*.debug=%1\n" "hifi.*.info=%1\n" - "hifi.audio-stream.warning=false\n" "hifi.audio-stream.debug=false\n" "hifi.audio-stream.info=false"; rules = rules.arg(enable ? "true" : "false"); diff --git a/libraries/audio/src/AudioLogging.cpp b/libraries/audio/src/AudioLogging.cpp index 8a668a4bcb..73091885cb 100644 --- a/libraries/audio/src/AudioLogging.cpp +++ b/libraries/audio/src/AudioLogging.cpp @@ -12,5 +12,4 @@ #include "AudioLogging.h" Q_LOGGING_CATEGORY(audio, "hifi.audio") -Q_LOGGING_CATEGORY(audiostream, "hifi.audio-stream", QtWarningMsg) - +Q_LOGGING_CATEGORY(audiostream, "hifi.audio-stream") From 4eba727849e4294625e31bdec2a8312b2c1445fd Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 11 May 2018 10:47:41 -0700 Subject: [PATCH 92/92] fix qml crash on start up --- .../resources/qml/dialogs/assetDialog/AssetDialogContent.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/resources/qml/dialogs/assetDialog/AssetDialogContent.qml b/interface/resources/qml/dialogs/assetDialog/AssetDialogContent.qml index 31e013638e..c3e842bc2f 100644 --- a/interface/resources/qml/dialogs/assetDialog/AssetDialogContent.qml +++ b/interface/resources/qml/dialogs/assetDialog/AssetDialogContent.qml @@ -21,6 +21,7 @@ Item { // Set from OffscreenUi::assetDialog() property alias dir: assetTableModel.folder property alias filter: selectionType.filtersString + property int options property bool selectDirectory: false property bool singleClickNavigate: false