Merge pull request #7439 from jherico/deadlock_qml

Fix potential deadlock in QML
This commit is contained in:
Brad Hefta-Gaub 2016-03-23 14:16:37 -07:00
commit dbfea6ec82
2 changed files with 29 additions and 9 deletions

View file

@ -23,6 +23,7 @@
#include <PerfStat.h>
#include <DependencyManager.h>
#include <NumericalConstants.h>
#include <Finally.h>
#include "OffscreenGLCanvas.h"
#include "GLEscrow.h"
@ -84,6 +85,7 @@ protected:
Queue _queue;
QMutex _mutex;
QWaitCondition _waitCondition;
std::atomic<bool> _rendering { false };
private:
// Event-driven methods
@ -271,15 +273,25 @@ void OffscreenQmlRenderThread::resize() {
}
void OffscreenQmlRenderThread::render() {
if (_surface->_paused) {
// Ensure we always release the main thread
Finally releaseMainThread([this] {
_waitCondition.wakeOne();
});
if (_surface->_paused) {
return;
}
QMutexLocker locker(&_mutex);
_renderControl->sync();
_waitCondition.wakeOne();
locker.unlock();
_rendering = true;
Finally unmarkRenderingFlag([this] {
_rendering = false;
});
{
QMutexLocker locker(&_mutex);
_renderControl->sync();
releaseMainThread.trigger();
}
using namespace oglplus;
@ -292,6 +304,7 @@ void OffscreenQmlRenderThread::render() {
_fbo->AttachTexture(Framebuffer::Target::Draw, FramebufferAttachment::Color, *texture, 0);
_fbo->Complete(Framebuffer::Target::Draw);
{
PROFILE_RANGE("qml_render->rendercontrol")
_renderControl->render();
// FIXME The web browsers seem to be leaving GL in an error state.
// Need a debug context with sync logging to figure out why.
@ -380,8 +393,6 @@ void OffscreenQmlSurface::resize(const QSize& newSize_) {
std::max(static_cast<int>(scale * newSize.height()), 10));
}
QSize currentSize = _renderer->_quickWindow->geometry().size();
if (newSize == currentSize) {
return;
@ -492,7 +503,12 @@ QObject* OffscreenQmlSurface::finishQmlLoad(std::function<void(QQmlContext*, QOb
}
void OffscreenQmlSurface::updateQuick() {
if (!_renderer || !_renderer->allowNewFrame(_maxFps)) {
// If we're
// a) not set up
// b) already rendering a frame
// c) rendering too fast
// then skip this
if (!_renderer || _renderer->_rendering || !_renderer->allowNewFrame(_maxFps)) {
return;
}
@ -502,11 +518,11 @@ void OffscreenQmlSurface::updateQuick() {
}
if (_render) {
PROFILE_RANGE(__FUNCTION__);
// Lock the GUI size while syncing
QMutexLocker locker(&(_renderer->_mutex));
_renderer->_queue.add(RENDER);
_renderer->_waitCondition.wait(&(_renderer->_mutex));
_render = false;
}

View file

@ -20,6 +20,10 @@ public:
template <typename F>
Finally(F f) : _f(f) {}
~Finally() { _f(); }
void trigger() {
_f();
_f = [] {};
}
private:
std::function<void()> _f;
};