Showing the changes to interface/src/Application.cpp (1 of 31 files). Show all
Unified · Split
| @@ -104,6 +104,7 @@ · 103 unmodified lines | |||
| 104 | #include <RenderableWebEntityItem.h> | 104 | #include <RenderableWebEntityItem.h> |
| 105 | 105 | ||
| 106 | #include "AudioClient.h" | 106 | #include "AudioClient.h" |
| 107 | #include "CrashHandler.h" | ||
| 107 | #include "DiscoverabilityManager.h" | 108 | #include "DiscoverabilityManager.h" |
| 108 | #include "GLCanvas.h" | 109 | #include "GLCanvas.h" |
| 109 | #include "LODManager.h" | 110 | #include "LODManager.h" |
| @@ -189,6 +190,11 @@ static QTimer* billboardPacketTimer = NULL; · 79 unmodified lines | |||
| 189 | static QTimer* checkFPStimer = NULL; | 190 | static QTimer* checkFPStimer = NULL; |
| 190 | static QTimer* idleTimer = NULL; | 191 | static QTimer* idleTimer = NULL; |
| 191 | 192 | ||
| 193 | static const unsigned int TARGET_SIM_FRAMERATE = 60; | ||
| 194 | static const unsigned int THROTTLED_SIM_FRAMERATE = 15; | ||
| 195 | static const int TARGET_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / TARGET_SIM_FRAMERATE; | ||
| 196 | static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SIM_FRAMERATE; | ||
| 197 | |||
| 192 | const QString CHECK_VERSION_URL = "https://highfidelity.com/latestVersion.xml"; | 198 | const QString CHECK_VERSION_URL = "https://highfidelity.com/latestVersion.xml"; |
| 193 | const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/hifi.skipversion"; | 199 | const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/hifi.skipversion"; |
| 194 | 200 | ||
| @@ -257,6 +263,12 @@ bool setupEssentials(int& argc, char** argv) { · 62 unmodified lines | |||
| 257 | // Set build version | 263 | // Set build version |
| 258 | QCoreApplication::setApplicationVersion(BUILD_VERSION); | 264 | QCoreApplication::setApplicationVersion(BUILD_VERSION); |
| 259 | 265 | ||
| 266 | Setting::preInit(); | ||
| 267 | |||
| 268 | CrashHandler::checkForAndHandleCrash(); | ||
| 269 | CrashHandler::writeRunningMarkerFiler(); | ||
| 270 | qAddPostRoutine(CrashHandler::deleteRunningMarkerFile); | ||
| 271 | |||
| 260 | DependencyManager::registerInheritance<LimitedNodeList, NodeList>(); | 272 | DependencyManager::registerInheritance<LimitedNodeList, NodeList>(); |
| 261 | DependencyManager::registerInheritance<AvatarHashMap, AvatarManager>(); | 273 | DependencyManager::registerInheritance<AvatarHashMap, AvatarManager>(); |
| 262 | DependencyManager::registerInheritance<EntityActionFactoryInterface, InterfaceActionFactory>(); | 274 | DependencyManager::registerInheritance<EntityActionFactoryInterface, InterfaceActionFactory>(); |
| @@ -347,7 +359,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 84 unmodified lines | |||
| 347 | _trayIcon(new QSystemTrayIcon(_window)), | 359 | _trayIcon(new QSystemTrayIcon(_window)), |
| 348 | _lastNackTime(usecTimestampNow()), | 360 | _lastNackTime(usecTimestampNow()), |
| 349 | _lastSendDownstreamAudioStats(usecTimestampNow()), | 361 | _lastSendDownstreamAudioStats(usecTimestampNow()), |
| 350 | _isVSyncOn(true), | ||
| 351 | _isThrottleFPSEnabled(true), | 362 | _isThrottleFPSEnabled(true), |
| 352 | _aboutToQuit(false), | 363 | _aboutToQuit(false), |
| 353 | _notifiedPacketVersionMismatchThisDomain(false), | 364 | _notifiedPacketVersionMismatchThisDomain(false), |
| @@ -745,8 +756,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 391 unmodified lines | |||
| 745 | }); | 756 | }); |
| 746 | 757 | ||
| 747 | connect(this, &Application::applicationStateChanged, this, &Application::activeChanged); | 758 | connect(this, &Application::applicationStateChanged, this, &Application::activeChanged); |
| 748 | |||
| 749 | setVSyncEnabled(); // make sure VSync is set properly at startup | ||
| 750 | } | 759 | } |
| 751 | 760 | ||
| 752 | void Application::aboutToQuit() { | 761 | void Application::aboutToQuit() { |
| @@ -921,7 +930,7 @@ void Application::initializeGL() { · 168 unmodified lines | |||
| 921 | // call our idle function whenever we can | 930 | // call our idle function whenever we can |
| 922 | idleTimer = new QTimer(this); | 931 | idleTimer = new QTimer(this); |
| 923 | connect(idleTimer, SIGNAL(timeout()), SLOT(idle())); | 932 | connect(idleTimer, SIGNAL(timeout()), SLOT(idle())); |
| 924 | idleTimer->start(0); | 933 | idleTimer->start(TARGET_SIM_FRAME_PERIOD_MS); |
| 925 | _idleLoopStdev.reset(); | 934 | _idleLoopStdev.reset(); |
| 926 | 935 | ||
| 927 | if (_justStarted) { | 936 | if (_justStarted) { |
| @@ -2034,38 +2043,38 @@ void Application::checkFPS() { · 1106 unmodified lines | |||
| 2034 | } | 2043 | } |
| 2035 | 2044 | ||
| 2036 | void Application::idle() { | 2045 | void Application::idle() { |
| 2037 | PROFILE_RANGE(__FUNCTION__); | 2046 | if (_aboutToQuit) { |
| 2038 | static SimpleAverage<float> interIdleDurations; | 2047 | return; // bail early, nothing to do here. |
| 2048 | } | ||
| 2039 | 2049 | ||
| 2040 | static uint64_t lastIdleStart{ 0 }; | 2050 | // depending on whether we're throttling or not. |
| 2041 | static uint64_t lastIdleEnd{ 0 }; | 2051 | // Once rendering is off on another thread we should be able to have Application::idle run at start(0) in |
| 2042 | uint64_t now = usecTimestampNow(); | 2052 | // perpetuity and not expect events to get backed up. |
| 2043 | uint64_t idleStartToStartDuration = now - lastIdleStart; | 2053 | bool isThrottled = getActiveDisplayPlugin()->isThrottled(); |
| 2054 | // Only run simulation code if more than the targetFramePeriod have passed since last time we ran | ||
| 2055 | // This attempts to lock the simulation at 60 updates per second, regardless of framerate | ||
| 2056 | float timeSinceLastUpdateUs = (float)_lastTimeUpdated.nsecsElapsed() / NSECS_PER_USEC; | ||
| 2057 | float secondsSinceLastUpdate = timeSinceLastUpdateUs / USECS_PER_SECOND; | ||
| 2044 | 2058 | ||
| 2045 | if (lastIdleStart > 0 && idleStartToStartDuration > 0) { | 2059 | if (isThrottled && (timeSinceLastUpdateUs / USECS_PER_MSEC) < THROTTLED_SIM_FRAME_PERIOD_MS) { |
| 2046 | _simsPerSecond.updateAverage((float)USECS_PER_SECOND / (float)idleStartToStartDuration); | 2060 | return; // bail early, we're throttled and not enough time has elapsed |
| 2047 | } | 2061 | } |
| 2048 | 2062 | ||
| 2049 | lastIdleStart = now; | 2063 | _lastTimeUpdated.start(); |
| 2050 | 2064 | ||
| 2051 | if (lastIdleEnd != 0) { | 2065 | |
| 2052 | interIdleDurations.update(now - lastIdleEnd); | 2066 | { |
| 2053 | static uint64_t lastReportTime = now; | 2067 | PROFILE_RANGE(__FUNCTION__); |
| 2054 | if ((now - lastReportTime) >= (USECS_PER_SECOND)) { | 2068 | uint64_t now = usecTimestampNow(); |
| 2055 | static QString LOGLINE("Average inter-idle time: %1 us for %2 samples"); | 2069 | static uint64_t lastIdleStart{ now }; |
| 2056 | if (Menu::getInstance()->isOptionChecked(MenuOption::LogExtraTimings)) { | 2070 | uint64_t idleStartToStartDuration = now - lastIdleStart; |
| 2057 | qCDebug(interfaceapp_timing) << LOGLINE.arg((int)interIdleDurations.getAverage()).arg(interIdleDurations.getCount()); | 2071 | if (idleStartToStartDuration != 0) { |
| 2058 | } | 2072 | _simsPerSecond.updateAverage((float)USECS_PER_SECOND / (float)idleStartToStartDuration); |
| 2059 | interIdleDurations.reset(); | ||
| 2060 | lastReportTime = now; | ||
| 2061 | } | 2073 | } |
| 2074 | lastIdleStart = now; | ||
| 2062 | } | 2075 | } |
| 2063 | 2076 | ||
| 2064 | PerformanceTimer perfTimer("idle"); | 2077 | PerformanceTimer perfTimer("idle"); |
| 2065 | if (_aboutToQuit) { | ||
| 2066 | return; // bail early, nothing to do here. | ||
| 2067 | } | ||
| 2068 | |||
| 2069 | // Drop focus from _keyboardFocusedItem if no keyboard messages for 30 seconds | 2078 | // Drop focus from _keyboardFocusedItem if no keyboard messages for 30 seconds |
| 2070 | if (!_keyboardFocusedItem.isInvalidID()) { | 2079 | if (!_keyboardFocusedItem.isInvalidID()) { |
| 2071 | const quint64 LOSE_FOCUS_AFTER_ELAPSED_TIME = 30 * USECS_PER_SECOND; // if idle for 30 seconds, drop focus | 2080 | const quint64 LOSE_FOCUS_AFTER_ELAPSED_TIME = 30 * USECS_PER_SECOND; // if idle for 30 seconds, drop focus |
| @@ -2081,69 +2090,42 @@ void Application::idle() { · 9 unmodified lines | |||
| 2081 | bool showWarnings = getLogger()->extraDebugging(); | 2090 | bool showWarnings = getLogger()->extraDebugging(); |
| 2082 | PerformanceWarning warn(showWarnings, "idle()"); | 2091 | PerformanceWarning warn(showWarnings, "idle()"); |
| 2083 | 2092 | ||
| 2084 | // Only run simulation code if more than the targetFramePeriod have passed since last time we ran | 2093 | { |
| 2085 | double targetFramePeriod = 0.0; | 2094 | PerformanceTimer perfTimer("update"); |
| 2086 | unsigned int targetFramerate = getRenderTargetFramerate(); | 2095 | PerformanceWarning warn(showWarnings, "Application::idle()... update()"); |
| 2087 | if (targetFramerate > 0) { | 2096 | static const float BIGGEST_DELTA_TIME_SECS = 0.25f; |
| 2088 | targetFramePeriod = 1000.0 / targetFramerate; | 2097 | update(glm::clamp(secondsSinceLastUpdate, 0.0f, BIGGEST_DELTA_TIME_SECS)); |
| 2089 | } | 2098 | } |
| 2090 | double timeSinceLastUpdate = (double)_lastTimeUpdated.nsecsElapsed() / 1000000.0; | 2099 | { |
| 2091 | if (timeSinceLastUpdate > targetFramePeriod) { | 2100 | PerformanceTimer perfTimer("pluginIdle"); |
| 2092 | _lastTimeUpdated.start(); | 2101 | PerformanceWarning warn(showWarnings, "Application::idle()... pluginIdle()"); |
| 2093 | { | 2102 | getActiveDisplayPlugin()->idle(); |
| 2094 | PerformanceTimer perfTimer("update"); | 2103 | auto inputPlugins = PluginManager::getInstance()->getInputPlugins(); |
| 2095 | PerformanceWarning warn(showWarnings, "Application::idle()... update()"); | 2104 | foreach(auto inputPlugin, inputPlugins) { |
| 2096 | const float BIGGEST_DELTA_TIME_SECS = 0.25f; | 2105 | QString name = inputPlugin->getName(); |
| 2097 | PROFILE_RANGE(__FUNCTION__ "/idleUpdate"); | 2106 | QAction* action = Menu::getInstance()->getActionForOption(name); |
| 2098 | update(glm::clamp((float)timeSinceLastUpdate / 1000.0f, 0.0f, BIGGEST_DELTA_TIME_SECS)); | 2107 | if (action && action->isChecked()) { |
| 2099 | } | 2108 | inputPlugin->idle(); |
| 2100 | { | ||
| 2101 | PerformanceTimer perfTimer("updateGL"); | ||
| 2102 | PerformanceWarning warn(showWarnings, "Application::idle()... updateGL()"); | ||
| 2103 | getActiveDisplayPlugin()->idle(); | ||
| 2104 | auto inputPlugins = PluginManager::getInstance()->getInputPlugins(); | ||
| 2105 | foreach(auto inputPlugin, inputPlugins) { | ||
| 2106 | QString name = inputPlugin->getName(); | ||
| 2107 | QAction* action = Menu::getInstance()->getActionForOption(name); | ||
| 2108 | if (action && action->isChecked()) { | ||
| 2109 | inputPlugin->idle(); | ||
| 2110 | } | ||
| 2111 | } | ||
| 2112 | } | ||
| 2113 | { | ||
| 2114 | PerformanceTimer perfTimer("rest"); | ||
| 2115 | PerformanceWarning warn(showWarnings, "Application::idle()... rest of it"); | ||
| 2116 | _idleLoopStdev.addValue(timeSinceLastUpdate); | ||
| 2117 | |||
| 2118 | // Record standard deviation and reset counter if needed | ||
| 2119 | const int STDEV_SAMPLES = 500; | ||
| 2120 | if (_idleLoopStdev.getSamples() > STDEV_SAMPLES) { | ||
| 2121 | _idleLoopMeasuredJitter = _idleLoopStdev.getStDev(); | ||
| 2122 | _idleLoopStdev.reset(); | ||
| 2123 | } | 2109 | } |
| 2124 | } | 2110 | } |
| 2125 | 2111 | } | |
| 2126 | float secondsSinceLastUpdate = (float)timeSinceLastUpdate / 1000.0f; | 2112 | { |
| 2127 | _overlayConductor.update(secondsSinceLastUpdate); | 2113 | PerformanceTimer perfTimer("rest"); |
| 2128 | 2114 | PerformanceWarning warn(showWarnings, "Application::idle()... rest of it"); | |
| 2129 | // depending on whether we're throttling or not. | 2115 | _idleLoopStdev.addValue(secondsSinceLastUpdate); |
| 2130 | // Once rendering is off on another thread we should be able to have Application::idle run at start(0) in | 2116 | |
| 2131 | // perpetuity and not expect events to get backed up. | 2117 | // Record standard deviation and reset counter if needed |
| 2132 | 2118 | const int STDEV_SAMPLES = 500; | |
| 2133 | bool isThrottled = getActiveDisplayPlugin()->isThrottled(); | 2119 | if (_idleLoopStdev.getSamples() > STDEV_SAMPLES) { |
| 2134 | static const int THROTTLED_IDLE_TIMER_DELAY = MSECS_PER_SECOND / 15; | 2120 | _idleLoopMeasuredJitter = _idleLoopStdev.getStDev(); |
| 2135 | static const int IDLE_TIMER_DELAY_MS = 2; | 2121 | _idleLoopStdev.reset(); |
| 2136 | int desiredInterval = isThrottled ? THROTTLED_IDLE_TIMER_DELAY : IDLE_TIMER_DELAY_MS; | ||
| 2137 | //qDebug() << "isThrottled:" << isThrottled << "desiredInterval:" << desiredInterval; | ||
| 2138 | |||
| 2139 | if (idleTimer->interval() != desiredInterval) { | ||
| 2140 | idleTimer->start(desiredInterval); | ||
| 2141 | } | 2122 | } |
| 2142 | } | 2123 | } |
| 2124 | |||
| 2125 | _overlayConductor.update(secondsSinceLastUpdate); | ||
| 2143 | 2126 | ||
| 2144 | // check for any requested background downloads. | 2127 | // check for any requested background downloads. |
| 2145 | emit checkBackgroundDownloads(); | 2128 | emit checkBackgroundDownloads(); |
| 2146 | lastIdleEnd = usecTimestampNow(); | ||
| 2147 | } | 2129 | } |
| 2148 | 2130 | ||
| 2149 | float Application::getAverageSimsPerSecond() { | 2131 | float Application::getAverageSimsPerSecond() { |
| @@ -4485,90 +4467,10 @@ void Application::takeSnapshot() { · 2335 unmodified lines | |||
| 4485 | 4467 | ||
| 4486 | } | 4468 | } |
| 4487 | 4469 | ||
| 4488 | void Application::setVSyncEnabled() { | ||
| 4489 | _glWidget->makeCurrent(); | ||
| 4490 | #if defined(Q_OS_WIN) | ||
| 4491 | bool vsyncOn = Menu::getInstance()->isOptionChecked(MenuOption::RenderTargetFramerateVSyncOn); | ||
| 4492 | if (wglewGetExtension("WGL_EXT_swap_control")) { | ||
| 4493 | wglSwapIntervalEXT(vsyncOn); | ||
| 4494 | int swapInterval = wglGetSwapIntervalEXT(); | ||
| 4495 | qCDebug(interfaceapp, "V-Sync is %s\n", (swapInterval > 0 ? "ON" : "OFF")); | ||
| 4496 | } else { | ||
| 4497 | qCDebug(interfaceapp, "V-Sync is FORCED ON on this system\n"); | ||
| 4498 | } | ||
| 4499 | #elif defined(Q_OS_LINUX) | ||
| 4500 | // TODO: write the poper code for linux | ||
| 4501 | /* | ||
| 4502 | if (glQueryExtension.... ("GLX_EXT_swap_control")) { | ||
| 4503 | glxSwapIntervalEXT(vsyncOn); | ||
| 4504 | int swapInterval = xglGetSwapIntervalEXT(); | ||
| 4505 | _isVSyncOn = swapInterval; | ||
| 4506 | qCDebug(interfaceapp, "V-Sync is %s\n", (swapInterval > 0 ? "ON" : "OFF")); | ||
| 4507 | } else { | ||
| 4508 | qCDebug(interfaceapp, "V-Sync is FORCED ON on this system\n"); | ||
| 4509 | } | ||
| 4510 | */ | ||
| 4511 | #else | ||
| 4512 | qCDebug(interfaceapp, "V-Sync is FORCED ON on this system\n"); | ||
| 4513 | #endif | ||
| 4514 | _offscreenContext->makeCurrent(); | ||
| 4515 | } | ||
| 4516 | |||
| 4517 | void Application::setThrottleFPSEnabled() { | 4470 | void Application::setThrottleFPSEnabled() { |
| 4518 | _isThrottleFPSEnabled = Menu::getInstance()->isOptionChecked(MenuOption::ThrottleFPSIfNotFocus); | 4471 | _isThrottleFPSEnabled = Menu::getInstance()->isOptionChecked(MenuOption::ThrottleFPSIfNotFocus); |
| 4519 | } | 4472 | } |
| 4520 | 4473 | ||
| 4521 | bool Application::isVSyncOn() const { | ||
| 4522 | #if defined(Q_OS_WIN) | ||
| 4523 | if (wglewGetExtension("WGL_EXT_swap_control")) { | ||
| 4524 | int swapInterval = wglGetSwapIntervalEXT(); | ||
| 4525 | return (swapInterval > 0); | ||
| 4526 | } | ||
| 4527 | #elif defined(Q_OS_LINUX) | ||
| 4528 | // TODO: write the poper code for linux | ||
| 4529 | /* | ||
| 4530 | if (glQueryExtension.... ("GLX_EXT_swap_control")) { | ||
| 4531 | int swapInterval = xglGetSwapIntervalEXT(); | ||
| 4532 | return (swapInterval > 0); | ||
| 4533 | } else { | ||
| 4534 | return true; | ||
| 4535 | } | ||
| 4536 | */ | ||
| 4537 | #endif | ||
| 4538 | return true; | ||
| 4539 | } | ||
| 4540 | |||
| 4541 | bool Application::isVSyncEditable() const { | ||
| 4542 | #if defined(Q_OS_WIN) | ||
| 4543 | if (wglewGetExtension("WGL_EXT_swap_control")) { | ||
| 4544 | return true; | ||
| 4545 | } | ||
| 4546 | #elif defined(Q_OS_LINUX) | ||
| 4547 | // TODO: write the poper code for linux | ||
| 4548 | /* | ||
| 4549 | if (glQueryExtension.... ("GLX_EXT_swap_control")) { | ||
| 4550 | return true; | ||
| 4551 | } | ||
| 4552 | */ | ||
| 4553 | #endif | ||
| 4554 | return false; | ||
| 4555 | } | ||
| 4556 | |||
| 4557 | unsigned int Application::getRenderTargetFramerate() const { | ||
| 4558 | if (Menu::getInstance()->isOptionChecked(MenuOption::RenderTargetFramerateUnlimited)) { | ||
| 4559 | return 0; | ||
| 4560 | } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderTargetFramerate60)) { | ||
| 4561 | return 60; | ||
| 4562 | } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderTargetFramerate50)) { | ||
| 4563 | return 50; | ||
| 4564 | } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderTargetFramerate40)) { | ||
| 4565 | return 40; | ||
| 4566 | } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderTargetFramerate30)) { | ||
| 4567 | return 30; | ||
| 4568 | } | ||
| 4569 | return 0; | ||
| 4570 | } | ||
| 4571 | |||
| 4572 | float Application::getRenderResolutionScale() const { | 4474 | float Application::getRenderResolutionScale() const { |
| 4573 | if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionOne)) { | 4475 | if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionOne)) { |
| 4574 | return 1.0f; | 4476 | return 1.0f; |
| @@ -5150,3 +5052,9 @@ void Application::emulateMouse(Hand* hand, float click, float shift, int index) · 575 unmodified lines | |||
| 5150 | _oldHandLeftClick[index] = false; | 5052 | _oldHandLeftClick[index] = false; |
| 5151 | } | 5053 | } |
| 5152 | } | 5054 | } |
| 5055 | |||
| 5056 | void Application::crashApplication() { | ||
| 5057 | QObject* object = nullptr; | ||
| 5058 | bool value = object->isWindowType(); | ||
| 5059 | qCDebug(interfaceapp) << "Intentionally crashed Interface"; | ||
| 5060 | } | ||