// // OffscreenGlCanvas.cpp // interface/src/renderer // // Created by Bradley Austin Davis on 2014/04/09. // Copyright 2015 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "FboCache.h" #include #include #include "ThreadHelpers.h" #include "RenderUtilsLogging.h" FboCache::FboCache() { // Why do we even HAVE that lever? } void FboCache::lockTexture(int texture) { withLock(_lock, [&] { Q_ASSERT(_fboMap.count(texture)); if (!_fboLocks.count(texture)) { Q_ASSERT(_readyFboQueue.front()->texture() == (GLuint)texture); _readyFboQueue.pop_front(); _fboLocks[texture] = 1; } else { _fboLocks[texture]++; } }); } void FboCache::releaseTexture(int texture) { withLock(_lock, [&] { Q_ASSERT(_fboMap.count(texture)); Q_ASSERT(_fboLocks.count(texture)); int newLockCount = --_fboLocks[texture]; if (!newLockCount) { auto fbo = _fboMap[texture].data(); if (fbo->size() != _size) { // Move the old FBO to the destruction queue. // We can't destroy the FBO here because we might // not be on the right thread or have the context active _destroyFboQueue.push_back(_fboMap[texture]); _fboMap.remove(texture); } else { _readyFboQueue.push_back(fbo); } _fboLocks.remove(texture); } }); } QOpenGLFramebufferObject* FboCache::getReadyFbo() { QOpenGLFramebufferObject* result = nullptr; withLock(_lock, [&] { // Delete any FBOs queued for deletion _destroyFboQueue.clear(); if (_readyFboQueue.empty()) { qCDebug(renderutils) << "Building new offscreen FBO number " << _fboMap.size() + 1; result = new QOpenGLFramebufferObject(_size, QOpenGLFramebufferObject::CombinedDepthStencil); _fboMap[result->texture()] = QSharedPointer(result); _readyFboQueue.push_back(result); } else { result = _readyFboQueue.front(); } }); return result; } void FboCache::setSize(const QSize& newSize) { if (_size == newSize) { return; } _size = newSize; withLock(_lock, [&] { // Clear out any fbos with the old id _readyFboQueue.clear(); QSet outdatedFbos; // FBOs that are locked will be removed as they are unlocked foreach(int texture, _fboMap.keys()) { if (!_fboLocks.count(texture)) { outdatedFbos.insert(texture); } } // Implicitly deletes the FBO via the shared pointer destruction mechanism foreach(int texture, outdatedFbos) { _fboMap.remove(texture); } }); } const QSize& FboCache::getSize() { return _size; }