fix throttled rendering for the 2D display plugin

This commit is contained in:
ZappoMan 2015-08-19 21:11:48 -07:00
parent 5a442bdb30
commit 6a7f367e5f
9 changed files with 64 additions and 69 deletions

View file

@ -175,8 +175,6 @@ public:
using namespace std;
// Starfield information
static uint8_t THROTTLED_IDLE_TIMER_DELAY = 10;
const qint64 MAXIMUM_CACHE_SIZE = 10 * BYTES_PER_GIGABYTES; // 10GB
static QTimer* locationUpdateTimer = NULL;
@ -737,6 +735,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
_keyboardFocusHighlight->setVisible(false);
}
});
connect(this, &Application::applicationStateChanged, this, &Application::activeChanged);
}
void Application::aboutToQuit() {
@ -2108,8 +2108,11 @@ void Application::idle() {
// Once rendering is off on another thread we should be able to have Application::idle run at start(0) in
// perpetuity and not expect events to get backed up.
bool isThrottled = getActiveDisplayPlugin()->isThrottled();
static const int THROTTLED_IDLE_TIMER_DELAY = MSECS_PER_SECOND / 15;
static const int IDLE_TIMER_DELAY_MS = 2;
int desiredInterval = getActiveDisplayPlugin()->isThrottled() ? THROTTLED_IDLE_TIMER_DELAY : IDLE_TIMER_DELAY_MS;
int desiredInterval = isThrottled ? THROTTLED_IDLE_TIMER_DELAY : IDLE_TIMER_DELAY_MS;
//qDebug() << "isThrottled:" << isThrottled << "desiredInterval:" << desiredInterval;
if (idleTimer->interval() != desiredInterval) {
idleTimer->start(desiredInterval);
@ -4612,6 +4615,24 @@ void Application::checkSkeleton() {
}
}
bool Application::isForeground() {
return _isForeground && !getWindow()->isMinimized();
}
void Application::activeChanged(Qt::ApplicationState state) {
switch (state) {
case Qt::ApplicationActive:
_isForeground = true;
break;
case Qt::ApplicationSuspended:
case Qt::ApplicationHidden:
case Qt::ApplicationInactive:
default:
_isForeground = false;
break;
}
}
void Application::showFriendsWindow() {
const QString FRIENDS_WINDOW_TITLE = "Add/Remove Friends";
const QString FRIENDS_WINDOW_URL = "https://metaverse.highfidelity.com/user/friends";

View file

@ -291,6 +291,7 @@ public:
virtual void unsetFullscreen(const QScreen* avoid) override;
virtual void showDisplayPluginsTools() override;
virtual QGLWidget* getPrimarySurface() override;
virtual bool isForeground() override;
void setActiveDisplayPlugin(const QString& pluginName);
@ -476,6 +477,7 @@ private slots:
void faceTrackerMuteToggled();
void setCursorVisible(bool visible);
void activeChanged(Qt::ApplicationState state);
private:
void resetCameras(Camera& camera, const glm::uvec2& size);
@ -688,6 +690,7 @@ private:
SimpleMovingAverage _simsPerSecond{10};
int _simsPerSecondReport = 0;
quint64 _lastSimsPerSecondUpdate = 0;
bool _isForeground = true; // starts out assumed to be in foreground
};
#endif // hifi_Application_h

View file

@ -18,8 +18,6 @@
#include "MainWindow.h"
const int MSECS_PER_FRAME_WHEN_THROTTLED = 66;
static QGLFormat& getDesiredGLFormat() {
// Specify an OpenGL 3.3 format using the Core profile.
// That is, no old-school fixed pipeline functionality
@ -35,10 +33,7 @@ static QGLFormat& getDesiredGLFormat() {
return glFormat;
}
GLCanvas::GLCanvas() : QGLWidget(getDesiredGLFormat()),
_throttleRendering(false),
_idleRenderInterval(MSECS_PER_FRAME_WHEN_THROTTLED)
{
GLCanvas::GLCanvas() : QGLWidget(getDesiredGLFormat()) {
#ifdef Q_OS_LINUX
// Cause GLCanvas::eventFilter to be called.
// It wouldn't hurt to do this on Mac and PC too; but apparently it's only needed on linux.
@ -46,15 +41,6 @@ GLCanvas::GLCanvas() : QGLWidget(getDesiredGLFormat()),
#endif
}
void GLCanvas::stopFrameTimer() {
_frameTimer.stop();
}
bool GLCanvas::isThrottleRendering() const {
return (_throttleRendering
|| (Application::getInstance()->getWindow()->isMinimized() && Application::getInstance()->isThrottleFPSEnabled()));
}
int GLCanvas::getDeviceWidth() const {
return width() * (windowHandle() ? (float)windowHandle()->devicePixelRatio() : 1.0f);
}
@ -66,17 +52,17 @@ int GLCanvas::getDeviceHeight() const {
void GLCanvas::initializeGL() {
setAttribute(Qt::WA_AcceptTouchEvents);
setAcceptDrops(true);
connect(Application::getInstance(), SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(activeChanged(Qt::ApplicationState)));
connect(&_frameTimer, SIGNAL(timeout()), this, SLOT(throttleRender()));
// Note, we *DO NOT* want Qt to automatically swap buffers for us. This results in the "ringing" bug mentioned in WL#19514 when we're throttling the framerate.
setAutoBufferSwap(false);
}
void GLCanvas::paintGL() {
PROFILE_RANGE(__FUNCTION__);
if (!_throttleRendering &&
(!Application::getInstance()->getWindow()->isMinimized() || !Application::getInstance()->isThrottleFPSEnabled())) {
// FIXME - I'm not sure why this still remains, it appears as if this GLCanvas gets a single paintGL call near
// the beginning of the application starting up. I'm not sure if we really need to call Application::paintGL()
// in this case, since the display plugins eventually handle all the painting
if ((!Application::getInstance()->getWindow()->isMinimized() || !Application::getInstance()->isThrottleFPSEnabled())) {
Application::getInstance()->paintGL();
}
}
@ -85,39 +71,6 @@ void GLCanvas::resizeGL(int width, int height) {
Application::getInstance()->resizeGL();
}
void GLCanvas::activeChanged(Qt::ApplicationState state) {
switch (state) {
case Qt::ApplicationActive:
// If we're active, stop the frame timer and the throttle.
_frameTimer.stop();
_throttleRendering = false;
break;
case Qt::ApplicationSuspended:
case Qt::ApplicationHidden:
// If we're hidden or are about to suspend, don't render anything.
_throttleRendering = false;
_frameTimer.stop();
break;
default:
// Otherwise, throttle.
if (!_throttleRendering && !Application::getInstance()->isAboutToQuit()
&& Application::getInstance()->isThrottleFPSEnabled()) {
_frameTimer.start(_idleRenderInterval);
_throttleRendering = true;
}
break;
}
}
void GLCanvas::throttleRender() {
_frameTimer.start(_idleRenderInterval);
if (!Application::getInstance()->getWindow()->isMinimized()) {
Application::getInstance()->paintGL();
}
}
int updateTime = 0;
bool GLCanvas::event(QEvent* event) {
switch (event->type()) {

View file

@ -23,28 +23,18 @@ class GLCanvas : public QGLWidget {
public:
GLCanvas();
void stopFrameTimer();
bool isThrottleRendering() const;
int getDeviceWidth() const;
int getDeviceHeight() const;
QSize getDeviceSize() const { return QSize(getDeviceWidth(), getDeviceHeight()); }
protected:
QTimer _frameTimer;
bool _throttleRendering;
int _idleRenderInterval;
virtual void initializeGL();
virtual void paintGL();
virtual void resizeGL(int width, int height);
virtual bool event(QEvent* event);
private slots:
void activeChanged(Qt::ApplicationState state);
void throttleRender();
bool eventFilter(QObject*, QEvent* event);
};

View file

@ -283,7 +283,7 @@ namespace MenuOption {
const QString TestPing = "Test Ping";
const QString ThirdPerson = "Third Person";
const QString ThreePointCalibration = "3 Point Calibration";
const QString ThrottleFPSIfNotFocus = "Throttle FPS If Not Focus";
const QString ThrottleFPSIfNotFocus = "Throttle FPS If Not Focus"; // FIXME - this value duplicated in Basic2DWindowOpenGLDisplayPlugin.cpp
const QString ToolWindow = "Tool Window";
const QString TransmitterDrive = "Transmitter Drive";
const QString TurnWithHead = "Turn using Head";

View file

@ -34,3 +34,24 @@ void Basic2DWindowOpenGLDisplayPlugin::deactivate() {
// container->removeMenu(MENU_PATH);
MainWindowOpenGLDisplayPlugin::deactivate();
}
int Basic2DWindowOpenGLDisplayPlugin::getDesiredInterval(bool isThrottled) const {
static const int THROTTLED_PAINT_TIMER_DELAY = MSECS_PER_SECOND / 15;
static const int PAINT_TIMER_DELAY_MS = 1;
return isThrottled ? THROTTLED_PAINT_TIMER_DELAY : PAINT_TIMER_DELAY_MS;
}
bool Basic2DWindowOpenGLDisplayPlugin::isThrottled() const {
static const QString ThrottleFPSIfNotFocus = "Throttle FPS If Not Focus"; // FIXME - this value duplicated in Menu.h
bool shouldThrottle = (!CONTAINER->isForeground() && CONTAINER->isOptionChecked(ThrottleFPSIfNotFocus));
if (_isThrottled != shouldThrottle) {
int desiredInterval = getDesiredInterval(shouldThrottle);
_timer.start(desiredInterval);
_isThrottled = shouldThrottle;
}
return shouldThrottle;
}

View file

@ -18,6 +18,12 @@ public:
virtual const QString & getName() const override;
virtual bool isThrottled() const override;
protected:
int getDesiredInterval(bool isThrottled) const;
mutable bool _isThrottled = false;
private:
static const QString NAME;
};

View file

@ -37,8 +37,8 @@ protected:
virtual void doneCurrent() = 0;
virtual void swapBuffers() = 0;
QTimer _timer;
ProgramPtr _program;
mutable QTimer _timer;
ProgramPtr _program;
ShapeWrapperPtr _plane;
};

View file

@ -26,4 +26,5 @@ public:
virtual void unsetFullscreen(const QScreen* avoidScreen = nullptr) = 0;
virtual void showDisplayPluginsTools() = 0;
virtual QGLWidget* getPrimarySurface() = 0;
virtual bool isForeground() = 0;
};