From f546524c1f92b7cad454726a8a751ba7bda9c8a0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 23 Sep 2016 09:46:10 -0700 Subject: [PATCH 01/28] don't checkout for user membership in a null list of groups --- domain-server/src/DomainGatekeeper.cpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index e33cbe1755..bf9d7d04a6 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -771,6 +771,21 @@ void DomainGatekeeper::getGroupMemberships(const QString& username) { // loop through the groups mentioned on the settings page and ask if this user is in each. The replies // will be received asynchronously and permissions will be updated as the answers come in. + QJsonObject json; + QSet groupIDSet; + foreach (QUuid groupID, _server->_settingsManager.getGroupIDs() + _server->_settingsManager.getBlacklistGroupIDs()) { + groupIDSet += groupID.toString().mid(1,36); + } + + if (groupIDSet.isEmpty()) { + // if no groups are in the permissions settings, don't ask who is in which groups. + return; + } + + QJsonArray groupIDs = QJsonArray::fromStringList(groupIDSet.toList()); + json["groups"] = groupIDs; + + // if we've already asked, wait for the answer before asking again QString lowerUsername = username.toLower(); if (_inFlightGroupMembershipsRequests.contains(lowerUsername)) { @@ -779,13 +794,6 @@ void DomainGatekeeper::getGroupMemberships(const QString& username) { } _inFlightGroupMembershipsRequests += lowerUsername; - QJsonObject json; - QSet groupIDSet; - foreach (QUuid groupID, _server->_settingsManager.getGroupIDs() + _server->_settingsManager.getBlacklistGroupIDs()) { - groupIDSet += groupID.toString().mid(1,36); - } - QJsonArray groupIDs = QJsonArray::fromStringList(groupIDSet.toList()); - json["groups"] = groupIDs; JSONCallbackParameters callbackParams; callbackParams.jsonCallbackReceiver = this; From b5de603921a779dc0ae3a8b4a0ba0845c4b49c23 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Tue, 27 Sep 2016 10:32:56 -0700 Subject: [PATCH 02/28] runtime disabling of sparse textures on less than 4 core systems --- .../gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index 6733475c01..61aae87884 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -26,8 +27,22 @@ using namespace gpu::gl; using namespace gpu::gl45; #ifdef Q_OS_WIN +#define MIN_CORES_FOR_SPARSE_TEXTURES 5 static const QString DEBUG_FLAG("HIFI_DISABLE_SPARSE_TEXTURES"); -static bool enableSparseTextures = !QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG); +static bool enableSparseTextures = !QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG) && + QThread::idealThreadCount() >= MIN_CORES_FOR_SPARSE_TEXTURES; + +class SparseTextureDebug { +public: + SparseTextureDebug() { + qDebug() << "[SPARSE TEXTURE SUPPORT]" + << "HIFI_DISABLE_SPARSE_TEXTURES:" << QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG) + << "idealThreadCount:" << QThread::idealThreadCount() + << "enableSparseTextures:" << enableSparseTextures; + } +}; +SparseTextureDebug sparseTextureDebugInfo; + #else static bool enableSparseTextures = false; #endif From 7361b9a1660f676b5f9084ed29f02ff373a38555 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 27 Sep 2016 17:36:49 -0700 Subject: [PATCH 03/28] Add support for disabling incremental texture transfers --- .../src/gpu/gl45/GL45BackendTexture.cpp | 57 +++++++++++++++---- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index 61aae87884..771d03ba6b 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -27,24 +27,32 @@ using namespace gpu::gl; using namespace gpu::gl45; #ifdef Q_OS_WIN -#define MIN_CORES_FOR_SPARSE_TEXTURES 5 -static const QString DEBUG_FLAG("HIFI_DISABLE_SPARSE_TEXTURES"); -static bool enableSparseTextures = !QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG) && - QThread::idealThreadCount() >= MIN_CORES_FOR_SPARSE_TEXTURES; -class SparseTextureDebug { +#define MIN_CORES_FOR_INCREMENTAL_TEXTURES 5 +static const QString DEBUG_FLAG_INCREMENTAL("HIFI_DISABLE_INCREMENTAL_TEXTURES"); +static const QString DEBUG_FLAG_SPARSE("HIFI_DISABLE_SPARSE_TEXTURES"); + +static const bool enableIncrementalTextures = (QThread::idealThreadCount() >= MIN_CORES_FOR_INCREMENTAL_TEXTURES) && + !QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG_INCREMENTAL); + +static const bool enableSparseTextures = enableIncrementalTextures && + !QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG_SPARSE); + +class TextureTransferDebug { public: - SparseTextureDebug() { - qDebug() << "[SPARSE TEXTURE SUPPORT]" - << "HIFI_DISABLE_SPARSE_TEXTURES:" << QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG) - << "idealThreadCount:" << QThread::idealThreadCount() - << "enableSparseTextures:" << enableSparseTextures; + TextureTransferDebug() { + qDebug() << "[TEXTURE TRANSFER SUPPORT]" + << "\n\tHIFI_DISABLE_INCREMENTAL_TEXTURES:" << QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG_INCREMENTAL) + << "\n\tHIFI_DISABLE_SPARSE_TEXTURES:" << QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG_SPARSE) + << "\n\tidealThreadCount:" << QThread::idealThreadCount() + << "\n\tenableSparseTextures:" << enableSparseTextures + << "\n\tenableIncrementalTextures:" << enableSparseTextures; } }; -SparseTextureDebug sparseTextureDebugInfo; - +TextureTransferDebug sparseTextureDebugInfo; #else static bool enableSparseTextures = false; +static bool enableIncrementalTextures = false; #endif // Allocate 1 MB of buffer space for paged transfers @@ -367,6 +375,31 @@ void GL45Texture::startTransfer() { } bool GL45Texture::continueTransfer() { + if (!enableIncrementalTextures) { + size_t maxFace = GL_TEXTURE_CUBE_MAP == _target ? CUBE_NUM_FACES : 1; + for (uint8_t face = 0; face < maxFace; ++face) { + for (uint16_t mipLevel = _minMip; mipLevel <= _maxMip; ++mipLevel) { + if (_gpuObject.isStoredMipFaceAvailable(mipLevel, face)) { + auto mip = _gpuObject.accessStoredMipFace(mipLevel, face); + GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat(), mip->getFormat()); + auto size = _gpuObject.evalMipDimensions(mipLevel); + if (GL_TEXTURE_2D == _target) { + glTextureSubImage2D(_id, mipLevel, 0, 0, size.x, size.y, texelFormat.format, texelFormat.type, mip->readData()); + } else if (GL_TEXTURE_CUBE_MAP == _target) { + // DSA ARB does not work on AMD, so use EXT + // glTextureSubImage3D(_id, mipLevel, 0, 0, face, size.x, size.y, 1, texelFormat.format, texelFormat.type, mip->readData()); + auto target = CUBE_FACE_LAYOUT[face]; + glTextureSubImage2DEXT(_id, target, mipLevel, 0, 0, size.x, size.y, texelFormat.format, texelFormat.type, mip->readData()); + } else { + Q_ASSERT(false); + } + (void)CHECK_GL_ERROR(); + } + } + } + return false; + } + static std::vector buffer; if (buffer.empty()) { buffer.resize(DEFAULT_PAGE_BUFFER_SIZE); From 31fb395c277008891997cd2a89ca3ac7ae4d5c44 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 27 Sep 2016 17:36:49 -0700 Subject: [PATCH 04/28] Add support for disabling incremental texture transfers Conflicts: libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp --- .../src/gpu/gl45/GL45BackendTexture.cpp | 50 ++++++++++++++++++- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index 6733475c01..275b1d54ab 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -26,10 +26,31 @@ using namespace gpu::gl; using namespace gpu::gl45; #ifdef Q_OS_WIN -static const QString DEBUG_FLAG("HIFI_DISABLE_SPARSE_TEXTURES"); -static bool enableSparseTextures = !QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG); +#define MIN_CORES_FOR_INCREMENTAL_TEXTURES 5 +static const QString DEBUG_FLAG_INCREMENTAL("HIFI_DISABLE_INCREMENTAL_TEXTURES"); +static const QString DEBUG_FLAG_SPARSE("HIFI_DISABLE_SPARSE_TEXTURES"); + +static const bool enableIncrementalTextures = (QThread::idealThreadCount() >= MIN_CORES_FOR_INCREMENTAL_TEXTURES) && + !QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG_INCREMENTAL); + +static const bool enableSparseTextures = enableIncrementalTextures && + !QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG_SPARSE); + +class TextureTransferDebug { +public: + TextureTransferDebug() { + qDebug() << "[TEXTURE TRANSFER SUPPORT]" + << "\n\tHIFI_DISABLE_INCREMENTAL_TEXTURES:" << QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG_INCREMENTAL) + << "\n\tHIFI_DISABLE_SPARSE_TEXTURES:" << QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG_SPARSE) + << "\n\tidealThreadCount:" << QThread::idealThreadCount() + << "\n\tenableSparseTextures:" << enableSparseTextures + << "\n\tenableIncrementalTextures:" << enableSparseTextures; + } +}; +TextureTransferDebug sparseTextureDebugInfo; #else static bool enableSparseTextures = false; +static bool enableIncrementalTextures = false; #endif // Allocate 1 MB of buffer space for paged transfers @@ -352,6 +373,31 @@ void GL45Texture::startTransfer() { } bool GL45Texture::continueTransfer() { + if (!enableIncrementalTextures) { + size_t maxFace = GL_TEXTURE_CUBE_MAP == _target ? CUBE_NUM_FACES : 1; + for (uint8_t face = 0; face < maxFace; ++face) { + for (uint16_t mipLevel = _minMip; mipLevel <= _maxMip; ++mipLevel) { + if (_gpuObject.isStoredMipFaceAvailable(mipLevel, face)) { + auto mip = _gpuObject.accessStoredMipFace(mipLevel, face); + GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat(), mip->getFormat()); + auto size = _gpuObject.evalMipDimensions(mipLevel); + if (GL_TEXTURE_2D == _target) { + glTextureSubImage2D(_id, mipLevel, 0, 0, size.x, size.y, texelFormat.format, texelFormat.type, mip->readData()); + } else if (GL_TEXTURE_CUBE_MAP == _target) { + // DSA ARB does not work on AMD, so use EXT + // glTextureSubImage3D(_id, mipLevel, 0, 0, face, size.x, size.y, 1, texelFormat.format, texelFormat.type, mip->readData()); + auto target = CUBE_FACE_LAYOUT[face]; + glTextureSubImage2DEXT(_id, target, mipLevel, 0, 0, size.x, size.y, texelFormat.format, texelFormat.type, mip->readData()); + } else { + Q_ASSERT(false); + } + (void)CHECK_GL_ERROR(); + } + } + } + return false; + } + static std::vector buffer; if (buffer.empty()) { buffer.resize(DEFAULT_PAGE_BUFFER_SIZE); From 4830b5c2a0d6e354fddbfc422cb299e704ea7ade Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 28 Sep 2016 19:17:24 -0700 Subject: [PATCH 05/28] Backup old domain. --- server-console/src/content-update.css | 62 ++++++++++++++++++++++++++ server-console/src/content-update.html | 22 +++++++++ server-console/src/content-update.js | 12 +++++ server-console/src/main.js | 61 +++++++++++++++---------- 4 files changed, 134 insertions(+), 23 deletions(-) create mode 100644 server-console/src/content-update.css create mode 100644 server-console/src/content-update.html create mode 100644 server-console/src/content-update.js diff --git a/server-console/src/content-update.css b/server-console/src/content-update.css new file mode 100644 index 0000000000..8c9a7c159b --- /dev/null +++ b/server-console/src/content-update.css @@ -0,0 +1,62 @@ +@font-face { + font-family: 'Raleway'; + src: url('vendor/Raleway/Raleway-Regular.ttf'); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: 'Raleway'; + src: url('vendor/Raleway/Raleway-ExtraLight.ttf'); + font-weight: 200; + font-style: normal; +} +@font-face { + font-family: 'Raleway'; + src: url('vendor/Raleway/Raleway-SemiBold.ttf'); + font-weight: bold; + font-style: normal; +} + + +* { + font-family: "Raleway", "Open Sans", Arial, Helvetica, sans-serif; + line-height: 130%; +} + +body { + margin: 0; + padding: 0; + color: #808785; + margin: 0 auto; + text-align: center; + font-size: 13.5pt; + -webkit-touch-callout: none; -webkit-user-select: none; + cursor: default; + overflow: hidden; + font-variant-numeric: lining-nums; + -moz-font-feature-settings: "lnum"; + -webkit-font-feature-settings: "lnum"; + font-feature-settings: "lnum"; +} + +.selectable { + -webkit-touch-callout: text; + -webkit-user-select: text; + cursor: text; +} + +h1 { + font-size: 29pt; + font-weight: normal; +} + +a:link, +a:visited, +a:hover, +a:active { + color: #B4B4B4; +} + +a:hover { + color: #2D88A4; +} diff --git a/server-console/src/content-update.html b/server-console/src/content-update.html new file mode 100644 index 0000000000..7b3d1f343d --- /dev/null +++ b/server-console/src/content-update.html @@ -0,0 +1,22 @@ + + + + Server Backup + + + + +
+

We backed up your old server just in case.
If you wish to restore it, do the following:

+

+ 1) Stop your server.
+ 2) Go to the backup directory bellow.
+ 3) Move the content in the parent directory.
+ 4) Restart your server.
+
+ Backup Directory:
+ +

+
+ + diff --git a/server-console/src/content-update.js b/server-console/src/content-update.js new file mode 100644 index 0000000000..c77cfc92c6 --- /dev/null +++ b/server-console/src/content-update.js @@ -0,0 +1,12 @@ +function ready() { + console.log("Ready"); + + const electron = require('electron'); + window.$ = require('./vendor/jquery/jquery-2.1.4.min.js'); + + electron.ipcRenderer.on('update', function(event, message) { + $('#directory').html(message); + }); + + electron.ipcRenderer.send('ready'); +} diff --git a/server-console/src/main.js b/server-console/src/main.js index 82fe6b6b4d..2835dd338b 100644 --- a/server-console/src/main.js +++ b/server-console/src/main.js @@ -488,27 +488,51 @@ function updateTrayMenu(serverState) { const httpStatusPort = 60332; -function deleteResourceDirectories() { - const dsResourceDirectory = getDomainServerClientResourcesDirectory(); +function backupResourceDirectories(folder) { try { - fs.removeSync(dsResourceDirectory); - console.log("Deleted directory " + dsResourceDirectory); - } catch (e) { - console.log(e); - } - const acResourceDirectory = getAssignmentClientResourcesDirectory(); - try { - fs.removeSync(acResourceDirectory); - console.log("Deleted directory " + acResourceDirectory); + fs.mkdirSync(folder); + console.log("Created directory " + folder); + + + var dsBackup = path.join(folder, '/domain-server'); + fs.renameSync(getDomainServerClientResourcesDirectory(), dsBackup); + console.log("Moved directory " + getDomainServerClientResourcesDirectory()); + console.log("to " + dsBackup); + + var acBackup = path.join(folder, '/assignment-client'); + fs.renameSync(getAssignmentClientResourcesDirectory(), acBackup); + console.log("Moved directory " + getDomainServerClientResourcesDirectory()); + console.log("to " + acBackup); } catch (e) { console.log(e); } } -function deleteResourceDirectoriesAndRestart() { +function backupResourceDirectoriesAndRestart() { homeServer.stop(); - deleteResourceDirectories(); + + var date = new Date(); + var folder = getRootHifiDataDirectory() + "/Server Backup - " + date; + backupResourceDirectories(folder); maybeInstallDefaultContentSet(onContentLoaded); + + // Explain user how to restore server + var window = new BrowserWindow({ + icon: appIcon, + width: 500, + height: 350, + }); + window.loadURL('file://' + __dirname + '/content-update.html'); + if (!debug) { + window.setMenu(null); + } + window.show(); + + electron.ipcMain.on('ready', function() { + console.log("got ready"); + + window.webContents.send('update', folder); + }); } function checkNewContent() { @@ -537,16 +561,7 @@ function checkNewContent() { message: 'A newer version of the home content set is available.\nDo you wish to update?' }, function(idx) { if (idx === 0) { - dialog.showMessageBox({ - type: 'question', - buttons: ['Yes', 'No'], - title: 'Are you sure?', - message: 'This action will delete your current sandbox content.\nDo you wish to continue?' - }, function(idx) { - if (idx === 0 && homeServer) { - deleteResourceDirectoriesAndRestart(); - } - }); + backupResourceDirectoriesAndRestart(); } else { // They don't want to update, mark content set as current userConfig.set('homeContentLastModified', new Date()); From 468281f92dbeab9b427751dde29963fb7d728d6d Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Thu, 29 Sep 2016 06:58:14 -0700 Subject: [PATCH 06/28] Fix the Debug build of Interface on Windows --- cmake/macros/PackageLibrariesForDeployment.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/macros/PackageLibrariesForDeployment.cmake b/cmake/macros/PackageLibrariesForDeployment.cmake index 7f826c1f8c..da0ee35769 100644 --- a/cmake/macros/PackageLibrariesForDeployment.cmake +++ b/cmake/macros/PackageLibrariesForDeployment.cmake @@ -49,6 +49,7 @@ macro(PACKAGE_LIBRARIES_FOR_DEPLOYMENT) TARGET ${TARGET_NAME} POST_BUILD COMMAND if exist ${QTAUDIO_PATH}/qtaudio_windows.dll ( ${CMAKE_COMMAND} -E remove ${QTAUDIO_PATH}/qtaudio_windows.dll && ${CMAKE_COMMAND} -E copy ${WASAPI_DLL_PATH}/qtaudio_wasapi.dll ${QTAUDIO_PATH} && ${CMAKE_COMMAND} -E copy ${WASAPI_DLL_PATH}/qtaudio_wasapi.pdb ${QTAUDIO_PATH} ) + COMMAND if exist ${QTAUDIO_PATH}/qtaudio_windowsd.dll ( ${CMAKE_COMMAND} -E remove ${QTAUDIO_PATH}/qtaudio_windowsd.dll && ${CMAKE_COMMAND} -E copy ${WASAPI_DLL_PATH}/qtaudio_wasapid.dll ${QTAUDIO_PATH} && ${CMAKE_COMMAND} -E copy ${WASAPI_DLL_PATH}/qtaudio_wasapid.pdb ${QTAUDIO_PATH} ) ) endif () From 38eccd32a8d5f6ce25181e6bfc4be6e625ba9a16 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 29 Sep 2016 10:18:54 -0700 Subject: [PATCH 07/28] add developer menu support to enable/disable dynamic texture management --- interface/src/Menu.cpp | 39 ++++++++++++++++++- interface/src/Menu.h | 2 + .../src/gpu/gl45/GL45BackendTexture.cpp | 33 +--------------- libraries/gpu/src/gpu/Texture.cpp | 31 +++++++++++++++ libraries/gpu/src/gpu/Texture.h | 9 +++++ 5 files changed, 82 insertions(+), 32 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 3c1aa26a4a..74490b6dd1 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -355,7 +355,7 @@ Menu::Menu() { //const QString = "1024 MB"; //const QString = "2048 MB"; - // Developer > Render > Resolution + // Developer > Render > Maximum Texture Memory MenuWrapper* textureMenu = renderOptionsMenu->addMenu(MenuOption::RenderMaxTextureMemory); QActionGroup* textureGroup = new QActionGroup(textureMenu); textureGroup->setExclusive(true); @@ -383,6 +383,43 @@ Menu::Menu() { gpu::Texture::setAllowedGPUMemoryUsage(newMaxTextureMemory); }); +#ifdef Q_OS_WIN + #define MIN_CORES_FOR_INCREMENTAL_TEXTURES 5 + bool recommendedIncrementalTransfers = (QThread::idealThreadCount() >= MIN_CORES_FOR_INCREMENTAL_TEXTURES); + bool recommendedSparseTextures = recommendedIncrementalTransfers; + + qDebug() << "[TEXTURE TRANSFER SUPPORT]" + << "\n\tidealThreadCount:" << QThread::idealThreadCount() + << "\n\tRECOMMENDED enableSparseTextures:" << recommendedSparseTextures + << "\n\tRECOMMENDED enableIncrementalTextures:" << recommendedIncrementalTransfers; + + gpu::Texture::setEnableIncrementalTextureTransfers(recommendedIncrementalTransfers); + gpu::Texture::setEnableSparseTextures(recommendedSparseTextures); + + // Developer > Render > Enable Dynamic Texture Management + { + auto action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::EnableDynamicTextureManagement, 0, recommendedSparseTextures); + connect(action, &QAction::triggered, [&](bool checked) { + qDebug() << "[TEXTURE TRANSFER SUPPORT] --- Enable Dynamic Texture Management menu option:" << checked; + gpu::Texture::setEnableSparseTextures(checked); + }); + } + + // Developer > Render > Enable Incremental Texture Transfer + { + auto action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::EnableIncrementalTextureTransfer, 0, recommendedIncrementalTransfers); + connect(action, &QAction::triggered, [&](bool checked) { + qDebug() << "[TEXTURE TRANSFER SUPPORT] --- Enable Incremental Texture Transfer menu option:" << checked; + gpu::Texture::setEnableIncrementalTextureTransfers(checked); + }); + } + +#else + qDebug() << "[TEXTURE TRANSFER SUPPORT] Incremental Texture Transfer and Dynamic Texture Management not supported on this platform."; +#endif + + + // Developer > Render > LOD Tools addActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::LodTools, 0, dialogsManager.data(), SLOT(lodTools())); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index b25603caeb..95cd4c5aa6 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -98,6 +98,8 @@ namespace MenuOption { const QString EchoLocalAudio = "Echo Local Audio"; const QString EchoServerAudio = "Echo Server Audio"; const QString EnableCharacterController = "Enable avatar collisions"; + const QString EnableIncrementalTextureTransfer = "Enable Incremental Texture Transfer"; + const QString EnableDynamicTextureManagement = "Enable Dynamic Texture Management"; const QString EnableInverseKinematics = "Enable Inverse Kinematics"; const QString ExpandMyAvatarSimulateTiming = "Expand /myAvatar/simulation"; const QString ExpandMyAvatarTiming = "Expand /myAvatar"; diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index b9e6a92d8e..3e6e53ffc3 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -18,7 +18,6 @@ #include #include -#include #include "../gl/GLTexelFormat.h" @@ -26,34 +25,6 @@ using namespace gpu; using namespace gpu::gl; using namespace gpu::gl45; -#ifdef Q_OS_WIN -#define MIN_CORES_FOR_INCREMENTAL_TEXTURES 5 -static const QString DEBUG_FLAG_INCREMENTAL("HIFI_DISABLE_INCREMENTAL_TEXTURES"); -static const QString DEBUG_FLAG_SPARSE("HIFI_DISABLE_SPARSE_TEXTURES"); - -static const bool enableIncrementalTextures = (QThread::idealThreadCount() >= MIN_CORES_FOR_INCREMENTAL_TEXTURES) && - !QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG_INCREMENTAL); - -static const bool enableSparseTextures = enableIncrementalTextures && - !QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG_SPARSE); - -class TextureTransferDebug { -public: - TextureTransferDebug() { - qDebug() << "[TEXTURE TRANSFER SUPPORT]" - << "\n\tHIFI_DISABLE_INCREMENTAL_TEXTURES:" << QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG_INCREMENTAL) - << "\n\tHIFI_DISABLE_SPARSE_TEXTURES:" << QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG_SPARSE) - << "\n\tidealThreadCount:" << QThread::idealThreadCount() - << "\n\tenableSparseTextures:" << enableSparseTextures - << "\n\tenableIncrementalTextures:" << enableSparseTextures; - } -}; -TextureTransferDebug sparseTextureDebugInfo; -#else -static bool enableSparseTextures = false; -static bool enableIncrementalTextures = false; -#endif - // Allocate 1 MB of buffer space for paged transfers #define DEFAULT_PAGE_BUFFER_SIZE (1024*1024) #define DEFAULT_GL_PIXEL_ALIGNMENT 4 @@ -275,7 +246,7 @@ GLuint GL45Backend::getTextureID(const TexturePointer& texture, bool transfer) { GL45Texture::GL45Texture(const std::weak_ptr& backend, const Texture& texture, bool transferrable) : GLTexture(backend, texture, allocate(texture), transferrable), _sparseInfo(*this), _transferState(*this) { - if (enableSparseTextures && _transferrable) { + if (_transferrable && Texture::getEnableSparseTextures()) { _sparseInfo.maybeMakeSparse(); } } @@ -374,7 +345,7 @@ void GL45Texture::startTransfer() { } bool GL45Texture::continueTransfer() { - if (!enableIncrementalTextures) { + if (!Texture::getEnableIncrementalTextureTransfers()) { size_t maxFace = GL_TEXTURE_CUBE_MAP == _target ? CUBE_NUM_FACES : 1; for (uint8_t face = 0; face < maxFace; ++face) { for (uint16_t mipLevel = _minMip; mipLevel <= _maxMip; ++mipLevel) { diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index b573c8e899..44804abebe 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // + +#include + #include "Texture.h" #include @@ -28,6 +31,34 @@ std::atomic Texture::_textureCPUCount{ 0 }; std::atomic Texture::_textureCPUMemoryUsage{ 0 }; std::atomic Texture::_allowedCPUMemoryUsage { 0 }; +std::atomic Texture::_enableSparseTextures { false }; +std::atomic Texture::_enableIncrementalTextureTransfers { false }; + +void Texture::setEnableSparseTextures(bool enabled) { +#ifdef Q_OS_WIN + qDebug() << "[TEXTURE TRANSFER SUPPORT] SETTING - Enable Sparse Textures and Dynamic Texture Management:" << enabled; + _enableSparseTextures = enabled; + if (!_enableIncrementalTextureTransfers && _enableSparseTextures) { + qDebug() << "[TEXTURE TRANSFER SUPPORT] WARNING - Sparse texture management requires incremental texture transfer enabled."; + } +#else + qDebug() << "[TEXTURE TRANSFER SUPPORT] Sparse Textures and Dynamic Texture Management not supported on this platform."; +#endif +} + +void Texture::setEnableIncrementalTextureTransfers(bool enabled) { +#ifdef Q_OS_WIN + qDebug() << "[TEXTURE TRANSFER SUPPORT] SETTING - Enable Incremental Texture Transfer:" << enabled; + _enableIncrementalTextureTransfers = enabled; + if (!_enableIncrementalTextureTransfers && _enableSparseTextures) { + qDebug() << "[TEXTURE TRANSFER SUPPORT] WARNING - Sparse texture management requires incremental texture transfer enabled."; + } +#else + qDebug() << "[TEXTURE TRANSFER SUPPORT] Incremental Texture Transfer not supported on this platform."; +#endif +} + + void Texture::updateTextureCPUMemoryUsage(Size prevObjectSize, Size newObjectSize) { if (prevObjectSize == newObjectSize) { return; diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index ae1afcafcb..61d03c070c 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -144,6 +144,9 @@ class Texture : public Resource { static std::atomic _textureCPUMemoryUsage; static std::atomic _allowedCPUMemoryUsage; static void updateTextureCPUMemoryUsage(Size prevObjectSize, Size newObjectSize); + + static std::atomic _enableSparseTextures; + static std::atomic _enableIncrementalTextureTransfers; public: static uint32_t getTextureCPUCount(); static Size getTextureCPUMemoryUsage(); @@ -154,6 +157,12 @@ public: static Size getAllowedGPUMemoryUsage(); static void setAllowedGPUMemoryUsage(Size size); + static bool getEnableSparseTextures() { return _enableSparseTextures.load(); } + static bool getEnableIncrementalTextureTransfers() { return _enableIncrementalTextureTransfers.load(); } + + static void setEnableSparseTextures(bool enabled); + static void setEnableIncrementalTextureTransfers(bool enabled); + class Usage { public: enum FlagBit { From 701c710857794745300bd371a44d78da358c2864 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 29 Sep 2016 12:15:48 -0700 Subject: [PATCH 08/28] Fix windows odd folder name issue --- server-console/src/main.js | 48 ++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/server-console/src/main.js b/server-console/src/main.js index 2835dd338b..b442d28855 100644 --- a/server-console/src/main.js +++ b/server-console/src/main.js @@ -503,36 +503,44 @@ function backupResourceDirectories(folder) { fs.renameSync(getAssignmentClientResourcesDirectory(), acBackup); console.log("Moved directory " + getDomainServerClientResourcesDirectory()); console.log("to " + acBackup); + return true; } catch (e) { console.log(e); + return false; } } function backupResourceDirectoriesAndRestart() { homeServer.stop(); - var date = new Date(); - var folder = getRootHifiDataDirectory() + "/Server Backup - " + date; - backupResourceDirectories(folder); - maybeInstallDefaultContentSet(onContentLoaded); + var folder = getRootHifiDataDirectory() + "/Server Backup - " + Date.now(); + if (backupResourceDirectories(folder)) { + maybeInstallDefaultContentSet(onContentLoaded); - // Explain user how to restore server - var window = new BrowserWindow({ - icon: appIcon, - width: 500, - height: 350, - }); - window.loadURL('file://' + __dirname + '/content-update.html'); - if (!debug) { - window.setMenu(null); + // Explain user how to restore server + var window = new BrowserWindow({ + icon: appIcon, + width: 500, + height: 350, + }); + window.loadURL('file://' + __dirname + '/content-update.html'); + if (!debug) { + window.setMenu(null); + } + window.show(); + + electron.ipcMain.on('ready', function() { + console.log("got ready"); + window.webContents.send('update', folder); + }); + } else { + dialog.showMessageBox({ + type: 'warning', + buttons: ['Ok'], + title: 'Update Error', + message: 'There was an error updating the content, aborting.' + }, function() {}); } - window.show(); - - electron.ipcMain.on('ready', function() { - console.log("got ready"); - - window.webContents.send('update', folder); - }); } function checkNewContent() { From 858297241b47fffa256c809ac523999d8725381a Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Thu, 29 Sep 2016 12:48:21 -0700 Subject: [PATCH 09/28] Even lower audio latency --- libraries/audio-client/src/AudioClient.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 97b5c14512..4ae19c55d4 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -87,7 +87,7 @@ public: AudioOutputIODevice(MixedProcessedAudioStream& receivedAudioStream, AudioClient* audio) : _receivedAudioStream(receivedAudioStream), _audio(audio), _unfulfilledReads(0) {}; - void start() { open(QIODevice::ReadOnly); } + void start() { open(QIODevice::ReadOnly | QIODevice::Unbuffered); } void stop() { close(); } qint64 readData(char * data, qint64 maxSize) override; qint64 writeData(const char * data, qint64 maxSize) override { return 0; } From f42c0dbd7c51a18ddd3e7ad43b3319e156c683ad Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Thu, 29 Sep 2016 13:01:15 -0700 Subject: [PATCH 10/28] Fix cmake checksum, for updated qtaudio_wasapi.zip with release and debug plugins --- cmake/externals/wasapi/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/wasapi/CMakeLists.txt b/cmake/externals/wasapi/CMakeLists.txt index 019920df77..1cb63531b8 100644 --- a/cmake/externals/wasapi/CMakeLists.txt +++ b/cmake/externals/wasapi/CMakeLists.txt @@ -7,7 +7,7 @@ if (WIN32) ExternalProject_Add( ${EXTERNAL_NAME} URL http://hifi-public.s3.amazonaws.com/dependencies/qtaudio_wasapi.zip - URL_MD5 11c8a7728d6eda7223df800e10b70723 + URL_MD5 272b27bd6c211c45c0c23d4701b63b5e CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" From 3d14a32d1755d6c4ce542508fc646846c116d66d Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 29 Sep 2016 22:11:12 +0200 Subject: [PATCH 11/28] fix controller::ScriptingInterface not found warning in AC --- interface/src/Application.cpp | 5 +++++ libraries/script-engine/src/ScriptEngine.cpp | 4 ---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8b8d1e531b..3890eae4c3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -68,6 +68,7 @@ #include #include #include +#include #include #include #include @@ -4918,6 +4919,10 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("Users", DependencyManager::get().data()); scriptEngine->registerGlobalObject("Steam", new SteamScriptingInterface(scriptEngine)); + + auto scriptingInterface = DependencyManager::get(); + scriptEngine->registerGlobalObject("Controller", scriptingInterface.data()); + UserInputMapper::registerControllerTypes(scriptEngine); } bool Application::canAcceptURL(const QString& urlString) const { diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 0ac2883cb5..e4d1cd7307 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -517,10 +517,6 @@ void ScriptEngine::init() { // constants globalObject().setProperty("TREE_SCALE", newVariant(QVariant(TREE_SCALE))); - auto scriptingInterface = DependencyManager::get(); - registerGlobalObject("Controller", scriptingInterface.data()); - UserInputMapper::registerControllerTypes(this); - auto recordingInterface = DependencyManager::get(); registerGlobalObject("Recording", recordingInterface.data()); From 7e3073e163d5efe592886946ae01179e6bca23de Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 29 Sep 2016 22:13:27 +0200 Subject: [PATCH 12/28] fix spelling bugs --- assignment-client/src/AssignmentClient.cpp | 36 +++++++++---------- .../src/AssignmentClientLogging.cpp | 2 +- .../src/AssignmentClientLogging.h | 2 +- domain-server/src/DomainServer.cpp | 2 +- libraries/script-engine/src/ScriptEngine.h | 2 +- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 4fc8975262..800f00b352 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -91,7 +91,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri // check for a wallet UUID on the command line or in the config // this would represent where the user running AC wants funds sent to if (!walletUUID.isNull()) { - qCDebug(assigmnentclient) << "The destination wallet UUID for credits is" << uuidStringWithoutCurlyBraces(walletUUID); + qCDebug(assignment_client) << "The destination wallet UUID for credits is" << uuidStringWithoutCurlyBraces(walletUUID); _requestAssignment.setWalletUUID(walletUUID); } @@ -102,16 +102,16 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri } _assignmentServerSocket = HifiSockAddr(_assignmentServerHostname, assignmentServerPort, true); - _assignmentServerSocket.setObjectName("AssigmentServer"); + _assignmentServerSocket.setObjectName("AssignmentServer"); nodeList->setAssignmentServerSocket(_assignmentServerSocket); - qCDebug(assigmnentclient) << "Assignment server socket is" << _assignmentServerSocket; + qCDebug(assignment_client) << "Assignment server socket is" << _assignmentServerSocket; // call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required - qCDebug(assigmnentclient) << "Waiting for assignment -" << _requestAssignment; + qCDebug(assignment_client) << "Waiting for assignment -" << _requestAssignment; if (_assignmentServerHostname != "localhost") { - qCDebug(assigmnentclient) << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); + qCDebug(assignment_client) << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); } connect(&_requestTimer, SIGNAL(timeout()), SLOT(sendAssignmentRequest())); @@ -129,7 +129,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri _assignmentClientMonitorSocket = HifiSockAddr(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME, assignmentMonitorPort); _assignmentClientMonitorSocket.setObjectName("AssignmentClientMonitor"); - qCDebug(assigmnentclient) << "Assignment-client monitor socket is" << _assignmentClientMonitorSocket; + qCDebug(assignment_client) << "Assignment-client monitor socket is" << _assignmentClientMonitorSocket; // Hook up a timer to send this child's status to the Monitor once per second setUpStatusToMonitor(); @@ -140,7 +140,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri } void AssignmentClient::stopAssignmentClient() { - qCDebug(assigmnentclient) << "Forced stop of assignment-client."; + qCDebug(assignment_client) << "Forced stop of assignment-client."; _requestTimer.stop(); _statsTimerACM.stop(); @@ -218,14 +218,14 @@ void AssignmentClient::sendAssignmentRequest() { quint16 localAssignmentServerPort; if (nodeList->getLocalServerPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, localAssignmentServerPort)) { if (localAssignmentServerPort != _assignmentServerSocket.getPort()) { - qCDebug(assigmnentclient) << "Port for local assignment server read from shared memory is" + qCDebug(assignment_client) << "Port for local assignment server read from shared memory is" << localAssignmentServerPort; _assignmentServerSocket.setPort(localAssignmentServerPort); nodeList->setAssignmentServerSocket(_assignmentServerSocket); } } else { - qCWarning(assigmnentclient) << "Failed to read local assignment server port from shared memory" + qCWarning(assignment_client) << "Failed to read local assignment server port from shared memory" << "- will send assignment request to previous assignment server socket."; } } @@ -235,10 +235,10 @@ void AssignmentClient::sendAssignmentRequest() { } void AssignmentClient::handleCreateAssignmentPacket(QSharedPointer message) { - qCDebug(assigmnentclient) << "Received a PacketType::CreateAssignment - attempting to unpack."; + qCDebug(assignment_client) << "Received a PacketType::CreateAssignment - attempting to unpack."; if (_currentAssignment) { - qCWarning(assigmnentclient) << "Received a PacketType::CreateAssignment while still running an active assignment. Ignoring."; + qCWarning(assignment_client) << "Received a PacketType::CreateAssignment while still running an active assignment. Ignoring."; return; } @@ -246,7 +246,7 @@ void AssignmentClient::handleCreateAssignmentPacket(QSharedPointer(); @@ -256,7 +256,7 @@ void AssignmentClient::handleCreateAssignmentPacket(QSharedPointergetDomainHandler().setSockAddr(message->getSenderSockAddr(), _assignmentServerHostname); nodeList->getDomainHandler().setAssignmentUUID(_currentAssignment->getUUID()); - qCDebug(assigmnentclient) << "Destination IP for assignment is" << nodeList->getDomainHandler().getIP().toString(); + qCDebug(assignment_client) << "Destination IP for assignment is" << nodeList->getDomainHandler().getIP().toString(); // start the deployed assignment QThread* workerThread = new QThread; @@ -284,7 +284,7 @@ void AssignmentClient::handleCreateAssignmentPacket(QSharedPointerstarted() workerThread->start(); } else { - qCWarning(assigmnentclient) << "Received an assignment that could not be unpacked. Re-requesting."; + qCWarning(assignment_client) << "Received an assignment that could not be unpacked. Re-requesting."; } } @@ -294,10 +294,10 @@ void AssignmentClient::handleStopNodePacket(QSharedPointer mess if (senderSockAddr.getAddress() == QHostAddress::LocalHost || senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) { - qCDebug(assigmnentclient) << "AssignmentClientMonitor at" << senderSockAddr << "requested stop via PacketType::StopNode."; + qCDebug(assignment_client) << "AssignmentClientMonitor at" << senderSockAddr << "requested stop via PacketType::StopNode."; QCoreApplication::quit(); } else { - qCWarning(assigmnentclient) << "Got a stop packet from other than localhost."; + qCWarning(assignment_client) << "Got a stop packet from other than localhost."; } } @@ -317,7 +317,7 @@ void AssignmentClient::handleAuthenticationRequest() { // ask the account manager to log us in from the env variables accountManager->requestAccessToken(username, password); } else { - qCWarning(assigmnentclient) << "Authentication was requested against" << qPrintable(accountManager->getAuthURL().toString()) + qCWarning(assignment_client) << "Authentication was requested against" << qPrintable(accountManager->getAuthURL().toString()) << "but both or one of" << qPrintable(DATA_SERVER_USERNAME_ENV) << "/" << qPrintable(DATA_SERVER_PASSWORD_ENV) << "are not set. Unable to authenticate."; @@ -335,7 +335,7 @@ void AssignmentClient::assignmentCompleted() { // reset the logging target to the the CHILD_TARGET_NAME LogHandler::getInstance().setTargetName(ASSIGNMENT_CLIENT_TARGET_NAME); - qCDebug(assigmnentclient) << "Assignment finished or never started - waiting for new assignment."; + qCDebug(assignment_client) << "Assignment finished or never started - waiting for new assignment."; auto nodeList = DependencyManager::get(); diff --git a/assignment-client/src/AssignmentClientLogging.cpp b/assignment-client/src/AssignmentClientLogging.cpp index 890187ecaa..9110dccc5f 100644 --- a/assignment-client/src/AssignmentClientLogging.cpp +++ b/assignment-client/src/AssignmentClientLogging.cpp @@ -11,4 +11,4 @@ #include "AssignmentClientLogging.h" -Q_LOGGING_CATEGORY(assigmnentclient, "hifi.assignment-client") \ No newline at end of file +Q_LOGGING_CATEGORY(assignment_client, "hifi.assignment-client") \ No newline at end of file diff --git a/assignment-client/src/AssignmentClientLogging.h b/assignment-client/src/AssignmentClientLogging.h index d6b5ee90e0..88e2add017 100644 --- a/assignment-client/src/AssignmentClientLogging.h +++ b/assignment-client/src/AssignmentClientLogging.h @@ -14,6 +14,6 @@ #include -Q_DECLARE_LOGGING_CATEGORY(assigmnentclient) +Q_DECLARE_LOGGING_CATEGORY(assignment_client) #endif // hifi_AssignmentClientLogging_h \ No newline at end of file diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index c1caa00d24..d7bcaa838e 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1749,7 +1749,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url _ephemeralACScripts[scriptAssignment->getUUID()] = formData[0].second; - // add the script assigment to the assignment queue + // add the script assignment to the assignment queue SharedAssignmentPointer sharedScriptedAssignment(scriptAssignment); _unfulfilledAssignments.enqueue(sharedScriptedAssignment); _allAssignments.insert(sharedScriptedAssignment->getUUID(), sharedScriptedAssignment); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index dd93dc2e03..62db99a431 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -166,7 +166,7 @@ public: void setUserLoaded(bool isUserLoaded) { _isUserLoaded = isUserLoaded; } bool isUserLoaded() const { return _isUserLoaded; } - // NOTE - this is used by the TypedArray implemetation. we need to review this for thread safety + // NOTE - this is used by the TypedArray implementation. we need to review this for thread safety ArrayBufferClass* getArrayBufferClass() { return _arrayBufferClass; } void setEmitScriptUpdatesFunction(std::function func) { _emitScriptUpdates = func; } From 5025b4a5ed51ea47d9e72b5f3d995b58257bf3d4 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 29 Sep 2016 22:15:53 +0200 Subject: [PATCH 13/28] NodeList set the sessionUUID before emitting the connectedToDomain signal --- libraries/networking/src/NodeList.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 593a79b311..f3934a51f9 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -536,8 +536,13 @@ void NodeList::processDomainServerList(QSharedPointer message) QUuid domainUUID; packetStream >> domainUUID; + // pull our owner UUID from the packet, it's always the first thing + QUuid newUUID; + packetStream >> newUUID; + // if this was the first domain-server list from this domain, we've now connected if (!_domainHandler.isConnected()) { + setSessionUUID(newUUID); _domainHandler.setUUID(domainUUID); _domainHandler.setIsConnected(true); @@ -548,13 +553,10 @@ void NodeList::processDomainServerList(QSharedPointer message) // Recieved packet from different domain. qWarning() << "IGNORING DomainList packet from" << domainUUID << "while connected to" << _domainHandler.getUUID(); return; + } else { + setSessionUUID(newUUID); } - // pull our owner UUID from the packet, it's always the first thing - QUuid newUUID; - packetStream >> newUUID; - setSessionUUID(newUUID); - // pull the permissions/right/privileges for this node out of the stream NodePermissions newPermissions; packetStream >> newPermissions; From d925a22fd4769d16ac00cef169760f3a5cefb9cf Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Thu, 29 Sep 2016 14:09:38 -0700 Subject: [PATCH 14/28] Use new filename for the external as a simple form of versioning --- cmake/externals/wasapi/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/wasapi/CMakeLists.txt b/cmake/externals/wasapi/CMakeLists.txt index 1cb63531b8..8ec327600f 100644 --- a/cmake/externals/wasapi/CMakeLists.txt +++ b/cmake/externals/wasapi/CMakeLists.txt @@ -6,7 +6,7 @@ if (WIN32) include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/qtaudio_wasapi.zip + URL http://hifi-public.s3.amazonaws.com/dependencies/qtaudio_wasapi2.zip URL_MD5 272b27bd6c211c45c0c23d4701b63b5e CONFIGURE_COMMAND "" BUILD_COMMAND "" From 768354e49f915cd29bfa0c4a698b7840099778f9 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 29 Sep 2016 12:06:09 -0700 Subject: [PATCH 15/28] loopback local injectors on server echo --- libraries/audio-client/src/AudioClient.h | 3 ++- libraries/audio/src/AbstractAudioInterface.h | 1 + libraries/audio/src/AudioInjector.cpp | 12 ++++++++---- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 97b5c14512..eeca9fbd02 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -167,7 +167,8 @@ public slots: int setOutputBufferSize(int numFrames, bool persist = true); - virtual bool outputLocalInjector(bool isStereo, AudioInjector* injector) override; + bool outputLocalInjector(bool isStereo, AudioInjector* injector) override; + bool shouldLoopbackInjectors() override { return _shouldEchoToServer; } bool switchInputToAudioDevice(const QString& inputDeviceName); bool switchOutputToAudioDevice(const QString& outputDeviceName); diff --git a/libraries/audio/src/AbstractAudioInterface.h b/libraries/audio/src/AbstractAudioInterface.h index 223421a7ab..ec96462e73 100644 --- a/libraries/audio/src/AbstractAudioInterface.h +++ b/libraries/audio/src/AbstractAudioInterface.h @@ -33,6 +33,7 @@ public: public slots: virtual bool outputLocalInjector(bool isStereo, AudioInjector* injector) = 0; + virtual bool shouldLoopbackInjectors() { return false; } virtual void setIsStereoInput(bool stereo) = 0; }; diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 43701a51d8..6f6534e2d2 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -211,6 +211,7 @@ int64_t AudioInjector::injectNextFrame() { } // if we haven't setup the packet to send then do so now + static int loopbackOptionOffset = -1; static int positionOptionOffset = -1; static int volumeOptionOffset = -1; static int audioDataOffset = -1; @@ -260,10 +261,9 @@ int64_t AudioInjector::injectNextFrame() { // pack the stereo/mono type of the stream audioPacketStream << _options.stereo; - // pack the flag for loopback. Now, we don't loopback - // and _always_ play locally, so loopbackFlag should be - // false always. - uchar loopbackFlag = (uchar)false; + // pack the flag for loopback, if requested + loopbackOptionOffset = _currentPacket->pos(); + uchar loopbackFlag = (_localAudioInterface && _localAudioInterface->shouldLoopbackInjectors()); audioPacketStream << loopbackFlag; // pack the position for injected audio @@ -293,6 +293,7 @@ int64_t AudioInjector::injectNextFrame() { return NEXT_FRAME_DELTA_ERROR_OR_FINISHED; } } + if (!_frameTimer->isValid()) { // in the case where we have been restarted, the frame timer will be invalid and we need to start it back over here _frameTimer->restart(); @@ -317,6 +318,9 @@ int64_t AudioInjector::injectNextFrame() { // pack the sequence number _currentPacket->writePrimitive(_outgoingSequenceNumber); + _currentPacket->seek(loopbackOptionOffset); + _currentPacket->writePrimitive((uchar)(_localAudioInterface && _localAudioInterface->shouldLoopbackInjectors())); + _currentPacket->seek(positionOptionOffset); _currentPacket->writePrimitive(_options.position); _currentPacket->writePrimitive(_options.orientation); From 43c40aa09017c71e289280707cb311886087c446 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 29 Sep 2016 15:22:21 -0700 Subject: [PATCH 16/28] avoid repetition with fade on injectors --- assignment-client/src/audio/AudioMixer.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 2d2f9c267e..ccd80a4a11 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -269,19 +269,17 @@ void AudioMixer::addStreamToMixForListeningNodeWithStream(AudioMixerClientData& bool forceSilentBlock = true; if (!streamToAdd.getLastPopOutput().isNull()) { + bool isInjector = dynamic_cast(&streamToAdd); - // reptition with fade is enabled, and we do have a valid previous frame to repeat - // so we mix the previously-mixed block - - // this is preferable to not mixing it at all to avoid the harsh jump to silence + // in an injector, just go silent - the injector has likely ended + // in other inputs (microphone, &c.), repeat with fade to avoid the harsh jump to silence // we'll repeat the last block until it has a block to mix // and we'll gradually fade that repeated block into silence. // calculate its fade factor, which depends on how many times it's already been repeated. - repeatedFrameFadeFactor = calculateRepeatedFrameFadeFactor(streamToAdd.getConsecutiveNotMixedCount() - 1); - if (repeatedFrameFadeFactor > 0.0f) { + if (!isInjector && repeatedFrameFadeFactor > 0.0f) { // apply the repeatedFrameFadeFactor to the gain gain *= repeatedFrameFadeFactor; From 165e609851b1561a8c838e63524a0570484f9825 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 29 Sep 2016 15:42:25 -0700 Subject: [PATCH 17/28] Update instructions UI --- server-console/src/content-update.css | 122 +++++++++++++++++++++++-- server-console/src/content-update.html | 71 ++++++++++---- server-console/src/images/step1.jpg | Bin 0 -> 10485 bytes server-console/src/images/step2.jpg | Bin 0 -> 3403 bytes server-console/src/images/step3.jpg | Bin 0 -> 6329 bytes server-console/src/images/step4.jpg | Bin 0 -> 10065 bytes server-console/src/main.js | 45 +++++---- 7 files changed, 197 insertions(+), 41 deletions(-) create mode 100644 server-console/src/images/step1.jpg create mode 100644 server-console/src/images/step2.jpg create mode 100644 server-console/src/images/step3.jpg create mode 100644 server-console/src/images/step4.jpg diff --git a/server-console/src/content-update.css b/server-console/src/content-update.css index 8c9a7c159b..ebfd8aeba0 100644 --- a/server-console/src/content-update.css +++ b/server-console/src/content-update.css @@ -28,7 +28,7 @@ body { padding: 0; color: #808785; margin: 0 auto; - text-align: center; + text-align: left; font-size: 13.5pt; -webkit-touch-callout: none; -webkit-user-select: none; cursor: default; @@ -45,11 +45,6 @@ body { cursor: text; } -h1 { - font-size: 29pt; - font-weight: normal; -} - a:link, a:visited, a:hover, @@ -60,3 +55,118 @@ a:active { a:hover { color: #2D88A4; } + +.header{ + width: 95%; + left: 2.5% +} +.colmask{ + width: 95%; + left: 2.5% +} +.colmid{ right: 25% } +.colin{ right: 25% } +.colleft{ right: 25% } +.col1{ + width: 23%; + left: 101% +} +.col2{ + width: 23%; + left: 53% +} +.col3{ + width: 23%; + left: 80% +} +.col4{ + width: 23%; + left: 82% +} +.footer{ + width: 95%; + left: 2.5% +} +.header{ + clear: both; + float: left; + position: relative; + border-bottom: #000 1px solid; + background-color: #b4d2f7 +} +.colmask{ + clear: both; + float: left; + overflow: hidden; + position: relative; + +} +.colmid{ + float: left; + width: 100%; + position: relative; + +} +.colin{ + float: left; + width: 100%; + position: relative; + +} +.colleft{ + float: left; + width: 100%; + position: relative; + +} +.col1{ + padding: 0px 0px 1em 0px; + overflow: hidden; + float: left; + position: relative; + +} +.col2{ + padding: 0px 0px 1em 0px; + overflow: hidden; + float: left; + position: relative; + +} +.col3{ + padding: 0px 0px 1em 0px; + overflow: hidden; + float: left; + position: relative; + +} +.col4{ + padding: 0px 0px 1em 0px; + overflow: hidden; + float: left; + position: relative; + +} +.footer{ + clear: both; + float: left; + position: relative; + padding-top: 8px; + border-top: #000 1px solid; + +} +.bottom{ + clear: both; + width: 100%; + float: left; + position: relative; + +} +body { + border-width: 0px; + padding: 0px; + margin: 0px; + font-size: 90%; + width: 100%; + min-width: 600px; +} diff --git a/server-console/src/content-update.html b/server-console/src/content-update.html index 7b3d1f343d..3c0eff2fa0 100644 --- a/server-console/src/content-update.html +++ b/server-console/src/content-update.html @@ -1,22 +1,57 @@ - - Server Backup - - - - -
-

We backed up your old server just in case.
If you wish to restore it, do the following:

-

- 1) Stop your server.
- 2) Go to the backup directory bellow.
- 3) Move the content in the parent directory.
- 4) Restart your server.
-
- Backup Directory:
- -

+ + Server Backup + + + + +
+

We backed up your old Sandbox content, just in case.

+

To restore it, follow these steps: + +

+
+ +
+ +
+ + Step 1 +

1. Stop your Sandbox server. + +

+ +
+ + Step 2 +

2. Go to your backup directory: + + +

+ +
+ + Step 3 +

3. Copy the backed up content and paste it into the parent directory. +

+ +
+ + Step 4 +

4. Restart your Sandbox server. +

+ +
+ +
+
- + + +
+ diff --git a/server-console/src/images/step1.jpg b/server-console/src/images/step1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cd80ae553782fb968216d5b0dc5494cc0fa63485 GIT binary patch literal 10485 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 z�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 literal 0 HcmV?d00001 diff --git a/server-console/src/images/step2.jpg b/server-console/src/images/step2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6bc285ac472f867528f5ecc1b4e6f77be574e32d GIT binary patch literal 3403 zcmcgsc|6p4AOFqec<7LdZ9As1>15`I!3<+6L#b$+8F#5M2ZK4xjLZn=ihb@2xFb_pPphF6x`%3@_00#ho0sx9`80ae!@$qOhS7=OQ@VuGEbRGvSrt#6B zF$N7-6UBTQ-JdB!dNY04TmovS^gas7W)M)WSVxQ_-UN10tSnKnjKVd zaIkT(sWDIBg9dRp92#SSHZd_0Fjz)H30FiD8*zmOa|$G;kS<{JMQk1ysZ^wS^MXVK z6l!h=9R3&CuX^>jKu5=aAIjl;i57~;%=vo1DlDW*_)IjJDdYtS=u9$`WuQ#O$J+{+ zG!aigRdbC*lcxd3>a;t;#jzCPx~b%~dvTR5Vo%v3jovE$4g)PR;#A2r<#%zvD;?aXROs;5-%b4fdF343b z2#zu{i78+oWispqJPuMda6EhAT5t>M&2kwF*Ro?lF4_iZjaE+Y-==%6iA=IretucJ zHpuzq&*U-)C;^ISqZkAhtClRl_zeI6h@u_%8Gu3{5GVu+g+gJ<8wOK8;4mfN2)GIe zgqoVVni@hwLsL^jLt9HrOM4zlDjW{iKp-@&L)devY*Xc};O4I4JI)?`>>*}px|gH%^5;*zH{A6(;~M@t&ZqKHhP`HFVqev$ zZF5=R{U#UvByT(>jDNRbV8}nFx;kvQu%taay^nq1MTJIEYW~f3?9&iu+bMmb{Ze(IlhTpFD zBV1CxWmwA062H~c(^VJU-N)lWOM|Yp3czQ7Qxm^d&%@JW+)7&WjRJT)SzfL?JU#^; zqad(UGPq*(nKOZGox-Su?N73QM*RJ{qVirpc*FL{;>p}4KfcL28|}Tj1q_R%U#KPq zwRQ%~e2(Z`)&A~YdsrN+?(UOcjocYIU0DCMlklUs};qp2;{eZRTrO5rD4UcO7d{`%pZ-v~_0(23zdl@-xVbsxvXaK+D@hxz zhE}ybrIgf8)b-z7okzQo@g_{}>1os%>h|%W0+1Z~Jn8HVA1*q1^Ma*Z(&BR4Q>{(f zR+R%jJ+PIPgj=JV=@%HDgI$%?ZkOs(S1_}$C~bQ z!>&LMww~R2UdzWUtn%fo|^JKTO)2?M@%F!$Q4!+(iwse!ukO;j?!ZLlnY1+0i zZtWVcW}&Y~iC$o~+uiTG$^Lxh!FB3`-m>Em-r(sYqoO`K1u@sw*(a@)$m{=t3H#B(bQ@B9D&fPTdKz)efnjwyhs=1~EQ!W2wALRTdJ$^Lk@ zDsSAmw=OGw!vSTW3XWD8!L22{xQuxVF3zYd@GLF7XS$4KNlofhM$)EENUv-UZJ9Ck ztbds3826}aTg7ML)yzN8i|@3$UfPo87H2=J2|&ySW4c&<6)xu|5(wj$lYOYSQz##U zLfxNSJGx1`-*JiVQ3E#c-vf{;?-cBha z`zB%>o|hf1Z;G0dysI{hjGdNUlixX)8!%%w_D3w~;g3$LUmy8A)Awynt^DZ%LS5T@ zXasRay~&Z-Z1F&ao2)YA{obe+QB>r?tQl<(mmRmC+SZ-=Ns?3JjhPHIT-0FI|I(ta z0X3pt(O4MuHg;lxiRy@huICG+4^!KbO();nzfxxtstefnFoWuvm{tD zbnSgd68a*^hpxO0Z)Ee-3r=2rZ+~_;vp#xCzq6W>{$}eV_gJU1=SM&EKJRhO7{MEG zQm``~iysT)dh#A-l12yLDBFFbi^VOUe62v4Yy2I<%esxFsgyXcm^AZN`Qe@`{k1qR zkB%hKey71OC+86R)9pUd5%E72uI`ce3)uApt9xTO=e||{cjO-g@A=tZ1P4 znYG=(?Heg+OhIMSosQ$l=wBMkYad&nV48iM^4@P_AU}@|1&%EG{fEks;JcqrzTQqF zSalq$5+E@tmj`WV_m=AKcbZs-={T*uF*Ed+1TINUcUC})V>mQnCP=@qayaz7zE`cw e*p_oAvZA~&xOII{&H!Lw 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 literal 0 HcmV?d00001 diff --git a/server-console/src/images/step4.jpg b/server-console/src/images/step4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..27694aee7437ea9acfabfab87112f58bb46910a0 GIT binary patch literal 10065 zcmcI|cT`hb_iaK40R^#u^xhH(y?22G>Alwg0YeF)cMud1kdE};qzHr#B2AmJ0r2p#7s3_*fI>L|1b~0+W(z>3 z;BM{c4FCdg004kC0C2N_4Y5a~UBq~JoZP^cHqKUXu(dOi$IH@%2Lk5h0Z2%Dxma2| z!qN0ra65#PB;#&NJ0m^9Mv_rqP?cBJMILUCQ1(H=wSCldtbH7uVEfW`ri<=qa>s3uc-6}sv7k2&L}v&AXo@w4S_)D zg+;*-K@omFL2i0JUWgzMuP6_M7sLw@gYb&+@zVb>Mk#s;l#Q*JmV)A+SSTA?Nya~u z^7Qlsd-8*wQFc5KQBhGIUOpZ^J`l>r7UbsbgtqhoIk_?Yt)KvRvqm9Y&hP^Y|+0EYBgWwM;eX}w zNYP91{94}svD|+TX(=fF`uU&cm7@Qr{ozhFl8h)uX{nnX0O{|R1=zd?006+7S->*@ z77z%;0%BodVPXIJVq^b0;9&nU99*2=hKq}bhmVJcOF%$KNI*b*>((vef9w|(2M31$ z7nk4`AwJfHW~1y8}JPP1OV`XK;S<& z0U$OGE*?Gs79kN32*CdR`Humy{yKRF0L1>4KLN=tQbLknlf=Tt0pOC6<1yUDhiFm| z$i|H@Y9~A-v~;ar7!}Y-EV!p@%bv?8hl*!n9>1?gq-C|pKZeGzxQEp}5Z3R=tC6=6 zN}i$&4(YVcuT>C)7kY?LkpZx<0617Uw{UUs@P8)=B*S8WkYj7&%DTqk>{$lqGHS)& z#k>EYx?^O4FCj;#7cZOeG*^x5Y7Q2cLC*HY7Y1=({H!2GFFP?lxP=QlFm5Jj6;c|^)HYHR=kfX5m^5$`9D(_-Sg>u$qjYwP`Z)^9C@ zPHtNTrQ%_eIsj$ZiBtwU?$idfVb|x%c&jV{WyEB1nA&q7pR%%ifMY#CGO?h65<+cw z9qps4a`Nzay;e~DzcEe@Pt7j?M1qYcXu^v4bSM&%FePve`k;iM zt)=w|Bal8Rj12=XuTRWX6S^}xLvx;lDI|pLX);m#povV0$|hyj9)Wti|2B8 zL>Z0S+#S=7W8h&E(@6|I5tTzl7u!l^VhqUO(spqrfp!S*T*e>`BJ8_M3iBT#zFI$D za7l=rl?s;85_Gwk@n?|nU0=-#LLYvXv7!+;941ZkUL!af%4k1Wl0jaLW!*C^xS#?y zyLG<7WLwJ!t9j{qBy8E^t$!w}9QBU|%!@AQ&Zt-CJSvvpY=NE#V53*V^bt}Yf}Aq; z%C_0Q43qpv!u**&Lb4zDFCN?6Jw3kh5)8IuJL~+C+325G)N4V66&w{jSL|$|L3{4K znnNQ!k^{+#cg>+;4MOM3I6Gj)UwB11*Y;(cX{ANZWN6(18r4KcC^KV0zX%D>a1<*(;A?s-^)8ybbSv`~D@6!GMS@s5weW zK}|&JGiP5-^9`W;ipi;V28?3uwVLqo2eB@*9Cce3G|@~A*Ky3{SQ!((|L!Vr!QrTA zjdW10jQv1o&1}%vo^LxF#|(ucSIt$xy`)bp-bPe*+RA0aiR3g6(pXp&NKFf{5DX>S zQ!Afq3nCkbx(Yt8^`~u6ld_cehk-zLCiw*ZN3{tgXMO3^kge@|_nI+EPrMJdLC6*s zkY()7hsr+f_brGkW6Nf{HMP>gXw3Sjf$|mjQWtd$vheOb^tTnik~u6rZ9lhqAqEE3Wb@eb== z;O2dX*+zaDL#y^Pe&2u|sX`!sfsX)o0j&?#v$7yt>LXmiuj}{k<>~Z}YjrD{crPyq@e&VO@Rbl+PHuaf~tF|D^n-e#H@aFdZh+p#IN&{m- zbnGVni{gnt@l#!@?9a#gBpolfy?tD;mv6x~fPmlWa7xLoP;<>lVGh)dt_Nt%{D42@mUhYJia(lkh517N$WOL8o=@&&>$+sN zNamUJ+O~Msh&+>gDDbjE9S-X;aMOPPIa7M)X`0g3n4H$V)KhqxWgHi%-DD2g)!Atw z{fs)iYhb`;7prA!P1Z4DbfIvbw2435m;PBX$XW8PjB*YIZb}5*^!&w7G0&^c&He+r z%kAuAj%#M0Zy(Gr15U5QSI@XndaUg#bU~3<{CMAZG~Y+@X@rtL2{%d-2$Cled7IQI zOYfPpgb7}oq**yBny=6;>k~?O@P2*ASZD5Qp)jbZzD8|&U9}5??(FV!&frl&cs~&< ziDgx-=fD3G2Wor+pv2di9qfxt;#-1)LWsOQ4vD{VS*NQ&OH~c)-$s*hOnxbjRgdbW z9r$)lU2!k-QDu^WUX;U>Z9+wh*n*Ff9ZnifxyqlbN zZmMel+j?f`kAxwf?fIa3$_MU8jd=LJ6tC9aQAxp7CbQ@^R&Bii@_^Psd5XHtk4OrB z$hqBd6_pX3|K_`WGS3UEA8LBG_iU!)$;w_=ks7Vx$9hjs&-!gUN94>s$3mkGWZ8tC z1G*sVS)H*~AD19XUtf*A!Pa(xmD5trN34*NPdHj2S*sT|c)!4+y>0tqTJP)WX1%^( z0P{|AedMfmY9}p!am>U07*Q+d`D@&jN9p%=sdPQIO&vaIjpgpJf#i=kzva!r?Y+pk z=dc%TE@rkzEO%KL)E7tPqcjomou2D*cM6k}Z5om+EMz&)hn2^Cvrm!Dj_gnU$6PJVp8d{6>)=)&IyD+eiQ9LFe$w6mTpe2WD(BlMlQA>n zZVv;>rtL;V??*3uXrbR56%K#J?5s+!{54Hh?8UAFy#q%j*mF2A5tQ9!SfzV59k_8C zXm_bA6?erHc>TQP`rB1YW-(b{NW)3QG1qteZIrF6jFOoBZ3?WQI>$z>g0-kYk2|IT z3Y5s28E?J1nu0>6G1k^tw)x6$zB6qZx@Hyc2nE@K&x%`|oKc?+>*|Y6X6B%-P8BT6 zwqXa_n|FT}O7Gm=db1lSc(A*qb7_6_E$apV3g|gYusAl~q@%S~Zzy0XeOdw{bPqRs znwX(zJ2x11TUI7ir@e=|zOT5o`uogbxu$>n`Zvjnq!jnoqAU)<=M>9=JpyBWB|LFn z>QlH8AhAywiKD5ID8eTXE$d%C7Aa~#K7*^_PAmoO)>402bPTy1OPH3QQ?t9!`(Onh zJOYe4YW)n#>imI81t`sY&GtHM-KWPs zZ`LjMdwVSparTqs7A0Ww*!$$oeS!3Csm=8HQJ4$89pj^(WGQQsw6+|GJaV)FDayKb=TvEFe9@eN$Qgdu+ZqN zJ16X*l#ssU?px%0qOc)vF;!51X>C1e-v%l@DRO8zoaco(@uhZAov&~mLY2^{u4aV4 z@D0pmG$I)@$)Hz_XgYqnDF}I5rkIpb(*=dUqC@~e^zn&7A$Wt1wT_EwhS0GV6O)xg z5#QDKHvlr{_0!Cm>qx|7hj_J5!|`EM<=-MLE#f)+lEiuf5b77tE;z?lDormPG6K~^ zcMqnv%wHVn{M~Y;hx*`aL8Y-6-^;p-2a6K_aQr3)+M_j(mi{ziEQ?yTd7Ae1f>eLD zAZm9>$6sW%eZagrfT>TrTz@6;2GFQpQ#@qSayCKtCrpI(;%(qrhefSI<5%?M8^8NI zdWm3_Qe_#fRX%c|yZw$+QlPWYCg+2zp|-XjM@in4(*()gbHtv$&`!p#bzq>?_-tj9 zGmAitnMd6CzGT_d4BL2BRCYNu5i3Z82q=Sw1LaG1qm2cAT*S{9uLaXg--5RiO(tvT z$+^C_aw%~lEK4@XT--^FKsL0y#gCa&mK^ERr&PKoPTJ&16o0Y95q^z;8g*(BV$g4h`wFCr&(vpkB#IS2N#|#*RJqNe#!19{?G=B!rjH6xoV|O z$yine)h`p;po+v{)U%=vk!z!~NMn^D^>q9g1IwAlynOY2PnmhAk?-%5f4t^1b{)@! zu;A2(XSgS{8>JE2B-OlqwE)%APNe1>d+FtogeXYww5uZC8&cGo^s=?V(ElpUueVwO z=M3Q+K&9PJH}ya$M8?3%SGNkIUMlk>hXQag{8#-r(VnK^o67#K$%`;;hPNS0HnEk; zu3TzNBT(8fLPct?+Xbq}4+L8e8;Ex~euDW4M^Ant8|7X#_RG0|wm^k!2qJMsFFxHVk5{1dSkMg z)PdUBd)bhsZ6A}Icywy+eYC69No&NfEV-@$<$%>-aT$c-%^K_n2F`~Q+Snfb)m`kk zzDWe#_%!sN-eU~Xk| zh&7Ki(Px@IH%%H2?b4W!gNMPKTCyZL_h=fwlL9huMck{T7e=30EaeJQTMFO$a9~Ql zZ~tLrl1Y)4d0yb~WgBIbxMqs5rg8vW9$dAN#h1Hax=5-Pqn2GG5?`85R zX0S3t%w;TAdm?l(&Gp%m|Bniza#PH5N?|3%kL_#IwtGU*$&teT#u<^r4#Pb$9U6Va zYwAjI%M~!$S6P&Ge=H@Sz7DH6Q|?ueP^nCC1YTLS>%v0lmSD!E;aL$=y^d>Ach(Ky zK015(Uids^m-s>S>)6?1C2c2pZH*|P12_yhG zKZUxGi0FMmu6%)FMCU@BjBe8FrEft9PW8Y|e$Z z#jhBLfHqOvw$~FV5&7W6ui% zxt4lBqp%_G3H|oyu?|6*_vD;<;C)U*N8#!44-6u4`kpNgL+4Ptl)_STJ-S1VFv`vj zN_}UiXi)R|tbUSVk`bt7n^U*Rfyr9+pBOhL?f+}o4t6->CL*rnA~dKK(Cm0ibKCF+ z*O&44buinK3ttpI7nj0Gl#(QF05<)z$SqL)l^`5_F39PmO|^FefHbPwB&M2`ZJ1Ut z&EmZ9Nt~N1H1p6WMLwOjF8x@;0<$$<*(>#AC3D67pnYK+r>xvdzDGJCG#RE-?XJ;` zX?FjVlCerEMk4-oLcC|^G*ETBVt=xMt2NE5AbD9^ckJAsvagJ`EK|9$uYjgO_1)&f zP+u-h^>Lw(yanjjpUrktd4dsFxcGb`hhq&(7AypOpF#yVcVgC{ zAvQ{n-R|2DtjT%w`YWXr&xsDUn|K#n&vk!L_=;z^dere6-iqh*|J~E_O#LEId$pSd zIoWx+E?)Tnn=%)A|G@vtX>57#o^v@7eCJy(+&tQdj&PIqvvFFtAsGz}FM?^9wh*`x zl%043n6{QtA1@gwVJ&{Wia(LVZhu?V*E06;Sy%l5E^tH#x7ciBZ6;9Otm?Buf@C^3 zrQ3WcNyTLo!HfPZZOxf(J6B5)W^2rX#vGGsW`l28WeQ$$*wn6kXWcsGOc}H9;}(OS zcXOaAU(@al5rT#FzHX8*?9nKnSfLpWHo-)v7!wJz1TpB6#mPz8L&@3q?INR!wJ&%>5Em7#|_e{}DQO z@4F7Li%cf?ZAOmblh{@%Oz{WJxBeuvUsc%ROG zrT1nmbiv{V5E4{~-A4QBm>n0Wn=*U@fJ6he%M-%O8eV zlc0k%l%YlIro9Qy&MP&&(L!cYIiboWUH8SY6SJy;l9l>VUmr1n=97^z(y(yel#P@z zJiAV_LJ9tn4BzpzmEk%1o&10&tEr|j)BB+h2s;Q97kLOQ`6*^Pr5&_B;$${j;GsLK z7rJNLqgzi5UMU+B8MuO19HDM-~M{sx_!>5FmRDpC-pZk>g`koa+qLn*oo$D zcdQX*y6{d+L9XLZe<}uHhG}0D@#O36$0PUFF z{5+Co1~^g~utCf2X^*eibW!4!JD)>CwYrnL_}nAt{|#jIvnW3*p@T-W6)hT5J!aq; zED~_1N@18b<#-&2ooKhGgecnmy3ynY;4gWtnFA8QZ@iw5xY)V9S5!h8kpoKmY=D@T z%-?Ca=uYg!Of&RlyQSv93?fJhB@Ul4lcRE(x9*XoA(1W9y0&vvZ=lD6)sI>g1&gv? zcQrPAv|TO)3rA>7_Ix7n;Aa-GZmy-0(W$S74>fXGGPAQz8X4<#4&)Eenz;C}P@l}h zvi7YTZjWxfX-P^m(oJ&~)aM<40EQfY{(k>i^*s1I2G4MF*$zY2*7nvoK*ys#w&L~k%V-`VY zQdsh=zyn(Hw9Zk=b37UJlkDlJpMr-+Zop@kI%#-w9p&9ek%!R|DS046qFMJO4(43{ zjj?`0>YPxmcb!%Fp#yyxdtOz9d=A)|t;;unFUjdQfE6+4Gr5x6T<05D6u6#?<9OoT zJCet~!QEWrT+hicVa;f04OI%3Sy^pQ63sYwn9$*E6}ee0waz4fl5No2pU`8g>!Ty- z3%J##M^H)aap=Z6-vu(_R)mq*(?0F(t?sZ#dWHqc{;MpQM1cX2iq>QuO)v*e!dnd* zq>N!>M9$G<>F|R#es7zP7>9@C+YLfkH5{(CHAS>A9ib4d+TblJ>*0m{@8@){rtI9e z=MB;PS#{Z(U|t8qYQ_ySW~H_n?h`_xOzzWelCCBrFbyYj>Zwv<1S!904_at=14bpQ zEQ&=mq0%#37w?g{TKWdwfl1$Z8Do6vBU$Ad+Z@GOe7{2J@w(51UX2=L{8&Y~yv4g6 z?6zRe44bOTl=X4iSZHo=fRin$HGa)8n{{mrTP7bMogMyyRJ+H46SCrTUULd%H__gz zZOF3N+VNkRb=df_>6zMfyftP`e4sNS3Cg6S;R(M(qouc|ObX&)hb4uNCdTIhC10u+ z8%ykomStGK-pP6U`y#&|?VevTb;ZUv#^EF|jw$BazC#0_oTNrf_TkvdjZ#1!S_zFC zLVb+*dj!Td9OzPO5K?rT1g&xjeyyfoS~&)Mc`XwacvC3Z&Gxs*Q>bAL{XiHS76IUC zpN)-Pe>)ww+~JJ3eR z#)Fp6gg%WfHvl=uRF5ddtSO(CaN%1t`9`L7vTdTI%U&(5m)>z(n%h-!v9v5rU;2?K zmd3(&z9*gJat^W%n}qLMSQ9f#+&x0&jc!GlkhafKO&JCB1_-xE*iA5SG;Dwb-L<1U z(Gd~yY68X7pbFIrQi_toT0HCbRnk?Ns7Z$PQ?I_#D!PXz>FiB&yX31XHvJ%s*8RiC z!Dq`vFw*y~)0lDWH%gg-pYjI!>86sFy>%2>!qr5m#p#D1PEq+?yhC5zDzG+fui$8? zxy1CWjXqLgSF@dL{h8XIr)a{x`N0+H^TX_AA1fr5mCr!M zLdfJ(!b41+hb1OX#!%$$IWz#R>Q-7ftN+HR=0%(?yYkEaY~wI6L)-L|B#~F*m#)|} z85q3L8$h&k#^J@tE9vybfK?d>GvVv_smuqD9i1aI%M4oC@*!+R%7~{er+aEoswZc7 z)gFn@d9M*i1>FD&Agi)dVkrL}pJgF=EEp3WlcLJH3#e_yo$~PnmZ;DjNn(5AZ`VS! zZf^tY*ghZnsn4yE$bSeNwLZ*S+x9q)rpk?KHnbJ*d>WnspFoFqy@oMWU@S6R9H!mN(BQwxtT%b;6Uj8foZAg`seLDx{!M`5 zgmN^Ax-kT@MTH$~j|*&SpPvWTwQih`>ZKo!x%O)E_1j2VELI#W4!V;kiv8ef&W2Ga zGUHNM*b{F}AGd{%^w5}gDvPBU8lJWJ)|jG`^Tw*F+KfT36q>Zb^(5wYBzD_|FC%JHeSR7Tb?^c4mtb!)SQ>9a_3nuDKU^TtP*#*AS%uO=?+{n3g?NWe_cxFkyO_9e>a=NI#yu6lMd-p(2Z;$KYdZwvYrZC= zFXn?jjKmh$i0wvl*^WH$V4Jg+bN@LcGV3gnJYEp)!Upbbj{7J4Q zx_;V}D~pYQxRG5&22H+k$ zedKfjmbhTQ#e4%`i^({JU6!qj_Z&s<%6{E-6+K*;O{X>SSdxLB3;L~`;R61@J0SLt fso<`IblP4FJ4yRdz|XF$tQ$bCznw?W&Gi2QTb-Bt literal 0 HcmV?d00001 diff --git a/server-console/src/main.js b/server-console/src/main.js index b442d28855..ea8ba6337e 100644 --- a/server-console/src/main.js +++ b/server-console/src/main.js @@ -408,6 +408,13 @@ var labels = { logWindow.open(); } }, + restoreBackup: { + label: 'Restore Backup Instructions', + click: function() { + var folder = getRootHifiDataDirectory() + "/Server Backup"; + openBackupInstructions(folder); + } + }, share: { label: 'Share', click: function() { @@ -443,6 +450,7 @@ function buildMenuArray(serverState) { menuArray.push(labels.stopServer); menuArray.push(labels.settings); menuArray.push(labels.viewLogs); + menuArray.push(labels.restoreBackup); menuArray.push(separator); menuArray.push(labels.share); menuArray.push(separator); @@ -510,29 +518,32 @@ function backupResourceDirectories(folder) { } } +function openBackupInstructions(folder) { + // Explain user how to restore server + var window = new BrowserWindow({ + icon: appIcon, + width: 800, + height: 520, + }); + window.loadURL('file://' + __dirname + '/content-update.html'); + if (!debug) { + window.setMenu(null); + } + window.show(); + + electron.ipcMain.on('ready', function() { + console.log("got ready"); + window.webContents.send('update', folder); + }); + +} function backupResourceDirectoriesAndRestart() { homeServer.stop(); var folder = getRootHifiDataDirectory() + "/Server Backup - " + Date.now(); if (backupResourceDirectories(folder)) { maybeInstallDefaultContentSet(onContentLoaded); - - // Explain user how to restore server - var window = new BrowserWindow({ - icon: appIcon, - width: 500, - height: 350, - }); - window.loadURL('file://' + __dirname + '/content-update.html'); - if (!debug) { - window.setMenu(null); - } - window.show(); - - electron.ipcMain.on('ready', function() { - console.log("got ready"); - window.webContents.send('update', folder); - }); + openBackupInstructions(folder); } else { dialog.showMessageBox({ type: 'warning', From b83243d65d5f85453eed1849d15878f08b24a79b Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 29 Sep 2016 15:49:47 -0700 Subject: [PATCH 18/28] Fixed CSS madness --- server-console/src/content-update.html | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/server-console/src/content-update.html b/server-console/src/content-update.html index 3c0eff2fa0..c4ed14473a 100644 --- a/server-console/src/content-update.html +++ b/server-console/src/content-update.html @@ -15,29 +15,25 @@
+ +
- - Step 1 -

1. Stop your Sandbox server. - + Step 2 +

2. Go to your backup directory: +

- - Step 2 -

2. Go to your backup directory: - - + Step 1 +

1. Stop your Sandbox server.

- Step 3

3. Copy the backed up content and paste it into the parent directory.

- Step 4

4. Restart your Sandbox server.

From f17a062399c9551ff213ab788211b2c81a4c421c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 29 Sep 2016 17:08:34 -0700 Subject: [PATCH 19/28] CR --- server-console/src/content-update.css | 42 ++++++++++++------------ server-console/src/main.js | 46 +++++++++++++-------------- 2 files changed, 43 insertions(+), 45 deletions(-) diff --git a/server-console/src/content-update.css b/server-console/src/content-update.css index ebfd8aeba0..9303e450b5 100644 --- a/server-console/src/content-update.css +++ b/server-console/src/content-update.css @@ -56,98 +56,98 @@ a:hover { color: #2D88A4; } -.header{ +.header { width: 95%; left: 2.5% } -.colmask{ +.colmask { width: 95%; left: 2.5% } -.colmid{ right: 25% } -.colin{ right: 25% } -.colleft{ right: 25% } -.col1{ +.colmid { right: 25% } +.colin { right: 25% } +.colleft { right: 25% } +.col1 { width: 23%; left: 101% } -.col2{ +.col2 { width: 23%; left: 53% } -.col3{ +.col3 { width: 23%; left: 80% } -.col4{ +.col4 { width: 23%; left: 82% } -.footer{ +.footer { width: 95%; left: 2.5% } -.header{ +.header { clear: both; float: left; position: relative; border-bottom: #000 1px solid; background-color: #b4d2f7 } -.colmask{ +.colmask { clear: both; float: left; overflow: hidden; position: relative; } -.colmid{ +.colmid { float: left; width: 100%; position: relative; } -.colin{ +.colin { float: left; width: 100%; position: relative; } -.colleft{ +.colleft { float: left; width: 100%; position: relative; } -.col1{ +.col1 { padding: 0px 0px 1em 0px; overflow: hidden; float: left; position: relative; } -.col2{ +.col2 { padding: 0px 0px 1em 0px; overflow: hidden; float: left; position: relative; } -.col3{ +.col3 { padding: 0px 0px 1em 0px; overflow: hidden; float: left; position: relative; } -.col4{ +.col4 { padding: 0px 0px 1em 0px; overflow: hidden; float: left; position: relative; } -.footer{ +.footer { clear: both; float: left; position: relative; @@ -155,7 +155,7 @@ a:hover { border-top: #000 1px solid; } -.bottom{ +.bottom { clear: both; width: 100%; float: left; diff --git a/server-console/src/main.js b/server-console/src/main.js index ea8ba6337e..e297ca3276 100644 --- a/server-console/src/main.js +++ b/server-console/src/main.js @@ -501,16 +501,15 @@ function backupResourceDirectories(folder) { fs.mkdirSync(folder); console.log("Created directory " + folder); - var dsBackup = path.join(folder, '/domain-server'); - fs.renameSync(getDomainServerClientResourcesDirectory(), dsBackup); - console.log("Moved directory " + getDomainServerClientResourcesDirectory()); - console.log("to " + dsBackup); - var acBackup = path.join(folder, '/assignment-client'); - fs.renameSync(getAssignmentClientResourcesDirectory(), acBackup); - console.log("Moved directory " + getDomainServerClientResourcesDirectory()); - console.log("to " + acBackup); + + fs.copySync(getDomainServerClientResourcesDirectory(), dsBackup); + fs.copySync(getAssignmentClientResourcesDirectory(), acBackup); + + fs.removeSync(getDomainServerClientResourcesDirectory()); + fs.removeSync(getAssignmentClientResourcesDirectory()); + return true; } catch (e) { console.log(e); @@ -519,23 +518,22 @@ function backupResourceDirectories(folder) { } function openBackupInstructions(folder) { - // Explain user how to restore server - var window = new BrowserWindow({ - icon: appIcon, - width: 800, - height: 520, - }); - window.loadURL('file://' + __dirname + '/content-update.html'); - if (!debug) { - window.setMenu(null); - } - window.show(); - - electron.ipcMain.on('ready', function() { - console.log("got ready"); - window.webContents.send('update', folder); - }); + // Explain user how to restore server + var window = new BrowserWindow({ + icon: appIcon, + width: 800, + height: 520, + }); + window.loadURL('file://' + __dirname + '/content-update.html'); + if (!debug) { + window.setMenu(null); + } + window.show(); + electron.ipcMain.on('ready', function() { + console.log("got ready"); + window.webContents.send('update', folder); + }); } function backupResourceDirectoriesAndRestart() { homeServer.stop(); From 4f7fdfc3451426dad666be48187d34244aad87a4 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Fri, 30 Sep 2016 03:31:35 +0200 Subject: [PATCH 20/28] eliminated `else`, this might look cleaner --- libraries/networking/src/NodeList.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index f3934a51f9..617ba85bad 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -536,25 +536,25 @@ void NodeList::processDomainServerList(QSharedPointer message) QUuid domainUUID; packetStream >> domainUUID; + if (_domainHandler.isConnected() && _domainHandler.getUUID() != domainUUID) { + // Recieved packet from different domain. + qWarning() << "IGNORING DomainList packet from" << domainUUID << "while connected to" << _domainHandler.getUUID(); + return; + } + // pull our owner UUID from the packet, it's always the first thing QUuid newUUID; packetStream >> newUUID; + setSessionUUID(newUUID); // if this was the first domain-server list from this domain, we've now connected if (!_domainHandler.isConnected()) { - setSessionUUID(newUUID); _domainHandler.setUUID(domainUUID); _domainHandler.setIsConnected(true); // in case we didn't use a place name to get to this domain, // give the address manager a chance to lookup a default one now DependencyManager::get()->lookupShareableNameForDomainID(domainUUID); - } else if (_domainHandler.getUUID() != domainUUID) { - // Recieved packet from different domain. - qWarning() << "IGNORING DomainList packet from" << domainUUID << "while connected to" << _domainHandler.getUUID(); - return; - } else { - setSessionUUID(newUUID); } // pull the permissions/right/privileges for this node out of the stream From 42e28fa010a4dd4615e430b3aa1e4a51000e9f23 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 30 Sep 2016 15:48:10 -0700 Subject: [PATCH 21/28] Fix crash in initializing texture transfer thread --- libraries/gpu-gl/src/gpu/gl/GLTextureTransfer.cpp | 13 ++++++++++++- libraries/gpu-gl/src/gpu/gl/GLTextureTransfer.h | 12 ++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/libraries/gpu-gl/src/gpu/gl/GLTextureTransfer.cpp b/libraries/gpu-gl/src/gpu/gl/GLTextureTransfer.cpp index 75af08d9a3..45403f4d4d 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTextureTransfer.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLTextureTransfer.cpp @@ -18,7 +18,6 @@ std::unordered_map _map; #endif -//#define TEXTURE_TRANSFER_PBOS #ifdef TEXTURE_TRANSFER_PBOS #define TEXTURE_TRANSFER_BLOCK_SIZE (64 * 1024) @@ -62,11 +61,16 @@ void GLTextureTransferHelper::transferTexture(const gpu::TexturePointer& texture void GLTextureTransferHelper::setup() { #ifdef THREADED_TEXTURE_TRANSFER _context.makeCurrent(); + +#ifdef TEXTURE_TRANSFER_FORCE_DRAW + // FIXME don't use opengl 4.5 DSA functionality without verifying it's present glCreateRenderbuffers(1, &_drawRenderbuffer); glNamedRenderbufferStorage(_drawRenderbuffer, GL_RGBA8, 128, 128); glCreateFramebuffers(1, &_drawFramebuffer); glNamedFramebufferRenderbuffer(_drawFramebuffer, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _drawRenderbuffer); glCreateFramebuffers(1, &_readFramebuffer); +#endif + #ifdef TEXTURE_TRANSFER_PBOS std::array pbos; glCreateBuffers(TEXTURE_TRANSFER_PBO_COUNT, &pbos[0]); @@ -84,7 +88,9 @@ void GLTextureTransferHelper::setup() { void GLTextureTransferHelper::shutdown() { #ifdef THREADED_TEXTURE_TRANSFER _context.makeCurrent(); +#endif +#ifdef TEXTURE_TRANSFER_FORCE_DRAW glNamedFramebufferRenderbuffer(_drawFramebuffer, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0); glDeleteFramebuffers(1, &_drawFramebuffer); _drawFramebuffer = 0; @@ -165,6 +171,11 @@ bool GLTextureTransferHelper::process() { } gltexture->finishTransfer(); + +#ifdef TEXTURE_TRANSFER_FORCE_DRAW + // FIXME force a draw on the texture transfer thread before passing the texture to the main thread for use +#endif + #ifdef THREADED_TEXTURE_TRANSFER clientWait(); #endif diff --git a/libraries/gpu-gl/src/gpu/gl/GLTextureTransfer.h b/libraries/gpu-gl/src/gpu/gl/GLTextureTransfer.h index 289aec40bb..a23c282fd4 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTextureTransfer.h +++ b/libraries/gpu-gl/src/gpu/gl/GLTextureTransfer.h @@ -21,6 +21,14 @@ #define THREADED_TEXTURE_TRANSFER #endif +#ifdef THREADED_TEXTURE_TRANSFER +// FIXME when sparse textures are enabled, it's harder to force a draw on the transfer thread +// also, the current draw code is implicitly using OpenGL 4.5 functionality +//#define TEXTURE_TRANSFER_FORCE_DRAW +// FIXME PBO's increase the complexity and don't seem to work reliably +//#define TEXTURE_TRANSFER_PBOS +#endif + namespace gpu { namespace gl { using TextureList = std::list; @@ -43,11 +51,15 @@ public: private: #ifdef THREADED_TEXTURE_TRANSFER ::gl::OffscreenContext _context; +#endif + +#ifdef TEXTURE_TRANSFER_FORCE_DRAW // Framebuffers / renderbuffers for forcing access to the texture on the transfer thread GLuint _drawRenderbuffer { 0 }; GLuint _drawFramebuffer { 0 }; GLuint _readFramebuffer { 0 }; #endif + // A mutex for protecting items access on the render and transfer threads Mutex _mutex; // Commands that have been submitted for execution on the texture transfer thread From c806f6cad2166518466eb30cb0b9089cfa067cc8 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Fri, 30 Sep 2016 16:05:39 -0700 Subject: [PATCH 22/28] better shutdown check for timer firings --- libraries/script-engine/src/ScriptEngine.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index e4d1cd7307..160ad77197 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -1017,9 +1017,12 @@ void ScriptEngine::updateMemoryCost(const qint64& deltaSize) { } void ScriptEngine::timerFired() { - if (DependencyManager::get()->isStopped()) { - qCDebug(scriptengine) << "Script.timerFired() while shutting down is ignored... parent script:" << getFilename(); - return; // bail early + { + auto engine = DependencyManager::get(); + if (!engine || engine->isStopped()) { + qCDebug(scriptengine) << "Script.timerFired() while shutting down is ignored... parent script:" << getFilename(); + return; // bail early + } } QTimer* callingTimer = reinterpret_cast(sender()); From 0f06d0e4cc9f974fe4ec90d80a65cd0fb86283e2 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sat, 1 Oct 2016 10:40:31 -0700 Subject: [PATCH 23/28] Don't use GL functions before making the context current --- libraries/gl/src/gl/GLWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/gl/src/gl/GLWidget.cpp b/libraries/gl/src/gl/GLWidget.cpp index f2b823a65e..23bdcff640 100644 --- a/libraries/gl/src/gl/GLWidget.cpp +++ b/libraries/gl/src/gl/GLWidget.cpp @@ -67,8 +67,8 @@ void GLWidget::createContext() { _context = new gl::Context(); _context->setWindow(windowHandle()); _context->create(); - _context->clear(); _context->makeCurrent(); + _context->clear(); } bool GLWidget::makeCurrent() { From 2cba3db2b6471d9e9b3adb5f9b3d5dfa4c15365b Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 30 Sep 2016 17:43:26 -0700 Subject: [PATCH 24/28] fix crash when bouncing to escotology, which may or may not be related --- .../src/model-networking/ModelCache.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 306a19c308..6eacbab46a 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -377,8 +377,10 @@ void GeometryResource::deleter() { } void GeometryResource::setTextures() { - for (const FBXMaterial& material : _fbxGeometry->materials) { - _materials.push_back(std::make_shared(material, _textureBaseUrl)); + if (_fbxGeometry) { + for (const FBXMaterial& material : _fbxGeometry->materials) { + _materials.push_back(std::make_shared(material, _textureBaseUrl)); + } } } @@ -457,7 +459,9 @@ model::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& baseUrl, c _textures[channel] = Texture { fbxTexture.name, texture }; auto map = std::make_shared(); - map->setTextureSource(texture->_textureSource); + if (texture) { + map->setTextureSource(texture->_textureSource); + } map->setTextureTransform(fbxTexture.transform); return map; From 265996156c5376c6c9846ea65ac4d81b7f1ca0e9 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 27 Sep 2016 11:44:51 -0700 Subject: [PATCH 25/28] Remove unused header and typedef --- .../display-plugins/src/display-plugins/OpenGLDisplayPlugin.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index ef15861843..74f8cdbc10 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -8,6 +8,7 @@ #pragma once #include "DisplayPlugin.h" +#include #include #include @@ -18,7 +19,6 @@ #include #include -#include #include namespace gpu { @@ -35,7 +35,6 @@ protected: using Mutex = std::mutex; using Lock = std::unique_lock; using Condition = std::condition_variable; - using TextureEscrow = GLEscrow; public: // These must be final to ensure proper ordering of operations // between the main thread and the presentation thread From 933388bc61c136312f4bd31fa655b0813fc5361b Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 27 Sep 2016 11:45:35 -0700 Subject: [PATCH 26/28] Remove oglplus usage from offscreen UI --- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 194 +++++++++++++++----- 1 file changed, 143 insertions(+), 51 deletions(-) diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index bdfa359b8b..d1c884f264 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -6,7 +6,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "OffscreenQmlSurface.h" -#include "OglplusHelpers.h" +#include "Config.h" + +#include +#include +#include #include #include @@ -116,6 +120,108 @@ static const QEvent::Type RENDER = QEvent::Type(QEvent::User + 2); static const QEvent::Type RESIZE = QEvent::Type(QEvent::User + 3); static const QEvent::Type STOP = QEvent::Type(QEvent::User + 4); +class RawTextureRecycler { +public: + using TexturePtr = GLuint; + RawTextureRecycler(bool useMipmaps) : _useMipmaps(useMipmaps) {} + void setSize(const uvec2& size); + void clear(); + TexturePtr getNextTexture(); + void recycleTexture(GLuint texture); + +private: + + struct TexInfo { + TexturePtr _tex { 0 }; + uvec2 _size; + bool _active { false }; + + TexInfo() {} + TexInfo(TexturePtr tex, const uvec2& size) : _tex(tex), _size(size) {} + }; + + using Map = std::map; + using Queue = std::queue; + + Map _allTextures; + Queue _readyTextures; + uvec2 _size { 1920, 1080 }; + bool _useMipmaps; +}; + + +void RawTextureRecycler::setSize(const uvec2& size) { + if (size == _size) { + return; + } + _size = size; + while (!_readyTextures.empty()) { + _readyTextures.pop(); + } + std::set toDelete; + std::for_each(_allTextures.begin(), _allTextures.end(), [&](Map::const_reference item) { + if (!item.second._active && item.second._size != _size) { + toDelete.insert(item.first); + } + }); + std::for_each(toDelete.begin(), toDelete.end(), [&](Map::key_type key) { + _allTextures.erase(key); + }); +} + +void RawTextureRecycler::clear() { + while (!_readyTextures.empty()) { + _readyTextures.pop(); + } + _allTextures.clear(); +} + +RawTextureRecycler::TexturePtr RawTextureRecycler::getNextTexture() { + if (_readyTextures.empty()) { + TexturePtr newTexture; + glGenTextures(1, &newTexture); + + glBindTexture(GL_TEXTURE_2D, newTexture); + if (_useMipmaps) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8.0f); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -0.2f); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8.0f); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, _size.x, _size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + _allTextures[newTexture] = TexInfo { newTexture, _size }; + _readyTextures.push(newTexture); + } + + TexturePtr result = _readyTextures.front(); + _readyTextures.pop(); + auto& item = _allTextures[result]; + item._active = true; + return result; +} + +void RawTextureRecycler::recycleTexture(GLuint texture) { + Q_ASSERT(_allTextures.count(texture)); + auto& item = _allTextures[texture]; + Q_ASSERT(item._active); + item._active = false; + if (item._size != _size) { + // Buh-bye + _allTextures.erase(texture); + return; + } + + _readyTextures.push(item._tex); +} + + class OffscreenQmlRenderThread : public QThread { public: OffscreenQmlRenderThread(OffscreenQmlSurface* surface, QOpenGLContext* shareContext); @@ -165,9 +271,9 @@ private: OffscreenQmlSurface* _surface{ nullptr }; QQuickWindow* _quickWindow{ nullptr }; QMyQuickRenderControl* _renderControl{ nullptr }; - FramebufferPtr _fbo; - RenderbufferPtr _depthStencil; - TextureRecycler _textures { true }; + GLuint _fbo { 0 }; + GLuint _depthStencil { 0 }; + RawTextureRecycler _textures { true }; GLTextureEscrow _escrow; uint64_t _lastRenderTime{ 0 }; @@ -253,24 +359,23 @@ bool OffscreenQmlRenderThread::event(QEvent *e) { } void OffscreenQmlRenderThread::setupFbo() { - using namespace oglplus; _textures.setSize(_size); - - try { - _depthStencil.reset(new Renderbuffer()); - Context::Bound(Renderbuffer::Target::Renderbuffer, *_depthStencil) - .Storage( - PixelDataInternalFormat::DepthComponent, - _size.x, _size.y); - - _fbo.reset(new Framebuffer()); - _fbo->Bind(Framebuffer::Target::Draw); - _fbo->AttachRenderbuffer(Framebuffer::Target::Draw, - FramebufferAttachment::Depth, *_depthStencil); - DefaultFramebuffer().Bind(Framebuffer::Target::Draw); - } catch (oglplus::Error& error) { - qWarning() << "OpenGL error in QML render setup: " << error.what(); + if (_depthStencil) { + glDeleteRenderbuffers(1, &_depthStencil); + _depthStencil = 0; } + glGenRenderbuffers(1, &_depthStencil); + glBindRenderbuffer(GL_RENDERBUFFER, _depthStencil); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, _size.x, _size.y); + + if (_fbo) { + glDeleteFramebuffers(1, &_fbo); + _fbo = 0; + } + glGenFramebuffers(1, &_fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthStencil); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); } QJsonObject OffscreenQmlRenderThread::getGLContextData() { @@ -309,8 +414,15 @@ void OffscreenQmlRenderThread::init() { void OffscreenQmlRenderThread::cleanup() { _renderControl->invalidate(); - _fbo.reset(); - _depthStencil.reset(); + if (_depthStencil) { + glDeleteRenderbuffers(1, &_depthStencil); + _depthStencil = 0; + } + if (_fbo) { + glDeleteFramebuffers(1, &_fbo); + _fbo = 0; + } + _textures.clear(); _canvas.doneCurrent(); @@ -371,42 +483,22 @@ void OffscreenQmlRenderThread::render() { releaseMainThread.trigger(); } - using namespace oglplus; - - _quickWindow->setRenderTarget(GetName(*_fbo), QSize(_size.x, _size.y)); + _quickWindow->setRenderTarget(_fbo, QSize(_size.x, _size.y)); try { - PROFILE_RANGE("qml_render") - - TexturePtr texture = _textures.getNextTexture(); - - try { - _fbo->Bind(Framebuffer::Target::Draw); - _fbo->AttachTexture(Framebuffer::Target::Draw, FramebufferAttachment::Color, *texture, 0); - _fbo->Complete(Framebuffer::Target::Draw); - } catch (oglplus::Error& error) { - qWarning() << "OpenGL error in QML render: " << error.what(); - - // In case we are failing from a failed setupFbo, reset fbo before next render - setupFbo(); - throw; - } - - { + GLuint texture = _textures.getNextTexture(); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo); + glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0); PROFILE_RANGE("qml_render->rendercontrol") _renderControl->render(); - // FIXME The web browsers seem to be leaving GL in an error state. - // Need a debug context with sync logging to figure out why. - // for now just clear the errors - glGetError(); - } - Context::Bound(oglplus::Texture::Target::_2D, *texture).GenerateMipmap(); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBindTexture(GL_TEXTURE_2D, texture); + glGenerateMipmap(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0); - // FIXME probably unecessary - DefaultFramebuffer().Bind(Framebuffer::Target::Draw); _quickWindow->resetOpenGLState(); - _escrow.submit(GetName(*texture)); + _escrow.submit(texture); _lastRenderTime = usecTimestampNow(); } catch (std::runtime_error& error) { qWarning() << "Failed to render QML: " << error.what(); From 04f654794069b451039f04bd139af994758e0103 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Sat, 1 Oct 2016 12:15:03 -0700 Subject: [PATCH 27/28] add guards to getShapeKey --- libraries/render-utils/src/MeshPartPayload.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 50c0c869ff..2644bc6096 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -429,7 +429,12 @@ ItemKey ModelMeshPartPayload::getKey() const { } ShapeKey ModelMeshPartPayload::getShapeKey() const { - assert(_model->isLoaded()); + + // guard against partially loaded meshes + if (!_model || !_model->isLoaded() || !_model->getGeometry()) { + return ShapeKey::Builder::invalid(); + } + const FBXGeometry& geometry = _model->getFBXGeometry(); const auto& networkMeshes = _model->getGeometry()->getMeshes(); From 7fe16442faea5bac5dc4107ad20763c914ad91c1 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Sat, 1 Oct 2016 15:45:59 -0700 Subject: [PATCH 28/28] make calculateTextureInfo thread safe --- libraries/model/src/model/Material.cpp | 42 +++++++++++++++++++ libraries/model/src/model/Material.h | 17 +++++++- .../render-utils/src/MeshPartPayload.cpp | 32 -------------- libraries/render-utils/src/MeshPartPayload.h | 10 ++--- libraries/render-utils/src/Model.cpp | 3 +- 5 files changed, 62 insertions(+), 42 deletions(-) diff --git a/libraries/model/src/model/Material.cpp b/libraries/model/src/model/Material.cpp index 6e7968a571..4e01c4b866 100755 --- a/libraries/model/src/model/Material.cpp +++ b/libraries/model/src/model/Material.cpp @@ -44,8 +44,11 @@ Material::Material(const Material& material) : } Material& Material::operator= (const Material& material) { + QMutexLocker locker(&_textureMapsMutex); + _key = (material._key); _textureMaps = (material._textureMaps); + _hasCalculatedTextureInfo = false; // copied: create the Buffer to store the properties, avoid holding a ref to the old Buffer Schema schema; @@ -112,6 +115,8 @@ void Material::setScattering(float scattering) { } void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textureMap) { + QMutexLocker locker(&_textureMapsMutex); + if (textureMap) { _key.setMapChannel(channel, (true)); _textureMaps[channel] = textureMap; @@ -119,6 +124,7 @@ void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textur _key.setMapChannel(channel, (false)); _textureMaps.erase(channel); } + _hasCalculatedTextureInfo = false; _schemaBuffer.edit()._key = (uint32)_key._flags.to_ulong(); @@ -173,6 +179,8 @@ void Material::resetOpacityMap() const { const TextureMapPointer Material::getTextureMap(MapChannel channel) const { + QMutexLocker locker(&_textureMapsMutex); + auto result = _textureMaps.find(channel); if (result != _textureMaps.end()) { return (result->second); @@ -180,3 +188,37 @@ const TextureMapPointer Material::getTextureMap(MapChannel channel) const { return TextureMapPointer(); } } + + +bool Material::calculateMaterialInfo() const { + if (!_hasCalculatedTextureInfo) { + QMutexLocker locker(&_textureMapsMutex); + + bool allTextures = true; // assume we got this... + _textureSize = 0; + _textureCount = 0; + + for (auto const &textureMapItem : _textureMaps) { + auto textureMap = textureMapItem.second; + if (textureMap) { + auto textureSoure = textureMap->getTextureSource(); + if (textureSoure) { + auto texture = textureSoure->getGPUTexture(); + if (texture) { + auto size = texture->getSize(); + _textureSize += size; + _textureCount++; + } else { + allTextures = false; + } + } else { + allTextures = false; + } + } else { + allTextures = false; + } + } + _hasCalculatedTextureInfo = allTextures; + } + return _hasCalculatedTextureInfo; +} diff --git a/libraries/model/src/model/Material.h b/libraries/model/src/model/Material.h index 304ef2e93b..8851ef4ce9 100755 --- a/libraries/model/src/model/Material.h +++ b/libraries/model/src/model/Material.h @@ -11,6 +11,8 @@ #ifndef hifi_model_Material_h #define hifi_model_Material_h +#include + #include #include @@ -324,7 +326,7 @@ public: // The texture map to channel association void setTextureMap(MapChannel channel, const TextureMapPointer& textureMap); - const TextureMaps& getTextureMaps() const { return _textureMaps; } + const TextureMaps& getTextureMaps() const { return _textureMaps; } // FIXME - not thread safe... const TextureMapPointer getTextureMap(MapChannel channel) const; // Albedo maps cannot have opacity detected until they are loaded @@ -344,12 +346,25 @@ public: }; const UniformBufferView& getTexMapArrayBuffer() const { return _texMapArrayBuffer; } + + int getTextureCount() const { calculateMaterialInfo(); return _textureCount; } + size_t getTextureSize() const { calculateMaterialInfo(); return _textureSize; } + bool hasTextureInfo() const { return _hasCalculatedTextureInfo; } + private: mutable MaterialKey _key; mutable UniformBufferView _schemaBuffer; mutable UniformBufferView _texMapArrayBuffer; TextureMaps _textureMaps; + + mutable QMutex _textureMapsMutex { QMutex::Recursive }; + mutable size_t _textureSize { 0 }; + mutable int _textureCount { 0 }; + mutable bool _hasCalculatedTextureInfo { false }; + bool calculateMaterialInfo() const; + + }; typedef std::shared_ptr< Material > MaterialPointer; diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 50c0c869ff..2994c7fa5b 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -71,39 +71,8 @@ void MeshPartPayload::updateTransform(const Transform& transform, const Transfor void MeshPartPayload::updateMaterial(model::MaterialPointer drawMaterial) { _drawMaterial = drawMaterial; - calculateMaterialSize(); } -bool MeshPartPayload::calculateMaterialSize() { - bool allTextures = true; // assume we got this... - _materialTextureSize = 0; - _materialTextureCount = 0; - auto textureMaps = _drawMaterial->getTextureMaps(); - for (auto const &textureMapItem : textureMaps) { - auto textureMap = textureMapItem.second; - if (textureMap) { - auto textureSoure = textureMap->getTextureSource(); - if (textureSoure) { - auto texture = textureSoure->getGPUTexture(); - if (texture) { - //auto storedSize = texture->getStoredSize(); - auto size = texture->getSize(); - _materialTextureSize += size; - _materialTextureCount++; - } else { - allTextures = false; - } - } else { - allTextures = false; - } - } else { - allTextures = false; - } - } - return allTextures; -} - - ItemKey MeshPartPayload::getKey() const { ItemKey::Builder builder; builder.withTypeShape(); @@ -378,7 +347,6 @@ void ModelMeshPartPayload::initCache() { auto networkMaterial = _model->getGeometry()->getShapeMaterial(_shapeID); if (networkMaterial) { _drawMaterial = networkMaterial; - calculateMaterialSize(); } } diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 3ecd8da03e..04b63874cd 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -66,13 +66,9 @@ public: bool _hasColorAttrib = false; size_t getVerticesCount() const { return _drawMesh ? _drawMesh->getNumVertices() : 0; } - size_t getMaterialTextureSize() { return _materialTextureSize; } - int getMaterialTextureCount() { return _materialTextureCount; } - bool calculateMaterialSize(); - -protected: - size_t _materialTextureSize { 0 }; - int _materialTextureCount { 0 }; + size_t getMaterialTextureSize() { return _drawMaterial ? _drawMaterial->getTextureSize() : 0; } + int getMaterialTextureCount() { return _drawMaterial ? _drawMaterial->getTextureCount() : 0; } + bool hasTextureInfo() const { return _drawMaterial ? _drawMaterial->hasTextureInfo() : false; } }; namespace render { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index f6caa7c3d3..28a1c3d579 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -168,10 +168,9 @@ void Model::calculateTextureInfo() { bool allTexturesLoaded = true; foreach(auto renderItem, _modelMeshRenderItemsSet) { auto meshPart = renderItem.get(); - bool allTexturesForThisMesh = meshPart->calculateMaterialSize(); - allTexturesLoaded = allTexturesLoaded & allTexturesForThisMesh; textureSize += meshPart->getMaterialTextureSize(); textureCount += meshPart->getMaterialTextureCount(); + allTexturesLoaded = allTexturesLoaded & meshPart->hasTextureInfo(); } _renderInfoTextureSize = textureSize; _renderInfoTextureCount = textureCount;