diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e5d5e696a1..f9ad6ec7ff 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -207,6 +207,17 @@ #if defined(Q_OS_WIN) #include +#ifdef DEBUG_EVENT_QUEUE +// This is a HACK that uses private headers included with the qt source distrubution. +// To use this feature you need to add these directores to your include path: +// E:/Qt/5.9.1/Src/qtbase/include/QtCore/5.9.1/QtCore +// E:/Qt/5.9.1/Src/qtbase/include/QtCore/5.9.1 +#define QT_BOOTSTRAPPED +#include +#include +#undef QT_BOOTSTRAPPED +#endif + extern "C" { _declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; } @@ -264,9 +275,7 @@ private: switch ((int)event->type()) { case ApplicationEvent::Render: render(); - // Ensure we never back up the render events. Each render should be triggered only in response - // to the NEXT render event after the last render occured - QCoreApplication::removePostedEvents(this, ApplicationEvent::Render); + qApp->_pendingRenderEvent.store(false); return true; default: @@ -2712,9 +2721,14 @@ bool Application::importFromZIP(const QString& filePath) { return true; } +// thread-safe void Application::onPresent(quint32 frameCount) { - postEvent(this, new QEvent((QEvent::Type)ApplicationEvent::Idle), Qt::HighEventPriority); - if (_renderEventHandler && !isAboutToQuit()) { + bool expected = false; + if (_pendingIdleEvent.compare_exchange_strong(expected, true)) { + postEvent(this, new QEvent((QEvent::Type)ApplicationEvent::Idle), Qt::HighEventPriority); + } + expected = false; + if (_renderEventHandler && !isAboutToQuit() && _pendingRenderEvent.compare_exchange_strong(expected, true)) { postEvent(_renderEventHandler, new QEvent((QEvent::Type)ApplicationEvent::Render)); } } @@ -2781,7 +2795,26 @@ bool Application::handleFileOpenEvent(QFileOpenEvent* fileEvent) { return false; } +#ifdef DEBUG_EVENT_QUEUE +static int getEventQueueSize(QThread* thread) { + auto threadData = QThreadData::get2(thread); + QMutexLocker locker(&threadData->postEventList.mutex); + return threadData->postEventList.size(); +} + +static void dumpEventQueue(QThread* thread) { + auto threadData = QThreadData::get2(thread); + QMutexLocker locker(&threadData->postEventList.mutex); + qDebug() << "AJT: event list, size =" << threadData->postEventList.size(); + for (auto& postEvent : threadData->postEventList) { + QEvent::Type type = (postEvent.event ? postEvent.event->type() : QEvent::None); + qDebug() << "AJT: " << type; + } +} +#endif // DEBUG_EVENT_QUEUE + bool Application::event(QEvent* event) { + if (!Menu::getInstance()) { return false; } @@ -2801,8 +2834,18 @@ bool Application::event(QEvent* event) { // see (windowMinimizedChanged) case ApplicationEvent::Idle: idle(); - // Don't process extra idle events that arrived in the event queue while we were doing this idle - QCoreApplication::removePostedEvents(this, ApplicationEvent::Idle); + +#ifdef DEBUG_EVENT_QUEUE + { + int count = getEventQueueSize(QThread::currentThread()); + if (count > 400) { + dumpEventQueue(QThread::currentThread()); + } + } +#endif // DEBUG_EVENT_QUEUE + + _pendingIdleEvent.store(false); + return true; case QEvent::MouseMove: @@ -7203,7 +7246,7 @@ void Application::updateDisplayMode() { _offscreenContext->makeCurrent(); getApplicationCompositor().setDisplayPlugin(newDisplayPlugin); _displayPlugin = newDisplayPlugin; - connect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent); + connect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent, Qt::DirectConnection); auto desktop = offscreenUi->getDesktop(); if (desktop) { desktop->setProperty("repositionLocked", wasRepositionLocked); diff --git a/interface/src/Application.h b/interface/src/Application.h index 772646f379..b6c09bbd87 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -717,5 +717,8 @@ private: LaserPointerManager _laserPointerManager; friend class RenderEventHandler; + + std::atomic _pendingIdleEvent { false }; + std::atomic _pendingRenderEvent { false }; }; #endif // hifi_Application_h diff --git a/interface/src/Application_render.cpp b/interface/src/Application_render.cpp index 541197a660..44d9dfee03 100644 --- a/interface/src/Application_render.cpp +++ b/interface/src/Application_render.cpp @@ -72,6 +72,12 @@ void Application::paintGL() { { QMutexLocker viewLocker(&_renderArgsMutex); renderArgs = _appRenderArgs._renderArgs; + + // don't render if there is no context. + if (!_appRenderArgs._renderArgs._context) { + return; + } + HMDSensorPose = _appRenderArgs._headPose; eyeToWorld = _appRenderArgs._eyeToWorld; sensorToWorld = _appRenderArgs._sensorToWorld;