mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 08:17:35 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into workload
This commit is contained in:
commit
50bdd1ad2f
23 changed files with 1308 additions and 854 deletions
|
@ -42,7 +42,7 @@ AvatarMixer::AvatarMixer(ReceivedMessage& message) :
|
||||||
ThreadedAssignment(message)
|
ThreadedAssignment(message)
|
||||||
{
|
{
|
||||||
// make sure we hear about node kills so we can tell the other nodes
|
// make sure we hear about node kills so we can tell the other nodes
|
||||||
connect(DependencyManager::get<NodeList>().data(), &NodeList::nodeKilled, this, &AvatarMixer::nodeKilled);
|
connect(DependencyManager::get<NodeList>().data(), &NodeList::nodeKilled, this, &AvatarMixer::handleAvatarKilled);
|
||||||
|
|
||||||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||||
packetReceiver.registerListener(PacketType::AvatarData, this, "queueIncomingPacket");
|
packetReceiver.registerListener(PacketType::AvatarData, this, "queueIncomingPacket");
|
||||||
|
@ -423,14 +423,15 @@ void AvatarMixer::throttle(std::chrono::microseconds duration, int frame) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarMixer::nodeKilled(SharedNodePointer killedNode) {
|
|
||||||
if (killedNode->getType() == NodeType::Agent
|
void AvatarMixer::handleAvatarKilled(SharedNodePointer avatarNode) {
|
||||||
&& killedNode->getLinkedData()) {
|
if (avatarNode->getType() == NodeType::Agent
|
||||||
|
&& avatarNode->getLinkedData()) {
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
|
||||||
{ // decrement sessionDisplayNames table and possibly remove
|
{ // decrement sessionDisplayNames table and possibly remove
|
||||||
QMutexLocker nodeDataLocker(&killedNode->getLinkedData()->getMutex());
|
QMutexLocker nodeDataLocker(&avatarNode->getLinkedData()->getMutex());
|
||||||
AvatarMixerClientData* nodeData = dynamic_cast<AvatarMixerClientData*>(killedNode->getLinkedData());
|
AvatarMixerClientData* nodeData = dynamic_cast<AvatarMixerClientData*>(avatarNode->getLinkedData());
|
||||||
const QString& baseDisplayName = nodeData->getBaseDisplayName();
|
const QString& baseDisplayName = nodeData->getBaseDisplayName();
|
||||||
// No sense guarding against very rare case of a node with no entry, as this will work without the guard and do one less lookup in the common case.
|
// No sense guarding against very rare case of a node with no entry, as this will work without the guard and do one less lookup in the common case.
|
||||||
if (--_sessionDisplayNames[baseDisplayName].second <= 0) {
|
if (--_sessionDisplayNames[baseDisplayName].second <= 0) {
|
||||||
|
@ -447,12 +448,12 @@ void AvatarMixer::nodeKilled(SharedNodePointer killedNode) {
|
||||||
// we relay avatar kill packets to agents that are not upstream
|
// we relay avatar kill packets to agents that are not upstream
|
||||||
// and downstream avatar mixers, if the node that was just killed was being replicated
|
// and downstream avatar mixers, if the node that was just killed was being replicated
|
||||||
return (node->getType() == NodeType::Agent && !node->isUpstream()) ||
|
return (node->getType() == NodeType::Agent && !node->isUpstream()) ||
|
||||||
(killedNode->isReplicated() && shouldReplicateTo(*killedNode, *node));
|
(avatarNode->isReplicated() && shouldReplicateTo(*avatarNode, *node));
|
||||||
}, [&](const SharedNodePointer& node) {
|
}, [&](const SharedNodePointer& node) {
|
||||||
if (node->getType() == NodeType::Agent) {
|
if (node->getType() == NodeType::Agent) {
|
||||||
if (!killPacket) {
|
if (!killPacket) {
|
||||||
killPacket = NLPacket::create(PacketType::KillAvatar, NUM_BYTES_RFC4122_UUID + sizeof(KillAvatarReason));
|
killPacket = NLPacket::create(PacketType::KillAvatar, NUM_BYTES_RFC4122_UUID + sizeof(KillAvatarReason));
|
||||||
killPacket->write(killedNode->getUUID().toRfc4122());
|
killPacket->write(avatarNode->getUUID().toRfc4122());
|
||||||
killPacket->writePrimitive(KillAvatarReason::AvatarDisconnected);
|
killPacket->writePrimitive(KillAvatarReason::AvatarDisconnected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,7 +463,7 @@ void AvatarMixer::nodeKilled(SharedNodePointer killedNode) {
|
||||||
if (!replicatedKillPacket) {
|
if (!replicatedKillPacket) {
|
||||||
replicatedKillPacket = NLPacket::create(PacketType::ReplicatedKillAvatar,
|
replicatedKillPacket = NLPacket::create(PacketType::ReplicatedKillAvatar,
|
||||||
NUM_BYTES_RFC4122_UUID + sizeof(KillAvatarReason));
|
NUM_BYTES_RFC4122_UUID + sizeof(KillAvatarReason));
|
||||||
replicatedKillPacket->write(killedNode->getUUID().toRfc4122());
|
replicatedKillPacket->write(avatarNode->getUUID().toRfc4122());
|
||||||
replicatedKillPacket->writePrimitive(KillAvatarReason::AvatarDisconnected);
|
replicatedKillPacket->writePrimitive(KillAvatarReason::AvatarDisconnected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,7 +480,7 @@ void AvatarMixer::nodeKilled(SharedNodePointer killedNode) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->getUUID() == killedNode->getUUID()) {
|
if (node->getUUID() == avatarNode->getUUID()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,7 +490,7 @@ void AvatarMixer::nodeKilled(SharedNodePointer killedNode) {
|
||||||
QMetaObject::invokeMethod(node->getLinkedData(),
|
QMetaObject::invokeMethod(node->getLinkedData(),
|
||||||
"cleanupKilledNode",
|
"cleanupKilledNode",
|
||||||
Qt::AutoConnection,
|
Qt::AutoConnection,
|
||||||
Q_ARG(const QUuid&, QUuid(killedNode->getUUID())));
|
Q_ARG(const QUuid&, QUuid(avatarNode->getUUID())));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -605,7 +606,9 @@ void AvatarMixer::handleAvatarIdentityPacket(QSharedPointer<ReceivedMessage> mes
|
||||||
|
|
||||||
void AvatarMixer::handleKillAvatarPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer node) {
|
void AvatarMixer::handleKillAvatarPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer node) {
|
||||||
auto start = usecTimestampNow();
|
auto start = usecTimestampNow();
|
||||||
DependencyManager::get<NodeList>()->processKillNode(*message);
|
handleAvatarKilled(node);
|
||||||
|
|
||||||
|
node->setLinkedData(nullptr);
|
||||||
auto end = usecTimestampNow();
|
auto end = usecTimestampNow();
|
||||||
_handleKillAvatarPacketElapsedTime += (end - start);
|
_handleKillAvatarPacketElapsedTime += (end - start);
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ public slots:
|
||||||
/// runs the avatar mixer
|
/// runs the avatar mixer
|
||||||
void run() override;
|
void run() override;
|
||||||
|
|
||||||
void nodeKilled(SharedNodePointer killedNode);
|
void handleAvatarKilled(SharedNodePointer killedNode);
|
||||||
|
|
||||||
void sendStatsPacket() override;
|
void sendStatsPacket() override;
|
||||||
|
|
||||||
|
|
|
@ -442,12 +442,16 @@ bool EntityTreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstream
|
||||||
PrioritizedEntity queuedItem = _sendQueue.top();
|
PrioritizedEntity queuedItem = _sendQueue.top();
|
||||||
EntityItemPointer entity = queuedItem.getEntity();
|
EntityItemPointer entity = queuedItem.getEntity();
|
||||||
if (entity) {
|
if (entity) {
|
||||||
// Only send entities that match the jsonFilters, but keep track of everything we've tried to send so we don't try to send it again
|
const QUuid& entityID = entity->getID();
|
||||||
|
// Only send entities that match the jsonFilters, but keep track of everything we've tried to send so we don't try to send it again;
|
||||||
|
// also send if we previously matched since this represents change to a matched item.
|
||||||
bool entityMatchesFilters = entity->matchesJSONFilters(jsonFilters);
|
bool entityMatchesFilters = entity->matchesJSONFilters(jsonFilters);
|
||||||
if (entityMatchesFilters || entityNodeData->isEntityFlaggedAsExtra(entity->getID())) {
|
bool entityPreviouslyMatchedFilter = entityNodeData->sentFilteredEntity(entityID);
|
||||||
|
|
||||||
|
if (entityMatchesFilters || entityNodeData->isEntityFlaggedAsExtra(entityID) || entityPreviouslyMatchedFilter) {
|
||||||
if (!jsonFilters.isEmpty() && entityMatchesFilters) {
|
if (!jsonFilters.isEmpty() && entityMatchesFilters) {
|
||||||
// Record explicitly filtered-in entity so that extra entities can be flagged.
|
// Record explicitly filtered-in entity so that extra entities can be flagged.
|
||||||
entityNodeData->insertSentFilteredEntity(entity->getID());
|
entityNodeData->insertSentFilteredEntity(entityID);
|
||||||
}
|
}
|
||||||
OctreeElement::AppendState appendEntityState = entity->appendEntityData(&_packetData, params, _extraEncodeData);
|
OctreeElement::AppendState appendEntityState = entity->appendEntityData(&_packetData, params, _extraEncodeData);
|
||||||
|
|
||||||
|
@ -458,6 +462,10 @@ bool EntityTreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstream
|
||||||
params.stopReason = EncodeBitstreamParams::DIDNT_FIT;
|
params.stopReason = EncodeBitstreamParams::DIDNT_FIT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (entityPreviouslyMatchedFilter && !entityMatchesFilters) {
|
||||||
|
entityNodeData->removeSentFilteredEntity(entityID);
|
||||||
|
}
|
||||||
++_numEntities;
|
++_numEntities;
|
||||||
}
|
}
|
||||||
if (queuedItem.shouldForceRemove()) {
|
if (queuedItem.shouldForceRemove()) {
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -46,6 +46,19 @@ static int YOUTUBE_MAX_FPS = 30;
|
||||||
|
|
||||||
static QTouchDevice _touchDevice;
|
static QTouchDevice _touchDevice;
|
||||||
|
|
||||||
|
WebEntityRenderer::ContentType WebEntityRenderer::getContentType(const QString& urlString) {
|
||||||
|
if (urlString.isEmpty()) {
|
||||||
|
return ContentType::NoContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QUrl url(urlString);
|
||||||
|
if (url.scheme() == "http" || url.scheme() == "https" ||
|
||||||
|
urlString.toLower().endsWith(".htm") || urlString.toLower().endsWith(".html")) {
|
||||||
|
return ContentType::HtmlContent;
|
||||||
|
}
|
||||||
|
return ContentType::QmlContent;
|
||||||
|
}
|
||||||
|
|
||||||
WebEntityRenderer::WebEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {
|
WebEntityRenderer::WebEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {
|
||||||
static std::once_flag once;
|
static std::once_flag once;
|
||||||
std::call_once(once, [&]{
|
std::call_once(once, [&]{
|
||||||
|
@ -123,13 +136,45 @@ void WebEntityRenderer::onTimeout() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||||
|
// If the content type has changed, or the old content type was QML, we need to
|
||||||
|
// destroy the existing surface (because surfaces don't support changing the root
|
||||||
|
// object, so subsequent loads of content just overlap the existing content
|
||||||
|
bool urlChanged = false;
|
||||||
|
{
|
||||||
|
auto newSourceUrl = entity->getSourceUrl();
|
||||||
|
auto newContentType = getContentType(newSourceUrl);
|
||||||
|
auto currentContentType = ContentType::NoContent;
|
||||||
|
withReadLock([&] {
|
||||||
|
urlChanged = _lastSourceUrl != newSourceUrl;
|
||||||
|
currentContentType = _contentType;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (urlChanged) {
|
||||||
|
if (newContentType != ContentType::HtmlContent || currentContentType != ContentType::HtmlContent) {
|
||||||
|
destroyWebSurface();
|
||||||
|
}
|
||||||
|
|
||||||
withWriteLock([&] {
|
withWriteLock([&] {
|
||||||
// This work must be done on the main thread
|
_lastSourceUrl = newSourceUrl;
|
||||||
if (!hasWebSurface()) {
|
_contentType = newContentType;
|
||||||
// If we couldn't create a new web surface, exit
|
});
|
||||||
if (!buildWebSurface(entity)) {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
withWriteLock([&] {
|
||||||
|
if (_contentType == ContentType::NoContent) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This work must be done on the main thread
|
||||||
|
// If we couldn't create a new web surface, exit
|
||||||
|
if (!hasWebSurface() && !buildWebSurface(entity)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (urlChanged) {
|
||||||
|
_webSurface->getRootItem()->setProperty("url", _lastSourceUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_contextPosition != entity->getWorldPosition()) {
|
if (_contextPosition != entity->getWorldPosition()) {
|
||||||
|
@ -138,11 +183,6 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene
|
||||||
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(_contextPosition));
|
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(_contextPosition));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_lastSourceUrl != entity->getSourceUrl()) {
|
|
||||||
_lastSourceUrl = entity->getSourceUrl();
|
|
||||||
loadSourceURL();
|
|
||||||
}
|
|
||||||
|
|
||||||
_lastDPI = entity->getDPI();
|
_lastDPI = entity->getDPI();
|
||||||
_lastLocked = entity->getLocked();
|
_lastLocked = entity->getLocked();
|
||||||
|
|
||||||
|
@ -232,9 +272,6 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
|
||||||
// Let us interact with the keyboard
|
// Let us interact with the keyboard
|
||||||
surfaceContext->setContextProperty("tabletInterface", DependencyManager::get<TabletScriptingInterface>().data());
|
surfaceContext->setContextProperty("tabletInterface", DependencyManager::get<TabletScriptingInterface>().data());
|
||||||
});
|
});
|
||||||
_fadeStartTime = usecTimestampNow();
|
|
||||||
loadSourceURL();
|
|
||||||
_webSurface->resume();
|
|
||||||
|
|
||||||
// forward web events to EntityScriptingInterface
|
// forward web events to EntityScriptingInterface
|
||||||
auto entities = DependencyManager::get<EntityScriptingInterface>();
|
auto entities = DependencyManager::get<EntityScriptingInterface>();
|
||||||
|
@ -243,6 +280,29 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
|
||||||
emit entities->webEventReceived(entityItemID, message);
|
emit entities->webEventReceived(entityItemID, message);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (_contentType == ContentType::HtmlContent) {
|
||||||
|
// We special case YouTube URLs since we know they are videos that we should play with at least 30 FPS.
|
||||||
|
// FIXME this doesn't handle redirects or shortened URLs, consider using a signaling method from the
|
||||||
|
// web entity
|
||||||
|
if (QUrl(_lastSourceUrl).host().endsWith("youtube.com", Qt::CaseInsensitive)) {
|
||||||
|
_webSurface->setMaxFps(YOUTUBE_MAX_FPS);
|
||||||
|
} else {
|
||||||
|
_webSurface->setMaxFps(DEFAULT_MAX_FPS);
|
||||||
|
}
|
||||||
|
_webSurface->load("controls/WebEntityView.qml", [this](QQmlContext* context, QObject* item) {
|
||||||
|
item->setProperty("url", _lastSourceUrl);
|
||||||
|
});
|
||||||
|
} else if (_contentType == ContentType::QmlContent) {
|
||||||
|
_webSurface->load(_lastSourceUrl, [this](QQmlContext* context, QObject* item) {
|
||||||
|
if (item && item->objectName() == "tabletRoot") {
|
||||||
|
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||||
|
tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface.data());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_fadeStartTime = usecTimestampNow();
|
||||||
|
_webSurface->resume();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,32 +349,6 @@ glm::vec2 WebEntityRenderer::getWindowSize(const TypedEntityPointer& entity) con
|
||||||
return dims;
|
return dims;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebEntityRenderer::loadSourceURL() {
|
|
||||||
const QUrl sourceUrl(_lastSourceUrl);
|
|
||||||
if (sourceUrl.scheme() == "http" || sourceUrl.scheme() == "https" ||
|
|
||||||
_lastSourceUrl.toLower().endsWith(".htm") || _lastSourceUrl.toLower().endsWith(".html")) {
|
|
||||||
_contentType = htmlContent;
|
|
||||||
|
|
||||||
// We special case YouTube URLs since we know they are videos that we should play with at least 30 FPS.
|
|
||||||
if (sourceUrl.host().endsWith("youtube.com", Qt::CaseInsensitive)) {
|
|
||||||
_webSurface->setMaxFps(YOUTUBE_MAX_FPS);
|
|
||||||
} else {
|
|
||||||
_webSurface->setMaxFps(DEFAULT_MAX_FPS);
|
|
||||||
}
|
|
||||||
|
|
||||||
_webSurface->load("controls/WebEntityView.qml", [this](QQmlContext* context, QObject* item) {
|
|
||||||
item->setProperty("url", _lastSourceUrl);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
_contentType = qmlContent;
|
|
||||||
_webSurface->load(_lastSourceUrl);
|
|
||||||
if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tabletRoot") {
|
|
||||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
|
||||||
tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface.data());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebEntityRenderer::hoverEnterEntity(const PointerEvent& event) {
|
void WebEntityRenderer::hoverEnterEntity(const PointerEvent& event) {
|
||||||
if (!_lastLocked && _webSurface) {
|
if (!_lastLocked && _webSurface) {
|
||||||
PointerEvent webEvent = event;
|
PointerEvent webEvent = event;
|
||||||
|
|
|
@ -47,15 +47,19 @@ private:
|
||||||
bool buildWebSurface(const TypedEntityPointer& entity);
|
bool buildWebSurface(const TypedEntityPointer& entity);
|
||||||
void destroyWebSurface();
|
void destroyWebSurface();
|
||||||
bool hasWebSurface();
|
bool hasWebSurface();
|
||||||
void loadSourceURL();
|
|
||||||
glm::vec2 getWindowSize(const TypedEntityPointer& entity) const;
|
glm::vec2 getWindowSize(const TypedEntityPointer& entity) const;
|
||||||
|
|
||||||
|
|
||||||
int _geometryId{ 0 };
|
int _geometryId{ 0 };
|
||||||
enum contentType {
|
enum class ContentType {
|
||||||
htmlContent,
|
NoContent,
|
||||||
qmlContent
|
HtmlContent,
|
||||||
|
QmlContent
|
||||||
};
|
};
|
||||||
contentType _contentType;
|
|
||||||
|
static ContentType getContentType(const QString& urlString);
|
||||||
|
|
||||||
|
ContentType _contentType{ ContentType::NoContent };
|
||||||
QSharedPointer<OffscreenQmlSurface> _webSurface;
|
QSharedPointer<OffscreenQmlSurface> _webSurface;
|
||||||
glm::vec3 _contextPosition;
|
glm::vec3 _contextPosition;
|
||||||
gpu::TexturePointer _texture;
|
gpu::TexturePointer _texture;
|
||||||
|
|
|
@ -33,7 +33,7 @@ public:
|
||||||
// these can only be called from the OctreeSendThread for the given Node
|
// these can only be called from the OctreeSendThread for the given Node
|
||||||
void insertSentFilteredEntity(const QUuid& entityID) { _sentFilteredEntities.insert(entityID); }
|
void insertSentFilteredEntity(const QUuid& entityID) { _sentFilteredEntities.insert(entityID); }
|
||||||
void removeSentFilteredEntity(const QUuid& entityID) { _sentFilteredEntities.remove(entityID); }
|
void removeSentFilteredEntity(const QUuid& entityID) { _sentFilteredEntities.remove(entityID); }
|
||||||
bool sentFilteredEntity(const QUuid& entityID) { return _sentFilteredEntities.contains(entityID); }
|
bool sentFilteredEntity(const QUuid& entityID) const { return _sentFilteredEntities.contains(entityID); }
|
||||||
QSet<QUuid> getSentFilteredEntities() { return _sentFilteredEntities; }
|
QSet<QUuid> getSentFilteredEntities() { return _sentFilteredEntities; }
|
||||||
|
|
||||||
// the following flagged extra entity methods can only be called from the OctreeSendThread for the given Node
|
// the following flagged extra entity methods can only be called from the OctreeSendThread for the given Node
|
||||||
|
|
|
@ -93,12 +93,16 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
|
||||||
(&::gpu::gl::GLBackend::do_setUniformBuffer),
|
(&::gpu::gl::GLBackend::do_setUniformBuffer),
|
||||||
(&::gpu::gl::GLBackend::do_setResourceBuffer),
|
(&::gpu::gl::GLBackend::do_setResourceBuffer),
|
||||||
(&::gpu::gl::GLBackend::do_setResourceTexture),
|
(&::gpu::gl::GLBackend::do_setResourceTexture),
|
||||||
|
(&::gpu::gl::GLBackend::do_setResourceFramebufferSwapChainTexture),
|
||||||
|
|
||||||
(&::gpu::gl::GLBackend::do_setFramebuffer),
|
(&::gpu::gl::GLBackend::do_setFramebuffer),
|
||||||
|
(&::gpu::gl::GLBackend::do_setFramebufferSwapChain),
|
||||||
(&::gpu::gl::GLBackend::do_clearFramebuffer),
|
(&::gpu::gl::GLBackend::do_clearFramebuffer),
|
||||||
(&::gpu::gl::GLBackend::do_blit),
|
(&::gpu::gl::GLBackend::do_blit),
|
||||||
(&::gpu::gl::GLBackend::do_generateTextureMips),
|
(&::gpu::gl::GLBackend::do_generateTextureMips),
|
||||||
|
|
||||||
|
(&::gpu::gl::GLBackend::do_advance),
|
||||||
|
|
||||||
(&::gpu::gl::GLBackend::do_beginQuery),
|
(&::gpu::gl::GLBackend::do_beginQuery),
|
||||||
(&::gpu::gl::GLBackend::do_endQuery),
|
(&::gpu::gl::GLBackend::do_endQuery),
|
||||||
(&::gpu::gl::GLBackend::do_getQuery),
|
(&::gpu::gl::GLBackend::do_getQuery),
|
||||||
|
|
|
@ -123,15 +123,19 @@ public:
|
||||||
// Resource Stage
|
// Resource Stage
|
||||||
virtual void do_setResourceBuffer(const Batch& batch, size_t paramOffset) final;
|
virtual void do_setResourceBuffer(const Batch& batch, size_t paramOffset) final;
|
||||||
virtual void do_setResourceTexture(const Batch& batch, size_t paramOffset) final;
|
virtual void do_setResourceTexture(const Batch& batch, size_t paramOffset) final;
|
||||||
|
virtual void do_setResourceFramebufferSwapChainTexture(const Batch& batch, size_t paramOffset) final;
|
||||||
|
|
||||||
// Pipeline Stage
|
// Pipeline Stage
|
||||||
virtual void do_setPipeline(const Batch& batch, size_t paramOffset) final;
|
virtual void do_setPipeline(const Batch& batch, size_t paramOffset) final;
|
||||||
|
|
||||||
// Output stage
|
// Output stage
|
||||||
virtual void do_setFramebuffer(const Batch& batch, size_t paramOffset) final;
|
virtual void do_setFramebuffer(const Batch& batch, size_t paramOffset) final;
|
||||||
|
virtual void do_setFramebufferSwapChain(const Batch& batch, size_t paramOffset) final;
|
||||||
virtual void do_clearFramebuffer(const Batch& batch, size_t paramOffset) final;
|
virtual void do_clearFramebuffer(const Batch& batch, size_t paramOffset) final;
|
||||||
virtual void do_blit(const Batch& batch, size_t paramOffset) = 0;
|
virtual void do_blit(const Batch& batch, size_t paramOffset) = 0;
|
||||||
|
|
||||||
|
virtual void do_advance(const Batch& batch, size_t paramOffset) final;
|
||||||
|
|
||||||
// Query section
|
// Query section
|
||||||
virtual void do_beginQuery(const Batch& batch, size_t paramOffset) final;
|
virtual void do_beginQuery(const Batch& batch, size_t paramOffset) final;
|
||||||
virtual void do_endQuery(const Batch& batch, size_t paramOffset) final;
|
virtual void do_endQuery(const Batch& batch, size_t paramOffset) final;
|
||||||
|
@ -242,6 +246,8 @@ protected:
|
||||||
void setupStereoSide(int side);
|
void setupStereoSide(int side);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
virtual void setResourceTexture(unsigned int slot, const TexturePointer& resourceTexture);
|
||||||
|
virtual void setFramebuffer(const FramebufferPointer& framebuffer);
|
||||||
virtual void initInput() final;
|
virtual void initInput() final;
|
||||||
virtual void killInput() final;
|
virtual void killInput() final;
|
||||||
virtual void syncInputStateCache() final;
|
virtual void syncInputStateCache() final;
|
||||||
|
|
|
@ -37,6 +37,19 @@ void GLBackend::resetOutputStage() {
|
||||||
|
|
||||||
void GLBackend::do_setFramebuffer(const Batch& batch, size_t paramOffset) {
|
void GLBackend::do_setFramebuffer(const Batch& batch, size_t paramOffset) {
|
||||||
auto framebuffer = batch._framebuffers.get(batch._params[paramOffset]._uint);
|
auto framebuffer = batch._framebuffers.get(batch._params[paramOffset]._uint);
|
||||||
|
setFramebuffer(framebuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::do_setFramebufferSwapChain(const Batch& batch, size_t paramOffset) {
|
||||||
|
auto swapChain = batch._swapChains.get(batch._params[paramOffset]._uint);
|
||||||
|
if (swapChain) {
|
||||||
|
auto index = batch._params[paramOffset + 1]._uint;
|
||||||
|
FramebufferPointer framebuffer = static_cast<const FramebufferSwapChain*>(swapChain.get())->get(index);
|
||||||
|
setFramebuffer(framebuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::setFramebuffer(const FramebufferPointer& framebuffer) {
|
||||||
if (_output._framebuffer != framebuffer) {
|
if (_output._framebuffer != framebuffer) {
|
||||||
auto newFBO = getFramebufferID(framebuffer);
|
auto newFBO = getFramebufferID(framebuffer);
|
||||||
if (_output._drawFBO != newFBO) {
|
if (_output._drawFBO != newFBO) {
|
||||||
|
@ -47,6 +60,13 @@ void GLBackend::do_setFramebuffer(const Batch& batch, size_t paramOffset) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLBackend::do_advance(const Batch& batch, size_t paramOffset) {
|
||||||
|
auto ringbuffer = batch._swapChains.get(batch._params[paramOffset]._uint);
|
||||||
|
if (ringbuffer) {
|
||||||
|
ringbuffer->advance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GLBackend::do_clearFramebuffer(const Batch& batch, size_t paramOffset) {
|
void GLBackend::do_clearFramebuffer(const Batch& batch, size_t paramOffset) {
|
||||||
if (_stereo.isStereo() && !_pipeline._stateCache.scissorEnable) {
|
if (_stereo.isStereo() && !_pipeline._stateCache.scissorEnable) {
|
||||||
qWarning("Clear without scissor in stereo mode");
|
qWarning("Clear without scissor in stereo mode");
|
||||||
|
|
|
@ -251,6 +251,31 @@ void GLBackend::do_setResourceTexture(const Batch& batch, size_t paramOffset) {
|
||||||
releaseResourceTexture(slot);
|
releaseResourceTexture(slot);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
setResourceTexture(slot, resourceTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::do_setResourceFramebufferSwapChainTexture(const Batch& batch, size_t paramOffset) {
|
||||||
|
GLuint slot = batch._params[paramOffset + 1]._uint;
|
||||||
|
if (slot >= (GLuint)MAX_NUM_RESOURCE_TEXTURES) {
|
||||||
|
qCDebug(gpugllogging) << "GLBackend::do_setResourceFramebufferSwapChainTexture: Trying to set a resource Texture at slot #" << slot << " which doesn't exist. MaxNumResourceTextures = " << getMaxNumResourceTextures();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SwapChainPointer swapChain = batch._swapChains.get(batch._params[paramOffset + 0]._uint);
|
||||||
|
|
||||||
|
if (!swapChain) {
|
||||||
|
releaseResourceTexture(slot);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto index = batch._params[paramOffset + 2]._uint;
|
||||||
|
auto renderBufferSlot = batch._params[paramOffset + 3]._uint;
|
||||||
|
FramebufferPointer resourceFramebuffer = static_cast<const FramebufferSwapChain*>(swapChain.get())->get(index);
|
||||||
|
TexturePointer resourceTexture = resourceFramebuffer->getRenderBuffer(renderBufferSlot);
|
||||||
|
|
||||||
|
setResourceTexture(slot, resourceTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::setResourceTexture(unsigned int slot, const TexturePointer& resourceTexture) {
|
||||||
// check cache before thinking
|
// check cache before thinking
|
||||||
if (_resource._textures[slot] == resourceTexture) {
|
if (_resource._textures[slot] == resourceTexture) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -105,7 +105,7 @@ void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const Stereo
|
||||||
if (_viewIsCamera && (_viewCorrectionEnabled && _correction.correction != glm::mat4())) {
|
if (_viewIsCamera && (_viewCorrectionEnabled && _correction.correction != glm::mat4())) {
|
||||||
// FIXME should I switch to using the camera correction buffer in Transform.slf and leave this out?
|
// FIXME should I switch to using the camera correction buffer in Transform.slf and leave this out?
|
||||||
Transform result;
|
Transform result;
|
||||||
_view.mult(result, _view, _correction.correction);
|
_view.mult(result, _view, _correction.correctionInverse);
|
||||||
if (_skybox) {
|
if (_skybox) {
|
||||||
result.setTranslation(vec3());
|
result.setTranslation(vec3());
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,8 +173,48 @@ GLenum GLTexelFormat::evalGLTexelFormatInternal(const gpu::Element& dstFormat) {
|
||||||
case gpu::RGB:
|
case gpu::RGB:
|
||||||
case gpu::RGBA:
|
case gpu::RGBA:
|
||||||
case gpu::XY:
|
case gpu::XY:
|
||||||
|
switch (dstFormat.getType()) {
|
||||||
|
case gpu::UINT32:
|
||||||
|
result = GL_RG32UI;
|
||||||
|
break;
|
||||||
|
case gpu::INT32:
|
||||||
|
result = GL_RG32I;
|
||||||
|
break;
|
||||||
|
case gpu::FLOAT:
|
||||||
|
result = GL_RG32F;
|
||||||
|
break;
|
||||||
|
case gpu::UINT16:
|
||||||
|
result = GL_RG16UI;
|
||||||
|
break;
|
||||||
|
case gpu::INT16:
|
||||||
|
result = GL_RG16I;
|
||||||
|
break;
|
||||||
|
case gpu::HALF:
|
||||||
|
result = GL_RG16F;
|
||||||
|
break;
|
||||||
|
case gpu::UINT8:
|
||||||
|
result = GL_RG8UI;
|
||||||
|
break;
|
||||||
|
case gpu::INT8:
|
||||||
|
result = GL_RG8I;
|
||||||
|
break;
|
||||||
|
case gpu::NUINT8:
|
||||||
result = GL_RG8;
|
result = GL_RG8;
|
||||||
break;
|
break;
|
||||||
|
case gpu::NINT8:
|
||||||
|
result = GL_RG8_SNORM;
|
||||||
|
break;
|
||||||
|
case gpu::NUINT32:
|
||||||
|
case gpu::NINT32:
|
||||||
|
case gpu::NUINT2:
|
||||||
|
case gpu::NINT2_10_10_10:
|
||||||
|
case gpu::COMPRESSED:
|
||||||
|
case gpu::NUINT16:
|
||||||
|
case gpu::NINT16:
|
||||||
|
case gpu::NUM_TYPES: // quiet compiler
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
qCWarning(gpugllogging) << "Unknown combination of texel format";
|
qCWarning(gpugllogging) << "Unknown combination of texel format";
|
||||||
}
|
}
|
||||||
|
@ -312,8 +352,49 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E
|
||||||
case gpu::RGB:
|
case gpu::RGB:
|
||||||
case gpu::RGBA:
|
case gpu::RGBA:
|
||||||
case gpu::XY:
|
case gpu::XY:
|
||||||
|
switch (dstFormat.getType()) {
|
||||||
|
case gpu::UINT32:
|
||||||
|
texel.internalFormat = GL_RG32UI;
|
||||||
|
break;
|
||||||
|
case gpu::INT32:
|
||||||
|
texel.internalFormat = GL_RG32I;
|
||||||
|
break;
|
||||||
|
case gpu::FLOAT:
|
||||||
|
texel.internalFormat = GL_RG32F;
|
||||||
|
break;
|
||||||
|
case gpu::UINT16:
|
||||||
|
texel.internalFormat = GL_RG16UI;
|
||||||
|
break;
|
||||||
|
case gpu::INT16:
|
||||||
|
texel.internalFormat = GL_RG16I;
|
||||||
|
break;
|
||||||
|
case gpu::HALF:
|
||||||
|
texel.type = GL_FLOAT;
|
||||||
|
texel.internalFormat = GL_RG16F;
|
||||||
|
break;
|
||||||
|
case gpu::UINT8:
|
||||||
|
texel.internalFormat = GL_RG8UI;
|
||||||
|
break;
|
||||||
|
case gpu::INT8:
|
||||||
|
texel.internalFormat = GL_RG8I;
|
||||||
|
break;
|
||||||
|
case gpu::NUINT8:
|
||||||
texel.internalFormat = GL_RG8;
|
texel.internalFormat = GL_RG8;
|
||||||
break;
|
break;
|
||||||
|
case gpu::NINT8:
|
||||||
|
texel.internalFormat = GL_RG8_SNORM;
|
||||||
|
break;
|
||||||
|
case gpu::NUINT32:
|
||||||
|
case gpu::NINT32:
|
||||||
|
case gpu::NUINT2:
|
||||||
|
case gpu::NINT2_10_10_10:
|
||||||
|
case gpu::COMPRESSED:
|
||||||
|
case gpu::NUINT16:
|
||||||
|
case gpu::NINT16:
|
||||||
|
case gpu::NUM_TYPES: // quiet compiler
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
qCWarning(gpugllogging) << "Unknown combination of texel format";
|
qCWarning(gpugllogging) << "Unknown combination of texel format";
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ public:
|
||||||
size_t getNumIndices() const { return _indexBuffer.getNumElements(); }
|
size_t getNumIndices() const { return _indexBuffer.getNumElements(); }
|
||||||
|
|
||||||
// Access vertex position value
|
// Access vertex position value
|
||||||
const Vec3& getPos3(Index index) const { return _vertexBuffer.get<Vec3>(index); }
|
const Vec3& getPos(Index index) const { return _vertexBuffer.get<Vec3>(index); }
|
||||||
|
|
||||||
enum Topology {
|
enum Topology {
|
||||||
POINTS = 0,
|
POINTS = 0,
|
||||||
|
|
|
@ -21,7 +21,7 @@ int SimpleMeshProxy::getNumVertices() const {
|
||||||
return (int)_mesh->getNumVertices();
|
return (int)_mesh->getNumVertices();
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 SimpleMeshProxy::getPos3(int index) const {
|
glm::vec3 SimpleMeshProxy::getPos(int index) const {
|
||||||
return _mesh->getPos3(index);
|
return _mesh->getPos(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,8 @@ public:
|
||||||
|
|
||||||
int getNumVertices() const override;
|
int getNumVertices() const override;
|
||||||
|
|
||||||
glm::vec3 getPos3(int index) const override;
|
glm::vec3 getPos(int index) const override;
|
||||||
|
glm::vec3 getPos3(int index) const override { return getPos(index); } // deprecated
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const MeshPointer _mesh;
|
const MeshPointer _mesh;
|
||||||
|
|
|
@ -576,7 +576,7 @@ void Connection::processControl(ControlPacketPointer controlPacket) {
|
||||||
// where the other end expired our connection. Let's reset.
|
// where the other end expired our connection. Let's reset.
|
||||||
|
|
||||||
#ifdef UDT_CONNECTION_DEBUG
|
#ifdef UDT_CONNECTION_DEBUG
|
||||||
qCDebug(networking) << "Got handshake request, stopping SendQueue";
|
qCDebug(networking) << "Got HandshakeRequest from" << _destination << ", stopping SendQueue";
|
||||||
#endif
|
#endif
|
||||||
_hasReceivedHandshakeACK = false;
|
_hasReceivedHandshakeACK = false;
|
||||||
stopSendQueue();
|
stopSendQueue();
|
||||||
|
|
|
@ -402,6 +402,10 @@ void Socket::readPendingDatagrams() {
|
||||||
packet->getDataSize(),
|
packet->getDataSize(),
|
||||||
packet->getPayloadSize())) {
|
packet->getPayloadSize())) {
|
||||||
// the connection could not be created or indicated that we should not continue processing this packet
|
// the connection could not be created or indicated that we should not continue processing this packet
|
||||||
|
#ifdef UDT_CONNECTION_DEBUG
|
||||||
|
qCDebug(networking) << "Can't process packet: version" << (unsigned int)NLPacket::versionInHeader(*packet)
|
||||||
|
<< ", type" << NLPacket::typeInHeader(*packet);
|
||||||
|
#endif
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,12 +188,14 @@ bool OffscreenSurface::eventFilter(QObject* originalDestination, QEvent* event)
|
||||||
event->ignore();
|
event->ignore();
|
||||||
if (QCoreApplication::sendEvent(window->activeFocusItem(), event)) {
|
if (QCoreApplication::sendEvent(window->activeFocusItem(), event)) {
|
||||||
bool eventAccepted = event->isAccepted();
|
bool eventAccepted = event->isAccepted();
|
||||||
|
if (event->type() == QEvent::InputMethodQuery) {
|
||||||
QInputMethodQueryEvent *imqEvent = static_cast<QInputMethodQueryEvent *>(event);
|
QInputMethodQueryEvent *imqEvent = static_cast<QInputMethodQueryEvent *>(event);
|
||||||
// this block disables the selection cursor in android which appears in
|
// this block disables the selection cursor in android which appears in
|
||||||
// the top-left corner of the screen
|
// the top-left corner of the screen
|
||||||
if (imqEvent->queries() & Qt::ImEnabled) {
|
if (imqEvent->queries() & Qt::ImEnabled) {
|
||||||
imqEvent->setValue(Qt::ImEnabled, QVariant(false));
|
imqEvent->setValue(Qt::ImEnabled, QVariant(false));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return eventAccepted;
|
return eventAccepted;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -98,6 +98,12 @@ void CompositeHUD::run(const RenderContextPointer& renderContext) {
|
||||||
// Grab the HUD texture
|
// Grab the HUD texture
|
||||||
#if !defined(DISABLE_QML)
|
#if !defined(DISABLE_QML)
|
||||||
gpu::doInBatch("CompositeHUD", renderContext->args->_context, [&](gpu::Batch& batch) {
|
gpu::doInBatch("CompositeHUD", renderContext->args->_context, [&](gpu::Batch& batch) {
|
||||||
|
glm::mat4 projMat;
|
||||||
|
Transform viewMat;
|
||||||
|
renderContext->args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||||
|
renderContext->args->getViewFrustum().evalViewTransform(viewMat);
|
||||||
|
batch.setProjectionTransform(projMat);
|
||||||
|
batch.setViewTransform(viewMat, true);
|
||||||
if (renderContext->args->_hudOperator) {
|
if (renderContext->args->_hudOperator) {
|
||||||
renderContext->args->_hudOperator(batch, renderContext->args->_hudTexture, renderContext->args->_renderMode == RenderArgs::RenderMode::MIRROR_RENDER_MODE);
|
renderContext->args->_hudOperator(batch, renderContext->args->_hudTexture, renderContext->args->_renderMode == RenderArgs::RenderMode::MIRROR_RENDER_MODE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -363,12 +363,13 @@ public:
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Get the position of a vertex in the mesh.
|
* Get the position of a vertex in the mesh.
|
||||||
* @function MeshProxy#getPos3
|
* @function MeshProxy#getPos
|
||||||
* @param {number} index - Integer index of the mesh vertex.
|
* @param {number} index - Integer index of the mesh vertex.
|
||||||
* @returns {Vec3} Local position of the vertex relative to the mesh.
|
* @returns {Vec3} Local position of the vertex relative to the mesh.
|
||||||
* @deprecated Use the {@link Graphics} API instead.
|
* @deprecated Use the {@link Graphics} API instead.
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE virtual glm::vec3 getPos3(int index) const = 0;
|
Q_INVOKABLE virtual glm::vec3 getPos(int index) const = 0;
|
||||||
|
Q_INVOKABLE virtual glm::vec3 getPos3(int index) const { return getPos(index); } // deprecated
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(MeshProxy*);
|
Q_DECLARE_METATYPE(MeshProxy*);
|
||||||
|
|
|
@ -17,7 +17,7 @@ var currentSelectedBtn;
|
||||||
|
|
||||||
var SETTING_CURRENT_MODE_KEY = 'Android/Mode';
|
var SETTING_CURRENT_MODE_KEY = 'Android/Mode';
|
||||||
var MODE_VR = "VR", MODE_RADAR = "RADAR", MODE_MY_VIEW = "MY VIEW";
|
var MODE_VR = "VR", MODE_RADAR = "RADAR", MODE_MY_VIEW = "MY VIEW";
|
||||||
var DEFAULT_MODE = MODE_RADAR;
|
var DEFAULT_MODE = MODE_MY_VIEW;
|
||||||
var logEnabled = true;
|
var logEnabled = true;
|
||||||
|
|
||||||
var radar = Script.require('./radar.js');
|
var radar = Script.require('./radar.js');
|
||||||
|
|
Loading…
Reference in a new issue