mirror of
https://github.com/overte-org/overte.git
synced 2025-04-08 03:33:25 +02:00
Address vsync weirdness
This commit is contained in:
parent
39b424645a
commit
82081d7d57
11 changed files with 75 additions and 92 deletions
|
@ -33,18 +33,6 @@ bool Basic2DWindowOpenGLDisplayPlugin::internalActivate() {
|
|||
return Parent::internalActivate();
|
||||
}
|
||||
|
||||
void Basic2DWindowOpenGLDisplayPlugin::submitFrame(const gpu::FramePointer& newFrame) {
|
||||
_wantVsync = true; // always
|
||||
Parent::submitFrame(newFrame);
|
||||
}
|
||||
|
||||
void Basic2DWindowOpenGLDisplayPlugin::internalPresent() {
|
||||
if (_wantVsync != isVsyncEnabled()) {
|
||||
enableVsync(_wantVsync);
|
||||
}
|
||||
Parent::internalPresent();
|
||||
}
|
||||
|
||||
static const uint32_t MIN_THROTTLE_CHECK_FRAMES = 60;
|
||||
|
||||
bool Basic2DWindowOpenGLDisplayPlugin::isThrottled() const {
|
||||
|
|
|
@ -24,10 +24,6 @@ public:
|
|||
|
||||
virtual bool internalActivate() override;
|
||||
|
||||
void submitFrame(const gpu::FramePointer& newFrame) override;
|
||||
|
||||
virtual void internalPresent() override;
|
||||
|
||||
virtual bool isThrottled() const override;
|
||||
|
||||
protected:
|
||||
|
@ -40,5 +36,4 @@ private:
|
|||
QAction* _vsyncAction { nullptr };
|
||||
uint32_t _framerateTarget { 0 };
|
||||
int _fullscreenTarget{ -1 };
|
||||
bool _wantVsync { true };
|
||||
};
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <QtGui/QImage>
|
||||
#include <ui-plugins/PluginContainer.h>
|
||||
#include <FramebufferCache.h>
|
||||
#include <gpu/Frame.h>
|
||||
|
||||
const QString NullDisplayPlugin::NAME("NullDisplayPlugin");
|
||||
|
||||
|
@ -24,6 +25,9 @@ bool NullDisplayPlugin::hasFocus() const {
|
|||
}
|
||||
|
||||
void NullDisplayPlugin::submitFrame(const gpu::FramePointer& resultFramebuffer) {
|
||||
if (resultFramebuffer) {
|
||||
resultFramebuffer->preRender();
|
||||
}
|
||||
}
|
||||
|
||||
QImage NullDisplayPlugin::getScreenshot() const {
|
||||
|
|
|
@ -133,8 +133,6 @@ public:
|
|||
// Main thread does it's thing while we wait on the lock to release
|
||||
Lock lock(_mutex);
|
||||
_condition.wait(lock, [&] { return _finishedMainThreadOperation; });
|
||||
_context->makeCurrent();
|
||||
Q_ASSERT(isCurrentContext(_context->contextHandle()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,13 +145,34 @@ public:
|
|||
if (newPlugin != currentPlugin) {
|
||||
// Deactivate the old plugin
|
||||
if (currentPlugin != nullptr) {
|
||||
_context->makeCurrent();
|
||||
currentPlugin->uncustomizeContext();
|
||||
CHECK_GL_ERROR();
|
||||
_context->doneCurrent();
|
||||
}
|
||||
|
||||
if (newPlugin) {
|
||||
bool hasVsync = true;
|
||||
bool wantVsync = newPlugin->wantVsync();
|
||||
_context->makeCurrent();
|
||||
#if defined(Q_OS_WIN)
|
||||
wglSwapIntervalEXT(wantVsync ? 1 : 0);
|
||||
hasVsync = wglGetSwapIntervalEXT() != 0;
|
||||
#elif defined(Q_OS_MAC)
|
||||
GLint interval = wantVsync ? 1 : 0;
|
||||
newPlugin->swapBuffers();
|
||||
CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &interval);
|
||||
newPlugin->swapBuffers();
|
||||
CGLGetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &interval);
|
||||
hasVsync = interval != 0;
|
||||
#else
|
||||
// TODO: Fill in for linux
|
||||
Q_UNUSED(wantVsync);
|
||||
#endif
|
||||
newPlugin->setVsyncEnabled(hasVsync);
|
||||
newPlugin->customizeContext();
|
||||
CHECK_GL_ERROR();
|
||||
_context->doneCurrent();
|
||||
}
|
||||
currentPlugin = newPlugin;
|
||||
_newPluginQueue.pop();
|
||||
|
@ -176,8 +195,8 @@ public:
|
|||
currentPlugin->present();
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
_context->doneCurrent();
|
||||
}
|
||||
_context->doneCurrent();
|
||||
|
||||
Lock lock(_mutex);
|
||||
_context->moveToThread(qApp->thread());
|
||||
|
@ -239,7 +258,6 @@ bool OpenGLDisplayPlugin::activate() {
|
|||
if (!_container) {
|
||||
return false;
|
||||
}
|
||||
_vsyncSupported = _container->getPrimaryWidget()->isVsyncSupported();
|
||||
|
||||
// Start the present thread if necessary
|
||||
QSharedPointer<PresentThread> presentThread;
|
||||
|
@ -309,7 +327,6 @@ void OpenGLDisplayPlugin::deactivate() {
|
|||
void OpenGLDisplayPlugin::customizeContext() {
|
||||
auto presentThread = DependencyManager::get<PresentThread>();
|
||||
Q_ASSERT(thread() == presentThread->thread());
|
||||
enableVsync();
|
||||
|
||||
getGLBackend()->setCameraCorrection(mat4());
|
||||
|
||||
|
@ -619,37 +636,6 @@ float OpenGLDisplayPlugin::presentRate() const {
|
|||
return _presentRate.rate();
|
||||
}
|
||||
|
||||
void OpenGLDisplayPlugin::enableVsync(bool enable) {
|
||||
if (!_vsyncSupported) {
|
||||
return;
|
||||
}
|
||||
#if defined(Q_OS_WIN)
|
||||
wglSwapIntervalEXT(enable ? 1 : 0);
|
||||
#elif defined(Q_OS_MAC)
|
||||
GLint interval = enable ? 1 : 0;
|
||||
CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &interval);
|
||||
#else
|
||||
// TODO: Fill in for linux
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool OpenGLDisplayPlugin::isVsyncEnabled() {
|
||||
if (!_vsyncSupported) {
|
||||
return true;
|
||||
}
|
||||
#if defined(Q_OS_WIN)
|
||||
return wglGetSwapIntervalEXT() != 0;
|
||||
#elif defined(Q_OS_MAC)
|
||||
GLint interval;
|
||||
CGLGetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &interval);
|
||||
return interval != 0;
|
||||
#else
|
||||
// TODO: Fill in for linux
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGLDisplayPlugin::swapBuffers() {
|
||||
static auto widget = _container->getPrimaryWidget();
|
||||
widget->swapBuffers();
|
||||
|
|
|
@ -63,6 +63,11 @@ public:
|
|||
float droppedFrameRate() const override;
|
||||
|
||||
bool beginFrameRender(uint32_t frameIndex) override;
|
||||
|
||||
virtual bool wantVsync() const { return true; }
|
||||
void setVsyncEnabled(bool vsyncEnabled) { _vsyncEnabled = vsyncEnabled; }
|
||||
bool isVsyncEnabled() const { return _vsyncEnabled; }
|
||||
|
||||
protected:
|
||||
friend class PresentThread;
|
||||
|
||||
|
@ -77,10 +82,6 @@ protected:
|
|||
|
||||
virtual bool hasFocus() const override;
|
||||
|
||||
// FIXME make thread safe?
|
||||
virtual bool isVsyncEnabled();
|
||||
virtual void enableVsync(bool enable = true);
|
||||
|
||||
// These functions must only be called on the presentation thread
|
||||
virtual void customizeContext();
|
||||
virtual void uncustomizeContext();
|
||||
|
@ -97,11 +98,12 @@ protected:
|
|||
void withMainThreadContext(std::function<void()> f) const;
|
||||
|
||||
void present();
|
||||
void swapBuffers();
|
||||
virtual void swapBuffers();
|
||||
ivec4 eyeViewport(Eye eye) const;
|
||||
|
||||
void render(std::function<void(gpu::Batch& batch)> f);
|
||||
|
||||
bool _vsyncEnabled { true };
|
||||
QThread* _presentThread{ nullptr };
|
||||
std::queue<gpu::FramePointer> _newFrameQueue;
|
||||
RateCounter<> _droppedFrameRate;
|
||||
|
@ -116,9 +118,6 @@ protected:
|
|||
gpu::PipelinePointer _cursorPipeline;
|
||||
float _compositeOverlayAlpha { 1.0f };
|
||||
|
||||
|
||||
bool _vsyncSupported { false };
|
||||
|
||||
struct CursorData {
|
||||
QImage image;
|
||||
vec2 hotSpot;
|
||||
|
|
|
@ -63,7 +63,24 @@ QRect HmdDisplayPlugin::getRecommendedOverlayRect() const {
|
|||
return CompositorHelper::VIRTUAL_SCREEN_RECOMMENDED_OVERLAY_RECT;
|
||||
}
|
||||
|
||||
bool HmdDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||
if (!_vsyncEnabled && !_disablePreviewItemAdded) {
|
||||
_container->addMenuItem(PluginType::DISPLAY_PLUGIN, MENU_PATH(), DISABLE_PREVIEW,
|
||||
[this](bool clicked) {
|
||||
_disablePreview = clicked;
|
||||
_container->setBoolSetting("disableHmdPreview", _disablePreview);
|
||||
if (_disablePreview) {
|
||||
_clearPreviewFlag = true;
|
||||
}
|
||||
}, true, _disablePreview);
|
||||
_disablePreviewItemAdded = true;
|
||||
}
|
||||
return Parent::beginFrameRender(frameIndex);
|
||||
}
|
||||
|
||||
|
||||
bool HmdDisplayPlugin::internalActivate() {
|
||||
_disablePreviewItemAdded = false;
|
||||
_monoPreview = _container->getBoolSetting("monoPreview", DEFAULT_MONO_VIEW);
|
||||
_clearPreviewFlag = true;
|
||||
_container->addMenuItem(PluginType::DISPLAY_PLUGIN, MENU_PATH(), MONO_PREVIEW,
|
||||
|
@ -74,17 +91,7 @@ bool HmdDisplayPlugin::internalActivate() {
|
|||
#if defined(Q_OS_MAC)
|
||||
_disablePreview = true;
|
||||
#else
|
||||
_disablePreview = _container->getBoolSetting("disableHmdPreview", DEFAULT_DISABLE_PREVIEW || !_vsyncSupported);
|
||||
if (_vsyncSupported) {
|
||||
_container->addMenuItem(PluginType::DISPLAY_PLUGIN, MENU_PATH(), DISABLE_PREVIEW,
|
||||
[this](bool clicked) {
|
||||
_disablePreview = clicked;
|
||||
_container->setBoolSetting("disableHmdPreview", _disablePreview);
|
||||
if (_disablePreview) {
|
||||
_clearPreviewFlag = true;
|
||||
}
|
||||
}, true, _disablePreview);
|
||||
}
|
||||
_disablePreview = _container->getBoolSetting("disableHmdPreview", DEFAULT_DISABLE_PREVIEW || _vsyncEnabled);
|
||||
#endif
|
||||
|
||||
_container->removeMenu(FRAMERATE);
|
||||
|
@ -103,15 +110,20 @@ void HmdDisplayPlugin::internalDeactivate() {
|
|||
|
||||
void HmdDisplayPlugin::customizeContext() {
|
||||
Parent::customizeContext();
|
||||
// Only enable mirroring if we know vsync is disabled
|
||||
// On Mac, this won't work due to how the contexts are handled, so don't try
|
||||
#if !defined(Q_OS_MAC)
|
||||
enableVsync(false);
|
||||
#endif
|
||||
_overlayRenderer.build();
|
||||
}
|
||||
|
||||
void HmdDisplayPlugin::uncustomizeContext() {
|
||||
// This stops the weirdness where if the preview was disabled, on switching back to 2D,
|
||||
// the vsync was stuck in the disabled state. No idea why that happens though.
|
||||
_disablePreview = false;
|
||||
render([&](gpu::Batch& batch) {
|
||||
batch.enableStereo(false);
|
||||
batch.clearViewTransform();
|
||||
batch.setFramebuffer(_compositeFramebuffer);
|
||||
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, vec4(0));
|
||||
});
|
||||
internalPresent();
|
||||
_overlayRenderer = OverlayRenderer();
|
||||
Parent::uncustomizeContext();
|
||||
}
|
||||
|
|
|
@ -38,12 +38,17 @@ public:
|
|||
|
||||
bool setHandLaser(uint32_t hands, HandLaserMode mode, const vec4& color, const vec3& direction) override;
|
||||
|
||||
bool wantVsync() const override {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void hmdPresent() = 0;
|
||||
virtual bool isHmdMounted() const = 0;
|
||||
virtual void postPreview() {};
|
||||
virtual void updatePresentPose();
|
||||
|
||||
bool beginFrameRender(uint32_t frameIndex) override;
|
||||
bool internalActivate() override;
|
||||
void internalDeactivate() override;
|
||||
void compositeOverlay() override;
|
||||
|
@ -94,10 +99,11 @@ protected:
|
|||
FrameInfo _currentPresentFrameInfo;
|
||||
FrameInfo _currentRenderFrameInfo;
|
||||
|
||||
bool _disablePreview{ true };
|
||||
private:
|
||||
ivec4 getViewportForSourceSize(const uvec2& size) const;
|
||||
|
||||
bool _disablePreview{ true };
|
||||
bool _disablePreviewItemAdded { false };
|
||||
bool _monoPreview { true };
|
||||
bool _clearPreviewFlag { false };
|
||||
gpu::TexturePointer _previewTexture;
|
||||
|
|
|
@ -118,7 +118,6 @@ Buffer::Update::Update(const Buffer& parent) : buffer(parent) {
|
|||
void Buffer::Update::apply() const {
|
||||
// Make sure we're loaded in order
|
||||
++buffer._applyUpdateCount;
|
||||
assert(isRenderThread());
|
||||
assert(buffer._applyUpdateCount.load() == updateNumber);
|
||||
const auto pageSize = buffer._pages._pageSize;
|
||||
buffer._renderSysmem.resize(size);
|
||||
|
|
|
@ -83,11 +83,6 @@ void OculusDisplayPlugin::customizeContext() {
|
|||
_sceneLayer.ColorTexture[0] = _textureSwapChain;
|
||||
// not needed since the structure was zeroed on init, but explicit
|
||||
_sceneLayer.ColorTexture[1] = nullptr;
|
||||
|
||||
enableVsync(false);
|
||||
// Only enable mirroring if we know vsync is disabled
|
||||
_enablePreview = !isVsyncEnabled();
|
||||
|
||||
}
|
||||
|
||||
void OculusDisplayPlugin::uncustomizeContext() {
|
||||
|
|
|
@ -29,8 +29,6 @@ protected:
|
|||
|
||||
private:
|
||||
static const QString NAME;
|
||||
bool _enablePreview { false };
|
||||
bool _monoPreview { true };
|
||||
ovrTextureSwapChain _textureSwapChain;
|
||||
gpu::FramebufferPointer _outputFramebuffer;
|
||||
};
|
||||
|
|
|
@ -297,7 +297,6 @@ bool OpenVrDisplayPlugin::internalActivate() {
|
|||
_submitThread = std::make_shared<OpenVrSubmitThread>(*this);
|
||||
});
|
||||
_submitThread->setObjectName("OpenVR Submit Thread");
|
||||
_submitThread->start(QThread::TimeCriticalPriority);
|
||||
#endif
|
||||
|
||||
return Parent::internalActivate();
|
||||
|
@ -306,11 +305,6 @@ bool OpenVrDisplayPlugin::internalActivate() {
|
|||
void OpenVrDisplayPlugin::internalDeactivate() {
|
||||
Parent::internalDeactivate();
|
||||
|
||||
#if OPENVR_THREADED_SUBMIT
|
||||
_submitThread->_quit = true;
|
||||
_submitThread->wait();
|
||||
#endif
|
||||
|
||||
_openVrDisplayActive = false;
|
||||
_container->setIsOptionChecked(StandingHMDSensorMode, false);
|
||||
if (_system) {
|
||||
|
@ -339,10 +333,17 @@ void OpenVrDisplayPlugin::customizeContext() {
|
|||
}
|
||||
_compositeInfos[i].textureID = getGLBackend()->getTextureID(_compositeInfos[i].texture, false);
|
||||
}
|
||||
|
||||
_submitThread->start(QThread::HighPriority);
|
||||
}
|
||||
|
||||
void OpenVrDisplayPlugin::uncustomizeContext() {
|
||||
Parent::uncustomizeContext();
|
||||
|
||||
#if OPENVR_THREADED_SUBMIT
|
||||
_submitThread->_quit = true;
|
||||
_submitThread->wait();
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenVrDisplayPlugin::resetSensors() {
|
||||
|
|
Loading…
Reference in a new issue