History

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

samcake committed 10 years ago

Commit 545f2762 parents 21c9b74 376c23f65 files · +732 −274Browse files

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

Unified · Split

interface/src/Application.cpp+71−26
@@ -210,6 +210,10 @@ static const QString INFO_EDIT_ENTITIES_PATH = "html/edit-commands.html"; · 209 unmodified lines
210210
211211 static const unsigned int THROTTLED_SIM_FRAMERATE = 15;
212212 static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SIM_FRAMERATE;
213+static const unsigned int CAPPED_SIM_FRAMERATE = 60;
214+static const int CAPPED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / CAPPED_SIM_FRAMERATE;
215+
216+static const uint32_t INVALID_FRAME = UINT32_MAX;
213217
214218 static const float PHYSICS_READY_RANGE = 3.0f; // how far from avatar to check for entities that aren't ready for simulation
215219
@@ -273,7 +277,8 @@ public: · 57 unmodified lines
273277 #endif
274278
275279 enum CustomEventTypes {
276− Lambda = QEvent::User + 1
280+ Lambda = QEvent::User + 1,
281+ Paint = Lambda + 1,
277282 };
278283
279284 class LambdaEvent : public QEvent {
@@ -984,6 +989,17 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : · 704 unmodified lines
984989
985990 connect(this, &Application::applicationStateChanged, this, &Application::activeChanged);
986991 qCDebug(interfaceapp, "Startup time: %4.2f seconds.", (double)startupTimer.elapsed() / 1000.0);
992+ _idleTimer = new QTimer(this);
993+ connect(_idleTimer, &QTimer::timeout, [=] {
994+ idle(usecTimestampNow());
995+ });
996+ connect(this, &Application::beforeAboutToQuit, [=] {
997+ disconnect(_idleTimer);
998+ });
999+ // Setting the interval to zero forces this to get called whenever there are no messages
1000+ // in the queue, which can be pretty damn frequent. Hence the idle function has a bunch
1001+ // of logic to abort early if it's being called too often.
1002+ _idleTimer->start(0);
9871003 }
9881004
9891005 void Application::aboutToQuit() {
@@ -1297,9 +1313,6 @@ void Application::initializeUi() { · 307 unmodified lines
12971313 }
12981314
12991315 void Application::paintGL() {
1300−
1301−
1302−
13031316 // paintGL uses a queued connection, so we can get messages from the queue even after we've quit
13041317 // and the plugins have shutdown
13051318 if (_aboutToQuit) {
@@ -1629,6 +1642,7 @@ void Application::paintGL() { · 323 unmodified lines
16291642 // Store both values now for use by next cycle.
16301643 _lastInstantaneousFps = instantaneousFps;
16311644 _lastUnsynchronizedFps = 1.0f / (((usecTimestampNow() - now) / (float)USECS_PER_SECOND) + paintWaitAndQTTimerAllowance);
1645+ _pendingPaint = false;
16321646 }
16331647
16341648 void Application::runTests() {
@@ -1717,6 +1731,10 @@ bool Application::event(QEvent* event) { · 82 unmodified lines
17171731 return true;
17181732 }
17191733
1734+ if ((int)event->type() == (int)Paint) {
1735+ paintGL();
1736+ }
1737+
17201738 if (!_keyboardFocusedItem.isInvalidID()) {
17211739 switch (event->type()) {
17221740 case QEvent::KeyPress:
@@ -2401,26 +2419,62 @@ bool Application::acceptSnapshot(const QString& urlString) { · 678 unmodified lines
24012419 return true;
24022420 }
24032421
2422+static uint32_t _renderedFrameIndex { INVALID_FRAME };
2423+
24042424 void Application::idle(uint64_t now) {
24052425 if (_aboutToQuit) {
24062426 return; // bail early, nothing to do here.
24072427 }
2408−
2428+
2429+ auto displayPlugin = getActiveDisplayPlugin();
24092430 // depending on whether we're throttling or not.
24102431 // Once rendering is off on another thread we should be able to have Application::idle run at start(0) in
24112432 // perpetuity and not expect events to get backed up.
2412− bool isThrottled = getActiveDisplayPlugin()->isThrottled();
2433+ bool isThrottled = displayPlugin->isThrottled();
24132434 // Only run simulation code if more than the targetFramePeriod have passed since last time we ran
24142435 // This attempts to lock the simulation at 60 updates per second, regardless of framerate
24152436 float timeSinceLastUpdateUs = (float)_lastTimeUpdated.nsecsElapsed() / NSECS_PER_USEC;
24162437 float secondsSinceLastUpdate = timeSinceLastUpdateUs / USECS_PER_SECOND;
24172438
24182439 if (isThrottled && (timeSinceLastUpdateUs / USECS_PER_MSEC) < THROTTLED_SIM_FRAME_PERIOD_MS) {
2440+ // Throttling both rendering and idle
24192441 return; // bail early, we're throttled and not enough time has elapsed
24202442 }
24212443
2422− _lastTimeUpdated.start();
2444+ auto presentCount = displayPlugin->presentCount();
2445+ if (presentCount < _renderedFrameIndex) {
2446+ _renderedFrameIndex = INVALID_FRAME;
2447+ }
2448+
2449+ // Nested ifs are for clarity in the logic. Don't collapse them into a giant single if.
2450+ // Don't saturate the main thread with rendering, no paint calls until the last one is complete
2451+ if (!_pendingPaint) {
2452+ // Also no paint calls until the display plugin has increased by at least one frame
2453+ // (don't render at 90fps if the display plugin only goes at 60)
2454+ if (_renderedFrameIndex == INVALID_FRAME || presentCount > _renderedFrameIndex) {
2455+ // Record what present frame we're on
2456+ _renderedFrameIndex = presentCount;
2457+ // Don't allow paint requests to stack up in the event queue
2458+ _pendingPaint = true;
2459+ // But when we DO request a paint, get to it as soon as possible: high priority
2460+ postEvent(this, new QEvent(static_cast<QEvent::Type>(Paint)), Qt::HighEventPriority);
2461+ }
2462+ }
2463+
2464+ // For the rest of idle, we want to cap at the max sim rate, so we might not call
2465+ // the remaining idle work every paint frame, or vice versa
2466+ // In theory this means we could call idle processing more often than painting,
2467+ // but in practice, when the paintGL calls aren't keeping up, there's no room left
2468+ // in the main thread to call idle more often than paint.
2469+ // This check is mostly to keep idle from burning up CPU cycles by running at
2470+ // hundreds of idles per second when the rendering is that fast
2471+ if ((timeSinceLastUpdateUs / USECS_PER_MSEC) < CAPPED_SIM_FRAME_PERIOD_MS) {
2472+ // No paint this round, but might be time for a new idle, otherwise return
2473+ return;
2474+ }
24232475
2476+ // We're going to execute idle processing, so restart the last idle timer
2477+ _lastTimeUpdated.start();
24242478
24252479 {
24262480 PROFILE_RANGE(__FUNCTION__);
@@ -3071,13 +3125,18 @@ void Application::update(float deltaTime) { · 644 unmodified lines
30713125
30723126 auto myAvatar = getMyAvatar();
30733127 auto userInputMapper = DependencyManager::get<UserInputMapper>();
3074− userInputMapper->setSensorToWorldMat(myAvatar->getSensorToWorldMatrix());
30753128 userInputMapper->update(deltaTime);
30763129
3130+ controller::InputCalibrationData calibrationData = {
3131+ myAvatar->getSensorToWorldMatrix(),
3132+ createMatFromQuatAndPos(myAvatar->getOrientation(), myAvatar->getPosition()),
3133+ myAvatar->getHMDSensorMatrix()
3134+ };
3135+
30773136 bool jointsCaptured = false;
30783137 for (auto inputPlugin : PluginManager::getInstance()->getInputPlugins()) {
30793138 if (inputPlugin->isActive()) {
3080− inputPlugin->pluginUpdate(deltaTime, jointsCaptured);
3139+ inputPlugin->pluginUpdate(deltaTime, calibrationData, jointsCaptured);
30813140 if (inputPlugin->isJointController()) {
30823141 jointsCaptured = true;
30833142 }
@@ -4777,17 +4836,9 @@ void Application::updateDisplayMode() { · 1693 unmodified lines
47774836
47784837 foreach(auto displayPlugin, standard) {
47794838 addDisplayPluginToMenu(displayPlugin, first);
4780− // This must be a queued connection to avoid a deadlock
4781− QObject::connect(displayPlugin.get(), &DisplayPlugin::requestRender, [=] {
4782− postEvent(this, new LambdaEvent([=] {
4783− paintGL();
4784− }), Qt::HighEventPriority);
4785− });
4786−
47874839 QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged, [this](const QSize & size) {
47884840 resizeGL();
47894841 });
4790−
47914842 first = false;
47924843 }
47934844
@@ -4979,17 +5030,11 @@ void Application::setPalmData(Hand* hand, const controller::Pose& pose, float de · 185 unmodified lines
49795030 // of this palm manipulation in the Hand class itself. But unfortunately the Hand and Palm don't knbow about
49805031 // controller::Pose. More work is needed to clean this up.
49815032 hand->modifyPalm(whichHand, [&](PalmData& palm) {
4982− auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
49835033 palm.setActive(pose.isValid());
49845034
4985− // transform from sensor space, to world space, to avatar model space.
4986− glm::mat4 poseMat = createMatFromQuatAndPos(pose.getRotation(), pose.getTranslation() * myAvatar->getScale());
4987− glm::mat4 sensorToWorldMat = myAvatar->getSensorToWorldMatrix();
4988− glm::mat4 modelMat = createMatFromQuatAndPos(myAvatar->getOrientation(), myAvatar->getPosition());
4989− glm::mat4 objectPose = glm::inverse(modelMat) * sensorToWorldMat * poseMat;
4990−
4991− glm::vec3 position = extractTranslation(objectPose);
4992− glm::quat rotation = glm::quat_cast(objectPose);
5035+ // controller pose is in Avatar frame.
5036+ glm::vec3 position = pose.getTranslation();
5037+ glm::quat rotation = pose.getRotation();
49935038
49945039 // Compute current velocity from position change
49955040 glm::vec3 rawVelocity;