mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-29 16:22:51 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into color
This commit is contained in:
commit
afcb5b8557
16 changed files with 300 additions and 170 deletions
4
cmake/externals/wasapi/CMakeLists.txt
vendored
4
cmake/externals/wasapi/CMakeLists.txt
vendored
|
@ -6,8 +6,8 @@ if (WIN32)
|
||||||
include(ExternalProject)
|
include(ExternalProject)
|
||||||
ExternalProject_Add(
|
ExternalProject_Add(
|
||||||
${EXTERNAL_NAME}
|
${EXTERNAL_NAME}
|
||||||
URL http://hifi-public.s3.amazonaws.com/dependencies/qtaudio_wasapi.zip
|
URL http://hifi-public.s3.amazonaws.com/dependencies/qtaudio_wasapi2.zip
|
||||||
URL_MD5 11c8a7728d6eda7223df800e10b70723
|
URL_MD5 272b27bd6c211c45c0c23d4701b63b5e
|
||||||
CONFIGURE_COMMAND ""
|
CONFIGURE_COMMAND ""
|
||||||
BUILD_COMMAND ""
|
BUILD_COMMAND ""
|
||||||
INSTALL_COMMAND ""
|
INSTALL_COMMAND ""
|
||||||
|
|
|
@ -49,6 +49,7 @@ macro(PACKAGE_LIBRARIES_FOR_DEPLOYMENT)
|
||||||
TARGET ${TARGET_NAME}
|
TARGET ${TARGET_NAME}
|
||||||
POST_BUILD
|
POST_BUILD
|
||||||
COMMAND if exist ${QTAUDIO_PATH}/qtaudio_windows.dll ( ${CMAKE_COMMAND} -E remove ${QTAUDIO_PATH}/qtaudio_windows.dll && ${CMAKE_COMMAND} -E copy ${WASAPI_DLL_PATH}/qtaudio_wasapi.dll ${QTAUDIO_PATH} && ${CMAKE_COMMAND} -E copy ${WASAPI_DLL_PATH}/qtaudio_wasapi.pdb ${QTAUDIO_PATH} )
|
COMMAND if exist ${QTAUDIO_PATH}/qtaudio_windows.dll ( ${CMAKE_COMMAND} -E remove ${QTAUDIO_PATH}/qtaudio_windows.dll && ${CMAKE_COMMAND} -E copy ${WASAPI_DLL_PATH}/qtaudio_wasapi.dll ${QTAUDIO_PATH} && ${CMAKE_COMMAND} -E copy ${WASAPI_DLL_PATH}/qtaudio_wasapi.pdb ${QTAUDIO_PATH} )
|
||||||
|
COMMAND if exist ${QTAUDIO_PATH}/qtaudio_windowsd.dll ( ${CMAKE_COMMAND} -E remove ${QTAUDIO_PATH}/qtaudio_windowsd.dll && ${CMAKE_COMMAND} -E copy ${WASAPI_DLL_PATH}/qtaudio_wasapid.dll ${QTAUDIO_PATH} && ${CMAKE_COMMAND} -E copy ${WASAPI_DLL_PATH}/qtaudio_wasapid.pdb ${QTAUDIO_PATH} )
|
||||||
)
|
)
|
||||||
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "DisplayPlugin.h"
|
#include "DisplayPlugin.h"
|
||||||
|
#include <gl/Config.h>
|
||||||
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -18,7 +19,6 @@
|
||||||
|
|
||||||
#include <GLMHelpers.h>
|
#include <GLMHelpers.h>
|
||||||
#include <SimpleMovingAverage.h>
|
#include <SimpleMovingAverage.h>
|
||||||
#include <gl/GLEscrow.h>
|
|
||||||
#include <shared/RateCounter.h>
|
#include <shared/RateCounter.h>
|
||||||
|
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
|
@ -35,7 +35,6 @@ protected:
|
||||||
using Mutex = std::mutex;
|
using Mutex = std::mutex;
|
||||||
using Lock = std::unique_lock<Mutex>;
|
using Lock = std::unique_lock<Mutex>;
|
||||||
using Condition = std::condition_variable;
|
using Condition = std::condition_variable;
|
||||||
using TextureEscrow = GLEscrow<gpu::TexturePointer>;
|
|
||||||
public:
|
public:
|
||||||
// These must be final to ensure proper ordering of operations
|
// These must be final to ensure proper ordering of operations
|
||||||
// between the main thread and the presentation thread
|
// between the main thread and the presentation thread
|
||||||
|
|
|
@ -58,9 +58,13 @@ void WebEntityAPIHelper::emitWebEvent(const QVariant& message) {
|
||||||
} else {
|
} else {
|
||||||
// special case to handle raising and lowering the virtual keyboard
|
// special case to handle raising and lowering the virtual keyboard
|
||||||
if (message.type() == QVariant::String && message.toString() == "_RAISE_KEYBOARD" && _renderableWebEntityItem) {
|
if (message.type() == QVariant::String && message.toString() == "_RAISE_KEYBOARD" && _renderableWebEntityItem) {
|
||||||
_renderableWebEntityItem->setKeyboardRaised(true);
|
if (_renderableWebEntityItem) {
|
||||||
|
_renderableWebEntityItem->setKeyboardRaised(true);
|
||||||
|
}
|
||||||
} else if (message.type() == QVariant::String && message.toString() == "_LOWER_KEYBOARD" && _renderableWebEntityItem) {
|
} else if (message.type() == QVariant::String && message.toString() == "_LOWER_KEYBOARD" && _renderableWebEntityItem) {
|
||||||
_renderableWebEntityItem->setKeyboardRaised(false);
|
if (_renderableWebEntityItem) {
|
||||||
|
_renderableWebEntityItem->setKeyboardRaised(false);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
emit webEventReceived(message);
|
emit webEventReceived(message);
|
||||||
}
|
}
|
||||||
|
@ -343,7 +347,7 @@ void RenderableWebEntityItem::destroyWebSurface() {
|
||||||
|
|
||||||
// The lifetime of the QML surface MUST be managed by the main thread
|
// The lifetime of the QML surface MUST be managed by the main thread
|
||||||
// Additionally, we MUST use local variables copied by value, rather than
|
// Additionally, we MUST use local variables copied by value, rather than
|
||||||
// member variables, since they would implicitly refer to a this that
|
// member variables, since they would implicitly refer to a this that
|
||||||
// is no longer valid
|
// is no longer valid
|
||||||
auto webSurface = _webSurface;
|
auto webSurface = _webSurface;
|
||||||
AbstractViewStateInterface::instance()->postLambdaEvent([webSurface] {
|
AbstractViewStateInterface::instance()->postLambdaEvent([webSurface] {
|
||||||
|
@ -388,35 +392,40 @@ static bool equals(const QByteArray& byteArray, const uint8_t* ptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderableWebEntityItem::synthesizeKeyPress(QString key) {
|
void RenderableWebEntityItem::synthesizeKeyPress(QString key) {
|
||||||
auto utf8Key = key.toUtf8();
|
auto eventHandler = getEventHandler();
|
||||||
|
if (eventHandler) {
|
||||||
|
auto utf8Key = key.toUtf8();
|
||||||
|
|
||||||
int scanCode = (int)utf8Key[0];
|
int scanCode = (int)utf8Key[0];
|
||||||
QString keyString = key;
|
QString keyString = key;
|
||||||
if (equals(utf8Key, UPWARDS_WHITE_ARROW_FROM_BAR) || equals(utf8Key, ASTERISIM) ||
|
if (equals(utf8Key, UPWARDS_WHITE_ARROW_FROM_BAR) || equals(utf8Key, ASTERISIM) ||
|
||||||
equals(utf8Key, (uint8_t*)PUNCTUATION_STRING) || equals(utf8Key, (uint8_t*)ALPHABET_STRING)) {
|
equals(utf8Key, (uint8_t*)PUNCTUATION_STRING) || equals(utf8Key, (uint8_t*)ALPHABET_STRING)) {
|
||||||
return; // ignore
|
return; // ignore
|
||||||
} else if (equals(utf8Key, LEFT_ARROW)) {
|
} else if (equals(utf8Key, LEFT_ARROW)) {
|
||||||
scanCode = Qt::Key_Backspace;
|
scanCode = Qt::Key_Backspace;
|
||||||
keyString = "\x08";
|
keyString = "\x08";
|
||||||
} else if (equals(utf8Key, RETURN_SYMBOL)) {
|
} else if (equals(utf8Key, RETURN_SYMBOL)) {
|
||||||
scanCode = Qt::Key_Return;
|
scanCode = Qt::Key_Return;
|
||||||
keyString = "\x0d";
|
keyString = "\x0d";
|
||||||
} else if (equals(utf8Key, LEFTWARD_WHITE_ARROW)) {
|
} else if (equals(utf8Key, LEFTWARD_WHITE_ARROW)) {
|
||||||
scanCode = Qt::Key_Left;
|
scanCode = Qt::Key_Left;
|
||||||
keyString = "";
|
keyString = "";
|
||||||
} else if (equals(utf8Key, RIGHTWARD_WHITE_ARROW)) {
|
} else if (equals(utf8Key, RIGHTWARD_WHITE_ARROW)) {
|
||||||
scanCode = Qt::Key_Right;
|
scanCode = Qt::Key_Right;
|
||||||
keyString = "";
|
keyString = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
QKeyEvent* pressEvent = new QKeyEvent(QEvent::KeyPress, scanCode, Qt::NoModifier, keyString);
|
||||||
|
QKeyEvent* releaseEvent = new QKeyEvent(QEvent::KeyRelease, scanCode, Qt::NoModifier, keyString);
|
||||||
|
QCoreApplication::postEvent(eventHandler, pressEvent);
|
||||||
|
QCoreApplication::postEvent(eventHandler, releaseEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
QKeyEvent* pressEvent = new QKeyEvent(QEvent::KeyPress, scanCode, Qt::NoModifier, keyString);
|
|
||||||
QKeyEvent* releaseEvent = new QKeyEvent(QEvent::KeyRelease, scanCode, Qt::NoModifier, keyString);
|
|
||||||
QCoreApplication::postEvent(getEventHandler(), pressEvent);
|
|
||||||
QCoreApplication::postEvent(getEventHandler(), releaseEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderableWebEntityItem::emitScriptEvent(const QVariant& message) {
|
void RenderableWebEntityItem::emitScriptEvent(const QVariant& message) {
|
||||||
_webEntityAPIHelper->emitScriptEvent(message);
|
if (_webEntityAPIHelper) {
|
||||||
|
_webEntityAPIHelper->emitScriptEvent(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderableWebEntityItem::setKeyboardRaised(bool raised) {
|
void RenderableWebEntityItem::setKeyboardRaised(bool raised) {
|
||||||
|
@ -424,5 +433,10 @@ void RenderableWebEntityItem::setKeyboardRaised(bool raised) {
|
||||||
// raise the keyboard only while in HMD mode and it's being requested.
|
// raise the keyboard only while in HMD mode and it's being requested.
|
||||||
bool value = AbstractViewStateInterface::instance()->isHMDMode() && raised;
|
bool value = AbstractViewStateInterface::instance()->isHMDMode() && raised;
|
||||||
|
|
||||||
_webSurface->getRootItem()->setProperty("keyboardRaised", QVariant(value));
|
if (_webSurface) {
|
||||||
|
auto rootItem = _webSurface->getRootItem();
|
||||||
|
if (rootItem) {
|
||||||
|
rootItem->setProperty("keyboardRaised", QVariant(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,8 +67,8 @@ void GLWidget::createContext() {
|
||||||
_context = new gl::Context();
|
_context = new gl::Context();
|
||||||
_context->setWindow(windowHandle());
|
_context->setWindow(windowHandle());
|
||||||
_context->create();
|
_context->create();
|
||||||
_context->clear();
|
|
||||||
_context->makeCurrent();
|
_context->makeCurrent();
|
||||||
|
_context->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLWidget::makeCurrent() {
|
bool GLWidget::makeCurrent() {
|
||||||
|
|
|
@ -6,7 +6,11 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
#include "OffscreenQmlSurface.h"
|
#include "OffscreenQmlSurface.h"
|
||||||
#include "OglplusHelpers.h"
|
#include "Config.h"
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
#include <set>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include <QtWidgets/QWidget>
|
#include <QtWidgets/QWidget>
|
||||||
#include <QtQml/QtQml>
|
#include <QtQml/QtQml>
|
||||||
|
@ -116,6 +120,108 @@ static const QEvent::Type RENDER = QEvent::Type(QEvent::User + 2);
|
||||||
static const QEvent::Type RESIZE = QEvent::Type(QEvent::User + 3);
|
static const QEvent::Type RESIZE = QEvent::Type(QEvent::User + 3);
|
||||||
static const QEvent::Type STOP = QEvent::Type(QEvent::User + 4);
|
static const QEvent::Type STOP = QEvent::Type(QEvent::User + 4);
|
||||||
|
|
||||||
|
class RawTextureRecycler {
|
||||||
|
public:
|
||||||
|
using TexturePtr = GLuint;
|
||||||
|
RawTextureRecycler(bool useMipmaps) : _useMipmaps(useMipmaps) {}
|
||||||
|
void setSize(const uvec2& size);
|
||||||
|
void clear();
|
||||||
|
TexturePtr getNextTexture();
|
||||||
|
void recycleTexture(GLuint texture);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
struct TexInfo {
|
||||||
|
TexturePtr _tex { 0 };
|
||||||
|
uvec2 _size;
|
||||||
|
bool _active { false };
|
||||||
|
|
||||||
|
TexInfo() {}
|
||||||
|
TexInfo(TexturePtr tex, const uvec2& size) : _tex(tex), _size(size) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
using Map = std::map<GLuint, TexInfo>;
|
||||||
|
using Queue = std::queue<TexturePtr>;
|
||||||
|
|
||||||
|
Map _allTextures;
|
||||||
|
Queue _readyTextures;
|
||||||
|
uvec2 _size { 1920, 1080 };
|
||||||
|
bool _useMipmaps;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void RawTextureRecycler::setSize(const uvec2& size) {
|
||||||
|
if (size == _size) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_size = size;
|
||||||
|
while (!_readyTextures.empty()) {
|
||||||
|
_readyTextures.pop();
|
||||||
|
}
|
||||||
|
std::set<Map::key_type> toDelete;
|
||||||
|
std::for_each(_allTextures.begin(), _allTextures.end(), [&](Map::const_reference item) {
|
||||||
|
if (!item.second._active && item.second._size != _size) {
|
||||||
|
toDelete.insert(item.first);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
std::for_each(toDelete.begin(), toDelete.end(), [&](Map::key_type key) {
|
||||||
|
_allTextures.erase(key);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void RawTextureRecycler::clear() {
|
||||||
|
while (!_readyTextures.empty()) {
|
||||||
|
_readyTextures.pop();
|
||||||
|
}
|
||||||
|
_allTextures.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
RawTextureRecycler::TexturePtr RawTextureRecycler::getNextTexture() {
|
||||||
|
if (_readyTextures.empty()) {
|
||||||
|
TexturePtr newTexture;
|
||||||
|
glGenTextures(1, &newTexture);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, newTexture);
|
||||||
|
if (_useMipmaps) {
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
} else {
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
}
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8.0f);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -0.2f);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8.0f);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, _size.x, _size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||||
|
_allTextures[newTexture] = TexInfo { newTexture, _size };
|
||||||
|
_readyTextures.push(newTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
TexturePtr result = _readyTextures.front();
|
||||||
|
_readyTextures.pop();
|
||||||
|
auto& item = _allTextures[result];
|
||||||
|
item._active = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RawTextureRecycler::recycleTexture(GLuint texture) {
|
||||||
|
Q_ASSERT(_allTextures.count(texture));
|
||||||
|
auto& item = _allTextures[texture];
|
||||||
|
Q_ASSERT(item._active);
|
||||||
|
item._active = false;
|
||||||
|
if (item._size != _size) {
|
||||||
|
// Buh-bye
|
||||||
|
_allTextures.erase(texture);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_readyTextures.push(item._tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class OffscreenQmlRenderThread : public QThread {
|
class OffscreenQmlRenderThread : public QThread {
|
||||||
public:
|
public:
|
||||||
OffscreenQmlRenderThread(OffscreenQmlSurface* surface, QOpenGLContext* shareContext);
|
OffscreenQmlRenderThread(OffscreenQmlSurface* surface, QOpenGLContext* shareContext);
|
||||||
|
@ -165,9 +271,9 @@ private:
|
||||||
OffscreenQmlSurface* _surface{ nullptr };
|
OffscreenQmlSurface* _surface{ nullptr };
|
||||||
QQuickWindow* _quickWindow{ nullptr };
|
QQuickWindow* _quickWindow{ nullptr };
|
||||||
QMyQuickRenderControl* _renderControl{ nullptr };
|
QMyQuickRenderControl* _renderControl{ nullptr };
|
||||||
FramebufferPtr _fbo;
|
GLuint _fbo { 0 };
|
||||||
RenderbufferPtr _depthStencil;
|
GLuint _depthStencil { 0 };
|
||||||
TextureRecycler _textures { true };
|
RawTextureRecycler _textures { true };
|
||||||
GLTextureEscrow _escrow;
|
GLTextureEscrow _escrow;
|
||||||
|
|
||||||
uint64_t _lastRenderTime{ 0 };
|
uint64_t _lastRenderTime{ 0 };
|
||||||
|
@ -253,24 +359,23 @@ bool OffscreenQmlRenderThread::event(QEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OffscreenQmlRenderThread::setupFbo() {
|
void OffscreenQmlRenderThread::setupFbo() {
|
||||||
using namespace oglplus;
|
|
||||||
_textures.setSize(_size);
|
_textures.setSize(_size);
|
||||||
|
if (_depthStencil) {
|
||||||
try {
|
glDeleteRenderbuffers(1, &_depthStencil);
|
||||||
_depthStencil.reset(new Renderbuffer());
|
_depthStencil = 0;
|
||||||
Context::Bound(Renderbuffer::Target::Renderbuffer, *_depthStencil)
|
|
||||||
.Storage(
|
|
||||||
PixelDataInternalFormat::DepthComponent,
|
|
||||||
_size.x, _size.y);
|
|
||||||
|
|
||||||
_fbo.reset(new Framebuffer());
|
|
||||||
_fbo->Bind(Framebuffer::Target::Draw);
|
|
||||||
_fbo->AttachRenderbuffer(Framebuffer::Target::Draw,
|
|
||||||
FramebufferAttachment::Depth, *_depthStencil);
|
|
||||||
DefaultFramebuffer().Bind(Framebuffer::Target::Draw);
|
|
||||||
} catch (oglplus::Error& error) {
|
|
||||||
qWarning() << "OpenGL error in QML render setup: " << error.what();
|
|
||||||
}
|
}
|
||||||
|
glGenRenderbuffers(1, &_depthStencil);
|
||||||
|
glBindRenderbuffer(GL_RENDERBUFFER, _depthStencil);
|
||||||
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, _size.x, _size.y);
|
||||||
|
|
||||||
|
if (_fbo) {
|
||||||
|
glDeleteFramebuffers(1, &_fbo);
|
||||||
|
_fbo = 0;
|
||||||
|
}
|
||||||
|
glGenFramebuffers(1, &_fbo);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo);
|
||||||
|
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthStencil);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject OffscreenQmlRenderThread::getGLContextData() {
|
QJsonObject OffscreenQmlRenderThread::getGLContextData() {
|
||||||
|
@ -309,8 +414,15 @@ void OffscreenQmlRenderThread::init() {
|
||||||
void OffscreenQmlRenderThread::cleanup() {
|
void OffscreenQmlRenderThread::cleanup() {
|
||||||
_renderControl->invalidate();
|
_renderControl->invalidate();
|
||||||
|
|
||||||
_fbo.reset();
|
if (_depthStencil) {
|
||||||
_depthStencil.reset();
|
glDeleteRenderbuffers(1, &_depthStencil);
|
||||||
|
_depthStencil = 0;
|
||||||
|
}
|
||||||
|
if (_fbo) {
|
||||||
|
glDeleteFramebuffers(1, &_fbo);
|
||||||
|
_fbo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
_textures.clear();
|
_textures.clear();
|
||||||
|
|
||||||
_canvas.doneCurrent();
|
_canvas.doneCurrent();
|
||||||
|
@ -371,42 +483,22 @@ void OffscreenQmlRenderThread::render() {
|
||||||
releaseMainThread.trigger();
|
releaseMainThread.trigger();
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace oglplus;
|
_quickWindow->setRenderTarget(_fbo, QSize(_size.x, _size.y));
|
||||||
|
|
||||||
_quickWindow->setRenderTarget(GetName(*_fbo), QSize(_size.x, _size.y));
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PROFILE_RANGE("qml_render")
|
GLuint texture = _textures.getNextTexture();
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo);
|
||||||
TexturePtr texture = _textures.getNextTexture();
|
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0);
|
||||||
|
|
||||||
try {
|
|
||||||
_fbo->Bind(Framebuffer::Target::Draw);
|
|
||||||
_fbo->AttachTexture(Framebuffer::Target::Draw, FramebufferAttachment::Color, *texture, 0);
|
|
||||||
_fbo->Complete(Framebuffer::Target::Draw);
|
|
||||||
} catch (oglplus::Error& error) {
|
|
||||||
qWarning() << "OpenGL error in QML render: " << error.what();
|
|
||||||
|
|
||||||
// In case we are failing from a failed setupFbo, reset fbo before next render
|
|
||||||
setupFbo();
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
PROFILE_RANGE("qml_render->rendercontrol")
|
PROFILE_RANGE("qml_render->rendercontrol")
|
||||||
_renderControl->render();
|
_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.
|
|
||||||
// for now just clear the errors
|
|
||||||
glGetError();
|
|
||||||
}
|
|
||||||
|
|
||||||
Context::Bound(oglplus::Texture::Target::_2D, *texture).GenerateMipmap();
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
// FIXME probably unecessary
|
|
||||||
DefaultFramebuffer().Bind(Framebuffer::Target::Draw);
|
|
||||||
_quickWindow->resetOpenGLState();
|
_quickWindow->resetOpenGLState();
|
||||||
_escrow.submit(GetName(*texture));
|
_escrow.submit(texture);
|
||||||
_lastRenderTime = usecTimestampNow();
|
_lastRenderTime = usecTimestampNow();
|
||||||
} catch (std::runtime_error& error) {
|
} catch (std::runtime_error& error) {
|
||||||
qWarning() << "Failed to render QML: " << error.what();
|
qWarning() << "Failed to render QML: " << error.what();
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
std::unordered_map<TexturePointer, nvtxRangeId_t> _map;
|
std::unordered_map<TexturePointer, nvtxRangeId_t> _map;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//#define TEXTURE_TRANSFER_PBOS
|
|
||||||
|
|
||||||
#ifdef TEXTURE_TRANSFER_PBOS
|
#ifdef TEXTURE_TRANSFER_PBOS
|
||||||
#define TEXTURE_TRANSFER_BLOCK_SIZE (64 * 1024)
|
#define TEXTURE_TRANSFER_BLOCK_SIZE (64 * 1024)
|
||||||
|
@ -62,11 +61,16 @@ void GLTextureTransferHelper::transferTexture(const gpu::TexturePointer& texture
|
||||||
void GLTextureTransferHelper::setup() {
|
void GLTextureTransferHelper::setup() {
|
||||||
#ifdef THREADED_TEXTURE_TRANSFER
|
#ifdef THREADED_TEXTURE_TRANSFER
|
||||||
_context.makeCurrent();
|
_context.makeCurrent();
|
||||||
|
|
||||||
|
#ifdef TEXTURE_TRANSFER_FORCE_DRAW
|
||||||
|
// FIXME don't use opengl 4.5 DSA functionality without verifying it's present
|
||||||
glCreateRenderbuffers(1, &_drawRenderbuffer);
|
glCreateRenderbuffers(1, &_drawRenderbuffer);
|
||||||
glNamedRenderbufferStorage(_drawRenderbuffer, GL_RGBA8, 128, 128);
|
glNamedRenderbufferStorage(_drawRenderbuffer, GL_RGBA8, 128, 128);
|
||||||
glCreateFramebuffers(1, &_drawFramebuffer);
|
glCreateFramebuffers(1, &_drawFramebuffer);
|
||||||
glNamedFramebufferRenderbuffer(_drawFramebuffer, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _drawRenderbuffer);
|
glNamedFramebufferRenderbuffer(_drawFramebuffer, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _drawRenderbuffer);
|
||||||
glCreateFramebuffers(1, &_readFramebuffer);
|
glCreateFramebuffers(1, &_readFramebuffer);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef TEXTURE_TRANSFER_PBOS
|
#ifdef TEXTURE_TRANSFER_PBOS
|
||||||
std::array<GLuint, TEXTURE_TRANSFER_PBO_COUNT> pbos;
|
std::array<GLuint, TEXTURE_TRANSFER_PBO_COUNT> pbos;
|
||||||
glCreateBuffers(TEXTURE_TRANSFER_PBO_COUNT, &pbos[0]);
|
glCreateBuffers(TEXTURE_TRANSFER_PBO_COUNT, &pbos[0]);
|
||||||
|
@ -84,7 +88,9 @@ void GLTextureTransferHelper::setup() {
|
||||||
void GLTextureTransferHelper::shutdown() {
|
void GLTextureTransferHelper::shutdown() {
|
||||||
#ifdef THREADED_TEXTURE_TRANSFER
|
#ifdef THREADED_TEXTURE_TRANSFER
|
||||||
_context.makeCurrent();
|
_context.makeCurrent();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TEXTURE_TRANSFER_FORCE_DRAW
|
||||||
glNamedFramebufferRenderbuffer(_drawFramebuffer, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
|
glNamedFramebufferRenderbuffer(_drawFramebuffer, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
|
||||||
glDeleteFramebuffers(1, &_drawFramebuffer);
|
glDeleteFramebuffers(1, &_drawFramebuffer);
|
||||||
_drawFramebuffer = 0;
|
_drawFramebuffer = 0;
|
||||||
|
@ -165,6 +171,11 @@ bool GLTextureTransferHelper::process() {
|
||||||
}
|
}
|
||||||
|
|
||||||
gltexture->finishTransfer();
|
gltexture->finishTransfer();
|
||||||
|
|
||||||
|
#ifdef TEXTURE_TRANSFER_FORCE_DRAW
|
||||||
|
// FIXME force a draw on the texture transfer thread before passing the texture to the main thread for use
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef THREADED_TEXTURE_TRANSFER
|
#ifdef THREADED_TEXTURE_TRANSFER
|
||||||
clientWait();
|
clientWait();
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,6 +21,14 @@
|
||||||
#define THREADED_TEXTURE_TRANSFER
|
#define THREADED_TEXTURE_TRANSFER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef THREADED_TEXTURE_TRANSFER
|
||||||
|
// FIXME when sparse textures are enabled, it's harder to force a draw on the transfer thread
|
||||||
|
// also, the current draw code is implicitly using OpenGL 4.5 functionality
|
||||||
|
//#define TEXTURE_TRANSFER_FORCE_DRAW
|
||||||
|
// FIXME PBO's increase the complexity and don't seem to work reliably
|
||||||
|
//#define TEXTURE_TRANSFER_PBOS
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace gpu { namespace gl {
|
namespace gpu { namespace gl {
|
||||||
|
|
||||||
using TextureList = std::list<TexturePointer>;
|
using TextureList = std::list<TexturePointer>;
|
||||||
|
@ -43,11 +51,15 @@ public:
|
||||||
private:
|
private:
|
||||||
#ifdef THREADED_TEXTURE_TRANSFER
|
#ifdef THREADED_TEXTURE_TRANSFER
|
||||||
::gl::OffscreenContext _context;
|
::gl::OffscreenContext _context;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TEXTURE_TRANSFER_FORCE_DRAW
|
||||||
// Framebuffers / renderbuffers for forcing access to the texture on the transfer thread
|
// Framebuffers / renderbuffers for forcing access to the texture on the transfer thread
|
||||||
GLuint _drawRenderbuffer { 0 };
|
GLuint _drawRenderbuffer { 0 };
|
||||||
GLuint _drawFramebuffer { 0 };
|
GLuint _drawFramebuffer { 0 };
|
||||||
GLuint _readFramebuffer { 0 };
|
GLuint _readFramebuffer { 0 };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// A mutex for protecting items access on the render and transfer threads
|
// A mutex for protecting items access on the render and transfer threads
|
||||||
Mutex _mutex;
|
Mutex _mutex;
|
||||||
// Commands that have been submitted for execution on the texture transfer thread
|
// Commands that have been submitted for execution on the texture transfer thread
|
||||||
|
|
|
@ -377,8 +377,10 @@ void GeometryResource::deleter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeometryResource::setTextures() {
|
void GeometryResource::setTextures() {
|
||||||
for (const FBXMaterial& material : _fbxGeometry->materials) {
|
if (_fbxGeometry) {
|
||||||
_materials.push_back(std::make_shared<NetworkMaterial>(material, _textureBaseUrl));
|
for (const FBXMaterial& material : _fbxGeometry->materials) {
|
||||||
|
_materials.push_back(std::make_shared<NetworkMaterial>(material, _textureBaseUrl));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,7 +459,9 @@ model::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& baseUrl, c
|
||||||
_textures[channel] = Texture { fbxTexture.name, texture };
|
_textures[channel] = Texture { fbxTexture.name, texture };
|
||||||
|
|
||||||
auto map = std::make_shared<model::TextureMap>();
|
auto map = std::make_shared<model::TextureMap>();
|
||||||
map->setTextureSource(texture->_textureSource);
|
if (texture) {
|
||||||
|
map->setTextureSource(texture->_textureSource);
|
||||||
|
}
|
||||||
map->setTextureTransform(fbxTexture.transform);
|
map->setTextureTransform(fbxTexture.transform);
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
|
|
|
@ -44,8 +44,11 @@ Material::Material(const Material& material) :
|
||||||
}
|
}
|
||||||
|
|
||||||
Material& Material::operator= (const Material& material) {
|
Material& Material::operator= (const Material& material) {
|
||||||
|
QMutexLocker locker(&_textureMapsMutex);
|
||||||
|
|
||||||
_key = (material._key);
|
_key = (material._key);
|
||||||
_textureMaps = (material._textureMaps);
|
_textureMaps = (material._textureMaps);
|
||||||
|
_hasCalculatedTextureInfo = false;
|
||||||
|
|
||||||
// copied: create the Buffer to store the properties, avoid holding a ref to the old Buffer
|
// copied: create the Buffer to store the properties, avoid holding a ref to the old Buffer
|
||||||
Schema schema;
|
Schema schema;
|
||||||
|
@ -112,6 +115,8 @@ void Material::setScattering(float scattering) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textureMap) {
|
void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textureMap) {
|
||||||
|
QMutexLocker locker(&_textureMapsMutex);
|
||||||
|
|
||||||
if (textureMap) {
|
if (textureMap) {
|
||||||
_key.setMapChannel(channel, (true));
|
_key.setMapChannel(channel, (true));
|
||||||
_textureMaps[channel] = textureMap;
|
_textureMaps[channel] = textureMap;
|
||||||
|
@ -119,6 +124,7 @@ void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textur
|
||||||
_key.setMapChannel(channel, (false));
|
_key.setMapChannel(channel, (false));
|
||||||
_textureMaps.erase(channel);
|
_textureMaps.erase(channel);
|
||||||
}
|
}
|
||||||
|
_hasCalculatedTextureInfo = false;
|
||||||
|
|
||||||
_schemaBuffer.edit<Schema>()._key = (uint32)_key._flags.to_ulong();
|
_schemaBuffer.edit<Schema>()._key = (uint32)_key._flags.to_ulong();
|
||||||
|
|
||||||
|
@ -173,6 +179,8 @@ void Material::resetOpacityMap() const {
|
||||||
|
|
||||||
|
|
||||||
const TextureMapPointer Material::getTextureMap(MapChannel channel) const {
|
const TextureMapPointer Material::getTextureMap(MapChannel channel) const {
|
||||||
|
QMutexLocker locker(&_textureMapsMutex);
|
||||||
|
|
||||||
auto result = _textureMaps.find(channel);
|
auto result = _textureMaps.find(channel);
|
||||||
if (result != _textureMaps.end()) {
|
if (result != _textureMaps.end()) {
|
||||||
return (result->second);
|
return (result->second);
|
||||||
|
@ -180,3 +188,37 @@ const TextureMapPointer Material::getTextureMap(MapChannel channel) const {
|
||||||
return TextureMapPointer();
|
return TextureMapPointer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Material::calculateMaterialInfo() const {
|
||||||
|
if (!_hasCalculatedTextureInfo) {
|
||||||
|
QMutexLocker locker(&_textureMapsMutex);
|
||||||
|
|
||||||
|
bool allTextures = true; // assume we got this...
|
||||||
|
_textureSize = 0;
|
||||||
|
_textureCount = 0;
|
||||||
|
|
||||||
|
for (auto const &textureMapItem : _textureMaps) {
|
||||||
|
auto textureMap = textureMapItem.second;
|
||||||
|
if (textureMap) {
|
||||||
|
auto textureSoure = textureMap->getTextureSource();
|
||||||
|
if (textureSoure) {
|
||||||
|
auto texture = textureSoure->getGPUTexture();
|
||||||
|
if (texture) {
|
||||||
|
auto size = texture->getSize();
|
||||||
|
_textureSize += size;
|
||||||
|
_textureCount++;
|
||||||
|
} else {
|
||||||
|
allTextures = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
allTextures = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
allTextures = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_hasCalculatedTextureInfo = allTextures;
|
||||||
|
}
|
||||||
|
return _hasCalculatedTextureInfo;
|
||||||
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
#ifndef hifi_model_Material_h
|
#ifndef hifi_model_Material_h
|
||||||
#define hifi_model_Material_h
|
#define hifi_model_Material_h
|
||||||
|
|
||||||
|
#include <QMutex>
|
||||||
|
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
@ -324,7 +326,7 @@ public:
|
||||||
|
|
||||||
// The texture map to channel association
|
// The texture map to channel association
|
||||||
void setTextureMap(MapChannel channel, const TextureMapPointer& textureMap);
|
void setTextureMap(MapChannel channel, const TextureMapPointer& textureMap);
|
||||||
const TextureMaps& getTextureMaps() const { return _textureMaps; }
|
const TextureMaps& getTextureMaps() const { return _textureMaps; } // FIXME - not thread safe...
|
||||||
const TextureMapPointer getTextureMap(MapChannel channel) const;
|
const TextureMapPointer getTextureMap(MapChannel channel) const;
|
||||||
|
|
||||||
// Albedo maps cannot have opacity detected until they are loaded
|
// Albedo maps cannot have opacity detected until they are loaded
|
||||||
|
@ -344,12 +346,25 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
const UniformBufferView& getTexMapArrayBuffer() const { return _texMapArrayBuffer; }
|
const UniformBufferView& getTexMapArrayBuffer() const { return _texMapArrayBuffer; }
|
||||||
|
|
||||||
|
int getTextureCount() const { calculateMaterialInfo(); return _textureCount; }
|
||||||
|
size_t getTextureSize() const { calculateMaterialInfo(); return _textureSize; }
|
||||||
|
bool hasTextureInfo() const { return _hasCalculatedTextureInfo; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable MaterialKey _key;
|
mutable MaterialKey _key;
|
||||||
mutable UniformBufferView _schemaBuffer;
|
mutable UniformBufferView _schemaBuffer;
|
||||||
mutable UniformBufferView _texMapArrayBuffer;
|
mutable UniformBufferView _texMapArrayBuffer;
|
||||||
|
|
||||||
TextureMaps _textureMaps;
|
TextureMaps _textureMaps;
|
||||||
|
|
||||||
|
mutable QMutex _textureMapsMutex { QMutex::Recursive };
|
||||||
|
mutable size_t _textureSize { 0 };
|
||||||
|
mutable int _textureCount { 0 };
|
||||||
|
mutable bool _hasCalculatedTextureInfo { false };
|
||||||
|
bool calculateMaterialInfo() const;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
typedef std::shared_ptr< Material > MaterialPointer;
|
typedef std::shared_ptr< Material > MaterialPointer;
|
||||||
|
|
||||||
|
|
|
@ -71,39 +71,8 @@ void MeshPartPayload::updateTransform(const Transform& transform, const Transfor
|
||||||
|
|
||||||
void MeshPartPayload::updateMaterial(model::MaterialPointer drawMaterial) {
|
void MeshPartPayload::updateMaterial(model::MaterialPointer drawMaterial) {
|
||||||
_drawMaterial = drawMaterial;
|
_drawMaterial = drawMaterial;
|
||||||
calculateMaterialSize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MeshPartPayload::calculateMaterialSize() {
|
|
||||||
bool allTextures = true; // assume we got this...
|
|
||||||
_materialTextureSize = 0;
|
|
||||||
_materialTextureCount = 0;
|
|
||||||
auto textureMaps = _drawMaterial->getTextureMaps();
|
|
||||||
for (auto const &textureMapItem : textureMaps) {
|
|
||||||
auto textureMap = textureMapItem.second;
|
|
||||||
if (textureMap) {
|
|
||||||
auto textureSoure = textureMap->getTextureSource();
|
|
||||||
if (textureSoure) {
|
|
||||||
auto texture = textureSoure->getGPUTexture();
|
|
||||||
if (texture) {
|
|
||||||
//auto storedSize = texture->getStoredSize();
|
|
||||||
auto size = texture->getSize();
|
|
||||||
_materialTextureSize += size;
|
|
||||||
_materialTextureCount++;
|
|
||||||
} else {
|
|
||||||
allTextures = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
allTextures = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
allTextures = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return allTextures;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ItemKey MeshPartPayload::getKey() const {
|
ItemKey MeshPartPayload::getKey() const {
|
||||||
ItemKey::Builder builder;
|
ItemKey::Builder builder;
|
||||||
builder.withTypeShape();
|
builder.withTypeShape();
|
||||||
|
@ -378,7 +347,6 @@ void ModelMeshPartPayload::initCache() {
|
||||||
auto networkMaterial = _model->getGeometry()->getShapeMaterial(_shapeID);
|
auto networkMaterial = _model->getGeometry()->getShapeMaterial(_shapeID);
|
||||||
if (networkMaterial) {
|
if (networkMaterial) {
|
||||||
_drawMaterial = networkMaterial;
|
_drawMaterial = networkMaterial;
|
||||||
calculateMaterialSize();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,7 +397,12 @@ ItemKey ModelMeshPartPayload::getKey() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
ShapeKey ModelMeshPartPayload::getShapeKey() const {
|
ShapeKey ModelMeshPartPayload::getShapeKey() const {
|
||||||
assert(_model->isLoaded());
|
|
||||||
|
// guard against partially loaded meshes
|
||||||
|
if (!_model || !_model->isLoaded() || !_model->getGeometry()) {
|
||||||
|
return ShapeKey::Builder::invalid();
|
||||||
|
}
|
||||||
|
|
||||||
const FBXGeometry& geometry = _model->getFBXGeometry();
|
const FBXGeometry& geometry = _model->getFBXGeometry();
|
||||||
const auto& networkMeshes = _model->getGeometry()->getMeshes();
|
const auto& networkMeshes = _model->getGeometry()->getMeshes();
|
||||||
|
|
||||||
|
|
|
@ -66,13 +66,9 @@ public:
|
||||||
bool _hasColorAttrib = false;
|
bool _hasColorAttrib = false;
|
||||||
|
|
||||||
size_t getVerticesCount() const { return _drawMesh ? _drawMesh->getNumVertices() : 0; }
|
size_t getVerticesCount() const { return _drawMesh ? _drawMesh->getNumVertices() : 0; }
|
||||||
size_t getMaterialTextureSize() { return _materialTextureSize; }
|
size_t getMaterialTextureSize() { return _drawMaterial ? _drawMaterial->getTextureSize() : 0; }
|
||||||
int getMaterialTextureCount() { return _materialTextureCount; }
|
int getMaterialTextureCount() { return _drawMaterial ? _drawMaterial->getTextureCount() : 0; }
|
||||||
bool calculateMaterialSize();
|
bool hasTextureInfo() const { return _drawMaterial ? _drawMaterial->hasTextureInfo() : false; }
|
||||||
|
|
||||||
protected:
|
|
||||||
size_t _materialTextureSize { 0 };
|
|
||||||
int _materialTextureCount { 0 };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace render {
|
namespace render {
|
||||||
|
|
|
@ -168,10 +168,9 @@ void Model::calculateTextureInfo() {
|
||||||
bool allTexturesLoaded = true;
|
bool allTexturesLoaded = true;
|
||||||
foreach(auto renderItem, _modelMeshRenderItemsSet) {
|
foreach(auto renderItem, _modelMeshRenderItemsSet) {
|
||||||
auto meshPart = renderItem.get();
|
auto meshPart = renderItem.get();
|
||||||
bool allTexturesForThisMesh = meshPart->calculateMaterialSize();
|
|
||||||
allTexturesLoaded = allTexturesLoaded & allTexturesForThisMesh;
|
|
||||||
textureSize += meshPart->getMaterialTextureSize();
|
textureSize += meshPart->getMaterialTextureSize();
|
||||||
textureCount += meshPart->getMaterialTextureCount();
|
textureCount += meshPart->getMaterialTextureCount();
|
||||||
|
allTexturesLoaded = allTexturesLoaded & meshPart->hasTextureInfo();
|
||||||
}
|
}
|
||||||
_renderInfoTextureSize = textureSize;
|
_renderInfoTextureSize = textureSize;
|
||||||
_renderInfoTextureCount = textureCount;
|
_renderInfoTextureCount = textureCount;
|
||||||
|
|
|
@ -1017,9 +1017,12 @@ void ScriptEngine::updateMemoryCost(const qint64& deltaSize) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptEngine::timerFired() {
|
void ScriptEngine::timerFired() {
|
||||||
if (DependencyManager::get<ScriptEngines>()->isStopped()) {
|
{
|
||||||
qCDebug(scriptengine) << "Script.timerFired() while shutting down is ignored... parent script:" << getFilename();
|
auto engine = DependencyManager::get<ScriptEngines>();
|
||||||
return; // bail early
|
if (!engine || engine->isStopped()) {
|
||||||
|
qCDebug(scriptengine) << "Script.timerFired() while shutting down is ignored... parent script:" << getFilename();
|
||||||
|
return; // bail early
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QTimer* callingTimer = reinterpret_cast<QTimer*>(sender());
|
QTimer* callingTimer = reinterpret_cast<QTimer*>(sender());
|
||||||
|
|
|
@ -17,11 +17,9 @@
|
||||||
// keystroke:
|
// keystroke:
|
||||||
//
|
//
|
||||||
// CTRL/s for snapshot.
|
// CTRL/s for snapshot.
|
||||||
// CTRL/m for mic mute and unmute.
|
|
||||||
|
|
||||||
// System generated notifications:
|
// System generated notifications:
|
||||||
// If Screen is resized.
|
// Connection refused.
|
||||||
// If mic is muted for any reason.
|
|
||||||
//
|
//
|
||||||
// To add a new System notification type:
|
// To add a new System notification type:
|
||||||
//
|
//
|
||||||
|
@ -92,16 +90,12 @@ var lodTextID = false;
|
||||||
|
|
||||||
var NotificationType = {
|
var NotificationType = {
|
||||||
UNKNOWN: 0,
|
UNKNOWN: 0,
|
||||||
MUTE_TOGGLE: 1,
|
SNAPSHOT: 1,
|
||||||
SNAPSHOT: 2,
|
LOD_WARNING: 2,
|
||||||
WINDOW_RESIZE: 3,
|
CONNECTION_REFUSED: 3,
|
||||||
LOD_WARNING: 4,
|
EDIT_ERROR: 4,
|
||||||
CONNECTION_REFUSED: 5,
|
|
||||||
EDIT_ERROR: 6,
|
|
||||||
properties: [
|
properties: [
|
||||||
{ text: "Mute Toggle" },
|
|
||||||
{ text: "Snapshot" },
|
{ text: "Snapshot" },
|
||||||
{ text: "Window Resize" },
|
|
||||||
{ text: "Level of Detail" },
|
{ text: "Level of Detail" },
|
||||||
{ text: "Connection Refused" },
|
{ text: "Connection Refused" },
|
||||||
{ text: "Edit error" }
|
{ text: "Edit error" }
|
||||||
|
@ -446,19 +440,6 @@ function wordWrap(str) {
|
||||||
return stringDivider(str, 43.0, "\n");
|
return stringDivider(str, 43.0, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// This fires a notification on window resize
|
|
||||||
function checkSize() {
|
|
||||||
if ((Window.innerWidth !== ourWidth) || (Window.innerHeight !== ourHeight)) {
|
|
||||||
var windowResize = "Window has been resized";
|
|
||||||
ourWidth = Window.innerWidth;
|
|
||||||
ourHeight = Window.innerHeight;
|
|
||||||
windowDimensions = Controller.getViewportDimensions();
|
|
||||||
overlayLocationX = (windowDimensions.x - (width + 60.0));
|
|
||||||
buttonLocationX = overlayLocationX + (width - 35.0);
|
|
||||||
createNotification(windowResize, NotificationType.WINDOW_RESIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function update() {
|
function update() {
|
||||||
var nextOverlay,
|
var nextOverlay,
|
||||||
noticeOut,
|
noticeOut,
|
||||||
|
@ -480,7 +461,6 @@ function update() {
|
||||||
|
|
||||||
frame += 1;
|
frame += 1;
|
||||||
if ((frame % 60.0) === 0) { // only update once a second
|
if ((frame % 60.0) === 0) { // only update once a second
|
||||||
checkSize(); // checks for size change to trigger windowResize notification
|
|
||||||
locationY = 20.0;
|
locationY = 20.0;
|
||||||
for (i = 0; i < arrays.length; i += 1) { //repositions overlays as others fade
|
for (i = 0; i < arrays.length; i += 1) { //repositions overlays as others fade
|
||||||
nextOverlay = Overlays.getOverlayAtPoint({ x: overlayLocationX, y: locationY });
|
nextOverlay = Overlays.getOverlayAtPoint({ x: overlayLocationX, y: locationY });
|
||||||
|
@ -533,16 +513,6 @@ function isStartingUp() {
|
||||||
return startingUp;
|
return startingUp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Triggers mic mute notification
|
|
||||||
function onMuteStateChanged() {
|
|
||||||
var muteState,
|
|
||||||
muteString;
|
|
||||||
|
|
||||||
muteState = AudioDevice.getMuted() ? "muted" : "unmuted";
|
|
||||||
muteString = "Microphone is now " + muteState;
|
|
||||||
createNotification(muteString, NotificationType.MUTE_TOGGLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onDomainConnectionRefused(reason) {
|
function onDomainConnectionRefused(reason) {
|
||||||
createNotification("Connection refused: " + reason, NotificationType.CONNECTION_REFUSED);
|
createNotification("Connection refused: " + reason, NotificationType.CONNECTION_REFUSED);
|
||||||
}
|
}
|
||||||
|
@ -653,7 +623,6 @@ LODManager.LODDecreased.connect(function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AudioDevice.muteToggled.connect(onMuteStateChanged);
|
|
||||||
Controller.keyPressEvent.connect(keyPressEvent);
|
Controller.keyPressEvent.connect(keyPressEvent);
|
||||||
Controller.mousePressEvent.connect(mousePressEvent);
|
Controller.mousePressEvent.connect(mousePressEvent);
|
||||||
Controller.keyReleaseEvent.connect(keyReleaseEvent);
|
Controller.keyReleaseEvent.connect(keyReleaseEvent);
|
||||||
|
|
Loading…
Reference in a new issue