Showing the changes to interface/src/Application.cpp (1 of 112 files). Show all
Unified · Split
| @@ -105,6 +105,7 @@ · 104 unmodified lines | ||
| 105 | 105 | #include <RenderableWebEntityItem.h> |
| 106 | 106 | |
| 107 | 107 | #include "AudioClient.h" |
| 108 | +#include "CrashHandler.h" | |
| 108 | 109 | #include "DiscoverabilityManager.h" |
| 109 | 110 | #include "GLCanvas.h" |
| 110 | 111 | #include "LODManager.h" |
| @@ -190,6 +191,11 @@ static QTimer* billboardPacketTimer = NULL; · 79 unmodified lines | ||
| 190 | 191 | static QTimer* checkFPStimer = NULL; |
| 191 | 192 | static QTimer* idleTimer = NULL; |
| 192 | 193 | |
| 194 | +static const unsigned int TARGET_SIM_FRAMERATE = 60; | |
| 195 | +static const unsigned int THROTTLED_SIM_FRAMERATE = 15; | |
| 196 | +static const int TARGET_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / TARGET_SIM_FRAMERATE; | |
| 197 | +static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SIM_FRAMERATE; | |
| 198 | + | |
| 193 | 199 | const QString CHECK_VERSION_URL = "https://highfidelity.com/latestVersion.xml"; |
| 194 | 200 | const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/hifi.skipversion"; |
| 195 | 201 | |
| @@ -258,6 +264,12 @@ bool setupEssentials(int& argc, char** argv) { · 62 unmodified lines | ||
| 258 | 264 | // Set build version |
| 259 | 265 | QCoreApplication::setApplicationVersion(BUILD_VERSION); |
| 260 | 266 | |
| 267 | + Setting::preInit(); | |
| 268 | + | |
| 269 | + CrashHandler::checkForAndHandleCrash(); | |
| 270 | + CrashHandler::writeRunningMarkerFiler(); | |
| 271 | + qAddPostRoutine(CrashHandler::deleteRunningMarkerFile); | |
| 272 | + | |
| 261 | 273 | DependencyManager::registerInheritance<LimitedNodeList, NodeList>(); |
| 262 | 274 | DependencyManager::registerInheritance<AvatarHashMap, AvatarManager>(); |
| 263 | 275 | DependencyManager::registerInheritance<EntityActionFactoryInterface, InterfaceActionFactory>(); |
| @@ -349,7 +361,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 85 unmodified lines | ||
| 349 | 361 | _trayIcon(new QSystemTrayIcon(_window)), |
| 350 | 362 | _lastNackTime(usecTimestampNow()), |
| 351 | 363 | _lastSendDownstreamAudioStats(usecTimestampNow()), |
| 352 | − _isVSyncOn(true), | |
| 353 | 364 | _isThrottleFPSEnabled(true), |
| 354 | 365 | _aboutToQuit(false), |
| 355 | 366 | _notifiedPacketVersionMismatchThisDomain(false), |
| @@ -757,8 +768,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : · 401 unmodified lines | ||
| 757 | 768 | }); |
| 758 | 769 | |
| 759 | 770 | connect(this, &Application::applicationStateChanged, this, &Application::activeChanged); |
| 760 | − | |
| 761 | − setVSyncEnabled(); // make sure VSync is set properly at startup | |
| 762 | 771 | } |
| 763 | 772 | |
| 764 | 773 | void Application::aboutToQuit() { |
| @@ -932,7 +941,7 @@ void Application::initializeGL() { · 167 unmodified lines | ||
| 932 | 941 | // call our idle function whenever we can |
| 933 | 942 | idleTimer = new QTimer(this); |
| 934 | 943 | connect(idleTimer, SIGNAL(timeout()), SLOT(idle())); |
| 935 | − idleTimer->start(0); | |
| 944 | + idleTimer->start(TARGET_SIM_FRAME_PERIOD_MS); | |
| 936 | 945 | _idleLoopStdev.reset(); |
| 937 | 946 | |
| 938 | 947 | if (_justStarted) { |
| @@ -1439,7 +1448,6 @@ void Application::keyPressEvent(QKeyEvent* event) { · 500 unmodified lines | ||
| 1439 | 1448 | bool isMeta = event->modifiers().testFlag(Qt::ControlModifier); |
| 1440 | 1449 | bool isOption = event->modifiers().testFlag(Qt::AltModifier); |
| 1441 | 1450 | switch (event->key()) { |
| 1442 | − break; | |
| 1443 | 1451 | case Qt::Key_Enter: |
| 1444 | 1452 | case Qt::Key_Return: |
| 1445 | 1453 | if (isOption) { |
| @@ -2047,38 +2055,38 @@ void Application::checkFPS() { · 601 unmodified lines | ||
| 2047 | 2055 | } |
| 2048 | 2056 | |
| 2049 | 2057 | void Application::idle() { |
| 2050 | − PROFILE_RANGE(__FUNCTION__); | |
| 2051 | − static SimpleAverage<float> interIdleDurations; | |
| 2058 | + if (_aboutToQuit) { | |
| 2059 | + return; // bail early, nothing to do here. | |
| 2060 | + } | |
| 2052 | 2061 | |
| 2053 | − static uint64_t lastIdleStart{ 0 }; | |
| 2054 | − static uint64_t lastIdleEnd{ 0 }; | |
| 2055 | − uint64_t now = usecTimestampNow(); | |
| 2056 | − uint64_t idleStartToStartDuration = now - lastIdleStart; | |
| 2062 | + // depending on whether we're throttling or not. | |
| 2063 | + // Once rendering is off on another thread we should be able to have Application::idle run at start(0) in | |
| 2064 | + // perpetuity and not expect events to get backed up. | |
| 2065 | + bool isThrottled = getActiveDisplayPlugin()->isThrottled(); | |
| 2066 | + // Only run simulation code if more than the targetFramePeriod have passed since last time we ran | |
| 2067 | + // This attempts to lock the simulation at 60 updates per second, regardless of framerate | |
| 2068 | + float timeSinceLastUpdateUs = (float)_lastTimeUpdated.nsecsElapsed() / NSECS_PER_USEC; | |
| 2069 | + float secondsSinceLastUpdate = timeSinceLastUpdateUs / USECS_PER_SECOND; | |
| 2057 | 2070 | |
| 2058 | − if (lastIdleStart > 0 && idleStartToStartDuration > 0) { | |
| 2059 | − _simsPerSecond.updateAverage((float)USECS_PER_SECOND / (float)idleStartToStartDuration); | |
| 2071 | + if (isThrottled && (timeSinceLastUpdateUs / USECS_PER_MSEC) < THROTTLED_SIM_FRAME_PERIOD_MS) { | |
| 2072 | + return; // bail early, we're throttled and not enough time has elapsed | |
| 2060 | 2073 | } |
| 2061 | 2074 | |
| 2062 | − lastIdleStart = now; | |
| 2075 | + _lastTimeUpdated.start(); | |
| 2063 | 2076 | |
| 2064 | − if (lastIdleEnd != 0) { | |
| 2065 | − interIdleDurations.update(now - lastIdleEnd); | |
| 2066 | − static uint64_t lastReportTime = now; | |
| 2067 | − if ((now - lastReportTime) >= (USECS_PER_SECOND)) { | |
| 2068 | − static QString LOGLINE("Average inter-idle time: %1 us for %2 samples"); | |
| 2069 | − if (Menu::getInstance()->isOptionChecked(MenuOption::LogExtraTimings)) { | |
| 2070 | − qCDebug(interfaceapp_timing) << LOGLINE.arg((int)interIdleDurations.getAverage()).arg(interIdleDurations.getCount()); | |
| 2071 | − } | |
| 2072 | − interIdleDurations.reset(); | |
| 2073 | − lastReportTime = now; | |
| 2077 | + | |
| 2078 | + { | |
| 2079 | + PROFILE_RANGE(__FUNCTION__); | |
| 2080 | + uint64_t now = usecTimestampNow(); | |
| 2081 | + static uint64_t lastIdleStart{ now }; | |
| 2082 | + uint64_t idleStartToStartDuration = now - lastIdleStart; | |
| 2083 | + if (idleStartToStartDuration != 0) { | |
| 2084 | + _simsPerSecond.updateAverage((float)USECS_PER_SECOND / (float)idleStartToStartDuration); | |
| 2074 | 2085 | } |
| 2086 | + lastIdleStart = now; | |
| 2075 | 2087 | } |
| 2076 | 2088 | |
| 2077 | 2089 | PerformanceTimer perfTimer("idle"); |
| 2078 | − if (_aboutToQuit) { | |
| 2079 | − return; // bail early, nothing to do here. | |
| 2080 | − } | |
| 2081 | − | |
| 2082 | 2090 | // Drop focus from _keyboardFocusedItem if no keyboard messages for 30 seconds |
| 2083 | 2091 | if (!_keyboardFocusedItem.isInvalidID()) { |
| 2084 | 2092 | const quint64 LOSE_FOCUS_AFTER_ELAPSED_TIME = 30 * USECS_PER_SECOND; // if idle for 30 seconds, drop focus |
| @@ -2094,69 +2102,42 @@ void Application::idle() { · 9 unmodified lines | ||
| 2094 | 2102 | bool showWarnings = getLogger()->extraDebugging(); |
| 2095 | 2103 | PerformanceWarning warn(showWarnings, "idle()"); |
| 2096 | 2104 | |
| 2097 | − // Only run simulation code if more than the targetFramePeriod have passed since last time we ran | |
| 2098 | − double targetFramePeriod = 0.0; | |
| 2099 | − unsigned int targetFramerate = getRenderTargetFramerate(); | |
| 2100 | − if (targetFramerate > 0) { | |
| 2101 | − targetFramePeriod = 1000.0 / targetFramerate; | |
| 2102 | − } | |
| 2103 | − double timeSinceLastUpdate = (double)_lastTimeUpdated.nsecsElapsed() / 1000000.0; | |
| 2104 | − if (timeSinceLastUpdate > targetFramePeriod) { | |
| 2105 | − _lastTimeUpdated.start(); | |
| 2106 | − { | |
| 2107 | − PerformanceTimer perfTimer("update"); | |
| 2108 | − PerformanceWarning warn(showWarnings, "Application::idle()... update()"); | |
| 2109 | − const float BIGGEST_DELTA_TIME_SECS = 0.25f; | |
| 2110 | − PROFILE_RANGE(__FUNCTION__ "/idleUpdate"); | |
| 2111 | − update(glm::clamp((float)timeSinceLastUpdate / 1000.0f, 0.0f, BIGGEST_DELTA_TIME_SECS)); | |
| 2112 | − } | |
| 2113 | − { | |
| 2114 | − PerformanceTimer perfTimer("updateGL"); | |
| 2115 | − PerformanceWarning warn(showWarnings, "Application::idle()... updateGL()"); | |
| 2116 | − getActiveDisplayPlugin()->idle(); | |
| 2117 | − auto inputPlugins = PluginManager::getInstance()->getInputPlugins(); | |
| 2118 | − foreach(auto inputPlugin, inputPlugins) { | |
| 2119 | − QString name = inputPlugin->getName(); | |
| 2120 | − QAction* action = Menu::getInstance()->getActionForOption(name); | |
| 2121 | − if (action && action->isChecked()) { | |
| 2122 | − inputPlugin->idle(); | |
| 2123 | − } | |
| 2124 | − } | |
| 2125 | − } | |
| 2126 | − { | |
| 2127 | − PerformanceTimer perfTimer("rest"); | |
| 2128 | − PerformanceWarning warn(showWarnings, "Application::idle()... rest of it"); | |
| 2129 | − _idleLoopStdev.addValue(timeSinceLastUpdate); | |
| 2130 | − | |
| 2131 | − // Record standard deviation and reset counter if needed | |
| 2132 | − const int STDEV_SAMPLES = 500; | |
| 2133 | − if (_idleLoopStdev.getSamples() > STDEV_SAMPLES) { | |
| 2134 | − _idleLoopMeasuredJitter = _idleLoopStdev.getStDev(); | |
| 2135 | − _idleLoopStdev.reset(); | |
| 2105 | + { | |
| 2106 | + PerformanceTimer perfTimer("update"); | |
| 2107 | + PerformanceWarning warn(showWarnings, "Application::idle()... update()"); | |
| 2108 | + static const float BIGGEST_DELTA_TIME_SECS = 0.25f; | |
| 2109 | + update(glm::clamp(secondsSinceLastUpdate, 0.0f, BIGGEST_DELTA_TIME_SECS)); | |
| 2110 | + } | |
| 2111 | + { | |
| 2112 | + PerformanceTimer perfTimer("pluginIdle"); | |
| 2113 | + PerformanceWarning warn(showWarnings, "Application::idle()... pluginIdle()"); | |
| 2114 | + getActiveDisplayPlugin()->idle(); | |
| 2115 | + auto inputPlugins = PluginManager::getInstance()->getInputPlugins(); | |
| 2116 | + foreach(auto inputPlugin, inputPlugins) { | |
| 2117 | + QString name = inputPlugin->getName(); | |
| 2118 | + QAction* action = Menu::getInstance()->getActionForOption(name); | |
| 2119 | + if (action && action->isChecked()) { | |
| 2120 | + inputPlugin->idle(); | |
| 2136 | 2121 | } |
| 2137 | 2122 | } |
| 2138 | − | |
| 2139 | − float secondsSinceLastUpdate = (float)timeSinceLastUpdate / 1000.0f; | |
| 2140 | − _overlayConductor.update(secondsSinceLastUpdate); | |
| 2141 | − | |
| 2142 | − // depending on whether we're throttling or not. | |
| 2143 | − // Once rendering is off on another thread we should be able to have Application::idle run at start(0) in | |
| 2144 | − // perpetuity and not expect events to get backed up. | |
| 2145 | − | |
| 2146 | − bool isThrottled = getActiveDisplayPlugin()->isThrottled(); | |
| 2147 | − static const int THROTTLED_IDLE_TIMER_DELAY = MSECS_PER_SECOND / 15; | |
| 2148 | − static const int IDLE_TIMER_DELAY_MS = 2; | |
| 2149 | − int desiredInterval = isThrottled ? THROTTLED_IDLE_TIMER_DELAY : IDLE_TIMER_DELAY_MS; | |
| 2150 | − //qDebug() << "isThrottled:" << isThrottled << "desiredInterval:" << desiredInterval; | |
| 2151 | − | |
| 2152 | − if (idleTimer->interval() != desiredInterval) { | |
| 2153 | − idleTimer->start(desiredInterval); | |
| 2123 | + } | |
| 2124 | + { | |
| 2125 | + PerformanceTimer perfTimer("rest"); | |
| 2126 | + PerformanceWarning warn(showWarnings, "Application::idle()... rest of it"); | |
| 2127 | + _idleLoopStdev.addValue(secondsSinceLastUpdate); | |
| 2128 | + | |
| 2129 | + // Record standard deviation and reset counter if needed | |
| 2130 | + const int STDEV_SAMPLES = 500; | |
| 2131 | + if (_idleLoopStdev.getSamples() > STDEV_SAMPLES) { | |
| 2132 | + _idleLoopMeasuredJitter = _idleLoopStdev.getStDev(); | |
| 2133 | + _idleLoopStdev.reset(); | |
| 2154 | 2134 | } |
| 2155 | 2135 | } |
| 2136 | + | |
| 2137 | + _overlayConductor.update(secondsSinceLastUpdate); | |
| 2156 | 2138 | |
| 2157 | 2139 | // check for any requested background downloads. |
| 2158 | 2140 | emit checkBackgroundDownloads(); |
| 2159 | − lastIdleEnd = usecTimestampNow(); | |
| 2160 | 2141 | } |
| 2161 | 2142 | |
| 2162 | 2143 | float Application::getAverageSimsPerSecond() { |
| @@ -4497,90 +4478,10 @@ void Application::takeSnapshot() { · 2334 unmodified lines | ||
| 4497 | 4478 | |
| 4498 | 4479 | } |
| 4499 | 4480 | |
| 4500 | −void Application::setVSyncEnabled() { | |
| 4501 | − _glWidget->makeCurrent(); | |
| 4502 | −#if defined(Q_OS_WIN) | |
| 4503 | − bool vsyncOn = Menu::getInstance()->isOptionChecked(MenuOption::RenderTargetFramerateVSyncOn); | |
| 4504 | − if (wglewGetExtension("WGL_EXT_swap_control")) { | |
| 4505 | − wglSwapIntervalEXT(vsyncOn); | |
| 4506 | − int swapInterval = wglGetSwapIntervalEXT(); | |
| 4507 | − qCDebug(interfaceapp, "V-Sync is %s\n", (swapInterval > 0 ? "ON" : "OFF")); | |
| 4508 | − } else { | |
| 4509 | − qCDebug(interfaceapp, "V-Sync is FORCED ON on this system\n"); | |
| 4510 | − } | |
| 4511 | −#elif defined(Q_OS_LINUX) | |
| 4512 | − // TODO: write the poper code for linux | |
| 4513 | − /* | |
| 4514 | − if (glQueryExtension.... ("GLX_EXT_swap_control")) { | |
| 4515 | − glxSwapIntervalEXT(vsyncOn); | |
| 4516 | − int swapInterval = xglGetSwapIntervalEXT(); | |
| 4517 | − _isVSyncOn = swapInterval; | |
| 4518 | − qCDebug(interfaceapp, "V-Sync is %s\n", (swapInterval > 0 ? "ON" : "OFF")); | |
| 4519 | − } else { | |
| 4520 | − qCDebug(interfaceapp, "V-Sync is FORCED ON on this system\n"); | |
| 4521 | − } | |
| 4522 | − */ | |
| 4523 | −#else | |
| 4524 | − qCDebug(interfaceapp, "V-Sync is FORCED ON on this system\n"); | |
| 4525 | −#endif | |
| 4526 | − _offscreenContext->makeCurrent(); | |
| 4527 | −} | |
| 4528 | − | |
| 4529 | 4481 | void Application::setThrottleFPSEnabled() { |
| 4530 | 4482 | _isThrottleFPSEnabled = Menu::getInstance()->isOptionChecked(MenuOption::ThrottleFPSIfNotFocus); |
| 4531 | 4483 | } |
| 4532 | 4484 | |
| 4533 | −bool Application::isVSyncOn() const { | |
| 4534 | −#if defined(Q_OS_WIN) | |
| 4535 | − if (wglewGetExtension("WGL_EXT_swap_control")) { | |
| 4536 | − int swapInterval = wglGetSwapIntervalEXT(); | |
| 4537 | − return (swapInterval > 0); | |
| 4538 | − } | |
| 4539 | −#elif defined(Q_OS_LINUX) | |
| 4540 | − // TODO: write the poper code for linux | |
| 4541 | − /* | |
| 4542 | − if (glQueryExtension.... ("GLX_EXT_swap_control")) { | |
| 4543 | − int swapInterval = xglGetSwapIntervalEXT(); | |
| 4544 | − return (swapInterval > 0); | |
| 4545 | − } else { | |
| 4546 | − return true; | |
| 4547 | − } | |
| 4548 | − */ | |
| 4549 | −#endif | |
| 4550 | − return true; | |
| 4551 | −} | |
| 4552 | − | |
| 4553 | −bool Application::isVSyncEditable() const { | |
| 4554 | −#if defined(Q_OS_WIN) | |
| 4555 | − if (wglewGetExtension("WGL_EXT_swap_control")) { | |
| 4556 | − return true; | |
| 4557 | − } | |
| 4558 | −#elif defined(Q_OS_LINUX) | |
| 4559 | − // TODO: write the poper code for linux | |
| 4560 | − /* | |
| 4561 | − if (glQueryExtension.... ("GLX_EXT_swap_control")) { | |
| 4562 | − return true; | |
| 4563 | − } | |
| 4564 | − */ | |
| 4565 | −#endif | |
| 4566 | − return false; | |
| 4567 | −} | |
| 4568 | − | |
| 4569 | −unsigned int Application::getRenderTargetFramerate() const { | |
| 4570 | − if (Menu::getInstance()->isOptionChecked(MenuOption::RenderTargetFramerateUnlimited)) { | |
| 4571 | − return 0; | |
| 4572 | − } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderTargetFramerate60)) { | |
| 4573 | − return 60; | |
| 4574 | − } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderTargetFramerate50)) { | |
| 4575 | − return 50; | |
| 4576 | − } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderTargetFramerate40)) { | |
| 4577 | − return 40; | |
| 4578 | − } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderTargetFramerate30)) { | |
| 4579 | − return 30; | |
| 4580 | − } | |
| 4581 | − return 0; | |
| 4582 | −} | |
| 4583 | − | |
| 4584 | 4485 | float Application::getRenderResolutionScale() const { |
| 4585 | 4486 | if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionOne)) { |
| 4586 | 4487 | return 1.0f; |
| @@ -5162,3 +5063,9 @@ void Application::emulateMouse(Hand* hand, float click, float shift, int index) · 575 unmodified lines | ||
| 5162 | 5063 | _oldHandLeftClick[index] = false; |
| 5163 | 5064 | } |
| 5164 | 5065 | } |
| 5066 | + | |
| 5067 | +void Application::crashApplication() { | |
| 5068 | + QObject* object = nullptr; | |
| 5069 | + bool value = object->isWindowType(); | |
| 5070 | + qCDebug(interfaceapp) << "Intentionally crashed Interface"; | |
| 5071 | +} | |