History

Merge branch 'master' of https://github.com/highfidelity/hifi into orange

Sam Gateau committed 9 years ago

Commit 156c20d2 parents ca7e782 baf6318191 files · +5682 −2482Browse files

Showing the changes to interface/src/Application.cpp (1 of 191 files). Show all

Unified · Split

interface/src/Application.cpp+427−192
@@ -25,6 +25,7 @@ · 24 unmodified lines
25#include <QtCore/QCommandLineParser>25#include <QtCore/QCommandLineParser>
26#include <QtCore/QMimeData>26#include <QtCore/QMimeData>
27#include <QtCore/QThreadPool>27#include <QtCore/QThreadPool>
28#include <QtConcurrent/QtConcurrentRun>
28 29
29#include <QtGui/QScreen>30#include <QtGui/QScreen>
30#include <QtGui/QWindow>31#include <QtGui/QWindow>
@@ -48,6 +49,7 @@ · 17 unmodified lines
48 49
49#include <gl/QOpenGLContextWrapper.h>50#include <gl/QOpenGLContextWrapper.h>
50 51
52#include <shared/QtHelpers.h>
51#include <shared/GlobalAppProperties.h>53#include <shared/GlobalAppProperties.h>
52#include <StatTracker.h>54#include <StatTracker.h>
53#include <Trace.h>55#include <Trace.h>
@@ -142,7 +144,6 @@ · 88 unmodified lines
142#include "avatar/MyHead.h"144#include "avatar/MyHead.h"
143#include "CrashHandler.h"145#include "CrashHandler.h"
144#include "devices/DdeFaceTracker.h"146#include "devices/DdeFaceTracker.h"
145#include "devices/Leapmotion.h"
146#include "DiscoverabilityManager.h"147#include "DiscoverabilityManager.h"
147#include "GLCanvas.h"148#include "GLCanvas.h"
148#include "InterfaceDynamicFactory.h"149#include "InterfaceDynamicFactory.h"
@@ -477,6 +478,12 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 328 unmodified lines
477 static const auto SUPPRESS_SETTINGS_RESET = "--suppress-settings-reset";478 static const auto SUPPRESS_SETTINGS_RESET = "--suppress-settings-reset";
478 bool suppressPrompt = cmdOptionExists(argc, const_cast<const char**>(argv), SUPPRESS_SETTINGS_RESET);479 bool suppressPrompt = cmdOptionExists(argc, const_cast<const char**>(argv), SUPPRESS_SETTINGS_RESET);
479 bool previousSessionCrashed = CrashHandler::checkForResetSettings(runningMarkerExisted, suppressPrompt);480 bool previousSessionCrashed = CrashHandler::checkForResetSettings(runningMarkerExisted, suppressPrompt);
481 // get dir to use for cache
482 static const auto CACHE_SWITCH = "--cache";
483 QString cacheDir = getCmdOption(argc, const_cast<const char**>(argv), CACHE_SWITCH);
484 if (!cacheDir.isEmpty()) {
485 qApp->setProperty(hifi::properties::APP_LOCAL_DATA_PATH, cacheDir);
486 }
480 487
481 Setting::init();488 Setting::init();
482 489
@@ -942,58 +949,68 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 459 unmodified lines
942 // Make sure we don't time out during slow operations at startup949 // Make sure we don't time out during slow operations at startup
943 updateHeartbeat();950 updateHeartbeat();
944 951
945
946 // sessionRunTime will be reset soon by loadSettings. Grab it now to get previous session value.
947 // The value will be 0 if the user blew away settings this session, which is both a feature and a bug.
948 static const QString TESTER = "HIFI_TESTER";
949 auto gpuIdent = GPUIdent::getInstance();
950 auto glContextData = getGLContextData();
951 QJsonObject properties = {
952 { "version", applicationVersion() },
953 { "tester", QProcessEnvironment::systemEnvironment().contains(TESTER) },
954 { "previousSessionCrashed", _previousSessionCrashed },
955 { "previousSessionRuntime", sessionRunTime.get() },
956 { "cpu_architecture", QSysInfo::currentCpuArchitecture() },
957 { "kernel_type", QSysInfo::kernelType() },
958 { "kernel_version", QSysInfo::kernelVersion() },
959 { "os_type", QSysInfo::productType() },
960 { "os_version", QSysInfo::productVersion() },
961 { "gpu_name", gpuIdent->getName() },
962 { "gpu_driver", gpuIdent->getDriver() },
963 { "gpu_memory", static_cast<qint64>(gpuIdent->getMemory()) },
964 { "gl_version_int", glVersionToInteger(glContextData.value("version").toString()) },
965 { "gl_version", glContextData["version"] },
966 { "gl_vender", glContextData["vendor"] },
967 { "gl_sl_version", glContextData["sl_version"] },
968 { "gl_renderer", glContextData["renderer"] },
969 { "ideal_thread_count", QThread::idealThreadCount() }
970 };
971 auto macVersion = QSysInfo::macVersion();
972 if (macVersion != QSysInfo::MV_None) {
973 properties["os_osx_version"] = QSysInfo::macVersion();
974 }
975 auto windowsVersion = QSysInfo::windowsVersion();
976 if (windowsVersion != QSysInfo::WV_None) {
977 properties["os_win_version"] = QSysInfo::windowsVersion();
978 }
979
980 ProcessorInfo procInfo;
981 if (getProcessorInfo(procInfo)) {
982 properties["processor_core_count"] = procInfo.numProcessorCores;
983 properties["logical_processor_count"] = procInfo.numLogicalProcessors;
984 properties["processor_l1_cache_count"] = procInfo.numProcessorCachesL1;
985 properties["processor_l2_cache_count"] = procInfo.numProcessorCachesL2;
986 properties["processor_l3_cache_count"] = procInfo.numProcessorCachesL3;
987 }
988
989 // add firstRun flag from settings to launch event
990 Setting::Handle<bool> firstRun { Settings::firstRun, true };952 Setting::Handle<bool> firstRun { Settings::firstRun, true };
991 properties["first_run"] = firstRun.get();
992 953
993 // add the user's machine ID to the launch event954 // once the settings have been loaded, check if we need to flip the default for UserActivityLogger
994 properties["machine_fingerprint"] = uuidStringWithoutCurlyBraces(FingerprintUtils::getMachineFingerprint());955 auto& userActivityLogger = UserActivityLogger::getInstance();
995 956 if (!userActivityLogger.isDisabledSettingSet()) {
996 UserActivityLogger::getInstance().logAction("launch", properties);957 // the user activity logger is opt-out for Interface
958 // but it's defaulted to disabled for other targets
959 // so we need to enable it here if it has never been disabled by the user
960 userActivityLogger.disable(false);
961 }
962
963 if (userActivityLogger.isEnabled()) {
964 // sessionRunTime will be reset soon by loadSettings. Grab it now to get previous session value.
965 // The value will be 0 if the user blew away settings this session, which is both a feature and a bug.
966 static const QString TESTER = "HIFI_TESTER";
967 auto gpuIdent = GPUIdent::getInstance();
968 auto glContextData = getGLContextData();
969 QJsonObject properties = {
970 { "version", applicationVersion() },
971 { "tester", QProcessEnvironment::systemEnvironment().contains(TESTER) },
972 { "previousSessionCrashed", _previousSessionCrashed },
973 { "previousSessionRuntime", sessionRunTime.get() },
974 { "cpu_architecture", QSysInfo::currentCpuArchitecture() },
975 { "kernel_type", QSysInfo::kernelType() },
976 { "kernel_version", QSysInfo::kernelVersion() },
977 { "os_type", QSysInfo::productType() },
978 { "os_version", QSysInfo::productVersion() },
979 { "gpu_name", gpuIdent->getName() },
980 { "gpu_driver", gpuIdent->getDriver() },
981 { "gpu_memory", static_cast<qint64>(gpuIdent->getMemory()) },
982 { "gl_version_int", glVersionToInteger(glContextData.value("version").toString()) },
983 { "gl_version", glContextData["version"] },
984 { "gl_vender", glContextData["vendor"] },
985 { "gl_sl_version", glContextData["sl_version"] },
986 { "gl_renderer", glContextData["renderer"] },
987 { "ideal_thread_count", QThread::idealThreadCount() }
988 };
989 auto macVersion = QSysInfo::macVersion();
990 if (macVersion != QSysInfo::MV_None) {
991 properties["os_osx_version"] = QSysInfo::macVersion();
992 }
993 auto windowsVersion = QSysInfo::windowsVersion();
994 if (windowsVersion != QSysInfo::WV_None) {
995 properties["os_win_version"] = QSysInfo::windowsVersion();
996 }
997
998 ProcessorInfo procInfo;
999 if (getProcessorInfo(procInfo)) {
1000 properties["processor_core_count"] = procInfo.numProcessorCores;
1001 properties["logical_processor_count"] = procInfo.numLogicalProcessors;
1002 properties["processor_l1_cache_count"] = procInfo.numProcessorCachesL1;
1003 properties["processor_l2_cache_count"] = procInfo.numProcessorCachesL2;
1004 properties["processor_l3_cache_count"] = procInfo.numProcessorCachesL3;
1005 }
1006
1007 properties["first_run"] = firstRun.get();
1008
1009 // add the user's machine ID to the launch event
1010 properties["machine_fingerprint"] = uuidStringWithoutCurlyBraces(FingerprintUtils::getMachineFingerprint());
1011
1012 userActivityLogger.logAction("launch", properties);
1013 }
997 1014
998 // Tell our entity edit sender about our known jurisdictions1015 // Tell our entity edit sender about our known jurisdictions
999 _entityEditSender.setServerJurisdictions(&_entityServerJurisdictions);1016 _entityEditSender.setServerJurisdictions(&_entityServerJurisdictions);
@@ -1205,15 +1222,26 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 205 unmodified lines
1205 // Make sure we don't time out during slow operations at startup1222 // Make sure we don't time out during slow operations at startup
1206 updateHeartbeat();1223 updateHeartbeat();
1207 1224
1208 int SAVE_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND; // Let's save every seconds for now1225
1209 connect(&_settingsTimer, &QTimer::timeout, this, &Application::saveSettings);1226 QTimer* settingsTimer = new QTimer();
1210 connect(&_settingsThread, SIGNAL(started()), &_settingsTimer, SLOT(start()));1227 moveToNewNamedThread(settingsTimer, "Settings Thread", [this, settingsTimer]{
1211 connect(&_settingsThread, SIGNAL(finished()), &_settingsTimer, SLOT(stop()));1228 connect(qApp, &Application::beforeAboutToQuit, [this, settingsTimer]{
1212 _settingsTimer.moveToThread(&_settingsThread);1229 // Disconnect the signal from the save settings
1213 _settingsTimer.setSingleShot(false);1230 QObject::disconnect(settingsTimer, &QTimer::timeout, this, &Application::saveSettings);
1214 _settingsTimer.setInterval(SAVE_SETTINGS_INTERVAL); // 10s, Qt::CoarseTimer acceptable1231 // Stop the settings timer
1215 _settingsThread.setPriority(QThread::LowestPriority);1232 settingsTimer->stop();
1216 _settingsThread.start();1233 // Delete it (this will trigger the thread destruction
1234 settingsTimer->deleteLater();
1235 // Mark the settings thread as finished, so we know we can safely save in the main application
1236 // shutdown code
1237 _settingsGuard.trigger();
1238 });
1239
1240 int SAVE_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND; // Let's save every seconds for now
1241 settingsTimer->setSingleShot(false);
1242 settingsTimer->setInterval(SAVE_SETTINGS_INTERVAL); // 10s, Qt::CoarseTimer acceptable
1243 QObject::connect(settingsTimer, &QTimer::timeout, this, &Application::saveSettings);
1244 }, QThread::LowestPriority);
1217 1245
1218 if (Menu::getInstance()->isOptionChecked(MenuOption::FirstPerson)) {1246 if (Menu::getInstance()->isOptionChecked(MenuOption::FirstPerson)) {
1219 getMyAvatar()->setBoomLength(MyAvatar::ZOOM_MIN); // So that camera doesn't auto-switch to third person.1247 getMyAvatar()->setBoomLength(MyAvatar::ZOOM_MIN); // So that camera doesn't auto-switch to third person.
@@ -1641,7 +1669,7 @@ QString Application::getUserAgent() { · 421 unmodified lines
1641 if (QThread::currentThread() != thread()) {1669 if (QThread::currentThread() != thread()) {
1642 QString userAgent;1670 QString userAgent;
1643 1671
1644 QMetaObject::invokeMethod(this, "getUserAgent", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, userAgent));1672 BLOCKING_INVOKE_METHOD(this, "getUserAgent", Q_RETURN_ARG(QString, userAgent));
1645 1673
1646 return userAgent;1674 return userAgent;
1647 }1675 }
@@ -1799,11 +1827,13 @@ void Application::cleanupBeforeQuit() { · 151 unmodified lines
1799 locationUpdateTimer.stop();1827 locationUpdateTimer.stop();
1800 identityPacketTimer.stop();1828 identityPacketTimer.stop();
1801 pingTimer.stop();1829 pingTimer.stop();
1802 QMetaObject::invokeMethod(&_settingsTimer, "stop", Qt::BlockingQueuedConnection);
1803 1830
1804 // save state1831 // Wait for the settings thread to shut down, and save the settings one last time when it's safe
1805 _settingsThread.quit();1832 if (_settingsGuard.wait()) {
1806 saveSettings();1833 // save state
1834 saveSettings();
1835 }
1836
1807 _window->saveGeometry();1837 _window->saveGeometry();
1808 1838
1809 // Destroy third party processes after scripts have finished using them.1839 // Destroy third party processes after scripts have finished using them.
@@ -1827,8 +1857,7 @@ void Application::cleanupBeforeQuit() { · 17 unmodified lines
1827 1857
1828 // FIXME: something else is holding a reference to AudioClient,1858 // FIXME: something else is holding a reference to AudioClient,
1829 // so it must be explicitly synchronously stopped here1859 // so it must be explicitly synchronously stopped here
1830 QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(),1860 DependencyManager::get<AudioClient>()->cleanupBeforeQuit();
1831 "cleanupBeforeQuit", Qt::BlockingQueuedConnection);
1832 1861
1833 // destroy Audio so it and its threads have a chance to go down safely1862 // destroy Audio so it and its threads have a chance to go down safely
1834 // this must happen after QML, as there are unexplained audio crashes originating in qtwebengine1863 // this must happen after QML, as there are unexplained audio crashes originating in qtwebengine
@@ -1883,8 +1912,6 @@ Application::~Application() { · 48 unmodified lines
1883 // remove the NodeList from the DependencyManager1912 // remove the NodeList from the DependencyManager
1884 DependencyManager::destroy<NodeList>();1913 DependencyManager::destroy<NodeList>();
1885 1914
1886 Leapmotion::destroy();
1887
1888 if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {1915 if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
1889 steamClient->shutdown();1916 steamClient->shutdown();
1890 }1917 }
@@ -2152,48 +2179,74 @@ void Application::paintGL() { · 261 unmodified lines
2152 return;2179 return;
2153 }2180 }
2154 2181
2155 auto displayPlugin = getActiveDisplayPlugin();2182 DisplayPluginPointer displayPlugin;
2156 // FIXME not needed anymore?2183 {
2157 _offscreenContext->makeCurrent();2184 PROFILE_RANGE(render, "/getActiveDisplayPlugin");
2185 displayPlugin = getActiveDisplayPlugin();
2186 }
2158 2187
2159 // If a display plugin loses it's underlying support, it2188 {
2160 // needs to be able to signal us to not use it2189 PROFILE_RANGE(render, "/offscreenMakeCurrent");
2161 if (!displayPlugin->beginFrameRender(_frameCount)) {2190 // FIXME not needed anymore?
2162 _inPaint = false;2191 _offscreenContext->makeCurrent();
2163 updateDisplayMode();2192 }
2164 return;2193
2194 {
2195 PROFILE_RANGE(render, "/pluginBeginFrameRender");
2196 // If a display plugin loses it's underlying support, it
2197 // needs to be able to signal us to not use it
2198 if (!displayPlugin->beginFrameRender(_frameCount)) {
2199 _inPaint = false;
2200 updateDisplayMode();
2201 return;
2202 }
2165 }2203 }
2166 2204
2167 // update the avatar with a fresh HMD pose2205 // update the avatar with a fresh HMD pose
2168 getMyAvatar()->updateFromHMDSensorMatrix(getHMDSensorPose());2206 {
2207 PROFILE_RANGE(render, "/updateAvatar");
2208 getMyAvatar()->updateFromHMDSensorMatrix(getHMDSensorPose());
2209 }
2169 2210
2170 auto lodManager = DependencyManager::get<LODManager>();2211 auto lodManager = DependencyManager::get<LODManager>();
2171 2212
2213 RenderArgs renderArgs;
2172 {2214 {
2173 QMutexLocker viewLocker(&_viewMutex);2215 PROFILE_RANGE(render, "/buildFrustrumAndArgs");
2174 _viewFrustum.calculate();2216 {
2217 QMutexLocker viewLocker(&_viewMutex);
2218 _viewFrustum.calculate();
2219 }
2220 renderArgs = RenderArgs(_gpuContext, getEntities(), lodManager->getOctreeSizeScale(),
2221 lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE,
2222 RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
2223 {
2224 QMutexLocker viewLocker(&_viewMutex);
2225 renderArgs.setViewFrustum(_viewFrustum);
2226 }
2175 }2227 }
2176 RenderArgs renderArgs(_gpuContext, getEntities(), lodManager->getOctreeSizeScale(),2228
2177 lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE,
2178 RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
2179 {2229 {
2180 QMutexLocker viewLocker(&_viewMutex);2230 PROFILE_RANGE(render, "/resizeGL");
2181 renderArgs.setViewFrustum(_viewFrustum);2231 PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings));
2232 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
2233 PerformanceWarning warn(showWarnings, "Application::paintGL()");
2234 resizeGL();
2182 }2235 }
2183 2236
2184 PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings));2237 {
2185 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);2238 PROFILE_RANGE(render, "/gpuContextReset");
2186 PerformanceWarning warn(showWarnings, "Application::paintGL()");2239 _gpuContext->beginFrame(getHMDSensorPose());
2187 resizeGL();2240 // Reset the gpu::Context Stages
2241 // Back to the default framebuffer;
2242 gpu::doInBatch(_gpuContext, [&](gpu::Batch& batch) {
2243 batch.resetStages();
2244 });
2245 }
2188 2246
2189 _gpuContext->beginFrame(getHMDSensorPose());
2190 // Reset the gpu::Context Stages
2191 // Back to the default framebuffer;
2192 gpu::doInBatch(_gpuContext, [&](gpu::Batch& batch) {
2193 batch.resetStages();
2194 });
2195 2247
2196 {2248 {
2249 PROFILE_RANGE(render, "/renderOverlay");
2197 PerformanceTimer perfTimer("renderOverlay");2250 PerformanceTimer perfTimer("renderOverlay");
2198 // NOTE: There is no batch associated with this renderArgs2251 // NOTE: There is no batch associated with this renderArgs
2199 // the ApplicationOverlay class assumes it's viewport is setup to be the device size2252 // the ApplicationOverlay class assumes it's viewport is setup to be the device size
@@ -2204,114 +2257,127 @@ void Application::paintGL() { · 4 unmodified lines
2204 2257
2205 glm::vec3 boomOffset;2258 glm::vec3 boomOffset;
2206 {2259 {
2207 PerformanceTimer perfTimer("CameraUpdates");2260 PROFILE_RANGE(render, "/updateCamera");
2261 {
2262 PerformanceTimer perfTimer("CameraUpdates");
2208 2263
2209 auto myAvatar = getMyAvatar();2264 auto myAvatar = getMyAvatar();
2210 boomOffset = myAvatar->getScale() * myAvatar->getBoomLength() * -IDENTITY_FORWARD;2265 boomOffset = myAvatar->getScale() * myAvatar->getBoomLength() * -IDENTITY_FORWARD;
2211 2266
2212 if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON || _myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {2267 if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON || _myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
2213 Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN);2268 Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN);
2214 Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, !(myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN));2269 Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, !(myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN));
2215 cameraMenuChanged();2270 cameraMenuChanged();
2216 }2271 }
2217 2272
2218 // The render mode is default or mirror if the camera is in mirror mode, assigned further below2273 // The render mode is default or mirror if the camera is in mirror mode, assigned further below
2219 renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE;2274 renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE;
2220 2275
2221 // Always use the default eye position, not the actual head eye position.2276 // Always use the default eye position, not the actual head eye position.
2222 // Using the latter will cause the camera to wobble with idle animations,2277 // Using the latter will cause the camera to wobble with idle animations,
2223 // or with changes from the face tracker2278 // or with changes from the face tracker
2224 if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {2279 if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
2225 if (isHMDMode()) {2280 if (isHMDMode()) {
2226 mat4 camMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();2281 mat4 camMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
2227 _myCamera.setPosition(extractTranslation(camMat));2282 _myCamera.setPosition(extractTranslation(camMat));
2228 _myCamera.setOrientation(glm::quat_cast(camMat));2283 _myCamera.setOrientation(glm::quat_cast(camMat));
2229 } else {
2230 _myCamera.setPosition(myAvatar->getDefaultEyePosition());
2231 _myCamera.setOrientation(myAvatar->getMyHead()->getHeadOrientation());
2232 }
2233 } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
2234 if (isHMDMode()) {
2235 auto hmdWorldMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
2236 _myCamera.setOrientation(glm::normalize(glm::quat_cast(hmdWorldMat)));
2237 _myCamera.setPosition(extractTranslation(hmdWorldMat) +
2238 myAvatar->getOrientation() * boomOffset);
2239 } else {
2240 _myCamera.setOrientation(myAvatar->getHead()->getOrientation());
2241 if (Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) {
2242 _myCamera.setPosition(myAvatar->getDefaultEyePosition()
2243 + _myCamera.getOrientation() * boomOffset);
2244 } else {2284 } else {
2245 _myCamera.setPosition(myAvatar->getDefaultEyePosition()2285 _myCamera.setPosition(myAvatar->getDefaultEyePosition());
2246 + myAvatar->getOrientation() * boomOffset);2286 _myCamera.setOrientation(myAvatar->getMyHead()->getHeadOrientation());
2247 }2287 }
2248 }2288 } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
2249 } else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {2289 if (isHMDMode()) {
2250 if (isHMDMode()) {2290 auto hmdWorldMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
2251 auto mirrorBodyOrientation = myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f));2291 _myCamera.setOrientation(glm::normalize(glm::quat_cast(hmdWorldMat)));
2252 2292 _myCamera.setPosition(extractTranslation(hmdWorldMat) +
2253 glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix());2293 myAvatar->getOrientation() * boomOffset);
2254 // Mirror HMD yaw and roll2294 } else {
2255 glm::vec3 mirrorHmdEulers = glm::eulerAngles(hmdRotation);2295 _myCamera.setOrientation(myAvatar->getHead()->getOrientation());
2256 mirrorHmdEulers.y = -mirrorHmdEulers.y;2296 if (Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) {
2257 mirrorHmdEulers.z = -mirrorHmdEulers.z;2297 _myCamera.setPosition(myAvatar->getDefaultEyePosition()
2258 glm::quat mirrorHmdRotation = glm::quat(mirrorHmdEulers);2298 + _myCamera.getOrientation() * boomOffset);
2299 } else {
2300 _myCamera.setPosition(myAvatar->getDefaultEyePosition()
2301 + myAvatar->getOrientation() * boomOffset);
2302 }
2303 }
2304 } else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
2305 if (isHMDMode()) {
2306 auto mirrorBodyOrientation = myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f));
2259 2307
2260 glm::quat worldMirrorRotation = mirrorBodyOrientation * mirrorHmdRotation;2308 glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix());
2309 // Mirror HMD yaw and roll
2310 glm::vec3 mirrorHmdEulers = glm::eulerAngles(hmdRotation);
2311 mirrorHmdEulers.y = -mirrorHmdEulers.y;
2312 mirrorHmdEulers.z = -mirrorHmdEulers.z;
2313 glm::quat mirrorHmdRotation = glm::quat(mirrorHmdEulers);
2261 2314
2262 _myCamera.setOrientation(worldMirrorRotation);2315 glm::quat worldMirrorRotation = mirrorBodyOrientation * mirrorHmdRotation;
2263 2316
2264 glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());2317 _myCamera.setOrientation(worldMirrorRotation);
2265 // Mirror HMD lateral offsets
2266 hmdOffset.x = -hmdOffset.x;
2267 2318
2268 _myCamera.setPosition(myAvatar->getDefaultEyePosition()
2269 + glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0)
2270 + mirrorBodyOrientation * glm::vec3(0.0f, 0.0f, 1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror
2271 + mirrorBodyOrientation * hmdOffset);
2272 } else {
2273 _myCamera.setOrientation(myAvatar->getWorldAlignedOrientation()
2274 * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
2275 _myCamera.setPosition(myAvatar->getDefaultEyePosition()
2276 + glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0)
2277 + (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) *
2278 glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
2279 }
2280 renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE;
2281 } else if (_myCamera.getMode() == CAMERA_MODE_ENTITY) {
2282 EntityItemPointer cameraEntity = _myCamera.getCameraEntityPointer();
2283 if (cameraEntity != nullptr) {
2284 if (isHMDMode()) {
2285 glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix());
2286 _myCamera.setOrientation(cameraEntity->getRotation() * hmdRotation);
2287 glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());2319 glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());
2288 _myCamera.setPosition(cameraEntity->getPosition() + (hmdRotation * hmdOffset));2320 // Mirror HMD lateral offsets
2321 hmdOffset.x = -hmdOffset.x;
2322
2323 _myCamera.setPosition(myAvatar->getDefaultEyePosition()
2324 + glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0)
2325 + mirrorBodyOrientation * glm::vec3(0.0f, 0.0f, 1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror
2326 + mirrorBodyOrientation * hmdOffset);
2289 } else {2327 } else {
2290 _myCamera.setOrientation(cameraEntity->getRotation());2328 _myCamera.setOrientation(myAvatar->getWorldAlignedOrientation()
2291 _myCamera.setPosition(cameraEntity->getPosition());2329 * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
2330 _myCamera.setPosition(myAvatar->getDefaultEyePosition()
2331 + glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0)
2332 + (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) *
2333 glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
2334 }
2335 renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE;
2336 } else if (_myCamera.getMode() == CAMERA_MODE_ENTITY) {
2337 EntityItemPointer cameraEntity = _myCamera.getCameraEntityPointer();
2338 if (cameraEntity != nullptr) {
2339 if (isHMDMode()) {
2340 glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix());
2341 _myCamera.setOrientation(cameraEntity->getRotation() * hmdRotation);
2342 glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());
2343 _myCamera.setPosition(cameraEntity->getPosition() + (hmdRotation * hmdOffset));
2344 } else {
2345 _myCamera.setOrientation(cameraEntity->getRotation());
2346 _myCamera.setPosition(cameraEntity->getPosition());
2347 }
2292 }2348 }
2293 }2349 }
2294 }2350 // Update camera position
2295 // Update camera position2351 if (!isHMDMode()) {
2296 if (!isHMDMode()) {2352 _myCamera.update(1.0f / _frameCounter.rate());
2297 _myCamera.update(1.0f / _frameCounter.rate());2353 }
2298 }2354 }
2299 }2355 }
2300 2356
2301 getApplicationCompositor().setFrameInfo(_frameCount, _myCamera.getTransform());2357 {
2358 PROFILE_RANGE(render, "/updateCompositor");
2359 getApplicationCompositor().setFrameInfo(_frameCount, _myCamera.getTransform());
2360 }
2302 2361
2303 // Primary rendering pass2362 gpu::FramebufferPointer finalFramebuffer;
2304 auto framebufferCache = DependencyManager::get<FramebufferCache>();2363 QSize finalFramebufferSize;
2305 const QSize size = framebufferCache->getFrameBufferSize();2364 {
2306 // Final framebuffer that will be handled to the display-plugin2365 PROFILE_RANGE(render, "/getOutputFramebuffer");
2307 auto finalFramebuffer = framebufferCache->getFramebuffer();2366 // Primary rendering pass
2367 auto framebufferCache = DependencyManager::get<FramebufferCache>();
2368 finalFramebufferSize = framebufferCache->getFrameBufferSize();
2369 // Final framebuffer that will be handled to the display-plugin
2370 finalFramebuffer = framebufferCache->getFramebuffer();
2371 }
2308 2372
2309 {2373 {
2310 PROFILE_RANGE(render, "/mainRender");2374 PROFILE_RANGE(render, "/mainRender");
2311 PerformanceTimer perfTimer("mainRender");2375 PerformanceTimer perfTimer("mainRender");
2312 renderArgs._boomOffset = boomOffset;2376 renderArgs._boomOffset = boomOffset;
2377 // FIXME is this ever going to be different from the size previously set in the render args
2378 // in the overlay render?
2313 // Viewport is assigned to the size of the framebuffer2379 // Viewport is assigned to the size of the framebuffer
2314 renderArgs._viewport = ivec4(0, 0, size.width(), size.height());2380 renderArgs._viewport = ivec4(0, 0, finalFramebufferSize.width(), finalFramebufferSize.height());
2315 if (displayPlugin->isStereo()) {2381 if (displayPlugin->isStereo()) {
2316 // Stereo modes will typically have a larger projection matrix overall,2382 // Stereo modes will typically have a larger projection matrix overall,
2317 // so we ask for the 'mono' projection matrix, which for stereo and HMD2383 // so we ask for the 'mono' projection matrix, which for stereo and HMD
@@ -3611,6 +3677,133 @@ bool Application::shouldPaint(float nsecsElapsed) { · 1293 unmodified lines
3611#include <TCHAR.h>3677#include <TCHAR.h>
3612#include <pdh.h>3678#include <pdh.h>
3613#pragma comment(lib, "pdh.lib")3679#pragma comment(lib, "pdh.lib")
3680#pragma comment(lib, "ntdll.lib")
3681
3682extern "C" {
3683 enum SYSTEM_INFORMATION_CLASS {
3684 SystemBasicInformation = 0,
3685 SystemProcessorPerformanceInformation = 8,
3686 };
3687
3688 struct SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION {
3689 LARGE_INTEGER IdleTime;
3690 LARGE_INTEGER KernelTime;
3691 LARGE_INTEGER UserTime;
3692 LARGE_INTEGER DpcTime;
3693 LARGE_INTEGER InterruptTime;
3694 ULONG InterruptCount;
3695 };
3696
3697 struct SYSTEM_BASIC_INFORMATION {
3698 ULONG Reserved;
3699 ULONG TimerResolution;
3700 ULONG PageSize;
3701 ULONG NumberOfPhysicalPages;
3702 ULONG LowestPhysicalPageNumber;
3703 ULONG HighestPhysicalPageNumber;
3704 ULONG AllocationGranularity;
3705 ULONG_PTR MinimumUserModeAddress;
3706 ULONG_PTR MaximumUserModeAddress;
3707 ULONG_PTR ActiveProcessorsAffinityMask;
3708 CCHAR NumberOfProcessors;
3709 };
3710
3711 NTSYSCALLAPI NTSTATUS NTAPI NtQuerySystemInformation(
3712 _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass,
3713 _Out_writes_bytes_opt_(SystemInformationLength) PVOID SystemInformation,
3714 _In_ ULONG SystemInformationLength,
3715 _Out_opt_ PULONG ReturnLength
3716 );
3717
3718}
3719template <typename T>
3720NTSTATUS NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, T& t) {
3721 return NtQuerySystemInformation(SystemInformationClass, &t, (ULONG)sizeof(T), nullptr);
3722}
3723
3724template <typename T>
3725NTSTATUS NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, std::vector<T>& t) {
3726 return NtQuerySystemInformation(SystemInformationClass, t.data(), (ULONG)(sizeof(T) * t.size()), nullptr);
3727}
3728
3729
3730template <typename T>
3731void updateValueAndDelta(std::pair<T, T>& pair, T newValue) {
3732 auto& value = pair.first;
3733 auto& delta = pair.second;
3734 delta = (value != 0) ? newValue - value : 0;
3735 value = newValue;
3736}
3737
3738struct MyCpuInfo {
3739 using ValueAndDelta = std::pair<LONGLONG, LONGLONG>;
3740 std::string name;
3741 ValueAndDelta kernel { 0, 0 };
3742 ValueAndDelta user { 0, 0 };
3743 ValueAndDelta idle { 0, 0 };
3744 float kernelUsage { 0.0f };
3745 float userUsage { 0.0f };
3746
3747 void update(const SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION& cpuInfo) {
3748 updateValueAndDelta(kernel, cpuInfo.KernelTime.QuadPart);
3749 updateValueAndDelta(user, cpuInfo.UserTime.QuadPart);
3750 updateValueAndDelta(idle, cpuInfo.IdleTime.QuadPart);
3751 auto totalTime = kernel.second + user.second + idle.second;
3752 if (totalTime != 0) {
3753 kernelUsage = (FLOAT)kernel.second / totalTime;
3754 userUsage = (FLOAT)user.second / totalTime;
3755 } else {
3756 kernelUsage = userUsage = 0.0f;
3757 }
3758 }
3759};
3760
3761void updateCpuInformation() {
3762 static std::once_flag once;
3763 static SYSTEM_BASIC_INFORMATION systemInfo {};
3764 static SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION cpuTotals;
3765 static std::vector<SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION> cpuInfos;
3766 static std::vector<MyCpuInfo> myCpuInfos;
3767 static MyCpuInfo myCpuTotals;
3768 std::call_once(once, [&] {
3769 NtQuerySystemInformation( SystemBasicInformation, systemInfo);
3770 cpuInfos.resize(systemInfo.NumberOfProcessors);
3771 myCpuInfos.resize(systemInfo.NumberOfProcessors);
3772 for (size_t i = 0; i < systemInfo.NumberOfProcessors; ++i) {
3773 myCpuInfos[i].name = "cpu." + std::to_string(i);
3774 }
3775 myCpuTotals.name = "cpu.total";
3776 });
3777 NtQuerySystemInformation(SystemProcessorPerformanceInformation, cpuInfos);
3778
3779 // Zero the CPU totals.
3780 memset(&cpuTotals, 0, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
3781 for (size_t i = 0; i < systemInfo.NumberOfProcessors; ++i) {
3782 auto& cpuInfo = cpuInfos[i];
3783 // KernelTime includes IdleTime.
3784 cpuInfo.KernelTime.QuadPart -= cpuInfo.IdleTime.QuadPart;
3785
3786 // Update totals
3787 cpuTotals.IdleTime.QuadPart += cpuInfo.IdleTime.QuadPart;
3788 cpuTotals.KernelTime.QuadPart += cpuInfo.KernelTime.QuadPart;
3789 cpuTotals.UserTime.QuadPart += cpuInfo.UserTime.QuadPart;
3790
3791 // Update friendly structure
3792 auto& myCpuInfo = myCpuInfos[i];
3793 myCpuInfo.update(cpuInfo);
3794 PROFILE_COUNTER(app, myCpuInfo.name.c_str(), {
3795 { "kernel", myCpuInfo.kernelUsage },
3796 { "user", myCpuInfo.userUsage }
3797 });
3798 }
3799
3800 myCpuTotals.update(cpuTotals);
3801 PROFILE_COUNTER(app, myCpuTotals.name.c_str(), {
3802 { "kernel", myCpuTotals.kernelUsage },
3803 { "user", myCpuTotals.userUsage }
3804 });
3805}
3806
3614 3807
3615static ULARGE_INTEGER lastCPU, lastSysCPU, lastUserCPU;3808static ULARGE_INTEGER lastCPU, lastSysCPU, lastUserCPU;
3616static int numProcessors;3809static int numProcessors;
@@ -3663,6 +3856,26 @@ void getCpuUsage(vec3& systemAndUser) { · 46 unmodified lines
3663 systemAndUser.z = (float)counterVal.doubleValue;3856 systemAndUser.z = (float)counterVal.doubleValue;
3664}3857}
3665 3858
3859void setupCpuMonitorThread() {
3860 initCpuUsage();
3861 auto cpuMonitorThread = QThread::currentThread();
3862
3863 QTimer* timer = new QTimer();
3864 timer->setInterval(50);
3865 QObject::connect(timer, &QTimer::timeout, [] {
3866 updateCpuInformation();
3867 vec3 kernelUserAndSystem;
3868 getCpuUsage(kernelUserAndSystem);
3869 PROFILE_COUNTER(app, "cpuProcess", { { "system", kernelUserAndSystem.x }, { "user", kernelUserAndSystem.y } });
3870 PROFILE_COUNTER(app, "cpuSystem", { { "system", kernelUserAndSystem.z } });
3871 });
3872 QObject::connect(cpuMonitorThread, &QThread::finished, [=] {
3873 timer->deleteLater();
3874 cpuMonitorThread->deleteLater();
3875 });
3876 timer->start();
3877}
3878
3666#endif3879#endif
3667 3880
3668 3881
@@ -3683,15 +3896,17 @@ void Application::idle(float nsecsElapsed) { · 14 unmodified lines
3683 }3896 }
3684 3897
3685#ifdef Q_OS_WIN3898#ifdef Q_OS_WIN
3899 // If tracing is enabled then monitor the CPU in a separate thread
3686 static std::once_flag once;3900 static std::once_flag once;
3687 std::call_once(once, [] {3901 std::call_once(once, [&] {
3688 initCpuUsage();3902 if (trace_app().isDebugEnabled()) {
3903 QThread* cpuMonitorThread = new QThread(qApp);
3904 cpuMonitorThread->setObjectName("cpuMonitorThread");
3905 QObject::connect(cpuMonitorThread, &QThread::started, [this] { setupCpuMonitorThread(); });
3906 QObject::connect(qApp, &QCoreApplication::aboutToQuit, cpuMonitorThread, &QThread::quit);
3907 cpuMonitorThread->start();
3908 }
3689 });3909 });
3690
3691 vec3 kernelUserAndSystem;
3692 getCpuUsage(kernelUserAndSystem);
3693 PROFILE_COUNTER(app, "cpuProcess", { { "system", kernelUserAndSystem.x }, { "user", kernelUserAndSystem.y } });
3694 PROFILE_COUNTER(app, "cpuSystem", { { "system", kernelUserAndSystem.z } });
3695#endif3910#endif
3696 3911
3697 3912
@@ -4053,8 +4268,6 @@ void Application::init() { · 355 unmodified lines
4053 4268
4054 qCDebug(interfaceapp) << "Loaded settings";4269 qCDebug(interfaceapp) << "Loaded settings";
4055 4270
4056 Leapmotion::init();
4057
4058 // fire off an immediate domain-server check in now that settings are loaded4271 // fire off an immediate domain-server check in now that settings are loaded
4059 DependencyManager::get<NodeList>()->sendDomainServerCheckIn();4272 DependencyManager::get<NodeList>()->sendDomainServerCheckIn();
4060 4273
@@ -4518,7 +4731,6 @@ void Application::update(float deltaTime) { · 457 unmodified lines
4518 4731
4519 {4732 {
4520 PerformanceTimer perfTimer("devices");4733 PerformanceTimer perfTimer("devices");
4521 DeviceTracker::updateAll();
4522 4734
4523 FaceTracker* tracker = getSelectedFaceTracker();4735 FaceTracker* tracker = getSelectedFaceTracker();
4524 if (tracker && Menu::getInstance()->isOptionChecked(MenuOption::MuteFaceTracking) != tracker->isMuted()) {4736 if (tracker && Menu::getInstance()->isOptionChecked(MenuOption::MuteFaceTracking) != tracker->isMuted()) {
@@ -4587,8 +4799,6 @@ void Application::update(float deltaTime) { · 62 unmodified lines
4587 keyboardMousePlugin->pluginUpdate(deltaTime, calibrationData);4799 keyboardMousePlugin->pluginUpdate(deltaTime, calibrationData);
4588 }4800 }
4589 4801
4590 _controllerScriptingInterface->updateInputControllers();
4591
4592 // Transfer the user inputs to the driveKeys4802 // Transfer the user inputs to the driveKeys
4593 // FIXME can we drop drive keys and just have the avatar read the action states directly?4803 // FIXME can we drop drive keys and just have the avatar read the action states directly?
4594 myAvatar->clearDriveKeys();4804 myAvatar->clearDriveKeys();
@@ -4613,6 +4823,31 @@ void Application::update(float deltaTime) { · 18 unmodified lines
4613 auto avatarToSensorMatrix = worldToSensorMatrix * myAvatarMatrix;4823 auto avatarToSensorMatrix = worldToSensorMatrix * myAvatarMatrix;
4614 myAvatar->setHandControllerPosesInSensorFrame(leftHandPose.transform(avatarToSensorMatrix), rightHandPose.transform(avatarToSensorMatrix));4824 myAvatar->setHandControllerPosesInSensorFrame(leftHandPose.transform(avatarToSensorMatrix), rightHandPose.transform(avatarToSensorMatrix));
4615 4825
4826 // If have previously done finger poses or there are new valid finger poses, update finger pose values. This so that if
4827 // fingers are not being controlled, finger joints are not updated in MySkeletonModel.
4828 // Assumption: Finger poses are either all present and valid or not present at all; thus can test just one joint.
4829 MyAvatar::FingerPosesMap leftHandFingerPoses;
4830 if (myAvatar->getLeftHandFingerControllerPosesInSensorFrame().size() > 0
4831 || userInputMapper->getPoseState(controller::Action::LEFT_HAND_THUMB1).isValid()) {
4832 for (int i = (int)controller::Action::LEFT_HAND_THUMB1; i <= (int)controller::Action::LEFT_HAND_PINKY4; i++) {
4833 leftHandFingerPoses[i] = {
4834 userInputMapper->getPoseState((controller::Action)i).transform(avatarToSensorMatrix),
4835 userInputMapper->getActionName((controller::Action)i)
4836 };
4837 }
4838 }
4839 MyAvatar::FingerPosesMap rightHandFingerPoses;
4840 if (myAvatar->getRightHandFingerControllerPosesInSensorFrame().size() > 0
4841 || userInputMapper->getPoseState(controller::Action::RIGHT_HAND_THUMB1).isValid()) {
4842 for (int i = (int)controller::Action::RIGHT_HAND_THUMB1; i <= (int)controller::Action::RIGHT_HAND_PINKY4; i++) {
4843 rightHandFingerPoses[i] = {
4844 userInputMapper->getPoseState((controller::Action)i).transform(avatarToSensorMatrix),
4845 userInputMapper->getActionName((controller::Action)i)
4846 };
4847 }
4848 }
4849 myAvatar->setFingerControllerPosesInSensorFrame(leftHandFingerPoses, rightHandFingerPoses);
4850
4616 controller::Pose leftFootPose = userInputMapper->getPoseState(controller::Action::LEFT_FOOT);4851 controller::Pose leftFootPose = userInputMapper->getPoseState(controller::Action::LEFT_FOOT);
4617 controller::Pose rightFootPose = userInputMapper->getPoseState(controller::Action::RIGHT_FOOT);4852 controller::Pose rightFootPose = userInputMapper->getPoseState(controller::Action::RIGHT_FOOT);
4618 myAvatar->setFootControllerPosesInSensorFrame(leftFootPose.transform(avatarToSensorMatrix), rightFootPose.transform(avatarToSensorMatrix));4853 myAvatar->setFootControllerPosesInSensorFrame(leftFootPose.transform(avatarToSensorMatrix), rightFootPose.transform(avatarToSensorMatrix));