mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 15:49:24 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into lemon
This commit is contained in:
commit
c96d5b093c
12 changed files with 215 additions and 26 deletions
|
@ -240,25 +240,26 @@ class DeadlockWatchdogThread : public QThread {
|
||||||
public:
|
public:
|
||||||
static const unsigned long HEARTBEAT_CHECK_INTERVAL_SECS = 1;
|
static const unsigned long HEARTBEAT_CHECK_INTERVAL_SECS = 1;
|
||||||
static const unsigned long HEARTBEAT_UPDATE_INTERVAL_SECS = 1;
|
static const unsigned long HEARTBEAT_UPDATE_INTERVAL_SECS = 1;
|
||||||
static const unsigned long MAX_HEARTBEAT_AGE_USECS = 15 * USECS_PER_SECOND;
|
static const unsigned long HEARTBEAT_REPORT_INTERVAL_USECS = 5 * USECS_PER_SECOND;
|
||||||
|
static const unsigned long MAX_HEARTBEAT_AGE_USECS = 30 * USECS_PER_SECOND;
|
||||||
|
static const int WARNING_ELAPSED_HEARTBEAT = 500 * USECS_PER_MSEC; // warn if elapsed heartbeat average is large
|
||||||
|
static const int HEARTBEAT_SAMPLES = 100000; // ~5 seconds worth of samples
|
||||||
|
|
||||||
// Set the heartbeat on launch
|
// Set the heartbeat on launch
|
||||||
DeadlockWatchdogThread() {
|
DeadlockWatchdogThread() {
|
||||||
setObjectName("Deadlock Watchdog");
|
setObjectName("Deadlock Watchdog");
|
||||||
QTimer* heartbeatTimer = new QTimer();
|
|
||||||
// Give the heartbeat an initial value
|
// Give the heartbeat an initial value
|
||||||
updateHeartbeat();
|
_heartbeat = usecTimestampNow();
|
||||||
connect(heartbeatTimer, &QTimer::timeout, [this] {
|
|
||||||
updateHeartbeat();
|
|
||||||
});
|
|
||||||
heartbeatTimer->start(HEARTBEAT_UPDATE_INTERVAL_SECS * MSECS_PER_SECOND);
|
|
||||||
connect(qApp, &QCoreApplication::aboutToQuit, [this] {
|
connect(qApp, &QCoreApplication::aboutToQuit, [this] {
|
||||||
_quit = true;
|
_quit = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateHeartbeat() {
|
void updateHeartbeat() {
|
||||||
_heartbeat = usecTimestampNow();
|
auto now = usecTimestampNow();
|
||||||
|
auto elapsed = now - _heartbeat;
|
||||||
|
_movingAverage.addSample(elapsed);
|
||||||
|
_heartbeat = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
void deadlockDetectionCrash() {
|
void deadlockDetectionCrash() {
|
||||||
|
@ -269,10 +270,52 @@ public:
|
||||||
void run() override {
|
void run() override {
|
||||||
while (!_quit) {
|
while (!_quit) {
|
||||||
QThread::sleep(HEARTBEAT_UPDATE_INTERVAL_SECS);
|
QThread::sleep(HEARTBEAT_UPDATE_INTERVAL_SECS);
|
||||||
#ifdef NDEBUG
|
|
||||||
auto now = usecTimestampNow();
|
auto now = usecTimestampNow();
|
||||||
auto lastHeartbeatAge = now - _heartbeat;
|
|
||||||
|
// in the unlikely event that now is less than _heartbeat, don't rollover and confuse ourselves
|
||||||
|
auto lastHeartbeatAge = (now > _heartbeat) ? now - _heartbeat : 0;
|
||||||
|
auto sinceLastReport = (now > _lastReport) ? now - _lastReport : 0;
|
||||||
|
auto elapsedMovingAverage = _movingAverage.getAverage();
|
||||||
|
|
||||||
|
if (elapsedMovingAverage > _maxElapsedAverage) {
|
||||||
|
qDebug() << "DEADLOCK WATCHDOG NEW maxElapsedAverage:"
|
||||||
|
<< "lastHeartbeatAge:" << lastHeartbeatAge
|
||||||
|
<< "elapsedMovingAverage:" << elapsedMovingAverage
|
||||||
|
<< "maxElapsed:" << _maxElapsed
|
||||||
|
<< "PREVIOUS maxElapsedAverage:" << _maxElapsedAverage
|
||||||
|
<< "NEW maxElapsedAverage:" << elapsedMovingAverage
|
||||||
|
<< "samples:" << _movingAverage.getSamples();
|
||||||
|
_maxElapsedAverage = elapsedMovingAverage;
|
||||||
|
}
|
||||||
|
if (lastHeartbeatAge > _maxElapsed) {
|
||||||
|
qDebug() << "DEADLOCK WATCHDOG NEW maxElapsed:"
|
||||||
|
<< "lastHeartbeatAge:" << lastHeartbeatAge
|
||||||
|
<< "elapsedMovingAverage:" << elapsedMovingAverage
|
||||||
|
<< "PREVIOUS maxElapsed:" << _maxElapsed
|
||||||
|
<< "NEW maxElapsed:" << lastHeartbeatAge
|
||||||
|
<< "maxElapsedAverage:" << _maxElapsedAverage
|
||||||
|
<< "samples:" << _movingAverage.getSamples();
|
||||||
|
_maxElapsed = lastHeartbeatAge;
|
||||||
|
}
|
||||||
|
if ((sinceLastReport > HEARTBEAT_REPORT_INTERVAL_USECS) || (elapsedMovingAverage > WARNING_ELAPSED_HEARTBEAT)) {
|
||||||
|
qDebug() << "DEADLOCK WATCHDOG STATUS -- lastHeartbeatAge:" << lastHeartbeatAge
|
||||||
|
<< "elapsedMovingAverage:" << elapsedMovingAverage
|
||||||
|
<< "maxElapsed:" << _maxElapsed
|
||||||
|
<< "maxElapsedAverage:" << _maxElapsedAverage
|
||||||
|
<< "samples:" << _movingAverage.getSamples();
|
||||||
|
_lastReport = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef NDEBUG
|
||||||
if (lastHeartbeatAge > MAX_HEARTBEAT_AGE_USECS) {
|
if (lastHeartbeatAge > MAX_HEARTBEAT_AGE_USECS) {
|
||||||
|
qDebug() << "DEADLOCK DETECTED -- "
|
||||||
|
<< "lastHeartbeatAge:" << lastHeartbeatAge
|
||||||
|
<< "[ _heartbeat:" << _heartbeat
|
||||||
|
<< "now:" << now << " ]"
|
||||||
|
<< "elapsedMovingAverage:" << elapsedMovingAverage
|
||||||
|
<< "maxElapsed:" << _maxElapsed
|
||||||
|
<< "maxElapsedAverage:" << _maxElapsedAverage
|
||||||
|
<< "samples:" << _movingAverage.getSamples();
|
||||||
deadlockDetectionCrash();
|
deadlockDetectionCrash();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -280,10 +323,19 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::atomic<uint64_t> _heartbeat;
|
static std::atomic<uint64_t> _heartbeat;
|
||||||
|
static std::atomic<uint64_t> _lastReport;
|
||||||
|
static std::atomic<uint64_t> _maxElapsed;
|
||||||
|
static std::atomic<int> _maxElapsedAverage;
|
||||||
|
static ThreadSafeMovingAverage<int, HEARTBEAT_SAMPLES> _movingAverage;
|
||||||
|
|
||||||
bool _quit { false };
|
bool _quit { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
std::atomic<uint64_t> DeadlockWatchdogThread::_heartbeat;
|
std::atomic<uint64_t> DeadlockWatchdogThread::_heartbeat;
|
||||||
|
std::atomic<uint64_t> DeadlockWatchdogThread::_lastReport;
|
||||||
|
std::atomic<uint64_t> DeadlockWatchdogThread::_maxElapsed;
|
||||||
|
std::atomic<int> DeadlockWatchdogThread::_maxElapsedAverage;
|
||||||
|
ThreadSafeMovingAverage<int, DeadlockWatchdogThread::HEARTBEAT_SAMPLES> DeadlockWatchdogThread::_movingAverage;
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
class MyNativeEventFilter : public QAbstractNativeEventFilter {
|
class MyNativeEventFilter : public QAbstractNativeEventFilter {
|
||||||
|
@ -1381,6 +1433,8 @@ void Application::initializeUi() {
|
||||||
|
|
||||||
void Application::paintGL() {
|
void Application::paintGL() {
|
||||||
|
|
||||||
|
updateHeartbeat();
|
||||||
|
|
||||||
// Some plugins process message events, potentially leading to
|
// Some plugins process message events, potentially leading to
|
||||||
// re-entering a paint event. don't allow further processing if this
|
// re-entering a paint event. don't allow further processing if this
|
||||||
// happens
|
// happens
|
||||||
|
@ -2502,6 +2556,8 @@ static uint32_t _renderedFrameIndex { INVALID_FRAME };
|
||||||
|
|
||||||
void Application::idle(uint64_t now) {
|
void Application::idle(uint64_t now) {
|
||||||
|
|
||||||
|
updateHeartbeat();
|
||||||
|
|
||||||
if (_aboutToQuit || _inPaint) {
|
if (_aboutToQuit || _inPaint) {
|
||||||
return; // bail early, nothing to do here.
|
return; // bail early, nothing to do here.
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "AddressManager.h"
|
#include "AddressManager.h"
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "InterfaceLogging.h"
|
#include "InterfaceLogging.h"
|
||||||
|
#include "UserActivityLogger.h"
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
|
|
||||||
#ifdef HAS_BUGSPLAT
|
#ifdef HAS_BUGSPLAT
|
||||||
|
@ -102,13 +103,21 @@ int main(int argc, const char* argv[]) {
|
||||||
// Check OpenGL version.
|
// Check OpenGL version.
|
||||||
// This is done separately from the main Application so that start-up and shut-down logic within the main Application is
|
// This is done separately from the main Application so that start-up and shut-down logic within the main Application is
|
||||||
// not made more complicated than it already is.
|
// not made more complicated than it already is.
|
||||||
|
bool override = false;
|
||||||
|
QString glVersion;
|
||||||
{
|
{
|
||||||
OpenGLVersionChecker openGLVersionChecker(argc, const_cast<char**>(argv));
|
OpenGLVersionChecker openGLVersionChecker(argc, const_cast<char**>(argv));
|
||||||
if (!openGLVersionChecker.isValidVersion()) {
|
bool valid = true;
|
||||||
|
glVersion = openGLVersionChecker.checkVersion(valid, override);
|
||||||
|
if (!valid) {
|
||||||
|
if (override) {
|
||||||
|
qCDebug(interfaceapp, "Running on insufficient OpenGL version: %s.", glVersion.toStdString().c_str());
|
||||||
|
} else {
|
||||||
qCDebug(interfaceapp, "Early exit due to OpenGL version.");
|
qCDebug(interfaceapp, "Early exit due to OpenGL version.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QElapsedTimer startupTime;
|
QElapsedTimer startupTime;
|
||||||
startupTime.start();
|
startupTime.start();
|
||||||
|
@ -134,6 +143,22 @@ int main(int argc, const char* argv[]) {
|
||||||
QSettings::setDefaultFormat(QSettings::IniFormat);
|
QSettings::setDefaultFormat(QSettings::IniFormat);
|
||||||
Application app(argc, const_cast<char**>(argv), startupTime);
|
Application app(argc, const_cast<char**>(argv), startupTime);
|
||||||
|
|
||||||
|
// If we failed the OpenGLVersion check, log it.
|
||||||
|
if (override) {
|
||||||
|
auto& accountManager = AccountManager::getInstance();
|
||||||
|
if (accountManager.isLoggedIn()) {
|
||||||
|
UserActivityLogger::getInstance().insufficientGLVersion(glVersion);
|
||||||
|
} else {
|
||||||
|
QObject::connect(&AccountManager::getInstance(), &AccountManager::loginComplete, [glVersion](){
|
||||||
|
static bool loggedInsufficientGL = false;
|
||||||
|
if (!loggedInsufficientGL) {
|
||||||
|
UserActivityLogger::getInstance().insufficientGLVersion(glVersion);
|
||||||
|
loggedInsufficientGL = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Setup local server
|
// Setup local server
|
||||||
QLocalServer server { &app };
|
QLocalServer server { &app };
|
||||||
|
|
||||||
|
|
|
@ -354,7 +354,9 @@ void RenderableModelEntityItem::updateModelBounds() {
|
||||||
bool movingOrAnimating = isMovingRelativeToParent() || isAnimatingSomething();
|
bool movingOrAnimating = isMovingRelativeToParent() || isAnimatingSomething();
|
||||||
if ((movingOrAnimating ||
|
if ((movingOrAnimating ||
|
||||||
_needsInitialSimulation ||
|
_needsInitialSimulation ||
|
||||||
|
_needsJointSimulation ||
|
||||||
_model->getTranslation() != getPosition() ||
|
_model->getTranslation() != getPosition() ||
|
||||||
|
_model->getScaleToFitDimensions() != getDimensions() ||
|
||||||
_model->getRotation() != getRotation() ||
|
_model->getRotation() != getRotation() ||
|
||||||
_model->getRegistrationPoint() != getRegistrationPoint())
|
_model->getRegistrationPoint() != getRegistrationPoint())
|
||||||
&& _model->isActive() && _dimensionsInitialized) {
|
&& _model->isActive() && _dimensionsInitialized) {
|
||||||
|
@ -370,6 +372,7 @@ void RenderableModelEntityItem::updateModelBounds() {
|
||||||
}
|
}
|
||||||
|
|
||||||
_needsInitialSimulation = false;
|
_needsInitialSimulation = false;
|
||||||
|
_needsJointSimulation = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -770,6 +773,7 @@ bool RenderableModelEntityItem::setAbsoluteJointRotationInObjectFrame(int index,
|
||||||
_absoluteJointRotationsInObjectFrameSet[index] = true;
|
_absoluteJointRotationsInObjectFrameSet[index] = true;
|
||||||
_absoluteJointRotationsInObjectFrameDirty[index] = true;
|
_absoluteJointRotationsInObjectFrameDirty[index] = true;
|
||||||
result = true;
|
result = true;
|
||||||
|
_needsJointSimulation = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
|
@ -785,11 +789,33 @@ bool RenderableModelEntityItem::setAbsoluteJointTranslationInObjectFrame(int ind
|
||||||
_absoluteJointTranslationsInObjectFrameSet[index] = true;
|
_absoluteJointTranslationsInObjectFrameSet[index] = true;
|
||||||
_absoluteJointTranslationsInObjectFrameDirty[index] = true;
|
_absoluteJointTranslationsInObjectFrameDirty[index] = true;
|
||||||
result = true;
|
result = true;
|
||||||
|
_needsJointSimulation = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderableModelEntityItem::setJointRotations(const QVector<glm::quat>& rotations) {
|
||||||
|
ModelEntityItem::setJointRotations(rotations);
|
||||||
|
_needsJointSimulation = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderableModelEntityItem::setJointRotationsSet(const QVector<bool>& rotationsSet) {
|
||||||
|
ModelEntityItem::setJointRotationsSet(rotationsSet);
|
||||||
|
_needsJointSimulation = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderableModelEntityItem::setJointTranslations(const QVector<glm::vec3>& translations) {
|
||||||
|
ModelEntityItem::setJointTranslations(translations);
|
||||||
|
_needsJointSimulation = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderableModelEntityItem::setJointTranslationsSet(const QVector<bool>& translationsSet) {
|
||||||
|
ModelEntityItem::setJointTranslationsSet(translationsSet);
|
||||||
|
_needsJointSimulation = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void RenderableModelEntityItem::locationChanged() {
|
void RenderableModelEntityItem::locationChanged() {
|
||||||
EntityItem::locationChanged();
|
EntityItem::locationChanged();
|
||||||
if (_model && _model->isActive()) {
|
if (_model && _model->isActive()) {
|
||||||
|
|
|
@ -69,6 +69,11 @@ public:
|
||||||
virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) override;
|
virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) override;
|
||||||
virtual bool setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) override;
|
virtual bool setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) override;
|
||||||
|
|
||||||
|
virtual void setJointRotations(const QVector<glm::quat>& rotations) override;
|
||||||
|
virtual void setJointRotationsSet(const QVector<bool>& rotationsSet) override;
|
||||||
|
virtual void setJointTranslations(const QVector<glm::vec3>& translations) override;
|
||||||
|
virtual void setJointTranslationsSet(const QVector<bool>& translationsSet) override;
|
||||||
|
|
||||||
virtual void loader() override;
|
virtual void loader() override;
|
||||||
virtual void locationChanged() override;
|
virtual void locationChanged() override;
|
||||||
|
|
||||||
|
@ -97,6 +102,8 @@ private:
|
||||||
bool _showCollisionHull = false;
|
bool _showCollisionHull = false;
|
||||||
|
|
||||||
bool getAnimationFrame();
|
bool getAnimationFrame();
|
||||||
|
|
||||||
|
bool _needsJointSimulation { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_RenderableModelEntityItem_h
|
#endif // hifi_RenderableModelEntityItem_h
|
||||||
|
|
|
@ -120,10 +120,10 @@ public:
|
||||||
virtual glm::vec3 getJointPosition(int jointIndex) const { return glm::vec3(); }
|
virtual glm::vec3 getJointPosition(int jointIndex) const { return glm::vec3(); }
|
||||||
virtual glm::quat getJointRotation(int jointIndex) const { return glm::quat(); }
|
virtual glm::quat getJointRotation(int jointIndex) const { return glm::quat(); }
|
||||||
|
|
||||||
void setJointRotations(const QVector<glm::quat>& rotations);
|
virtual void setJointRotations(const QVector<glm::quat>& rotations);
|
||||||
void setJointRotationsSet(const QVector<bool>& rotationsSet);
|
virtual void setJointRotationsSet(const QVector<bool>& rotationsSet);
|
||||||
void setJointTranslations(const QVector<glm::vec3>& translations);
|
virtual void setJointTranslations(const QVector<glm::vec3>& translations);
|
||||||
void setJointTranslationsSet(const QVector<bool>& translationsSet);
|
virtual void setJointTranslationsSet(const QVector<bool>& translationsSet);
|
||||||
QVector<glm::quat> getJointRotations() const;
|
QVector<glm::quat> getJointRotations() const;
|
||||||
QVector<bool> getJointRotationsSet() const;
|
QVector<bool> getJointRotationsSet() const;
|
||||||
QVector<glm::vec3> getJointTranslations() const;
|
QVector<glm::vec3> getJointTranslations() const;
|
||||||
|
|
|
@ -50,7 +50,9 @@ void GLWidget::initializeGL() {
|
||||||
// TODO: write the proper code for linux
|
// TODO: write the proper code for linux
|
||||||
makeCurrent();
|
makeCurrent();
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
|
if (isValid() && context() && context()->contextHandle()) {
|
||||||
_vsyncSupported = context()->contextHandle()->hasExtension("WGL_EXT_swap_control");;
|
_vsyncSupported = context()->contextHandle()->hasExtension("WGL_EXT_swap_control");;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,11 +22,26 @@ OpenGLVersionChecker::OpenGLVersionChecker(int& argc, char** argv) :
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenGLVersionChecker::isValidVersion() {
|
QString OpenGLVersionChecker::checkVersion(bool& valid, bool& override) {
|
||||||
bool valid = true;
|
valid = true;
|
||||||
|
override = false;
|
||||||
|
|
||||||
|
GLWidget* glWidget = new GLWidget();
|
||||||
|
valid = glWidget->isValid();
|
||||||
|
// Inform user if no OpenGL support
|
||||||
|
if (!valid) {
|
||||||
|
QMessageBox messageBox;
|
||||||
|
messageBox.setWindowTitle("Missing OpenGL Support");
|
||||||
|
messageBox.setIcon(QMessageBox::Warning);
|
||||||
|
messageBox.setText(QString().sprintf("Your system does not support OpenGL, Interface cannot run."));
|
||||||
|
messageBox.setInformativeText("Press OK to exit.");
|
||||||
|
messageBox.setStandardButtons(QMessageBox::Ok);
|
||||||
|
messageBox.setDefaultButton(QMessageBox::Ok);
|
||||||
|
messageBox.exec();
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
// Retrieve OpenGL version
|
// Retrieve OpenGL version
|
||||||
GLWidget* glWidget = new GLWidget();
|
|
||||||
glWidget->initializeGL();
|
glWidget->initializeGL();
|
||||||
QString glVersion = QString((const char*)glGetString(GL_VERSION));
|
QString glVersion = QString((const char*)glGetString(GL_VERSION));
|
||||||
delete glWidget;
|
delete glWidget;
|
||||||
|
@ -54,8 +69,8 @@ bool OpenGLVersionChecker::isValidVersion() {
|
||||||
messageBox.setInformativeText("Press OK to exit; Ignore to continue.");
|
messageBox.setInformativeText("Press OK to exit; Ignore to continue.");
|
||||||
messageBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Ignore);
|
messageBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Ignore);
|
||||||
messageBox.setDefaultButton(QMessageBox::Ok);
|
messageBox.setDefaultButton(QMessageBox::Ok);
|
||||||
valid = messageBox.exec() == QMessageBox::Ignore;
|
override = messageBox.exec() == QMessageBox::Ignore;
|
||||||
}
|
}
|
||||||
|
|
||||||
return valid;
|
return glVersion;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ class OpenGLVersionChecker : public QApplication {
|
||||||
public:
|
public:
|
||||||
OpenGLVersionChecker(int& argc, char** argv);
|
OpenGLVersionChecker(int& argc, char** argv);
|
||||||
|
|
||||||
static bool isValidVersion();
|
static QString checkVersion(bool& valid, bool& override);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_OpenGLVersionChecker_h
|
#endif // hifi_OpenGLVersionChecker_h
|
||||||
|
|
|
@ -85,6 +85,15 @@ void UserActivityLogger::launch(QString applicationVersion, bool previousSession
|
||||||
logAction(ACTION_NAME, actionDetails);
|
logAction(ACTION_NAME, actionDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UserActivityLogger::insufficientGLVersion(QString glVersion) {
|
||||||
|
const QString ACTION_NAME = "insufficient_gl";
|
||||||
|
QJsonObject actionDetails;
|
||||||
|
QString GL_VERSION = "glVersion";
|
||||||
|
actionDetails.insert(GL_VERSION, glVersion);
|
||||||
|
|
||||||
|
logAction(ACTION_NAME, actionDetails);
|
||||||
|
}
|
||||||
|
|
||||||
void UserActivityLogger::changedDisplayName(QString displayName) {
|
void UserActivityLogger::changedDisplayName(QString displayName) {
|
||||||
const QString ACTION_NAME = "changed_display_name";
|
const QString ACTION_NAME = "changed_display_name";
|
||||||
QJsonObject actionDetails;
|
QJsonObject actionDetails;
|
||||||
|
|
|
@ -31,6 +31,8 @@ public slots:
|
||||||
|
|
||||||
void launch(QString applicationVersion, bool previousSessionCrashed, int previousSessionRuntime);
|
void launch(QString applicationVersion, bool previousSessionCrashed, int previousSessionRuntime);
|
||||||
|
|
||||||
|
void insufficientGLVersion(QString glVersion);
|
||||||
|
|
||||||
void changedDisplayName(QString displayName);
|
void changedDisplayName(QString displayName);
|
||||||
void changedModel(QString typeOfModel, QString modelURL);
|
void changedModel(QString typeOfModel, QString modelURL);
|
||||||
void changedDomain(QString domainURL);
|
void changedDomain(QString domainURL);
|
||||||
|
|
|
@ -45,18 +45,23 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool process() {
|
virtual bool process() {
|
||||||
|
lock();
|
||||||
if (!_items.size()) {
|
if (!_items.size()) {
|
||||||
|
unlock();
|
||||||
_hasItemsMutex.lock();
|
_hasItemsMutex.lock();
|
||||||
_hasItems.wait(&_hasItemsMutex, getMaxWait());
|
_hasItems.wait(&_hasItemsMutex, getMaxWait());
|
||||||
_hasItemsMutex.unlock();
|
_hasItemsMutex.unlock();
|
||||||
|
} else {
|
||||||
|
unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lock();
|
||||||
if (!_items.size()) {
|
if (!_items.size()) {
|
||||||
|
unlock();
|
||||||
return isStillRunning();
|
return isStillRunning();
|
||||||
}
|
}
|
||||||
|
|
||||||
Queue processItems;
|
Queue processItems;
|
||||||
lock();
|
|
||||||
processItems.swap(_items);
|
processItems.swap(_items);
|
||||||
unlock();
|
unlock();
|
||||||
return processQueueItems(processItems);
|
return processQueueItems(processItems);
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#ifndef hifi_SimpleMovingAverage_h
|
#ifndef hifi_SimpleMovingAverage_h
|
||||||
#define hifi_SimpleMovingAverage_h
|
#define hifi_SimpleMovingAverage_h
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
class SimpleMovingAverage {
|
class SimpleMovingAverage {
|
||||||
|
@ -64,4 +65,45 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class T, int MAX_NUM_SAMPLES> class ThreadSafeMovingAverage {
|
||||||
|
public:
|
||||||
|
void clear() {
|
||||||
|
std::unique_lock<std::mutex> lock(_lock);
|
||||||
|
_samples = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isAverageValid() const {
|
||||||
|
std::unique_lock<std::mutex> lock(_lock);
|
||||||
|
return (_samples > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addSample(T sample) {
|
||||||
|
std::unique_lock<std::mutex> lock(_lock);
|
||||||
|
if (_samples > 0) {
|
||||||
|
_average = (sample * WEIGHTING) + (_average * ONE_MINUS_WEIGHTING);
|
||||||
|
} else {
|
||||||
|
_average = sample;
|
||||||
|
}
|
||||||
|
_samples++;
|
||||||
|
}
|
||||||
|
|
||||||
|
T getAverage() const {
|
||||||
|
std::unique_lock<std::mutex> lock(_lock);
|
||||||
|
return _average;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSamples() const {
|
||||||
|
std::unique_lock<std::mutex> lock(_lock);
|
||||||
|
return _samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const float WEIGHTING = 1.0f / (float)MAX_NUM_SAMPLES;
|
||||||
|
const float ONE_MINUS_WEIGHTING = 1.0f - WEIGHTING;
|
||||||
|
size_t _samples { 0 };
|
||||||
|
T _average;
|
||||||
|
mutable std::mutex _lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // hifi_SimpleMovingAverage_h
|
#endif // hifi_SimpleMovingAverage_h
|
||||||
|
|
Loading…
Reference in a new issue