Merge pull request #9163 from jherico/gl_context_preservation

Preserve and restore the GL context when resizing QML surfaces
This commit is contained in:
Chris Collins 2016-12-07 09:08:36 -08:00 committed by GitHub
commit bc9f2b4007
3 changed files with 46 additions and 28 deletions

View file

@ -69,3 +69,15 @@ QThread* RENDER_THREAD = nullptr;
bool isRenderThread() { bool isRenderThread() {
return QThread::currentThread() == RENDER_THREAD; return QThread::currentThread() == RENDER_THREAD;
} }
namespace gl {
void withSavedContext(const std::function<void()>& f) {
// Save the original GL context, because creating a QML surface will create a new context
QOpenGLContext * savedContext = QOpenGLContext::currentContext();
QSurface * savedSurface = savedContext ? savedContext->surface() : nullptr;
f();
if (savedContext) {
savedContext->makeCurrent(savedSurface);
}
}
}

View file

@ -10,6 +10,7 @@
#ifndef hifi_GLHelpers_h #ifndef hifi_GLHelpers_h
#define hifi_GLHelpers_h #define hifi_GLHelpers_h
#include <functional>
#include <QJsonObject> #include <QJsonObject>
// 16 bits of depth precision // 16 bits of depth precision
@ -34,4 +35,8 @@ int glVersionToInteger(QString glVersion);
bool isRenderThread(); bool isRenderThread();
namespace gl {
void withSavedContext(const std::function<void()>& f);
}
#endif #endif

View file

@ -467,40 +467,41 @@ void OffscreenQmlSurface::resize(const QSize& newSize_, bool forceResize) {
} }
qCDebug(glLogging) << "Offscreen UI resizing to " << newSize.width() << "x" << newSize.height(); qCDebug(glLogging) << "Offscreen UI resizing to " << newSize.width() << "x" << newSize.height();
gl::withSavedContext([&] {
_canvas->makeCurrent();
_canvas->makeCurrent(); // Release hold on the textures of the old size
if (uvec2() != _size) {
// Release hold on the textures of the old size // If the most recent texture was unused, we can directly recycle it
if (uvec2() != _size) { if (_latestTextureAndFence.first) {
// If the most recent texture was unused, we can directly recycle it offscreenTextures.releaseTexture(_latestTextureAndFence);
if (_latestTextureAndFence.first) { _latestTextureAndFence = { 0, 0 };
offscreenTextures.releaseTexture(_latestTextureAndFence); }
_latestTextureAndFence = { 0, 0 }; offscreenTextures.releaseSize(_size);
} }
offscreenTextures.releaseSize(_size);
}
_size = newOffscreenSize; _size = newOffscreenSize;
// Acquire the new texture size // Acquire the new texture size
if (uvec2() != _size) { if (uvec2() != _size) {
offscreenTextures.acquireSize(_size); offscreenTextures.acquireSize(_size);
if (_depthStencil) { if (_depthStencil) {
glDeleteRenderbuffers(1, &_depthStencil); glDeleteRenderbuffers(1, &_depthStencil);
_depthStencil = 0; _depthStencil = 0;
}
glGenRenderbuffers(1, &_depthStencil);
glBindRenderbuffer(GL_RENDERBUFFER, _depthStencil);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, _size.x, _size.y);
if (!_fbo) {
glGenFramebuffers(1, &_fbo);
}
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthStencil);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
} }
glGenRenderbuffers(1, &_depthStencil);
glBindRenderbuffer(GL_RENDERBUFFER, _depthStencil);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, _size.x, _size.y);
if (!_fbo) {
glGenFramebuffers(1, &_fbo);
}
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthStencil);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
_canvas->doneCurrent(); _canvas->doneCurrent();
});
} }
QQuickItem* OffscreenQmlSurface::getRootItem() { QQuickItem* OffscreenQmlSurface::getRootItem() {