Showing the changes to interface/src/Application.cpp (1 of 31 files). Show all
Unified · Split
| @@ -104,6 +104,7 @@ · 103 unmodified lines | ||
| 104 | 104 | #include <RenderableWebEntityItem.h> |
| 105 | 105 | |
| 106 | 106 | #include "AudioClient.h" |
| 107 | +#include "CrashHandler.h" | |
| 107 | 108 | #include "DiscoverabilityManager.h" |
| 108 | 109 | #include "GLCanvas.h" |
| 109 | 110 | #include "LODManager.h" |
| @@ -189,6 +190,11 @@ static QTimer* billboardPacketTimer = NULL; · 79 unmodified lines | ||
| 189 | 190 | static QTimer* checkFPStimer = NULL; |
| 190 | 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 | 198 | const QString CHECK_VERSION_URL = "https://highfidelity.com/latestVersion.xml"; |
| 193 | 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 | 263 | // Set build version |
| 258 | 264 | QCoreApplication::setApplicationVersion(BUILD_VERSION); |
| 259 | 265 | |
| 266 | + Setting::preInit(); | |
| 267 | + | |
| 268 | + CrashHandler::checkForAndHandleCrash(); | |
| 269 | + CrashHandler::writeRunningMarkerFiler(); | |
| 270 | + qAddPostRoutine(CrashHandler::deleteRunningMarkerFile); | |
| 271 | + | |
| 260 | 272 | DependencyManager::registerInheritance<LimitedNodeList, NodeList>(); |
| 261 | 273 | DependencyManager::registerInheritance<AvatarHashMap, AvatarManager>(); |
| 262 | 274 | DependencyManager::registerInheritance<EntityActionFactoryInterface, InterfaceActionFactory>(); |
| @@ -347,7 +359,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 84 unmodified lines | ||
| 347 | 359 | _trayIcon(new QSystemTrayIcon(_window)), |
| 348 | 360 | _lastNackTime(usecTimestampNow()), |
| 349 | 361 | _lastSendDownstreamAudioStats(usecTimestampNow()), |
| 350 | − _isVSyncOn(true), | |
| 351 | 362 | _isThrottleFPSEnabled(true), |
| 352 | 363 | _aboutToQuit(false), |
| 353 | 364 | _notifiedPacketVersionMismatchThisDomain(false), |
| @@ -745,8 +756,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 391 unmodified lines | ||
| 745 | 756 | }); |
| 746 | 757 | |
| 747 | 758 | connect(this, &Application::applicationStateChanged, this, &Application::activeChanged); |
| 748 | − | |
| 749 | − setVSyncEnabled(); // make sure VSync is set properly at startup | |
| 750 | 759 | } |
| 751 | 760 | |
| 752 | 761 | void Application::aboutToQuit() { |
| @@ -921,7 +930,7 @@ void Application::initializeGL() { · 168 unmodified lines | ||
| 921 | 930 | // call our idle function whenever we can |
| 922 | 931 | idleTimer = new QTimer(this); |
| 923 | 932 | connect(idleTimer, SIGNAL(timeout()), SLOT(idle())); |
| 924 | − idleTimer->start(0); | |
| 933 | + idleTimer->start(TARGET_SIM_FRAME_PERIOD_MS); | |
| 925 | 934 | _idleLoopStdev.reset(); |
| 926 | 935 | |
| 927 | 936 | if (_justStarted) { |
| @@ -2034,38 +2043,38 @@ void Application::checkFPS() { · 1106 unmodified lines | ||
| 2034 | 2043 | } |
| 2035 | 2044 | |
| 2036 | 2045 | void Application::idle() { |
| 2037 | − PROFILE_RANGE(__FUNCTION__); | |
| 2038 | − static SimpleAverage<float> interIdleDurations; | |
| 2046 | + if (_aboutToQuit) { | |
| 2047 | + return; // bail early, nothing to do here. | |
| 2048 | + } | |
| 2039 | 2049 | |
| 2040 | − static uint64_t lastIdleStart{ 0 }; | |
| 2041 | − static uint64_t lastIdleEnd{ 0 }; | |
| 2042 | − uint64_t now = usecTimestampNow(); | |
| 2043 | − uint64_t idleStartToStartDuration = now - lastIdleStart; | |
| 2050 | + // depending on whether we're throttling or not. | |
| 2051 | + // Once rendering is off on another thread we should be able to have Application::idle run at start(0) in | |
| 2052 | + // perpetuity and not expect events to get backed up. | |
| 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) { | |
| 2046 | − _simsPerSecond.updateAverage((float)USECS_PER_SECOND / (float)idleStartToStartDuration); | |
| 2059 | + if (isThrottled && (timeSinceLastUpdateUs / USECS_PER_MSEC) < THROTTLED_SIM_FRAME_PERIOD_MS) { | |
| 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) { | |
| 2052 | − interIdleDurations.update(now - lastIdleEnd); | |
| 2053 | − static uint64_t lastReportTime = now; | |
| 2054 | − if ((now - lastReportTime) >= (USECS_PER_SECOND)) { | |
| 2055 | − static QString LOGLINE("Average inter-idle time: %1 us for %2 samples"); | |
| 2056 | − if (Menu::getInstance()->isOptionChecked(MenuOption::LogExtraTimings)) { | |
| 2057 | − qCDebug(interfaceapp_timing) << LOGLINE.arg((int)interIdleDurations.getAverage()).arg(interIdleDurations.getCount()); | |
| 2058 | − } | |
| 2059 | − interIdleDurations.reset(); | |
| 2060 | − lastReportTime = now; | |
| 2065 | + | |
| 2066 | + { | |
| 2067 | + PROFILE_RANGE(__FUNCTION__); | |
| 2068 | + uint64_t now = usecTimestampNow(); | |
| 2069 | + static uint64_t lastIdleStart{ now }; | |
| 2070 | + uint64_t idleStartToStartDuration = now - lastIdleStart; | |
| 2071 | + if (idleStartToStartDuration != 0) { | |
| 2072 | + _simsPerSecond.updateAverage((float)USECS_PER_SECOND / (float)idleStartToStartDuration); | |
| 2061 | 2073 | } |
| 2074 | + lastIdleStart = now; | |
| 2062 | 2075 | } |
| 2063 | 2076 | |
| 2064 | 2077 | PerformanceTimer perfTimer("idle"); |
| 2065 | − if (_aboutToQuit) { | |
| 2066 | − return; // bail early, nothing to do here. | |
| 2067 | − } | |
| 2068 | − | |
| 2069 | 2078 | // Drop focus from _keyboardFocusedItem if no keyboard messages for 30 seconds |
| 2070 | 2079 | if (!_keyboardFocusedItem.isInvalidID()) { |
| 2071 | 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 | 2090 | bool showWarnings = getLogger()->extraDebugging(); |
| 2082 | 2091 | PerformanceWarning warn(showWarnings, "idle()"); |
| 2083 | 2092 | |
| 2084 | − // Only run simulation code if more than the targetFramePeriod have passed since last time we ran | |
| 2085 | − double targetFramePeriod = 0.0; | |
| 2086 | − unsigned int targetFramerate = getRenderTargetFramerate(); | |
| 2087 | − if (targetFramerate > 0) { | |
| 2088 | − targetFramePeriod = 1000.0 / targetFramerate; | |
| 2089 | − } | |
| 2090 | − double timeSinceLastUpdate = (double)_lastTimeUpdated.nsecsElapsed() / 1000000.0; | |
| 2091 | − if (timeSinceLastUpdate > targetFramePeriod) { | |
| 2092 | − _lastTimeUpdated.start(); | |
| 2093 | − { | |
| 2094 | − PerformanceTimer perfTimer("update"); | |
| 2095 | − PerformanceWarning warn(showWarnings, "Application::idle()... update()"); | |
| 2096 | − const float BIGGEST_DELTA_TIME_SECS = 0.25f; | |
| 2097 | − PROFILE_RANGE(__FUNCTION__ "/idleUpdate"); | |
| 2098 | − update(glm::clamp((float)timeSinceLastUpdate / 1000.0f, 0.0f, BIGGEST_DELTA_TIME_SECS)); | |
| 2099 | − } | |
| 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(); | |
| 2093 | + { | |
| 2094 | + PerformanceTimer perfTimer("update"); | |
| 2095 | + PerformanceWarning warn(showWarnings, "Application::idle()... update()"); | |
| 2096 | + static const float BIGGEST_DELTA_TIME_SECS = 0.25f; | |
| 2097 | + update(glm::clamp(secondsSinceLastUpdate, 0.0f, BIGGEST_DELTA_TIME_SECS)); | |
| 2098 | + } | |
| 2099 | + { | |
| 2100 | + PerformanceTimer perfTimer("pluginIdle"); | |
| 2101 | + PerformanceWarning warn(showWarnings, "Application::idle()... pluginIdle()"); | |
| 2102 | + getActiveDisplayPlugin()->idle(); | |
| 2103 | + auto inputPlugins = PluginManager::getInstance()->getInputPlugins(); | |
| 2104 | + foreach(auto inputPlugin, inputPlugins) { | |
| 2105 | + QString name = inputPlugin->getName(); | |
| 2106 | + QAction* action = Menu::getInstance()->getActionForOption(name); | |
| 2107 | + if (action && action->isChecked()) { | |
| 2108 | + inputPlugin->idle(); | |
| 2123 | 2109 | } |
| 2124 | 2110 | } |
| 2125 | − | |
| 2126 | − float secondsSinceLastUpdate = (float)timeSinceLastUpdate / 1000.0f; | |
| 2127 | − _overlayConductor.update(secondsSinceLastUpdate); | |
| 2128 | − | |
| 2129 | − // depending on whether we're throttling or not. | |
| 2130 | − // Once rendering is off on another thread we should be able to have Application::idle run at start(0) in | |
| 2131 | − // perpetuity and not expect events to get backed up. | |
| 2132 | − | |
| 2133 | − bool isThrottled = getActiveDisplayPlugin()->isThrottled(); | |
| 2134 | − static const int THROTTLED_IDLE_TIMER_DELAY = MSECS_PER_SECOND / 15; | |
| 2135 | − static const int IDLE_TIMER_DELAY_MS = 2; | |
| 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); | |
| 2111 | + } | |
| 2112 | + { | |
| 2113 | + PerformanceTimer perfTimer("rest"); | |
| 2114 | + PerformanceWarning warn(showWarnings, "Application::idle()... rest of it"); | |
| 2115 | + _idleLoopStdev.addValue(secondsSinceLastUpdate); | |
| 2116 | + | |
| 2117 | + // Record standard deviation and reset counter if needed | |
| 2118 | + const int STDEV_SAMPLES = 500; | |
| 2119 | + if (_idleLoopStdev.getSamples() > STDEV_SAMPLES) { | |
| 2120 | + _idleLoopMeasuredJitter = _idleLoopStdev.getStDev(); | |
| 2121 | + _idleLoopStdev.reset(); | |
| 2141 | 2122 | } |
| 2142 | 2123 | } |
| 2124 | + | |
| 2125 | + _overlayConductor.update(secondsSinceLastUpdate); | |
| 2143 | 2126 | |
| 2144 | 2127 | // check for any requested background downloads. |
| 2145 | 2128 | emit checkBackgroundDownloads(); |
| 2146 | − lastIdleEnd = usecTimestampNow(); | |
| 2147 | 2129 | } |
| 2148 | 2130 | |
| 2149 | 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 | 4470 | void Application::setThrottleFPSEnabled() { |
| 4518 | 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 | 4474 | float Application::getRenderResolutionScale() const { |
| 4573 | 4475 | if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionOne)) { |
| 4574 | 4476 | return 1.0f; |
| @@ -5150,3 +5052,9 @@ void Application::emulateMouse(Hand* hand, float click, float shift, int index) · 575 unmodified lines | ||
| 5150 | 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 | +} | |