From da4f2b8c2f1810528cac4001aa9f97b3a2c30326 Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Fri, 30 Mar 2018 15:34:00 -0300 Subject: [PATCH 01/46] Fix zoom in unresponsive in radar mode --- scripts/system/+android/radar.js | 47 +++++++++++++++++--------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/scripts/system/+android/radar.js b/scripts/system/+android/radar.js index 455299dd5f..2b87f8955d 100644 --- a/scripts/system/+android/radar.js +++ b/scripts/system/+android/radar.js @@ -21,7 +21,7 @@ function printd(str) { } var radar = false; -var radarHeight = 10; // camera position meters above the avatar +var radarHeight = MyAvatar.position.y + 10; // camera position (absolute y) var tablet; var RADAR_CAMERA_OFFSET = -1; // 1 meter below the avatar @@ -46,11 +46,11 @@ var uniqueColor; function moveTo(position) { if (radar) { MyAvatar.position = position; - Camera.position = Vec3.sum(MyAvatar.position, { - x : 0, + Camera.position = { + x : MyAvatar.position.x, y : radarHeight, - z : 0 - }); + z : MyAvatar.position.z + }; } } @@ -386,12 +386,12 @@ function pinchUpdate(event) { radarHeight -= pinchIncrement; } } - var deltaHeight = avatarY + radarHeight - Camera.position.y; - Camera.position = Vec3.sum(Camera.position, { - x : 0, - y : deltaHeight, - z : 0 - }); + Camera.position = { + x: Camera.position.x, + y:radarHeight, + z:Camera.position.z + }; + if (!draggingCamera) { startedDraggingCamera = true; draggingCamera = true; @@ -401,7 +401,8 @@ function pinchUpdate(event) { } function isInsideSquare(coords0, coords1, halfside) { - return Math.abs(coords0.x - coords1.x) <= halfside + return coords0 != undefined && coords1!= undefined && + Math.abs(coords0.x - coords1.x) <= halfside && Math.abs(coords0.y - coords1.y) <= halfside; } @@ -412,7 +413,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)); + radarHeight-MyAvatar.position.y)); if (lastDragAt === undefined || lastDragAt === null) { lastDragAt = dragAt; @@ -722,7 +723,7 @@ function Teleporter() { return { dragTeleportBegin : function(event) { printd("[newTeleport] TELEPORT began"); - var overlayDimensions = entityIconModelDimensions(); + var overlayDimensions = entityIconModelDimensions(MyAvatar.position.y); // var destination = computeDestination(event, MyAvatar.position, // Camera.position, radarHeight); // Dimension teleport and cancel overlays (not show them yet) @@ -843,7 +844,7 @@ var avatarIconDimensionsVal = { }; function avatarIconPlaneDimensions() { // given the current height, give a size - var xy = -0.003531 * radarHeight + 0.1; + var xy = -0.003531 * (radarHeight - MyAvatar.position.y) + 0.1; avatarIconDimensionsVal.x = Math.abs(xy); avatarIconDimensionsVal.y = Math.abs(xy); // reuse object @@ -1165,9 +1166,10 @@ var entityIconModelDimensionsVal = { y : 0.00001, z : 0 }; -function entityIconModelDimensions() { +function entityIconModelDimensions(y) { // given the current height, give a size - var xz = -0.002831 * radarHeight + 0.1; + // TODO: receive entity.position.y and substract to radarHeight + var xz = -0.002831 * (radarHeight - y) + 0.1; entityIconModelDimensionsVal.x = xz; entityIconModelDimensionsVal.z = xz; // reuse object @@ -1177,8 +1179,8 @@ function entityIconModelDimensions() { * entityIconPlaneDimensions: similar to entityIconModelDimensions but using xy * plane */ -function entityIconPlaneDimensions() { - var dim = entityIconModelDimensions(); +function entityIconPlaneDimensions(y) { + var dim = entityIconModelDimensions(y); var z = dim.z; dim.z = dim.y; dim.y = z; @@ -1255,15 +1257,15 @@ function hideAllEntitiesIcons() { function renderAllEntitiesIcons() { var entityPos; var entityProps; - var iconDimensions = entityIconModelDimensions(); - var planeDimensions = entityIconPlaneDimensions(); // plane overlays uses - // xy instead of xz + for ( var QUuid in entitiesData) { if (entitiesData.hasOwnProperty(QUuid)) { entityProps = Entities.getEntityProperties(QUuid, [ "position", "visible" ]); if (entityProps != null) { entityPos = entityProps.position; + var planeDimensions = entityIconPlaneDimensions(entityPos.y); // plane overlays uses + // xy instead of xz if (entitiesData[QUuid].icon != undefined && entityPos) { var iconPos = findLineToHeightIntersectionCoords( entityPos.x, @@ -1276,6 +1278,7 @@ function renderAllEntitiesIcons() { printd("entity icon pos bad for " + QUuid); continue; } + var iconDimensions = entityIconModelDimensions(entityPos.y); var dimensions = entitiesData[QUuid].planar ? planeDimensions : iconDimensions; Overlays.editOverlay(entitiesData[QUuid].icon, { From 36bc5f841627e170cb0d15c35586106d5c176eb5 Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Thu, 5 Apr 2018 15:35:08 -0300 Subject: [PATCH 02/46] Fix the view snap when user starts zooming --- scripts/system/+android/radar.js | 37 ++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/scripts/system/+android/radar.js b/scripts/system/+android/radar.js index 2b87f8955d..120bec33c3 100644 --- a/scripts/system/+android/radar.js +++ b/scripts/system/+android/radar.js @@ -21,7 +21,8 @@ function printd(str) { } var radar = false; -var radarHeight = MyAvatar.position.y + 10; // camera position (absolute y) +var RADAR_HEIGHT_INIT_DELTA = 10; +var radarHeight = MyAvatar.position.y + RADAR_HEIGHT_INIT_DELTA; // camera position (absolute y) var tablet; var RADAR_CAMERA_OFFSET = -1; // 1 meter below the avatar @@ -386,6 +387,7 @@ function pinchUpdate(event) { radarHeight -= pinchIncrement; } } + Camera.position = { x: Camera.position.x, y:radarHeight, @@ -655,6 +657,7 @@ function Teleporter() { return; } + Camera.position = Vec3.sum(Camera.position, { x : xDelta, y : 0, @@ -1301,11 +1304,12 @@ function startRadar() { saveAllOthersAvatarsData(); Camera.mode = "independent"; - Camera.position = Vec3.sum(MyAvatar.position, { - x : 0, - y : radarHeight, - z : 0 - }); + Camera.position = { + x : MyAvatar.position.x, + y : radarHeight, + z : MyAvatar.position.z + }; + Camera.orientation = Quat.fromPitchYawRollDegrees(-90, 0, 0); radar = true; @@ -1394,15 +1398,25 @@ function connectRadarModeEvents() { Controller.keyPressEvent.connect(keyPressEvent); Controller.mousePressEvent.connect(mousePress); // single click/touch Controller.touchUpdateEvent.connect(touchUpdate); + Window.domainChanged.connect(domainChanged); MyAvatar.positionGoneTo.connect(positionGoneTo); } -function positionGoneTo() { - Camera.position = Vec3.sum(MyAvatar.position, { - x : 0, +function domainChanged() { + radarHeight = MyAvatar.position.y + RADAR_HEIGHT_INIT_DELTA; + Camera.position = { + x : MyAvatar.position.x, y : radarHeight, - z : 0 - }); + z : MyAvatar.position.z + }; +} + +function positionGoneTo() { + Camera.position = { + x : MyAvatar.position.x, + y : radarHeight, + z : MyAvatar.position.z + }; } function disconnectRadarModeEvents() { @@ -1411,6 +1425,7 @@ function disconnectRadarModeEvents() { Controller.mousePressEvent.disconnect(mousePress); Controller.touchUpdateEvent.disconnect(touchUpdate); MyAvatar.positionGoneTo.disconnect(positionGoneTo); + Window.domainChanged.disconnect(domainChanged); } function init() { From d5c252c9ad70cfb2e46c95b75cd3a71d7b8f5196 Mon Sep 17 00:00:00 2001 From: Cristian Duarte Date: Mon, 9 Apr 2018 16:24:03 -0300 Subject: [PATCH 03/46] Use MyAvatar.goToLocation in radar teleport. Use MyAvatar.goToLocation in radar teleport to prevent synchronization issues that make it fail occasionally when directly modifying its world position. It will work just as teleport.js does. --- scripts/system/+android/radar.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/system/+android/radar.js b/scripts/system/+android/radar.js index 120bec33c3..8100cc0887 100644 --- a/scripts/system/+android/radar.js +++ b/scripts/system/+android/radar.js @@ -46,11 +46,11 @@ var uniqueColor; function moveTo(position) { if (radar) { - MyAvatar.position = position; + MyAvatar.goToLocation(position, false); Camera.position = { - x : MyAvatar.position.x, + x : position.x, y : radarHeight, - z : MyAvatar.position.z + z : position.z }; } } From 63e17e87b0fa4e00db8b871e731c34684a1f4f08 Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Tue, 10 Apr 2018 19:21:23 -0300 Subject: [PATCH 04/46] Fix radar initial position. Clean radar.js --- scripts/system/+android/radar.js | 232 ++----------------------------- 1 file changed, 8 insertions(+), 224 deletions(-) diff --git a/scripts/system/+android/radar.js b/scripts/system/+android/radar.js index 8100cc0887..67ba896207 100644 --- a/scripts/system/+android/radar.js +++ b/scripts/system/+android/radar.js @@ -90,46 +90,6 @@ function keyPressEvent(event) { } } -function actionOnObjectFromEvent(event) { - var rayIntersection = findRayIntersection(Camera.computePickRay(event.x, - event.y)); - if (rayIntersection && rayIntersection.intersects - && rayIntersection.overlayID) { - printd("found overlayID touched " + rayIntersection.overlayID); - if (entitiesByOverlayID[rayIntersection.overlayID]) { - var entity = Entities.getEntityProperties( - entitiesByOverlayID[rayIntersection.overlayID], - [ "sourceUrl" ]); - App.openUrl(entity.sourceUrl); - return true; - } - } - if (rayIntersection && rayIntersection.intersects - && rayIntersection.entityID && rayIntersection.properties) { - printd("found " + rayIntersection.entityID + " of type " - + rayIntersection.properties.type); - if (rayIntersection.properties.type == "Web") { - printd("found web element to " - + rayIntersection.properties.sourceUrl); - App.openUrl(rayIntersection.properties.sourceUrl); - return true; - } - } - return false; -} - -function mousePress(event) { - mousePressOrTouchEnd(event); -} - -function mousePressOrTouchEnd(event) { - if (radar) { - if (actionOnObjectFromEvent(event)) { - return; - } - } -} - function toggleRadarMode() { if (radar) { endRadar(); @@ -230,9 +190,6 @@ function touchEnd(event) { if (analyzeDoubleTap(event)) return; // double tap detected, finish - if (radar) { - mousePressOrTouchEnd(event); - } } /** @@ -726,7 +683,7 @@ function Teleporter() { return { dragTeleportBegin : function(event) { printd("[newTeleport] TELEPORT began"); - var overlayDimensions = entityIconModelDimensions(MyAvatar.position.y); + var overlayDimensions = teleportIconModelDimensions(MyAvatar.position.y); // var destination = computeDestination(event, MyAvatar.position, // Camera.position, radarHeight); // Dimension teleport and cancel overlays (not show them yet) @@ -1125,39 +1082,10 @@ function renderAllOthersAvatarIcons() { } } -function entityAdded(entityID) { - printd("Entity added " + entityID); - var props = Entities.getEntityProperties(entityID, [ "type" ]); - printd("Entity added " + entityID + " PROPS " + JSON.stringify(props)); - if (props && props.type == "Web") { - printd("Entity Web added " + entityID); - saveEntityData(entityID, true); - } -} - -function entityRemoved(entityID) { - printd("Entity removed " + entityID); - var props = Entities.getEntityProperties(entityID, [ "type" ]); - if (props && props.type == "Web") { - print("Entity Web removed " + entityID); - removeEntityData(entityID); - } -} - /******************************************************************************* * Entities (to remark) cache structure for showing entities markers ******************************************************************************/ -var entitiesData = {}; // by entityID -var entitiesByOverlayID = {}; // by overlayID -var entitiesIcons = []; // a parallel list of icons (overlays) to easily run - // through - -var ICON_ENTITY_WEB_MODEL_URL = Script.resolvePath("../assets/images/web.svg"); -var ICON_ENTITY_IMG_MODEL_URL = Script - .resolvePath("../assets/models/teleport-cancel.fbx"); // FIXME - use - // correct - // model&texture var ICON_ENTITY_DEFAULT_DIMENSIONS = { x : 0.10, y : 0.00001, @@ -1169,7 +1097,7 @@ var entityIconModelDimensionsVal = { y : 0.00001, z : 0 }; -function entityIconModelDimensions(y) { +function teleportIconModelDimensions(y) { // given the current height, give a size // TODO: receive entity.position.y and substract to radarHeight var xz = -0.002831 * (radarHeight - y) + 0.1; @@ -1178,122 +1106,6 @@ function entityIconModelDimensions(y) { // reuse object return entityIconModelDimensionsVal; } -/* - * entityIconPlaneDimensions: similar to entityIconModelDimensions but using xy - * plane - */ -function entityIconPlaneDimensions(y) { - var dim = entityIconModelDimensions(y); - var z = dim.z; - dim.z = dim.y; - dim.y = z; - return dim; -} - -function currentOverlayForEntity(QUuid) { - if (entitiesData[QUuid] != undefined) { - return entitiesData[QUuid].icon; - } else { - return null; - } -} - -function saveEntityData(QUuid, planar) { - if (QUuid == null) - return; - var entity = Entities.getEntityProperties(QUuid, [ "position" ]); - printd("entity added save entity " + QUuid); - if (entitiesData[QUuid] != undefined) { - entitiesData[QUuid].position = entity.position; - } else { - var entityIcon = Overlays.addOverlay("image3d", { - subImage : { - x : 0, - y : 0, - width : 150, - height : 150 - }, - url : ICON_ENTITY_WEB_MODEL_URL, - dimensions : ICON_ENTITY_DEFAULT_DIMENSIONS, - visible : false, - ignoreRayIntersection : false, - orientation : Quat.fromPitchYawRollDegrees(-90, 0, 0) - }); - - entitiesIcons.push(entityIcon); - entitiesData[QUuid] = { - position : entity.position, - icon : entityIcon - }; - entitiesByOverlayID[entityIcon] = QUuid; - } -} - -function removeEntityData(QUuid) { - if (QUuid == null) - return; - - var itsOverlay = currentOverlayForEntity(QUuid); - if (itsOverlay != null) { - Overlays.deleteOverlay(itsOverlay); - delete entitiesByOverlayID[itsOverlay]; - } - var idx = entitiesIcons.indexOf(itsOverlay); - entitiesIcons.splice(idx, 1); - - delete entitiesData[QUuid]; -} - -/******************************************************************************* - * Entities to remark Icon/Markers rendering - ******************************************************************************/ - -function hideAllEntitiesIcons() { - var len = entitiesIcons.length; - for (var i = 0; i < len; i++) { - Overlays.editOverlay(entitiesIcons[i], { - visible : false - }); - } -} - -function renderAllEntitiesIcons() { - var entityPos; - var entityProps; - - for ( var QUuid in entitiesData) { - if (entitiesData.hasOwnProperty(QUuid)) { - entityProps = Entities.getEntityProperties(QUuid, [ "position", - "visible" ]); - if (entityProps != null) { - entityPos = entityProps.position; - var planeDimensions = entityIconPlaneDimensions(entityPos.y); // plane overlays uses - // xy instead of xz - if (entitiesData[QUuid].icon != undefined && entityPos) { - var iconPos = findLineToHeightIntersectionCoords( - entityPos.x, - entityPos.y - + RADAR_ICONS_APPARENT_DISTANCE_TO_AVATAR_BASE, - entityPos.z, Camera.position.x, Camera.position.y, - Camera.position.z, Camera.position.y - - RADAR_CAMERA_DISTANCE_TO_ICONS); - if (!iconPos) { - printd("entity icon pos bad for " + QUuid); - continue; - } - var iconDimensions = entityIconModelDimensions(entityPos.y); - var dimensions = entitiesData[QUuid].planar ? planeDimensions - : iconDimensions; - Overlays.editOverlay(entitiesData[QUuid].icon, { - visible : entityProps.visible, - dimensions : dimensions, - position : iconPos - }); - } - } - } - } -} /******************************************************************************* * @@ -1304,11 +1116,7 @@ function startRadar() { saveAllOthersAvatarsData(); Camera.mode = "independent"; - Camera.position = { - x : MyAvatar.position.x, - y : radarHeight, - z : MyAvatar.position.z - }; + initCameraOverMyAvatar(); Camera.orientation = Quat.fromPitchYawRollDegrees(-90, 0, 0); radar = true; @@ -1326,7 +1134,6 @@ function endRadar() { Controller.setVPadEnabled(true); disconnectRadarModeEvents(); - hideAllEntitiesIcons(); hideAllAvatarIcons(); } @@ -1360,12 +1167,10 @@ function updateRadar() { // Update avatar icons if (startedDraggingCamera) { hideAllAvatarIcons(); - hideAllEntitiesIcons(); startedDraggingCamera = false; } else if (!draggingCamera) { renderMyAvatarIcon(); renderAllOthersAvatarIcons(); - renderAllEntitiesIcons(); } } @@ -1373,36 +1178,15 @@ function valueIfDefined(value) { return value !== undefined ? value : ""; } -function entitiesAnalysis() { - var ids = Entities.findEntitiesInFrustum(Camera.frustum); - var entities = []; - for (var i = 0; i < ids.length; i++) { - var id = ids[i]; - var properties = Entities.getEntityProperties(id); - entities.push({ - id : id, - name : properties.name, - type : properties.type, - url : properties.type == "Model" ? properties.modelURL : "", - sourceUrl : properties.sourceUrl, - locked : properties.locked, - visible : properties.visible, - drawCalls : valueIfDefined(properties.renderInfo.drawCalls), - hasScript : properties.script !== "" - }); - } -} - function connectRadarModeEvents() { Script.update.connect(updateRadar); // 60Hz loop Controller.keyPressEvent.connect(keyPressEvent); - Controller.mousePressEvent.connect(mousePress); // single click/touch Controller.touchUpdateEvent.connect(touchUpdate); Window.domainChanged.connect(domainChanged); MyAvatar.positionGoneTo.connect(positionGoneTo); } -function domainChanged() { +function initCameraOverMyAvatar() { radarHeight = MyAvatar.position.y + RADAR_HEIGHT_INIT_DELTA; Camera.position = { x : MyAvatar.position.x, @@ -1411,6 +1195,10 @@ function domainChanged() { }; } +function domainChanged() { + initCameraOverMyAvatar(); +} + function positionGoneTo() { Camera.position = { x : MyAvatar.position.x, @@ -1422,7 +1210,6 @@ function positionGoneTo() { function disconnectRadarModeEvents() { Script.update.disconnect(updateRadar); Controller.keyPressEvent.disconnect(keyPressEvent); - Controller.mousePressEvent.disconnect(mousePress); Controller.touchUpdateEvent.disconnect(touchUpdate); MyAvatar.positionGoneTo.disconnect(positionGoneTo); Window.domainChanged.disconnect(domainChanged); @@ -1436,7 +1223,4 @@ function init() { AvatarList.avatarAddedEvent.connect(avatarAdded); AvatarList.avatarRemovedEvent.connect(avatarRemoved); - - Entities.addingEntity.connect(entityAdded); - Entities.deletingEntity.connect(entityRemoved); } From 99ad51189c66ed5e6c2f425c55d39be9953df464 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Tue, 24 Apr 2018 23:03:56 +0100 Subject: [PATCH 05/46] 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 06/46] 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 07/46] 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 08/46] 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 09/46] 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 10/46] 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 11/46] 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 12/46] 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 13/46] 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 cfc5892d63f342949bf886dc45e99e07809aa0db Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Mon, 30 Apr 2018 13:41:56 -0700 Subject: [PATCH 14/46] 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 a35517d9851aad3ea1c324840912670a3c54bcd0 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 5 May 2018 07:05:10 +1200 Subject: [PATCH 15/46] 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 00d2f9494bbc493a8efad13ea2cbe29a1983339c Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Fri, 4 May 2018 15:07:20 -0700 Subject: [PATCH 16/46] 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 72526781d9b1fabaeede002d972c48d76e1f631b Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 19 Apr 2018 16:15:22 -0700 Subject: [PATCH 17/46] 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 18/46] 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 19/46] 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 c2004debd57921c6d2f3658ea05e0b0e2232b94a Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 7 May 2018 11:41:19 -0700 Subject: [PATCH 20/46] 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 0513204781cc4104faf3d0fd4d35b2c034d0a47f Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 8 May 2018 15:05:55 -0700 Subject: [PATCH 21/46] 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 22/46] 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 540f200b99a6df817799bb9b1f29588985c939ef Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 8 May 2018 16:34:28 -0700 Subject: [PATCH 23/46] 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 24/46] 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 25/46] 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 542e707de8d6d1cacb0e6b3e05f4b5258bff9921 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 9 May 2018 09:35:42 -0700 Subject: [PATCH 26/46] 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 27/46] 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 28/46] 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 29/46] 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 30/46] 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 31/46] 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 32/46] 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 33/46] 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 34/46] 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 35/46] 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 36/46] 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 37/46] 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 38/46] 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 39/46] 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 40/46] 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 41/46] 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 42/46] 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 fab85c3f6d433940d7c503d3a103317447300593 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 11 May 2018 09:52:48 +1200 Subject: [PATCH 43/46] Fix JSDoc function definitions specifying properties instead of params --- .../entities/src/EntityScriptingInterface.h | 4 +- .../src/AssetScriptingInterface.h | 58 +++++++++---------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 8adb5138f2..7e47d9e2d4 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -481,8 +481,8 @@ public slots: /**jsdoc * Gets the status of server entity script attached to an entity * @function Entities.getServerScriptStatus - * @property {Uuid} entityID - The ID of the entity to get the server entity script status for. - * @property {Entities~getServerScriptStatusCallback} callback - The function to call upon completion. + * @param {Uuid} entityID - The ID of the entity to get the server entity script status for. + * @param {Entities~getServerScriptStatusCallback} callback - The function to call upon completion. * @returns {boolean} true always. */ /**jsdoc diff --git a/libraries/script-engine/src/AssetScriptingInterface.h b/libraries/script-engine/src/AssetScriptingInterface.h index eb9a628ae3..7f7a3a68b0 100644 --- a/libraries/script-engine/src/AssetScriptingInterface.h +++ b/libraries/script-engine/src/AssetScriptingInterface.h @@ -186,36 +186,36 @@ public: /**jsdoc * @function Assets.deleteAsset - * @property {} options - * @property {} scope - * @property {} [callback = ""] + * @param {} options + * @param {} scope + * @param {} [callback = ""] */ Q_INVOKABLE void deleteAsset(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue()); /**jsdoc * @function Assets.resolveAsset - * @property {} options - * @property {} scope - * @property {} [callback = ""] + * @param {} options + * @param {} scope + * @param {} [callback = ""] */ Q_INVOKABLE void resolveAsset(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue()); /**jsdoc * @function Assets.decompressData - * @property {} options - * @property {} scope - * @property {} [callback = ""] + * @param {} options + * @param {} scope + * @param {} [callback = ""] */ Q_INVOKABLE void decompressData(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue()); /**jsdoc * @function Assets.compressData - * @property {} options - * @property {} scope - * @property {} [callback = ""] + * @param {} options + * @param {} scope + * @param {} [callback = ""] */ Q_INVOKABLE void compressData(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue()); @@ -229,7 +229,7 @@ public: /**jsdoc * @function Assets.canWriteCacheValue - * @property {string} url + * @param {string} url * @returns {boolean} */ @@ -237,8 +237,8 @@ public: /**jsdoc * @function Assets.getCacheStatus - * @property {} scope - * @property {} [callback=undefined] + * @param {} scope + * @param {} [callback=undefined] */ Q_INVOKABLE void getCacheStatus(QScriptValue scope, QScriptValue callback = QScriptValue()) { @@ -247,38 +247,38 @@ public: /**jsdoc * @function Assets.queryCacheMeta - * @property {} options - * @property {} scope - * @property {} [callback=undefined] + * @param {} options + * @param {} scope + * @param {} [callback=undefined] */ Q_INVOKABLE void queryCacheMeta(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue()); /**jsdoc * @function Assets.loadFromCache - * @property {} options - * @property {} scope - * @property {} [callback=undefined] + * @param {} options + * @param {} scope + * @param {} [callback=undefined] */ Q_INVOKABLE void loadFromCache(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue()); /**jsdoc * @function Assets.saveToCache - * @property {} options - * @property {} scope - * @property {} [callback=undefined] + * @param {} options + * @param {} scope + * @param {} [callback=undefined] */ Q_INVOKABLE void saveToCache(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue()); /**jsdoc * @function Assets.saveToCache - * @property {} url - * @property {} data - * @property {} metadata - * @property {} scope - * @property {} [callback=undefined] + * @param {} url + * @param {} data + * @param {} metadata + * @param {} scope + * @param {} [callback=undefined] */ Q_INVOKABLE void saveToCache(const QUrl& url, const QByteArray& data, const QVariantMap& metadata, From 826c427e2a0d12bfd2e72dc166a7e66b6db33c61 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 10 May 2018 15:42:59 -0700 Subject: [PATCH 44/46] 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 45/46] 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 From 85a6e2555fcec45ce812fd898088913b1e206089 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 11 May 2018 13:55:29 -0700 Subject: [PATCH 46/46] don't assert when unserializing a 'spring' action --- libraries/physics/src/ObjectActionTractor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/physics/src/ObjectActionTractor.cpp b/libraries/physics/src/ObjectActionTractor.cpp index a48989be33..4235bbd616 100644 --- a/libraries/physics/src/ObjectActionTractor.cpp +++ b/libraries/physics/src/ObjectActionTractor.cpp @@ -397,7 +397,7 @@ void ObjectActionTractor::deserialize(QByteArray serializedArguments) { EntityDynamicType type; dataStream >> type; - assert(type == getType()); + assert(type == getType() || type == DYNAMIC_TYPE_SPRING); QUuid id; dataStream >> id;