mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Merge branch 'master' into tony/vive-rendering-work
This commit is contained in:
commit
0d37515784
16 changed files with 173 additions and 79 deletions
2
cmake/externals/oglplus/CMakeLists.txt
vendored
2
cmake/externals/oglplus/CMakeLists.txt
vendored
|
@ -4,7 +4,7 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
|||
include(ExternalProject)
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL http://iweb.dl.sourceforge.net/project/oglplus/oglplus-0.63.x/oglplus-0.63.0.zip
|
||||
URL http://hifi-public.s3.amazonaws.com/dependencies/oglplus-0.63.0.zip
|
||||
URL_MD5 de984ab245b185b45c87415c0e052135
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
|
|
|
@ -17,7 +17,6 @@ Windows.Window {
|
|||
visible: false
|
||||
width: 384; height: 640;
|
||||
title: "Tools"
|
||||
property string newTabSource
|
||||
property alias tabView: tabView
|
||||
onParentChanged: {
|
||||
if (parent) {
|
||||
|
@ -32,26 +31,21 @@ Windows.Window {
|
|||
property alias y: toolWindow.y
|
||||
}
|
||||
|
||||
property var webTabCreator: Component {
|
||||
Controls.WebView {
|
||||
id: webView
|
||||
property string originalUrl;
|
||||
|
||||
// Both toolWindow.newTabSource and url can change, so we need
|
||||
// to store the original url here, without creating any bindings
|
||||
Component.onCompleted: {
|
||||
originalUrl = toolWindow.newTabSource;
|
||||
url = originalUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TabView {
|
||||
anchors.fill: parent
|
||||
id: tabView;
|
||||
onCountChanged: {
|
||||
if (0 == count) {
|
||||
toolWindow.visible = false
|
||||
Repeater {
|
||||
model: 4
|
||||
Tab {
|
||||
active: true
|
||||
enabled: false;
|
||||
// we need to store the original url here for future identification
|
||||
property string originalUrl: "";
|
||||
onEnabledChanged: toolWindow.updateVisiblity();
|
||||
Controls.WebView {
|
||||
id: webView;
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,8 +62,7 @@ Windows.Window {
|
|||
function findIndexForUrl(source) {
|
||||
for (var i = 0; i < tabView.count; ++i) {
|
||||
var tab = tabView.getTab(i);
|
||||
if (tab && tab.item && tab.item.originalUrl &&
|
||||
tab.item.originalUrl === source) {
|
||||
if (tab.originalUrl === source) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
@ -101,21 +94,32 @@ Windows.Window {
|
|||
}
|
||||
}
|
||||
|
||||
function findFreeTab() {
|
||||
for (var i = 0; i < tabView.count; ++i) {
|
||||
var tab = tabView.getTab(i);
|
||||
if (tab && (!tab.originalUrl || tab.originalUrl === "")) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
console.warn("Could not find free tab");
|
||||
return -1;
|
||||
}
|
||||
|
||||
function removeTabForUrl(source) {
|
||||
var index = findIndexForUrl(source);
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var tab = tabView.getTab(index);
|
||||
tab.enabledChanged.disconnect(updateVisiblity);
|
||||
tabView.removeTab(index);
|
||||
console.log("Updating visibility based on child tab removed");
|
||||
updateVisiblity();
|
||||
tab.title = "";
|
||||
tab.originalUrl = "";
|
||||
tab.enabled = false;
|
||||
}
|
||||
|
||||
function addWebTab(properties) {
|
||||
if (!properties.source) {
|
||||
console.warn("Attempted to open Web Tool Pane without URl")
|
||||
console.warn("Attempted to open Web Tool Pane without URL")
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -125,11 +129,17 @@ Windows.Window {
|
|||
return tabView.getTab(existingTabIndex);
|
||||
}
|
||||
|
||||
var title = properties.title || "Unknown";
|
||||
newTabSource = properties.source;
|
||||
var newTab = tabView.addTab(title, webTabCreator);
|
||||
var freeTabIndex = findFreeTab();
|
||||
if (freeTabIndex === -1) {
|
||||
console.warn("Unable to add new tab");
|
||||
return;
|
||||
}
|
||||
|
||||
var newTab = tabView.getTab(freeTabIndex);
|
||||
newTab.title = properties.title || "Unknown";
|
||||
newTab.originalUrl = properties.source;
|
||||
newTab.item.url = properties.source;
|
||||
newTab.active = true;
|
||||
newTab.enabled = false;
|
||||
|
||||
if (properties.width) {
|
||||
tabView.width = Math.min(Math.max(tabView.width, properties.width),
|
||||
|
|
|
@ -239,11 +239,7 @@ class DeadlockWatchdogThread : public QThread {
|
|||
public:
|
||||
static const unsigned long HEARTBEAT_CHECK_INTERVAL_SECS = 1;
|
||||
static const unsigned long HEARTBEAT_UPDATE_INTERVAL_SECS = 1;
|
||||
#ifdef DEBUG
|
||||
static const unsigned long MAX_HEARTBEAT_AGE_USECS = 600 * USECS_PER_SECOND;
|
||||
#else
|
||||
static const unsigned long MAX_HEARTBEAT_AGE_USECS = 10 * USECS_PER_SECOND;
|
||||
#endif
|
||||
|
||||
// Set the heartbeat on launch
|
||||
DeadlockWatchdogThread() {
|
||||
|
@ -511,8 +507,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
|
||||
// Set up a watchdog thread to intentionally crash the application on deadlocks
|
||||
auto deadlockWatchdog = new DeadlockWatchdogThread();
|
||||
deadlockWatchdog->start();
|
||||
_deadlockWatchdogThread = new DeadlockWatchdogThread();
|
||||
_deadlockWatchdogThread->start();
|
||||
|
||||
qCDebug(interfaceapp) << "[VERSION] Build sequence:" << qPrintable(applicationVersion());
|
||||
|
||||
|
@ -586,7 +582,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
|
||||
ResourceManager::init();
|
||||
// Make sure we don't time out during slow operations at startup
|
||||
deadlockWatchdog->updateHeartbeat();
|
||||
updateHeartbeat();
|
||||
|
||||
// Setup MessagesClient
|
||||
auto messagesClient = DependencyManager::get<MessagesClient>();
|
||||
|
@ -734,7 +730,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
initializeGL();
|
||||
_offscreenContext->makeCurrent();
|
||||
// Make sure we don't time out during slow operations at startup
|
||||
deadlockWatchdog->updateHeartbeat();
|
||||
updateHeartbeat();
|
||||
|
||||
// Tell our entity edit sender about our known jurisdictions
|
||||
_entityEditSender.setServerJurisdictions(&_entityServerJurisdictions);
|
||||
|
@ -746,7 +742,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
|
||||
_overlays.init(); // do this before scripts load
|
||||
// Make sure we don't time out during slow operations at startup
|
||||
deadlockWatchdog->updateHeartbeat();
|
||||
updateHeartbeat();
|
||||
|
||||
connect(this, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit()));
|
||||
|
||||
|
@ -900,11 +896,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
// do this as late as possible so that all required subsystems are initialized
|
||||
scriptEngines->loadScripts();
|
||||
// Make sure we don't time out during slow operations at startup
|
||||
deadlockWatchdog->updateHeartbeat();
|
||||
updateHeartbeat();
|
||||
|
||||
loadSettings();
|
||||
// Make sure we don't time out during slow operations at startup
|
||||
deadlockWatchdog->updateHeartbeat();
|
||||
updateHeartbeat();
|
||||
|
||||
int SAVE_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND; // Let's save every seconds for now
|
||||
connect(&_settingsTimer, &QTimer::timeout, this, &Application::saveSettings);
|
||||
|
@ -1019,7 +1015,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
});
|
||||
|
||||
// Make sure we don't time out during slow operations at startup
|
||||
deadlockWatchdog->updateHeartbeat();
|
||||
updateHeartbeat();
|
||||
|
||||
connect(this, &Application::applicationStateChanged, this, &Application::activeChanged);
|
||||
qCDebug(interfaceapp, "Startup time: %4.2f seconds.", (double)startupTimer.elapsed() / 1000.0);
|
||||
|
@ -1060,6 +1056,10 @@ void Application::showCursor(const QCursor& cursor) {
|
|||
_cursorNeedsChanging = true;
|
||||
}
|
||||
|
||||
void Application::updateHeartbeat() {
|
||||
static_cast<DeadlockWatchdogThread*>(_deadlockWatchdogThread)->updateHeartbeat();
|
||||
}
|
||||
|
||||
void Application::aboutToQuit() {
|
||||
emit beforeAboutToQuit();
|
||||
|
||||
|
|
|
@ -271,6 +271,8 @@ public slots:
|
|||
|
||||
void reloadResourceCaches();
|
||||
|
||||
void updateHeartbeat();
|
||||
|
||||
void crashApplication();
|
||||
void deadlockApplication();
|
||||
|
||||
|
@ -505,6 +507,8 @@ private:
|
|||
mutable QMutex _changeCursorLock { QMutex::Recursive };
|
||||
QCursor _desiredCursor{ Qt::BlankCursor };
|
||||
bool _cursorNeedsChanging { false };
|
||||
|
||||
QThread* _deadlockWatchdogThread;
|
||||
};
|
||||
|
||||
#endif // hifi_Application_h
|
||||
|
|
|
@ -968,9 +968,10 @@ bool AvatarData::hasIdentityChangedAfterParsing(const QByteArray& data) {
|
|||
|
||||
bool hasIdentityChanged = false;
|
||||
|
||||
if (skeletonModelURL != _skeletonModelURL) {
|
||||
if (_firstSkeletonCheck || (skeletonModelURL != _skeletonModelURL)) {
|
||||
setSkeletonModelURL(skeletonModelURL);
|
||||
hasIdentityChanged = true;
|
||||
_firstSkeletonCheck = false;
|
||||
}
|
||||
|
||||
if (displayName != _displayName) {
|
||||
|
|
|
@ -368,7 +368,8 @@ protected:
|
|||
|
||||
HeadData* _headData;
|
||||
|
||||
QUrl _skeletonModelURL; // These need to be empty so that on first time setting them they will not short circuit
|
||||
QUrl _skeletonModelURL;
|
||||
bool _firstSkeletonCheck { true };
|
||||
QUrl _skeletonFBXURL;
|
||||
QVector<AttachmentData> _attachmentData;
|
||||
QString _displayName;
|
||||
|
|
|
@ -78,10 +78,14 @@ bool FBXGeometry::convexHullContains(const glm::vec3& point) const {
|
|||
|
||||
auto checkEachPrimitive = [=](FBXMesh& mesh, QVector<int> indices, int primitiveSize) -> bool {
|
||||
// Check whether the point is "behind" all the primitives.
|
||||
int verticesSize = mesh.vertices.size();
|
||||
for (int j = 0;
|
||||
j < indices.size() - 2; // -2 in case the vertices aren't the right size -- we access j + 2 below
|
||||
j += primitiveSize) {
|
||||
if (!isPointBehindTrianglesPlane(point,
|
||||
if (indices[j] < verticesSize &&
|
||||
indices[j + 1] < verticesSize &&
|
||||
indices[j + 2] < verticesSize &&
|
||||
!isPointBehindTrianglesPlane(point,
|
||||
mesh.vertices[indices[j]],
|
||||
mesh.vertices[indices[j + 1]],
|
||||
mesh.vertices[indices[j + 2]])) {
|
||||
|
|
|
@ -44,12 +44,6 @@ bool OffscreenGLCanvas::create(QOpenGLContext* sharedContext) {
|
|||
return true;
|
||||
}
|
||||
|
||||
qWarning() << "GL Version: " << QString((const char*) glGetString(GL_VERSION));
|
||||
qWarning() << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
qWarning() << "GL Vendor: " << QString((const char*) glGetString(GL_VENDOR));
|
||||
qWarning() << "GL Renderer: " << QString((const char*) glGetString(GL_RENDERER));
|
||||
qWarning() << "Failed to create OffscreenGLCanvas";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -187,6 +187,15 @@ bool OffscreenQmlRenderThread::event(QEvent *e) {
|
|||
void OffscreenQmlRenderThread::setupFbo() {
|
||||
using namespace oglplus;
|
||||
_textures.setSize(_size);
|
||||
|
||||
// Before making any ogl calls, clear any outstanding errors
|
||||
// FIXME: Something upstream is polluting the context with a GL_INVALID_ENUM,
|
||||
// likely from glewExperimental = true
|
||||
GLenum err = glGetError();
|
||||
if (err != GL_NO_ERROR) {
|
||||
qDebug() << "Clearing outstanding GL error to set up QML FBO:" << glewGetErrorString(err);
|
||||
}
|
||||
|
||||
_depthStencil.reset(new Renderbuffer());
|
||||
Context::Bound(Renderbuffer::Target::Renderbuffer, *_depthStencil)
|
||||
.Storage(
|
||||
|
@ -417,7 +426,11 @@ void OffscreenQmlSurface::setBaseUrl(const QUrl& baseUrl) {
|
|||
}
|
||||
|
||||
QObject* OffscreenQmlSurface::load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f) {
|
||||
_qmlComponent->loadUrl(qmlSource);
|
||||
// Synchronous loading may take a while; restart the deadlock timer
|
||||
QMetaObject::invokeMethod(qApp, "updateHeartbeat", Qt::DirectConnection);
|
||||
|
||||
_qmlComponent->loadUrl(qmlSource, QQmlComponent::PreferSynchronous);
|
||||
|
||||
if (_qmlComponent->isLoading()) {
|
||||
connect(_qmlComponent, &QQmlComponent::statusChanged, this,
|
||||
[this, f](QQmlComponent::Status){
|
||||
|
|
|
@ -87,18 +87,15 @@ void GLBackend::init() {
|
|||
static std::once_flag once;
|
||||
std::call_once(once, [] {
|
||||
qCDebug(gpulogging) << "GL Version: " << QString((const char*) glGetString(GL_VERSION));
|
||||
|
||||
qCDebug(gpulogging) << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
|
||||
qCDebug(gpulogging) << "GL Vendor: " << QString((const char*) glGetString(GL_VENDOR));
|
||||
|
||||
qCDebug(gpulogging) << "GL Renderer: " << QString((const char*) glGetString(GL_RENDERER));
|
||||
|
||||
glewExperimental = true;
|
||||
GLenum err = glewInit();
|
||||
glGetError();
|
||||
glGetError(); // clear the potential error from glewExperimental
|
||||
if (GLEW_OK != err) {
|
||||
/* Problem: glewInit failed, something is seriously wrong. */
|
||||
// glewInit failed, something is seriously wrong.
|
||||
qCDebug(gpulogging, "Error: %s\n", glewGetErrorString(err));
|
||||
}
|
||||
qCDebug(gpulogging, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));
|
||||
|
|
|
@ -10,11 +10,74 @@
|
|||
//
|
||||
#include "Resource.h"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include <SharedUtil.h>
|
||||
#include <NumericalConstants.h>
|
||||
#include <QDebug>
|
||||
|
||||
using namespace gpu;
|
||||
|
||||
class AllocationDebugger {
|
||||
public:
|
||||
void operator+=(size_t size) {
|
||||
_allocatedMemory += size;
|
||||
maybeReport();
|
||||
}
|
||||
|
||||
void operator-=(size_t size) {
|
||||
_allocatedMemory -= size;
|
||||
maybeReport();
|
||||
}
|
||||
|
||||
private:
|
||||
QString formatSize(size_t size) {
|
||||
float num = size;
|
||||
QStringList list;
|
||||
list << "KB" << "MB" << "GB" << "TB";
|
||||
|
||||
QStringListIterator i(list);
|
||||
QString unit("bytes");
|
||||
|
||||
while (num >= K && i.hasNext()) {
|
||||
unit = i.next();
|
||||
num /= K;
|
||||
}
|
||||
return QString().setNum(num, 'f', 2) + " " + unit;
|
||||
}
|
||||
|
||||
void maybeReport() {
|
||||
auto now = usecTimestampNow();
|
||||
if (now - _lastReportTime < MAX_REPORT_FREQUENCY) {
|
||||
return;
|
||||
}
|
||||
size_t current = _allocatedMemory;
|
||||
size_t last = _lastReportedMemory;
|
||||
size_t delta = (current > last) ? (current - last) : (last - current);
|
||||
if (delta > MIN_REPORT_DELTA) {
|
||||
_lastReportTime = now;
|
||||
_lastReportedMemory = current;
|
||||
qDebug() << "Total allocation " << formatSize(current);
|
||||
}
|
||||
}
|
||||
|
||||
std::atomic<size_t> _allocatedMemory;
|
||||
std::atomic<size_t> _lastReportedMemory;
|
||||
std::atomic<uint64_t> _lastReportTime;
|
||||
|
||||
static const float K;
|
||||
// Report changes of 5 megabytes
|
||||
static const size_t MIN_REPORT_DELTA = 1024 * 1024 * 5;
|
||||
// Report changes no more frequently than every 15 seconds
|
||||
static const uint64_t MAX_REPORT_FREQUENCY = USECS_PER_SECOND * 15;
|
||||
};
|
||||
|
||||
const float AllocationDebugger::K = 1024.0f;
|
||||
|
||||
static AllocationDebugger allocationDebugger;
|
||||
|
||||
Resource::Size Resource::Sysmem::allocateMemory(Byte** dataAllocated, Size size) {
|
||||
allocationDebugger += size;
|
||||
if ( !dataAllocated ) {
|
||||
qWarning() << "Buffer::Sysmem::allocateMemory() : Must have a valid dataAllocated pointer.";
|
||||
return NOT_ALLOCATED;
|
||||
|
@ -38,6 +101,7 @@ Resource::Size Resource::Sysmem::allocateMemory(Byte** dataAllocated, Size size)
|
|||
}
|
||||
|
||||
void Resource::Sysmem::deallocateMemory(Byte* dataAllocated, Size size) {
|
||||
allocationDebugger -= size;
|
||||
if (dataAllocated) {
|
||||
delete[] dataAllocated;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
static int modelPointerTypeId = qRegisterMetaType<QPointer<Model> >();
|
||||
static int nakedModelPointerTypeId = qRegisterMetaType<ModelPointer>();
|
||||
static int weakNetworkGeometryPointerTypeId = qRegisterMetaType<QWeakPointer<NetworkGeometry> >();
|
||||
static int vec3VectorTypeId = qRegisterMetaType<QVector<glm::vec3> >();
|
||||
float Model::FAKE_DIMENSION_PLACEHOLDER = -1.0f;
|
||||
|
@ -821,21 +821,21 @@ QStringList Model::getJointNames() const {
|
|||
class Blender : public QRunnable {
|
||||
public:
|
||||
|
||||
Blender(Model* model, int blendNumber, const QWeakPointer<NetworkGeometry>& geometry,
|
||||
Blender(ModelPointer model, int blendNumber, const QWeakPointer<NetworkGeometry>& geometry,
|
||||
const QVector<FBXMesh>& meshes, const QVector<float>& blendshapeCoefficients);
|
||||
|
||||
virtual void run();
|
||||
|
||||
private:
|
||||
|
||||
QPointer<Model> _model;
|
||||
ModelPointer _model;
|
||||
int _blendNumber;
|
||||
QWeakPointer<NetworkGeometry> _geometry;
|
||||
QVector<FBXMesh> _meshes;
|
||||
QVector<float> _blendshapeCoefficients;
|
||||
};
|
||||
|
||||
Blender::Blender(Model* model, int blendNumber, const QWeakPointer<NetworkGeometry>& geometry,
|
||||
Blender::Blender(ModelPointer model, int blendNumber, const QWeakPointer<NetworkGeometry>& geometry,
|
||||
const QVector<FBXMesh>& meshes, const QVector<float>& blendshapeCoefficients) :
|
||||
_model(model),
|
||||
_blendNumber(blendNumber),
|
||||
|
@ -847,7 +847,7 @@ Blender::Blender(Model* model, int blendNumber, const QWeakPointer<NetworkGeomet
|
|||
void Blender::run() {
|
||||
PROFILE_RANGE(__FUNCTION__);
|
||||
QVector<glm::vec3> vertices, normals;
|
||||
if (!_model.isNull()) {
|
||||
if (_model) {
|
||||
int offset = 0;
|
||||
foreach (const FBXMesh& mesh, _meshes) {
|
||||
if (mesh.blendshapes.isEmpty()) {
|
||||
|
@ -877,7 +877,7 @@ void Blender::run() {
|
|||
}
|
||||
// post the result to the geometry cache, which will dispatch to the model if still alive
|
||||
QMetaObject::invokeMethod(DependencyManager::get<ModelBlender>().data(), "setBlendedVertices",
|
||||
Q_ARG(const QPointer<Model>&, _model), Q_ARG(int, _blendNumber),
|
||||
Q_ARG(ModelPointer, _model), Q_ARG(int, _blendNumber),
|
||||
Q_ARG(const QWeakPointer<NetworkGeometry>&, _geometry), Q_ARG(const QVector<glm::vec3>&, vertices),
|
||||
Q_ARG(const QVector<glm::vec3>&, normals));
|
||||
}
|
||||
|
@ -1088,7 +1088,7 @@ float Model::getLimbLength(int jointIndex) const {
|
|||
bool Model::maybeStartBlender() {
|
||||
const FBXGeometry& fbxGeometry = _geometry->getFBXGeometry();
|
||||
if (fbxGeometry.hasBlendedMeshes()) {
|
||||
QThreadPool::globalInstance()->start(new Blender(this, ++_blendNumber, _geometry,
|
||||
QThreadPool::globalInstance()->start(new Blender(getThisPointer(), ++_blendNumber, _geometry,
|
||||
fbxGeometry.meshes, _blendshapeCoefficients));
|
||||
return true;
|
||||
}
|
||||
|
@ -1277,20 +1277,25 @@ void ModelBlender::noteRequiresBlend(ModelPointer model) {
|
|||
}
|
||||
return;
|
||||
}
|
||||
_modelsRequiringBlends.insert(model);
|
||||
|
||||
{
|
||||
Lock lock(_mutex);
|
||||
_modelsRequiringBlends.insert(model);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelBlender::setBlendedVertices(const QPointer<Model>& model, int blendNumber,
|
||||
void ModelBlender::setBlendedVertices(ModelPointer model, int blendNumber,
|
||||
const QWeakPointer<NetworkGeometry>& geometry, const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals) {
|
||||
if (!model.isNull()) {
|
||||
if (model) {
|
||||
model->setBlendedVertices(blendNumber, geometry, vertices, normals);
|
||||
}
|
||||
_pendingBlenders--;
|
||||
while (!_modelsRequiringBlends.empty()) {
|
||||
auto firstItem = _modelsRequiringBlends.begin();
|
||||
if (firstItem != _modelsRequiringBlends.end()) {
|
||||
_modelsRequiringBlends.erase(firstItem);
|
||||
ModelPointer nextModel = firstItem->lock();
|
||||
{
|
||||
Lock lock(_mutex);
|
||||
for (auto i = _modelsRequiringBlends.begin(); i != _modelsRequiringBlends.end();) {
|
||||
auto weakPtr = *i;
|
||||
_modelsRequiringBlends.erase(i++); // remove front of the set
|
||||
ModelPointer nextModel = weakPtr.lock();
|
||||
if (nextModel && nextModel->maybeStartBlender()) {
|
||||
_pendingBlenders++;
|
||||
return;
|
||||
|
|
|
@ -384,7 +384,7 @@ protected:
|
|||
RigPointer _rig;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(QPointer<Model>)
|
||||
Q_DECLARE_METATYPE(ModelPointer)
|
||||
Q_DECLARE_METATYPE(QWeakPointer<NetworkGeometry>)
|
||||
|
||||
/// Handle management of pending models that need blending
|
||||
|
@ -398,15 +398,19 @@ public:
|
|||
void noteRequiresBlend(ModelPointer model);
|
||||
|
||||
public slots:
|
||||
void setBlendedVertices(const QPointer<Model>& model, int blendNumber, const QWeakPointer<NetworkGeometry>& geometry,
|
||||
void setBlendedVertices(ModelPointer model, int blendNumber, const QWeakPointer<NetworkGeometry>& geometry,
|
||||
const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals);
|
||||
|
||||
private:
|
||||
using Mutex = std::mutex;
|
||||
using Lock = std::unique_lock<Mutex>;
|
||||
|
||||
ModelBlender();
|
||||
virtual ~ModelBlender();
|
||||
|
||||
std::set<ModelWeakPointer, std::owner_less<ModelWeakPointer>> _modelsRequiringBlends;
|
||||
int _pendingBlenders;
|
||||
Mutex _mutex;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -172,7 +172,6 @@ QScriptValue QmlWindowClass::internalConstructor(const QString& qmlSource,
|
|||
setupServer();
|
||||
retVal = builder(newTab);
|
||||
retVal->_toolWindow = true;
|
||||
offscreenUi->getRootContext()->engine()->setObjectOwnership(retVal->_qmlWindow, QQmlEngine::CppOwnership);
|
||||
registerObject(url.toLower(), retVal);
|
||||
return QVariant();
|
||||
});
|
||||
|
@ -330,10 +329,8 @@ void QmlWindowClass::close() {
|
|||
if (_qmlWindow) {
|
||||
if (_toolWindow) {
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
auto qmlWindow = _qmlWindow;
|
||||
offscreenUi->executeOnUiThread([=] {
|
||||
auto toolWindow = offscreenUi->getToolWindow();
|
||||
offscreenUi->getRootContext()->engine()->setObjectOwnership(qmlWindow, QQmlEngine::JavaScriptOwnership);
|
||||
auto invokeResult = QMetaObject::invokeMethod(toolWindow, "removeTabForUrl", Qt::DirectConnection,
|
||||
Q_ARG(QVariant, _source));
|
||||
Q_ASSERT(invokeResult);
|
||||
|
|
|
@ -30,7 +30,7 @@ bool OculusBaseDisplayPlugin::isSupported() const {
|
|||
void OculusBaseDisplayPlugin::customizeContext() {
|
||||
glewExperimental = true;
|
||||
GLenum err = glewInit();
|
||||
glGetError();
|
||||
glGetError(); // clear the potential error from glewExperimental
|
||||
Parent::customizeContext();
|
||||
}
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ void OpenVrDisplayPlugin::customizeContext() {
|
|||
std::call_once(once, []{
|
||||
glewExperimental = true;
|
||||
GLenum err = glewInit();
|
||||
glGetError();
|
||||
glGetError(); // clear the potential error from glewExperimental
|
||||
});
|
||||
Parent::customizeContext();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue