mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 18:56:55 +02:00
Merging with the new GL45Backend
This commit is contained in:
commit
b37df393e2
43 changed files with 1823 additions and 503 deletions
72
.eslintrc.js
Normal file
72
.eslintrc.js
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
module.exports = {
|
||||||
|
"root": true,
|
||||||
|
"extends": "eslint:recommended",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 5
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"Account": false,
|
||||||
|
"AnimationCache": false,
|
||||||
|
"Assets": false,
|
||||||
|
"Audio": false,
|
||||||
|
"AudioDevice": false,
|
||||||
|
"AudioEffectOptions": false,
|
||||||
|
"AvatarList": false,
|
||||||
|
"AvatarManager": false,
|
||||||
|
"Camera": false,
|
||||||
|
"Clipboard": false,
|
||||||
|
"Controller": false,
|
||||||
|
"DialogsManager": false,
|
||||||
|
"Entities": false,
|
||||||
|
"FaceTracker": false,
|
||||||
|
"GlobalServices": false,
|
||||||
|
"HMD": false,
|
||||||
|
"LODManager": false,
|
||||||
|
"Mat4": false,
|
||||||
|
"Menu": false,
|
||||||
|
"Messages": false,
|
||||||
|
"ModelCache": false,
|
||||||
|
"MyAvatar": false,
|
||||||
|
"Overlays": false,
|
||||||
|
"Paths": false,
|
||||||
|
"Quat": false,
|
||||||
|
"Rates": false,
|
||||||
|
"Recording": false,
|
||||||
|
"Reticle": false,
|
||||||
|
"Scene": false,
|
||||||
|
"Script": false,
|
||||||
|
"ScriptDiscoveryService": false,
|
||||||
|
"Settings": false,
|
||||||
|
"SoundCache": false,
|
||||||
|
"Stats": false,
|
||||||
|
"TextureCache": false,
|
||||||
|
"Uuid": false,
|
||||||
|
"UndoStack": false,
|
||||||
|
"Vec3": false,
|
||||||
|
"WebSocket": false,
|
||||||
|
"WebWindow": false,
|
||||||
|
"Window": false,
|
||||||
|
"XMLHttpRequest": false,
|
||||||
|
"location": false,
|
||||||
|
"print": false
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"brace-style": ["error", "1tbs", { "allowSingleLine": false }],
|
||||||
|
"comma-dangle": ["error", "only-multiline"],
|
||||||
|
"camelcase": ["error"],
|
||||||
|
"curly": ["error", "all"],
|
||||||
|
"indent": ["error", 4, { "SwitchCase": 1 }],
|
||||||
|
"keyword-spacing": ["error", { "before": true, "after": true }],
|
||||||
|
"max-len": ["error", 128, 4],
|
||||||
|
"new-cap": ["error"],
|
||||||
|
//"no-magic-numbers": ["error", { "ignore": [0, 1], "ignoreArrayIndexes": true }],
|
||||||
|
"no-multiple-empty-lines": ["error"],
|
||||||
|
"no-multi-spaces": ["error"],
|
||||||
|
"no-unused-vars": ["error", { "args": "none", "vars": "local" }],
|
||||||
|
"semi": ["error", "always"],
|
||||||
|
"spaced-comment": ["error", "always", {
|
||||||
|
"line": { "markers": ["/"] }
|
||||||
|
}],
|
||||||
|
"space-before-function-paren": ["error", "never"]
|
||||||
|
}
|
||||||
|
};
|
|
@ -60,6 +60,50 @@ const QString DomainMetadata::Descriptors::Hours::CLOSE = "close";
|
||||||
//
|
//
|
||||||
// it is meant to be sent to and consumed by an external API
|
// it is meant to be sent to and consumed by an external API
|
||||||
|
|
||||||
|
// merge delta into target
|
||||||
|
// target should be of the form [ OpenTime, CloseTime ],
|
||||||
|
// delta should be of the form [ { open: Time, close: Time } ]
|
||||||
|
void parseHours(QVariant delta, QVariant& target) {
|
||||||
|
using Hours = DomainMetadata::Descriptors::Hours;
|
||||||
|
|
||||||
|
assert(target.canConvert<QVariantList>());
|
||||||
|
auto& targetList = *static_cast<QVariantList*>(target.data());
|
||||||
|
|
||||||
|
// if/when multiple ranges are allowed, this list will need to be iterated
|
||||||
|
assert(targetList[0].canConvert<QVariantList>());
|
||||||
|
auto& hours = *static_cast<QVariantList*>(targetList[0].data());
|
||||||
|
|
||||||
|
if (!delta.canConvert<QVariantList>()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& deltaList = *static_cast<QVariantList*>(delta.data());
|
||||||
|
if (deltaList.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& deltaHours = *static_cast<QVariantMap*>(deltaList.first().data());
|
||||||
|
if (deltaHours.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge delta into base
|
||||||
|
static const int OPEN_INDEX = 0;
|
||||||
|
static const int CLOSE_INDEX = 1;
|
||||||
|
auto open = deltaHours.find(Hours::OPEN);
|
||||||
|
if (open != deltaHours.end()) {
|
||||||
|
hours[OPEN_INDEX] = open.value();
|
||||||
|
}
|
||||||
|
assert(hours[OPEN_INDEX].canConvert<QString>());
|
||||||
|
|
||||||
|
auto close = deltaHours.find(Hours::CLOSE);
|
||||||
|
if (close != deltaHours.end()) {
|
||||||
|
hours[CLOSE_INDEX] = close.value();
|
||||||
|
}
|
||||||
|
assert(hours[CLOSE_INDEX].canConvert<QString>());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
DomainMetadata::DomainMetadata(QObject* domainServer) : QObject(domainServer) {
|
DomainMetadata::DomainMetadata(QObject* domainServer) : QObject(domainServer) {
|
||||||
// set up the structure necessary for casting during parsing (see parseHours, esp.)
|
// set up the structure necessary for casting during parsing (see parseHours, esp.)
|
||||||
_metadata[USERS] = QVariantMap {};
|
_metadata[USERS] = QVariantMap {};
|
||||||
|
@ -100,45 +144,12 @@ QJsonObject DomainMetadata::get(const QString& group) {
|
||||||
return QJsonObject::fromVariantMap(_metadata[group].toMap());
|
return QJsonObject::fromVariantMap(_metadata[group].toMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
// merge delta into target
|
|
||||||
// target should be of the form [ OpenTime, CloseTime ],
|
|
||||||
// delta should be of the form [ { open: Time, close: Time } ]
|
|
||||||
void parseHours(QVariant delta, QVariant& target) {
|
|
||||||
using Hours = DomainMetadata::Descriptors::Hours;
|
|
||||||
|
|
||||||
assert(target.canConvert<QVariantList>());
|
|
||||||
auto& targetList = *static_cast<QVariantList*>(target.data());
|
|
||||||
|
|
||||||
// if/when multiple ranges are allowed, this list will need to be iterated
|
|
||||||
assert(targetList[0].canConvert<QVariantList>());
|
|
||||||
auto& hours = *static_cast<QVariantList*>(targetList[0].data());
|
|
||||||
|
|
||||||
auto deltaHours = delta.toList()[0].toMap();
|
|
||||||
if (deltaHours.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// merge delta into base
|
|
||||||
static const int OPEN_INDEX = 0;
|
|
||||||
static const int CLOSE_INDEX = 1;
|
|
||||||
auto open = deltaHours.find(Hours::OPEN);
|
|
||||||
if (open != deltaHours.end()) {
|
|
||||||
hours[OPEN_INDEX] = open.value();
|
|
||||||
}
|
|
||||||
assert(hours[OPEN_INDEX].canConvert<QString>());
|
|
||||||
auto close = deltaHours.find(Hours::CLOSE);
|
|
||||||
if (close != deltaHours.end()) {
|
|
||||||
hours[CLOSE_INDEX] = close.value();
|
|
||||||
}
|
|
||||||
assert(hours[CLOSE_INDEX].canConvert<QString>());
|
|
||||||
}
|
|
||||||
|
|
||||||
void DomainMetadata::descriptorsChanged() {
|
void DomainMetadata::descriptorsChanged() {
|
||||||
// get descriptors
|
// get descriptors
|
||||||
assert(_metadata[DESCRIPTORS].canConvert<QVariantMap>());
|
assert(_metadata[DESCRIPTORS].canConvert<QVariantMap>());
|
||||||
auto& state = *static_cast<QVariantMap*>(_metadata[DESCRIPTORS].data());
|
auto& state = *static_cast<QVariantMap*>(_metadata[DESCRIPTORS].data());
|
||||||
auto settings = static_cast<DomainServer*>(parent())->_settingsManager.getSettingsMap();
|
auto& settings = static_cast<DomainServer*>(parent())->_settingsManager.getSettingsMap();
|
||||||
auto descriptors = settings[DESCRIPTORS].toMap();
|
auto& descriptors = static_cast<DomainServer*>(parent())->_settingsManager.getDescriptorsMap();
|
||||||
|
|
||||||
// copy simple descriptors (description/maturity)
|
// copy simple descriptors (description/maturity)
|
||||||
state[Descriptors::DESCRIPTION] = descriptors[Descriptors::DESCRIPTION];
|
state[Descriptors::DESCRIPTION] = descriptors[Descriptors::DESCRIPTION];
|
||||||
|
@ -149,20 +160,20 @@ void DomainMetadata::descriptorsChanged() {
|
||||||
state[Descriptors::TAGS] = descriptors[Descriptors::TAGS].toList();
|
state[Descriptors::TAGS] = descriptors[Descriptors::TAGS].toList();
|
||||||
|
|
||||||
// parse capacity
|
// parse capacity
|
||||||
const QString CAPACITY = "security.maximum_user_capacity";
|
static const QString CAPACITY = "security.maximum_user_capacity";
|
||||||
const QVariant* capacityVariant = valueForKeyPath(settings, CAPACITY);
|
const QVariant* capacityVariant = valueForKeyPath(settings, CAPACITY);
|
||||||
unsigned int capacity = capacityVariant ? capacityVariant->toUInt() : 0;
|
unsigned int capacity = capacityVariant ? capacityVariant->toUInt() : 0;
|
||||||
state[Descriptors::CAPACITY] = capacity;
|
state[Descriptors::CAPACITY] = capacity;
|
||||||
|
|
||||||
// parse operating hours
|
// parse operating hours
|
||||||
const QString WEEKDAY_HOURS = "weekday_hours";
|
static const QString WEEKDAY_HOURS = "weekday_hours";
|
||||||
const QString WEEKEND_HOURS = "weekend_hours";
|
static const QString WEEKEND_HOURS = "weekend_hours";
|
||||||
const QString UTC_OFFSET = "utc_offset";
|
static const QString UTC_OFFSET = "utc_offset";
|
||||||
assert(state[Descriptors::HOURS].canConvert<QVariantMap>());
|
assert(state[Descriptors::HOURS].canConvert<QVariantMap>());
|
||||||
auto& hours = *static_cast<QVariantMap*>(state[Descriptors::HOURS].data());
|
auto& hours = *static_cast<QVariantMap*>(state[Descriptors::HOURS].data());
|
||||||
parseHours(descriptors.take(WEEKDAY_HOURS), hours[Descriptors::Hours::WEEKDAY]);
|
|
||||||
parseHours(descriptors.take(WEEKEND_HOURS), hours[Descriptors::Hours::WEEKEND]);
|
|
||||||
hours[Descriptors::Hours::UTC_OFFSET] = descriptors.take(UTC_OFFSET);
|
hours[Descriptors::Hours::UTC_OFFSET] = descriptors.take(UTC_OFFSET);
|
||||||
|
parseHours(descriptors[WEEKDAY_HOURS], hours[Descriptors::Hours::WEEKDAY]);
|
||||||
|
parseHours(descriptors[WEEKEND_HOURS], hours[Descriptors::Hours::WEEKEND]);
|
||||||
|
|
||||||
#if DEV_BUILD || PR_BUILD
|
#if DEV_BUILD || PR_BUILD
|
||||||
qDebug() << "Domain metadata descriptors set:" << QJsonObject::fromVariantMap(_metadata[DESCRIPTORS].toMap());
|
qDebug() << "Domain metadata descriptors set:" << QJsonObject::fromVariantMap(_metadata[DESCRIPTORS].toMap());
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <HifiConfigVariantMap.h>
|
#include <HifiConfigVariantMap.h>
|
||||||
#include <HTTPConnection.h>
|
#include <HTTPConnection.h>
|
||||||
#include <NLPacketList.h>
|
#include <NLPacketList.h>
|
||||||
|
#include <NumericalConstants.h>
|
||||||
|
|
||||||
#include "DomainServerSettingsManager.h"
|
#include "DomainServerSettingsManager.h"
|
||||||
|
|
||||||
|
@ -263,23 +264,7 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList
|
||||||
|
|
||||||
if (oldVersion < 1.5) {
|
if (oldVersion < 1.5) {
|
||||||
// This was prior to operating hours, so add default hours
|
// This was prior to operating hours, so add default hours
|
||||||
static const QString WEEKDAY_HOURS{ "descriptors.weekday_hours" };
|
validateDescriptorsMap();
|
||||||
static const QString WEEKEND_HOURS{ "descriptors.weekend_hours" };
|
|
||||||
static const QString UTC_OFFSET{ "descriptors.utc_offset" };
|
|
||||||
|
|
||||||
QVariant* weekdayHours = valueForKeyPath(_configMap.getUserConfig(), WEEKDAY_HOURS, true);
|
|
||||||
QVariant* weekendHours = valueForKeyPath(_configMap.getUserConfig(), WEEKEND_HOURS, true);
|
|
||||||
QVariant* utcOffset = valueForKeyPath(_configMap.getUserConfig(), UTC_OFFSET, true);
|
|
||||||
|
|
||||||
*weekdayHours = QVariantList { QVariantMap{ { "open", QVariant("00:00") }, { "close", QVariant("23:59") } } };
|
|
||||||
*weekendHours = QVariantList { QVariantMap{ { "open", QVariant("00:00") }, { "close", QVariant("23:59") } } };
|
|
||||||
*utcOffset = QVariant(QTimeZone::systemTimeZone().offsetFromUtc(QDateTime::currentDateTime()) / (float)3600);
|
|
||||||
|
|
||||||
// write the new settings to file
|
|
||||||
persistToFile();
|
|
||||||
|
|
||||||
// reload the master and user config so the merged config is correct
|
|
||||||
_configMap.loadMasterAndUserConfig(_argumentList);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,6 +274,49 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList
|
||||||
appSettings.setValue(JSON_SETTINGS_VERSION_KEY, _descriptionVersion);
|
appSettings.setValue(JSON_SETTINGS_VERSION_KEY, _descriptionVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariantMap& DomainServerSettingsManager::getDescriptorsMap() {
|
||||||
|
validateDescriptorsMap();
|
||||||
|
|
||||||
|
static const QString DESCRIPTORS{ "descriptors" };
|
||||||
|
return *static_cast<QVariantMap*>(getSettingsMap()[DESCRIPTORS].data());
|
||||||
|
}
|
||||||
|
|
||||||
|
void DomainServerSettingsManager::validateDescriptorsMap() {
|
||||||
|
static const QString WEEKDAY_HOURS{ "descriptors.weekday_hours" };
|
||||||
|
static const QString WEEKEND_HOURS{ "descriptors.weekend_hours" };
|
||||||
|
static const QString UTC_OFFSET{ "descriptors.utc_offset" };
|
||||||
|
|
||||||
|
QVariant* weekdayHours = valueForKeyPath(_configMap.getUserConfig(), WEEKDAY_HOURS, true);
|
||||||
|
QVariant* weekendHours = valueForKeyPath(_configMap.getUserConfig(), WEEKEND_HOURS, true);
|
||||||
|
QVariant* utcOffset = valueForKeyPath(_configMap.getUserConfig(), UTC_OFFSET, true);
|
||||||
|
|
||||||
|
static const QString OPEN{ "open" };
|
||||||
|
static const QString CLOSE{ "close" };
|
||||||
|
static const QString DEFAULT_OPEN{ "00:00" };
|
||||||
|
static const QString DEFAULT_CLOSE{ "23:59" };
|
||||||
|
bool wasMalformed = false;
|
||||||
|
if (weekdayHours->isNull()) {
|
||||||
|
*weekdayHours = QVariantList{ QVariantMap{ { OPEN, QVariant(DEFAULT_OPEN) }, { CLOSE, QVariant(DEFAULT_CLOSE) } } };
|
||||||
|
wasMalformed = true;
|
||||||
|
}
|
||||||
|
if (weekendHours->isNull()) {
|
||||||
|
*weekendHours = QVariantList{ QVariantMap{ { OPEN, QVariant(DEFAULT_OPEN) }, { CLOSE, QVariant(DEFAULT_CLOSE) } } };
|
||||||
|
wasMalformed = true;
|
||||||
|
}
|
||||||
|
if (utcOffset->isNull()) {
|
||||||
|
*utcOffset = QVariant(QTimeZone::systemTimeZone().offsetFromUtc(QDateTime::currentDateTime()) / (float)SECS_PER_HOUR);
|
||||||
|
wasMalformed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wasMalformed) {
|
||||||
|
// write the new settings to file
|
||||||
|
persistToFile();
|
||||||
|
|
||||||
|
// reload the master and user config so the merged config is correct
|
||||||
|
_configMap.loadMasterAndUserConfig(_argumentList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DomainServerSettingsManager::packPermissionsForMap(QString mapName,
|
void DomainServerSettingsManager::packPermissionsForMap(QString mapName,
|
||||||
NodePermissionsMap& agentPermissions,
|
NodePermissionsMap& agentPermissions,
|
||||||
QString keyPath) {
|
QString keyPath) {
|
||||||
|
|
|
@ -41,6 +41,8 @@ public:
|
||||||
QVariantMap& getUserSettingsMap() { return _configMap.getUserConfig(); }
|
QVariantMap& getUserSettingsMap() { return _configMap.getUserConfig(); }
|
||||||
QVariantMap& getSettingsMap() { return _configMap.getMergedConfig(); }
|
QVariantMap& getSettingsMap() { return _configMap.getMergedConfig(); }
|
||||||
|
|
||||||
|
QVariantMap& getDescriptorsMap();
|
||||||
|
|
||||||
bool haveStandardPermissionsForName(const QString& name) const { return _standardAgentPermissions.contains(name); }
|
bool haveStandardPermissionsForName(const QString& name) const { return _standardAgentPermissions.contains(name); }
|
||||||
bool havePermissionsForName(const QString& name) const { return _agentPermissions.contains(name); }
|
bool havePermissionsForName(const QString& name) const { return _agentPermissions.contains(name); }
|
||||||
NodePermissions getStandardPermissionsForName(const QString& name) const;
|
NodePermissions getStandardPermissionsForName(const QString& name) const;
|
||||||
|
@ -72,6 +74,8 @@ private:
|
||||||
|
|
||||||
friend class DomainServer;
|
friend class DomainServer;
|
||||||
|
|
||||||
|
void validateDescriptorsMap();
|
||||||
|
|
||||||
void packPermissionsForMap(QString mapName, NodePermissionsMap& agentPermissions, QString keyPath);
|
void packPermissionsForMap(QString mapName, NodePermissionsMap& agentPermissions, QString keyPath);
|
||||||
void packPermissions();
|
void packPermissions();
|
||||||
void unpackPermissions();
|
void unpackPermissions();
|
||||||
|
|
|
@ -24,6 +24,13 @@ FocusScope {
|
||||||
readonly property int invalid_position: -9999;
|
readonly property int invalid_position: -9999;
|
||||||
property rect recommendedRect: Qt.rect(0,0,0,0);
|
property rect recommendedRect: Qt.rect(0,0,0,0);
|
||||||
property var expectedChildren;
|
property var expectedChildren;
|
||||||
|
property bool repositionLocked: true
|
||||||
|
|
||||||
|
onRepositionLockedChanged: {
|
||||||
|
if (!repositionLocked) {
|
||||||
|
d.handleSizeChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onHeightChanged: d.handleSizeChanged();
|
onHeightChanged: d.handleSizeChanged();
|
||||||
|
|
||||||
|
@ -52,11 +59,14 @@ FocusScope {
|
||||||
readonly property real menu: 8000
|
readonly property real menu: 8000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: d
|
id: d
|
||||||
|
|
||||||
function handleSizeChanged() {
|
function handleSizeChanged() {
|
||||||
|
if (desktop.repositionLocked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var oldRecommendedRect = recommendedRect;
|
var oldRecommendedRect = recommendedRect;
|
||||||
var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedOverlayRect();
|
var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedOverlayRect();
|
||||||
var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y,
|
var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y,
|
||||||
|
@ -235,6 +245,10 @@ FocusScope {
|
||||||
}
|
}
|
||||||
|
|
||||||
function repositionAll() {
|
function repositionAll() {
|
||||||
|
if (desktop.repositionLocked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var oldRecommendedRect = recommendedRect;
|
var oldRecommendedRect = recommendedRect;
|
||||||
var oldRecommendedDimmensions = { x: oldRecommendedRect.width, y: oldRecommendedRect.height };
|
var oldRecommendedDimmensions = { x: oldRecommendedRect.width, y: oldRecommendedRect.height };
|
||||||
var newRecommendedRect = Controller.getRecommendedOverlayRect();
|
var newRecommendedRect = Controller.getRecommendedOverlayRect();
|
||||||
|
|
|
@ -39,6 +39,19 @@ Item {
|
||||||
onSelected: d.handleSelection(subMenu, currentItem, item)
|
onSelected: d.handleSelection(subMenu, currentItem, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
property var delay: Timer { // No setTimeout in QML.
|
||||||
|
property var menuItem: null;
|
||||||
|
interval: 0
|
||||||
|
repeat: false
|
||||||
|
running: false
|
||||||
|
function trigger(item) { // Capture item and schedule asynchronous Timer.
|
||||||
|
menuItem = item;
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
onTriggered: {
|
||||||
|
menuItem.trigger(); // Now trigger the item.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function toModel(items) {
|
function toModel(items) {
|
||||||
var result = modelMaker.createObject(desktop);
|
var result = modelMaker.createObject(desktop);
|
||||||
|
@ -128,7 +141,8 @@ Item {
|
||||||
|
|
||||||
case MenuItemType.Item:
|
case MenuItemType.Item:
|
||||||
console.log("Triggering " + item.text)
|
console.log("Triggering " + item.text)
|
||||||
item.trigger();
|
// Don't block waiting for modal dialogs and such that the menu might open.
|
||||||
|
delay.trigger(item);
|
||||||
clearMenus();
|
clearMenus();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -773,6 +773,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
||||||
auto gpuIdent = GPUIdent::getInstance();
|
auto gpuIdent = GPUIdent::getInstance();
|
||||||
auto glContextData = getGLContextData();
|
auto glContextData = getGLContextData();
|
||||||
QJsonObject properties = {
|
QJsonObject properties = {
|
||||||
|
{ "version", applicationVersion() },
|
||||||
{ "previousSessionCrashed", _previousSessionCrashed },
|
{ "previousSessionCrashed", _previousSessionCrashed },
|
||||||
{ "previousSessionRuntime", sessionRunTime.get() },
|
{ "previousSessionRuntime", sessionRunTime.get() },
|
||||||
{ "cpu_architecture", QSysInfo::currentCpuArchitecture() },
|
{ "cpu_architecture", QSysInfo::currentCpuArchitecture() },
|
||||||
|
@ -963,6 +964,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
||||||
updateHeartbeat();
|
updateHeartbeat();
|
||||||
|
|
||||||
loadSettings();
|
loadSettings();
|
||||||
|
|
||||||
|
// Now that we've loaded the menu and thus switched to the previous display plugin
|
||||||
|
// we can unlock the desktop repositioning code, since all the positions will be
|
||||||
|
// relative to the desktop size for this plugin
|
||||||
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
|
offscreenUi->getDesktop()->setProperty("repositionLocked", false);
|
||||||
|
|
||||||
// Make sure we don't time out during slow operations at startup
|
// Make sure we don't time out during slow operations at startup
|
||||||
updateHeartbeat();
|
updateHeartbeat();
|
||||||
|
|
||||||
|
@ -1579,13 +1587,7 @@ void Application::initializeUi() {
|
||||||
});
|
});
|
||||||
offscreenUi->resume();
|
offscreenUi->resume();
|
||||||
connect(_window, &MainWindow::windowGeometryChanged, [this](const QRect& r){
|
connect(_window, &MainWindow::windowGeometryChanged, [this](const QRect& r){
|
||||||
static qreal oldDevicePixelRatio = 0;
|
resizeGL();
|
||||||
qreal devicePixelRatio = getActiveDisplayPlugin()->devicePixelRatio();
|
|
||||||
if (devicePixelRatio != oldDevicePixelRatio) {
|
|
||||||
oldDevicePixelRatio = devicePixelRatio;
|
|
||||||
qDebug() << "Device pixel ratio changed, triggering GL resize";
|
|
||||||
resizeGL();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// This will set up the input plugins UI
|
// This will set up the input plugins UI
|
||||||
|
@ -1717,22 +1719,22 @@ void Application::paintGL() {
|
||||||
if (isHMDMode()) {
|
if (isHMDMode()) {
|
||||||
mat4 camMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
mat4 camMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
||||||
_myCamera.setPosition(extractTranslation(camMat));
|
_myCamera.setPosition(extractTranslation(camMat));
|
||||||
_myCamera.setRotation(glm::quat_cast(camMat));
|
_myCamera.setOrientation(glm::quat_cast(camMat));
|
||||||
} else {
|
} else {
|
||||||
_myCamera.setPosition(myAvatar->getDefaultEyePosition());
|
_myCamera.setPosition(myAvatar->getDefaultEyePosition());
|
||||||
_myCamera.setRotation(myAvatar->getHead()->getCameraOrientation());
|
_myCamera.setOrientation(myAvatar->getHead()->getCameraOrientation());
|
||||||
}
|
}
|
||||||
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
||||||
if (isHMDMode()) {
|
if (isHMDMode()) {
|
||||||
auto hmdWorldMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
auto hmdWorldMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
||||||
_myCamera.setRotation(glm::normalize(glm::quat_cast(hmdWorldMat)));
|
_myCamera.setOrientation(glm::normalize(glm::quat_cast(hmdWorldMat)));
|
||||||
_myCamera.setPosition(extractTranslation(hmdWorldMat) +
|
_myCamera.setPosition(extractTranslation(hmdWorldMat) +
|
||||||
myAvatar->getOrientation() * boomOffset);
|
myAvatar->getOrientation() * boomOffset);
|
||||||
} else {
|
} else {
|
||||||
_myCamera.setRotation(myAvatar->getHead()->getOrientation());
|
_myCamera.setOrientation(myAvatar->getHead()->getOrientation());
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) {
|
||||||
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
||||||
+ _myCamera.getRotation() * boomOffset);
|
+ _myCamera.getOrientation() * boomOffset);
|
||||||
} else {
|
} else {
|
||||||
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
||||||
+ myAvatar->getOrientation() * boomOffset);
|
+ myAvatar->getOrientation() * boomOffset);
|
||||||
|
@ -1751,7 +1753,7 @@ void Application::paintGL() {
|
||||||
|
|
||||||
glm::quat worldMirrorRotation = mirrorBodyOrientation * mirrorHmdRotation;
|
glm::quat worldMirrorRotation = mirrorBodyOrientation * mirrorHmdRotation;
|
||||||
|
|
||||||
_myCamera.setRotation(worldMirrorRotation);
|
_myCamera.setOrientation(worldMirrorRotation);
|
||||||
|
|
||||||
glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());
|
glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());
|
||||||
// Mirror HMD lateral offsets
|
// Mirror HMD lateral offsets
|
||||||
|
@ -1762,7 +1764,7 @@ void Application::paintGL() {
|
||||||
+ mirrorBodyOrientation * glm::vec3(0.0f, 0.0f, 1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror
|
+ mirrorBodyOrientation * glm::vec3(0.0f, 0.0f, 1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror
|
||||||
+ mirrorBodyOrientation * hmdOffset);
|
+ mirrorBodyOrientation * hmdOffset);
|
||||||
} else {
|
} else {
|
||||||
_myCamera.setRotation(myAvatar->getWorldAlignedOrientation()
|
_myCamera.setOrientation(myAvatar->getWorldAlignedOrientation()
|
||||||
* glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
|
* glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
|
||||||
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
||||||
+ glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0)
|
+ glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0)
|
||||||
|
@ -1775,11 +1777,11 @@ void Application::paintGL() {
|
||||||
if (cameraEntity != nullptr) {
|
if (cameraEntity != nullptr) {
|
||||||
if (isHMDMode()) {
|
if (isHMDMode()) {
|
||||||
glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix());
|
glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix());
|
||||||
_myCamera.setRotation(cameraEntity->getRotation() * hmdRotation);
|
_myCamera.setOrientation(cameraEntity->getRotation() * hmdRotation);
|
||||||
glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());
|
glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());
|
||||||
_myCamera.setPosition(cameraEntity->getPosition() + (hmdRotation * hmdOffset));
|
_myCamera.setPosition(cameraEntity->getPosition() + (hmdRotation * hmdOffset));
|
||||||
} else {
|
} else {
|
||||||
_myCamera.setRotation(cameraEntity->getRotation());
|
_myCamera.setOrientation(cameraEntity->getRotation());
|
||||||
_myCamera.setPosition(cameraEntity->getPosition());
|
_myCamera.setPosition(cameraEntity->getPosition());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1960,7 +1962,8 @@ void Application::resizeGL() {
|
||||||
static qreal lastDevicePixelRatio = 0;
|
static qreal lastDevicePixelRatio = 0;
|
||||||
qreal devicePixelRatio = _window->devicePixelRatio();
|
qreal devicePixelRatio = _window->devicePixelRatio();
|
||||||
if (offscreenUi->size() != fromGlm(uiSize) || devicePixelRatio != lastDevicePixelRatio) {
|
if (offscreenUi->size() != fromGlm(uiSize) || devicePixelRatio != lastDevicePixelRatio) {
|
||||||
offscreenUi->resize(fromGlm(uiSize));
|
qDebug() << "Device pixel ratio changed, triggering resize";
|
||||||
|
offscreenUi->resize(fromGlm(uiSize), true);
|
||||||
_offscreenContext->makeCurrent();
|
_offscreenContext->makeCurrent();
|
||||||
lastDevicePixelRatio = devicePixelRatio;
|
lastDevicePixelRatio = devicePixelRatio;
|
||||||
}
|
}
|
||||||
|
@ -3314,9 +3317,9 @@ void Application::updateMyAvatarLookAtPosition() {
|
||||||
if (isLookingAtSomeone) {
|
if (isLookingAtSomeone) {
|
||||||
deflection *= GAZE_DEFLECTION_REDUCTION_DURING_EYE_CONTACT;
|
deflection *= GAZE_DEFLECTION_REDUCTION_DURING_EYE_CONTACT;
|
||||||
}
|
}
|
||||||
lookAtSpot = origin + _myCamera.getRotation() * glm::quat(glm::radians(glm::vec3(
|
lookAtSpot = origin + _myCamera.getOrientation() * glm::quat(glm::radians(glm::vec3(
|
||||||
eyePitch * deflection, eyeYaw * deflection, 0.0f))) *
|
eyePitch * deflection, eyeYaw * deflection, 0.0f))) *
|
||||||
glm::inverse(_myCamera.getRotation()) * (lookAtSpot - origin);
|
glm::inverse(_myCamera.getOrientation()) * (lookAtSpot - origin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4032,7 +4035,7 @@ void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) {
|
||||||
|
|
||||||
// Set the viewFrustum up with the correct position and orientation of the camera
|
// Set the viewFrustum up with the correct position and orientation of the camera
|
||||||
viewFrustum.setPosition(camera.getPosition());
|
viewFrustum.setPosition(camera.getPosition());
|
||||||
viewFrustum.setOrientation(camera.getRotation());
|
viewFrustum.setOrientation(camera.getOrientation());
|
||||||
|
|
||||||
// Ask the ViewFrustum class to calculate our corners
|
// Ask the ViewFrustum class to calculate our corners
|
||||||
viewFrustum.calculate();
|
viewFrustum.calculate();
|
||||||
|
@ -4305,7 +4308,7 @@ void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& regi
|
||||||
myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_DISTANCE * myAvatar->getScale());
|
myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_DISTANCE * myAvatar->getScale());
|
||||||
}
|
}
|
||||||
_mirrorCamera.setProjection(glm::perspective(glm::radians(fov), aspect, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP));
|
_mirrorCamera.setProjection(glm::perspective(glm::radians(fov), aspect, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP));
|
||||||
_mirrorCamera.setRotation(myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI, 0.0f)));
|
_mirrorCamera.setOrientation(myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI, 0.0f)));
|
||||||
|
|
||||||
|
|
||||||
// set the bounds of rear mirror view
|
// set the bounds of rear mirror view
|
||||||
|
@ -5348,7 +5351,6 @@ void Application::updateDisplayMode() {
|
||||||
_displayPlugin = newDisplayPlugin;
|
_displayPlugin = newDisplayPlugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
emit activeDisplayPluginChanged();
|
emit activeDisplayPluginChanged();
|
||||||
|
|
||||||
// reset the avatar, to set head and hand palms back to a reasonable default pose.
|
// reset the avatar, to set head and hand palms back to a reasonable default pose.
|
||||||
|
|
|
@ -62,14 +62,14 @@ void Camera::update(float deltaTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera::recompose() {
|
void Camera::recompose() {
|
||||||
mat4 orientation = glm::mat4_cast(_rotation);
|
mat4 orientation = glm::mat4_cast(_orientation);
|
||||||
mat4 translation = glm::translate(mat4(), _position);
|
mat4 translation = glm::translate(mat4(), _position);
|
||||||
_transform = translation * orientation;
|
_transform = translation * orientation;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera::decompose() {
|
void Camera::decompose() {
|
||||||
_position = vec3(_transform[3]);
|
_position = vec3(_transform[3]);
|
||||||
_rotation = glm::quat_cast(_transform);
|
_orientation = glm::quat_cast(_transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera::setTransform(const glm::mat4& transform) {
|
void Camera::setTransform(const glm::mat4& transform) {
|
||||||
|
@ -85,8 +85,8 @@ void Camera::setPosition(const glm::vec3& position) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera::setRotation(const glm::quat& rotation) {
|
void Camera::setOrientation(const glm::quat& orientation) {
|
||||||
_rotation = rotation;
|
_orientation = orientation;
|
||||||
recompose();
|
recompose();
|
||||||
if (_isKeepLookingAt) {
|
if (_isKeepLookingAt) {
|
||||||
lookAt(_lookingAt);
|
lookAt(_lookingAt);
|
||||||
|
@ -154,9 +154,9 @@ QString Camera::getModeString() const {
|
||||||
void Camera::lookAt(const glm::vec3& lookAt) {
|
void Camera::lookAt(const glm::vec3& lookAt) {
|
||||||
glm::vec3 up = IDENTITY_UP;
|
glm::vec3 up = IDENTITY_UP;
|
||||||
glm::mat4 lookAtMatrix = glm::lookAt(_position, lookAt, up);
|
glm::mat4 lookAtMatrix = glm::lookAt(_position, lookAt, up);
|
||||||
glm::quat rotation = glm::quat_cast(lookAtMatrix);
|
glm::quat orientation = glm::quat_cast(lookAtMatrix);
|
||||||
rotation.w = -rotation.w; // Rosedale approved
|
orientation.w = -orientation.w; // Rosedale approved
|
||||||
_rotation = rotation;
|
_orientation = orientation;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera::keepLookingAt(const glm::vec3& point) {
|
void Camera::keepLookingAt(const glm::vec3& point) {
|
||||||
|
@ -171,7 +171,7 @@ void Camera::loadViewFrustum(ViewFrustum& frustum) const {
|
||||||
|
|
||||||
// Set the viewFrustum up with the correct position and orientation of the camera
|
// Set the viewFrustum up with the correct position and orientation of the camera
|
||||||
frustum.setPosition(getPosition());
|
frustum.setPosition(getPosition());
|
||||||
frustum.setOrientation(getRotation());
|
frustum.setOrientation(getOrientation());
|
||||||
|
|
||||||
// Ask the ViewFrustum class to calculate our corners
|
// Ask the ViewFrustum class to calculate our corners
|
||||||
frustum.calculate();
|
frustum.calculate();
|
||||||
|
|
|
@ -45,7 +45,7 @@ class Camera : public QObject {
|
||||||
public:
|
public:
|
||||||
Camera();
|
Camera();
|
||||||
|
|
||||||
void initialize(); // instantly put the camera at the ideal position and rotation.
|
void initialize(); // instantly put the camera at the ideal position and orientation.
|
||||||
|
|
||||||
void update( float deltaTime );
|
void update( float deltaTime );
|
||||||
|
|
||||||
|
@ -57,25 +57,22 @@ public:
|
||||||
|
|
||||||
EntityItemPointer getCameraEntityPointer() const { return _cameraEntity; }
|
EntityItemPointer getCameraEntityPointer() const { return _cameraEntity; }
|
||||||
|
|
||||||
public slots:
|
|
||||||
QString getModeString() const;
|
|
||||||
void setModeString(const QString& mode);
|
|
||||||
|
|
||||||
glm::quat getRotation() const { return _rotation; }
|
|
||||||
void setRotation(const glm::quat& rotation);
|
|
||||||
|
|
||||||
glm::vec3 getPosition() const { return _position; }
|
|
||||||
void setPosition(const glm::vec3& position);
|
|
||||||
|
|
||||||
glm::quat getOrientation() const { return getRotation(); }
|
|
||||||
void setOrientation(const glm::quat& orientation) { setRotation(orientation); }
|
|
||||||
|
|
||||||
const glm::mat4& getTransform() const { return _transform; }
|
const glm::mat4& getTransform() const { return _transform; }
|
||||||
void setTransform(const glm::mat4& transform);
|
void setTransform(const glm::mat4& transform);
|
||||||
|
|
||||||
const glm::mat4& getProjection() const { return _projection; }
|
const glm::mat4& getProjection() const { return _projection; }
|
||||||
void setProjection(const glm::mat4& projection);
|
void setProjection(const glm::mat4& projection);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
QString getModeString() const;
|
||||||
|
void setModeString(const QString& mode);
|
||||||
|
|
||||||
|
glm::vec3 getPosition() const { return _position; }
|
||||||
|
void setPosition(const glm::vec3& position);
|
||||||
|
|
||||||
|
glm::quat getOrientation() const { return _orientation; }
|
||||||
|
void setOrientation(const glm::quat& orientation);
|
||||||
|
|
||||||
QUuid getCameraEntity() const;
|
QUuid getCameraEntity() const;
|
||||||
void setCameraEntity(QUuid entityID);
|
void setCameraEntity(QUuid entityID);
|
||||||
|
|
||||||
|
@ -105,7 +102,7 @@ private:
|
||||||
|
|
||||||
// derived
|
// derived
|
||||||
glm::vec3 _position;
|
glm::vec3 _position;
|
||||||
glm::quat _rotation;
|
glm::quat _orientation;
|
||||||
bool _isKeepLookingAt{ false };
|
bool _isKeepLookingAt{ false };
|
||||||
glm::vec3 _lookingAt;
|
glm::vec3 _lookingAt;
|
||||||
EntityItemPointer _cameraEntity;
|
EntityItemPointer _cameraEntity;
|
||||||
|
|
|
@ -150,7 +150,8 @@ void ApplicationOverlay::renderRearViewToFbo(RenderArgs* renderArgs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplicationOverlay::renderRearView(RenderArgs* renderArgs) {
|
void ApplicationOverlay::renderRearView(RenderArgs* renderArgs) {
|
||||||
if (!qApp->isHMDMode() && Menu::getInstance()->isOptionChecked(MenuOption::MiniMirror)) {
|
if (!qApp->isHMDMode() && Menu::getInstance()->isOptionChecked(MenuOption::MiniMirror) &&
|
||||||
|
!Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) {
|
||||||
gpu::Batch& batch = *renderArgs->_batch;
|
gpu::Batch& batch = *renderArgs->_batch;
|
||||||
|
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
|
@ -166,7 +167,7 @@ void ApplicationOverlay::renderRearView(RenderArgs* renderArgs) {
|
||||||
batch.setViewTransform(Transform());
|
batch.setViewTransform(Transform());
|
||||||
|
|
||||||
float screenRatio = ((float)qApp->getDevicePixelRatio());
|
float screenRatio = ((float)qApp->getDevicePixelRatio());
|
||||||
float renderRatio = ((float)screenRatio * qApp->getRenderResolutionScale());
|
float renderRatio = ((float)qApp->getRenderResolutionScale());
|
||||||
|
|
||||||
auto viewport = qApp->getMirrorViewRect();
|
auto viewport = qApp->getMirrorViewRect();
|
||||||
glm::vec2 bottomLeft(viewport.left(), viewport.top() + viewport.height());
|
glm::vec2 bottomLeft(viewport.left(), viewport.top() + viewport.height());
|
||||||
|
|
|
@ -191,9 +191,11 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties
|
||||||
if (success) {
|
if (success) {
|
||||||
emit debitEnergySource(cost);
|
emit debitEnergySource(cost);
|
||||||
queueEntityMessage(PacketType::EntityAdd, id, propertiesWithSimID);
|
queueEntityMessage(PacketType::EntityAdd, id, propertiesWithSimID);
|
||||||
}
|
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
|
} else {
|
||||||
|
return QUuid();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QUuid EntityScriptingInterface::addModelEntity(const QString& name, const QString& modelUrl, const glm::vec3& position) {
|
QUuid EntityScriptingInterface::addModelEntity(const QString& name, const QString& modelUrl, const glm::vec3& position) {
|
||||||
|
|
|
@ -320,6 +320,11 @@ EntityItemPointer EntityTree::addEntity(const EntityItemID& entityID, const Enti
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!properties.getClientOnly() && getIsClient() &&
|
||||||
|
!nodeList->getThisNodeCanRez() && !nodeList->getThisNodeCanRezTmp()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
bool recordCreationTime = false;
|
bool recordCreationTime = false;
|
||||||
if (props.getCreated() == UNKNOWN_CREATED_TIME) {
|
if (props.getCreated() == UNKNOWN_CREATED_TIME) {
|
||||||
// the entity's creation time was not specified in properties, which means this is a NEW entity
|
// the entity's creation time was not specified in properties, which means this is a NEW entity
|
||||||
|
|
|
@ -6,6 +6,14 @@
|
||||||
#include <QtOpenGL/QGL>
|
#include <QtOpenGL/QGL>
|
||||||
#include <QOpenGLContext>
|
#include <QOpenGLContext>
|
||||||
#include <QtCore/QRegularExpression>
|
#include <QtCore/QRegularExpression>
|
||||||
|
#include <QtCore/QProcessEnvironment>
|
||||||
|
#ifdef DEBUG
|
||||||
|
static bool enableDebug = true;
|
||||||
|
#else
|
||||||
|
static const QString DEBUG_FLAG("HIFI_ENABLE_OPENGL_45");
|
||||||
|
static bool enableDebug = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
const QSurfaceFormat& getDefaultOpenGLSurfaceFormat() {
|
const QSurfaceFormat& getDefaultOpenGLSurfaceFormat() {
|
||||||
static QSurfaceFormat format;
|
static QSurfaceFormat format;
|
||||||
|
@ -15,9 +23,9 @@ const QSurfaceFormat& getDefaultOpenGLSurfaceFormat() {
|
||||||
format.setDepthBufferSize(DEFAULT_GL_DEPTH_BUFFER_BITS);
|
format.setDepthBufferSize(DEFAULT_GL_DEPTH_BUFFER_BITS);
|
||||||
format.setStencilBufferSize(DEFAULT_GL_STENCIL_BUFFER_BITS);
|
format.setStencilBufferSize(DEFAULT_GL_STENCIL_BUFFER_BITS);
|
||||||
setGLFormatVersion(format);
|
setGLFormatVersion(format);
|
||||||
#ifdef DEBUG
|
if (enableDebug) {
|
||||||
format.setOption(QSurfaceFormat::DebugContext);
|
format.setOption(QSurfaceFormat::DebugContext);
|
||||||
#endif
|
}
|
||||||
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
|
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
|
||||||
QSurfaceFormat::setDefaultFormat(format);
|
QSurfaceFormat::setDefaultFormat(format);
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,23 +12,30 @@
|
||||||
|
|
||||||
#include "OffscreenGLCanvas.h"
|
#include "OffscreenGLCanvas.h"
|
||||||
|
|
||||||
|
#include <QtCore/QProcessEnvironment>
|
||||||
#include <QtGui/QOffscreenSurface>
|
#include <QtGui/QOffscreenSurface>
|
||||||
#include <QtGui/QOpenGLDebugLogger>
|
#include <QtGui/QOpenGLDebugLogger>
|
||||||
#include <QtGui/QOpenGLContext>
|
#include <QtGui/QOpenGLContext>
|
||||||
|
|
||||||
#include "GLHelpers.h"
|
#include "GLHelpers.h"
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
static bool enableDebugLogger = true;
|
||||||
|
#else
|
||||||
|
static const QString DEBUG_FLAG("HIFI_ENABLE_OPENGL_45");
|
||||||
|
static bool enableDebugLogger = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
OffscreenGLCanvas::OffscreenGLCanvas() : _context(new QOpenGLContext), _offscreenSurface(new QOffscreenSurface){
|
OffscreenGLCanvas::OffscreenGLCanvas() : _context(new QOpenGLContext), _offscreenSurface(new QOffscreenSurface){
|
||||||
}
|
}
|
||||||
|
|
||||||
OffscreenGLCanvas::~OffscreenGLCanvas() {
|
OffscreenGLCanvas::~OffscreenGLCanvas() {
|
||||||
#ifdef DEBUG
|
|
||||||
if (_logger) {
|
if (_logger) {
|
||||||
makeCurrent();
|
makeCurrent();
|
||||||
delete _logger;
|
delete _logger;
|
||||||
_logger = nullptr;
|
_logger = nullptr;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
_context->doneCurrent();
|
_context->doneCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +67,7 @@ bool OffscreenGLCanvas::makeCurrent() {
|
||||||
qDebug() << "GL Renderer: " << QString((const char*) glGetString(GL_RENDERER));
|
qDebug() << "GL Renderer: " << QString((const char*) glGetString(GL_RENDERER));
|
||||||
});
|
});
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (result && !_logger) {
|
if (result && !_logger) {
|
||||||
_logger = new QOpenGLDebugLogger(this);
|
_logger = new QOpenGLDebugLogger(this);
|
||||||
if (_logger->initialize()) {
|
if (_logger->initialize()) {
|
||||||
|
@ -71,7 +78,6 @@ bool OffscreenGLCanvas::makeCurrent() {
|
||||||
_logger->startLogging(QOpenGLDebugLogger::LoggingMode::SynchronousLogging);
|
_logger->startLogging(QOpenGLDebugLogger::LoggingMode::SynchronousLogging);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,10 +36,7 @@ protected:
|
||||||
std::once_flag _reportOnce;
|
std::once_flag _reportOnce;
|
||||||
QOpenGLContext* _context;
|
QOpenGLContext* _context;
|
||||||
QOffscreenSurface* _offscreenSurface;
|
QOffscreenSurface* _offscreenSurface;
|
||||||
#ifdef DEBUG
|
|
||||||
QOpenGLDebugLogger* _logger{ nullptr };
|
QOpenGLDebugLogger* _logger{ nullptr };
|
||||||
#endif
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_OffscreenGLCanvas_h
|
#endif // hifi_OffscreenGLCanvas_h
|
||||||
|
|
|
@ -416,7 +416,7 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) {
|
||||||
_updateTimer.start();
|
_updateTimer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OffscreenQmlSurface::resize(const QSize& newSize_) {
|
void OffscreenQmlSurface::resize(const QSize& newSize_, bool forceResize) {
|
||||||
|
|
||||||
if (!_renderer || !_renderer->_quickWindow) {
|
if (!_renderer || !_renderer->_quickWindow) {
|
||||||
return;
|
return;
|
||||||
|
@ -435,7 +435,7 @@ void OffscreenQmlSurface::resize(const QSize& newSize_) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize currentSize = _renderer->_quickWindow->geometry().size();
|
QSize currentSize = _renderer->_quickWindow->geometry().size();
|
||||||
if (newSize == currentSize) {
|
if (newSize == currentSize && !forceResize) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ public:
|
||||||
using MouseTranslator = std::function<QPoint(const QPointF&)>;
|
using MouseTranslator = std::function<QPoint(const QPointF&)>;
|
||||||
|
|
||||||
virtual void create(QOpenGLContext* context);
|
virtual void create(QOpenGLContext* context);
|
||||||
void resize(const QSize& size);
|
void resize(const QSize& size, bool forceResize = false);
|
||||||
QSize size() const;
|
QSize size() const;
|
||||||
Q_INVOKABLE QObject* load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
Q_INVOKABLE QObject* load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
||||||
Q_INVOKABLE QObject* load(const QString& qmlSourceFile, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {}) {
|
Q_INVOKABLE QObject* load(const QString& qmlSourceFile, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {}) {
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
#include "../gl41/GL41Backend.h"
|
#include "../gl41/GL41Backend.h"
|
||||||
|
#include "../gl45/GL45Backend.h"
|
||||||
|
|
||||||
#if defined(NSIGHT_FOUND)
|
#if defined(NSIGHT_FOUND)
|
||||||
#include "nvToolsExt.h"
|
#include "nvToolsExt.h"
|
||||||
|
@ -31,25 +32,21 @@
|
||||||
using namespace gpu;
|
using namespace gpu;
|
||||||
using namespace gpu::gl;
|
using namespace gpu::gl;
|
||||||
|
|
||||||
|
|
||||||
static const QString DEBUG_FLAG("HIFI_ENABLE_OPENGL_45");
|
static const QString DEBUG_FLAG("HIFI_ENABLE_OPENGL_45");
|
||||||
bool enableOpenGL45 = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG);
|
static bool enableOpenGL45 = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG);
|
||||||
|
|
||||||
Backend* GLBackend::createBackend() {
|
Backend* GLBackend::createBackend() {
|
||||||
|
|
||||||
#if 0
|
|
||||||
// FIXME provide a mechanism to override the backend for testing
|
// FIXME provide a mechanism to override the backend for testing
|
||||||
// Where the gpuContext is initialized and where the TRUE Backend is created and assigned
|
// Where the gpuContext is initialized and where the TRUE Backend is created and assigned
|
||||||
auto version = QOpenGLContextWrapper::currentContextVersion();
|
auto version = QOpenGLContextWrapper::currentContextVersion();
|
||||||
GLBackend* result;
|
GLBackend* result;
|
||||||
if (enableOpenGL45 && version >= 0x0405) {
|
if (enableOpenGL45 && version >= 0x0405) {
|
||||||
result = new gpu::gl45::GLBackend;
|
qDebug() << "Using OpenGL 4.5 backend";
|
||||||
|
result = new gpu::gl45::GL45Backend();
|
||||||
} else {
|
} else {
|
||||||
result = new gpu::gl41::GLBackend;
|
qDebug() << "Using OpenGL 4.1 backend";
|
||||||
|
result = new gpu::gl41::GL41Backend();
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
GLBackend* result = new gpu::gl41::GL41Backend;
|
|
||||||
#endif
|
|
||||||
result->initInput();
|
result->initInput();
|
||||||
result->initTransform();
|
result->initTransform();
|
||||||
gl::GLTexture::initTextureTransferHelper();
|
gl::GLTexture::initTextureTransferHelper();
|
||||||
|
|
|
@ -186,7 +186,7 @@ protected:
|
||||||
virtual void killInput() final;
|
virtual void killInput() final;
|
||||||
virtual void syncInputStateCache() final;
|
virtual void syncInputStateCache() final;
|
||||||
virtual void resetInputStage() final;
|
virtual void resetInputStage() final;
|
||||||
virtual void updateInput() = 0;
|
virtual void updateInput();
|
||||||
|
|
||||||
struct InputStageState {
|
struct InputStageState {
|
||||||
bool _invalidFormat { true };
|
bool _invalidFormat { true };
|
||||||
|
|
|
@ -150,3 +150,176 @@ void GLBackend::do_setIndirectBuffer(Batch& batch, size_t paramOffset) {
|
||||||
|
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Core 41 doesn't expose the features to really separate the vertex format from the vertex buffers binding
|
||||||
|
// Core 43 does :)
|
||||||
|
// FIXME crashing problem with glVertexBindingDivisor / glVertexAttribFormat
|
||||||
|
// Once resolved, break this up into the GL 4.1 and 4.5 backends
|
||||||
|
#if 1 || (GPU_INPUT_PROFILE == GPU_CORE_41)
|
||||||
|
#define NO_SUPPORT_VERTEX_ATTRIB_FORMAT
|
||||||
|
#else
|
||||||
|
#define SUPPORT_VERTEX_ATTRIB_FORMAT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void GLBackend::updateInput() {
|
||||||
|
#if defined(SUPPORT_VERTEX_ATTRIB_FORMAT)
|
||||||
|
if (_input._invalidFormat) {
|
||||||
|
|
||||||
|
InputStageState::ActivationCache newActivation;
|
||||||
|
|
||||||
|
// Assign the vertex format required
|
||||||
|
if (_input._format) {
|
||||||
|
for (auto& it : _input._format->getAttributes()) {
|
||||||
|
const Stream::Attribute& attrib = (it).second;
|
||||||
|
|
||||||
|
GLuint slot = attrib._slot;
|
||||||
|
GLuint count = attrib._element.getLocationScalarCount();
|
||||||
|
uint8_t locationCount = attrib._element.getLocationCount();
|
||||||
|
GLenum type = _elementTypeToGL41Type[attrib._element.getType()];
|
||||||
|
GLuint offset = attrib._offset;;
|
||||||
|
GLboolean isNormalized = attrib._element.isNormalized();
|
||||||
|
|
||||||
|
GLenum perLocationSize = attrib._element.getLocationSize();
|
||||||
|
|
||||||
|
for (size_t locNum = 0; locNum < locationCount; ++locNum) {
|
||||||
|
newActivation.set(slot + locNum);
|
||||||
|
glVertexAttribFormat(slot + locNum, count, type, isNormalized, offset + locNum * perLocationSize);
|
||||||
|
glVertexAttribBinding(slot + locNum, attrib._channel);
|
||||||
|
}
|
||||||
|
glVertexBindingDivisor(attrib._channel, attrib._frequency);
|
||||||
|
}
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manage Activation what was and what is expected now
|
||||||
|
for (size_t i = 0; i < newActivation.size(); i++) {
|
||||||
|
bool newState = newActivation[i];
|
||||||
|
if (newState != _input._attributeActivation[i]) {
|
||||||
|
if (newState) {
|
||||||
|
glEnableVertexAttribArray(i);
|
||||||
|
} else {
|
||||||
|
glDisableVertexAttribArray(i);
|
||||||
|
}
|
||||||
|
_input._attributeActivation.flip(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
_input._invalidFormat = false;
|
||||||
|
_stats._ISNumFormatChanges++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_input._invalidBuffers.any()) {
|
||||||
|
int numBuffers = _input._buffers.size();
|
||||||
|
auto buffer = _input._buffers.data();
|
||||||
|
auto vbo = _input._bufferVBOs.data();
|
||||||
|
auto offset = _input._bufferOffsets.data();
|
||||||
|
auto stride = _input._bufferStrides.data();
|
||||||
|
|
||||||
|
for (int bufferNum = 0; bufferNum < numBuffers; bufferNum++) {
|
||||||
|
if (_input._invalidBuffers.test(bufferNum)) {
|
||||||
|
glBindVertexBuffer(bufferNum, (*vbo), (*offset), (*stride));
|
||||||
|
}
|
||||||
|
buffer++;
|
||||||
|
vbo++;
|
||||||
|
offset++;
|
||||||
|
stride++;
|
||||||
|
}
|
||||||
|
_input._invalidBuffers.reset();
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (_input._invalidFormat || _input._invalidBuffers.any()) {
|
||||||
|
|
||||||
|
if (_input._invalidFormat) {
|
||||||
|
InputStageState::ActivationCache newActivation;
|
||||||
|
|
||||||
|
_stats._ISNumFormatChanges++;
|
||||||
|
|
||||||
|
// Check expected activation
|
||||||
|
if (_input._format) {
|
||||||
|
for (auto& it : _input._format->getAttributes()) {
|
||||||
|
const Stream::Attribute& attrib = (it).second;
|
||||||
|
uint8_t locationCount = attrib._element.getLocationCount();
|
||||||
|
for (int i = 0; i < locationCount; ++i) {
|
||||||
|
newActivation.set(attrib._slot + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manage Activation what was and what is expected now
|
||||||
|
for (unsigned int i = 0; i < newActivation.size(); i++) {
|
||||||
|
bool newState = newActivation[i];
|
||||||
|
if (newState != _input._attributeActivation[i]) {
|
||||||
|
|
||||||
|
if (newState) {
|
||||||
|
glEnableVertexAttribArray(i);
|
||||||
|
} else {
|
||||||
|
glDisableVertexAttribArray(i);
|
||||||
|
}
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
_input._attributeActivation.flip(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we need to bind the buffers and assign the attrib pointers
|
||||||
|
if (_input._format) {
|
||||||
|
const Buffers& buffers = _input._buffers;
|
||||||
|
const Offsets& offsets = _input._bufferOffsets;
|
||||||
|
const Offsets& strides = _input._bufferStrides;
|
||||||
|
|
||||||
|
const Stream::Format::AttributeMap& attributes = _input._format->getAttributes();
|
||||||
|
auto& inputChannels = _input._format->getChannels();
|
||||||
|
_stats._ISNumInputBufferChanges++;
|
||||||
|
|
||||||
|
GLuint boundVBO = 0;
|
||||||
|
for (auto& channelIt : inputChannels) {
|
||||||
|
const Stream::Format::ChannelMap::value_type::second_type& channel = (channelIt).second;
|
||||||
|
if ((channelIt).first < buffers.size()) {
|
||||||
|
int bufferNum = (channelIt).first;
|
||||||
|
|
||||||
|
if (_input._invalidBuffers.test(bufferNum) || _input._invalidFormat) {
|
||||||
|
// GLuint vbo = gpu::GL41Backend::getBufferID((*buffers[bufferNum]));
|
||||||
|
GLuint vbo = _input._bufferVBOs[bufferNum];
|
||||||
|
if (boundVBO != vbo) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
boundVBO = vbo;
|
||||||
|
}
|
||||||
|
_input._invalidBuffers[bufferNum] = false;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < channel._slots.size(); i++) {
|
||||||
|
const Stream::Attribute& attrib = attributes.at(channel._slots[i]);
|
||||||
|
GLuint slot = attrib._slot;
|
||||||
|
GLuint count = attrib._element.getLocationScalarCount();
|
||||||
|
uint8_t locationCount = attrib._element.getLocationCount();
|
||||||
|
GLenum type = gl::ELEMENT_TYPE_TO_GL[attrib._element.getType()];
|
||||||
|
// GLenum perLocationStride = strides[bufferNum];
|
||||||
|
GLenum perLocationStride = attrib._element.getLocationSize();
|
||||||
|
GLuint stride = (GLuint)strides[bufferNum];
|
||||||
|
GLuint pointer = (GLuint)(attrib._offset + offsets[bufferNum]);
|
||||||
|
GLboolean isNormalized = attrib._element.isNormalized();
|
||||||
|
|
||||||
|
for (size_t locNum = 0; locNum < locationCount; ++locNum) {
|
||||||
|
glVertexAttribPointer(slot + (GLuint)locNum, count, type, isNormalized, stride,
|
||||||
|
reinterpret_cast<GLvoid*>(pointer + perLocationStride * (GLuint)locNum));
|
||||||
|
glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Support properly the IAttrib version
|
||||||
|
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// everything format related should be in sync now
|
||||||
|
_input._invalidFormat = false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,173 +13,7 @@
|
||||||
using namespace gpu;
|
using namespace gpu;
|
||||||
using namespace gpu::gl41;
|
using namespace gpu::gl41;
|
||||||
|
|
||||||
// Core 41 doesn't expose the features to really separate the vertex format from the vertex buffers binding
|
|
||||||
// Core 43 does :)
|
|
||||||
// FIXME crashing problem with glVertexBindingDivisor / glVertexAttribFormat
|
|
||||||
#if 1 || (GPU_INPUT_PROFILE == GPU_CORE_41)
|
|
||||||
#define NO_SUPPORT_VERTEX_ATTRIB_FORMAT
|
|
||||||
#else
|
|
||||||
#define SUPPORT_VERTEX_ATTRIB_FORMAT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void GL41Backend::updateInput() {
|
void GL41Backend::updateInput() {
|
||||||
#if defined(SUPPORT_VERTEX_ATTRIB_FORMAT)
|
Parent::updateInput();
|
||||||
if (_input._invalidFormat) {
|
|
||||||
|
|
||||||
InputStageState::ActivationCache newActivation;
|
|
||||||
|
|
||||||
// Assign the vertex format required
|
|
||||||
if (_input._format) {
|
|
||||||
for (auto& it : _input._format->getAttributes()) {
|
|
||||||
const Stream::Attribute& attrib = (it).second;
|
|
||||||
|
|
||||||
GLuint slot = attrib._slot;
|
|
||||||
GLuint count = attrib._element.getLocationScalarCount();
|
|
||||||
uint8_t locationCount = attrib._element.getLocationCount();
|
|
||||||
GLenum type = _elementTypeToGL41Type[attrib._element.getType()];
|
|
||||||
GLuint offset = attrib._offset;;
|
|
||||||
GLboolean isNormalized = attrib._element.isNormalized();
|
|
||||||
|
|
||||||
GLenum perLocationSize = attrib._element.getLocationSize();
|
|
||||||
|
|
||||||
for (size_t locNum = 0; locNum < locationCount; ++locNum) {
|
|
||||||
newActivation.set(slot + locNum);
|
|
||||||
glVertexAttribFormat(slot + locNum, count, type, isNormalized, offset + locNum * perLocationSize);
|
|
||||||
glVertexAttribBinding(slot + locNum, attrib._channel);
|
|
||||||
}
|
|
||||||
glVertexBindingDivisor(attrib._channel, attrib._frequency);
|
|
||||||
}
|
|
||||||
(void) CHECK_GL_ERROR();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Manage Activation what was and what is expected now
|
|
||||||
for (size_t i = 0; i < newActivation.size(); i++) {
|
|
||||||
bool newState = newActivation[i];
|
|
||||||
if (newState != _input._attributeActivation[i]) {
|
|
||||||
if (newState) {
|
|
||||||
glEnableVertexAttribArray(i);
|
|
||||||
} else {
|
|
||||||
glDisableVertexAttribArray(i);
|
|
||||||
}
|
|
||||||
_input._attributeActivation.flip(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(void) CHECK_GL_ERROR();
|
|
||||||
|
|
||||||
_input._invalidFormat = false;
|
|
||||||
_stats._ISNumFormatChanges++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_input._invalidBuffers.any()) {
|
|
||||||
int numBuffers = _input._buffers.size();
|
|
||||||
auto buffer = _input._buffers.data();
|
|
||||||
auto vbo = _input._bufferVBOs.data();
|
|
||||||
auto offset = _input._bufferOffsets.data();
|
|
||||||
auto stride = _input._bufferStrides.data();
|
|
||||||
|
|
||||||
for (int bufferNum = 0; bufferNum < numBuffers; bufferNum++) {
|
|
||||||
if (_input._invalidBuffers.test(bufferNum)) {
|
|
||||||
glBindVertexBuffer(bufferNum, (*vbo), (*offset), (*stride));
|
|
||||||
}
|
|
||||||
buffer++;
|
|
||||||
vbo++;
|
|
||||||
offset++;
|
|
||||||
stride++;
|
|
||||||
}
|
|
||||||
_input._invalidBuffers.reset();
|
|
||||||
(void) CHECK_GL_ERROR();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (_input._invalidFormat || _input._invalidBuffers.any()) {
|
|
||||||
|
|
||||||
if (_input._invalidFormat) {
|
|
||||||
InputStageState::ActivationCache newActivation;
|
|
||||||
|
|
||||||
_stats._ISNumFormatChanges++;
|
|
||||||
|
|
||||||
// Check expected activation
|
|
||||||
if (_input._format) {
|
|
||||||
for (auto& it : _input._format->getAttributes()) {
|
|
||||||
const Stream::Attribute& attrib = (it).second;
|
|
||||||
uint8_t locationCount = attrib._element.getLocationCount();
|
|
||||||
for (int i = 0; i < locationCount; ++i) {
|
|
||||||
newActivation.set(attrib._slot + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Manage Activation what was and what is expected now
|
|
||||||
for (unsigned int i = 0; i < newActivation.size(); i++) {
|
|
||||||
bool newState = newActivation[i];
|
|
||||||
if (newState != _input._attributeActivation[i]) {
|
|
||||||
|
|
||||||
if (newState) {
|
|
||||||
glEnableVertexAttribArray(i);
|
|
||||||
} else {
|
|
||||||
glDisableVertexAttribArray(i);
|
|
||||||
}
|
|
||||||
(void) CHECK_GL_ERROR();
|
|
||||||
|
|
||||||
_input._attributeActivation.flip(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now we need to bind the buffers and assign the attrib pointers
|
|
||||||
if (_input._format) {
|
|
||||||
const Buffers& buffers = _input._buffers;
|
|
||||||
const Offsets& offsets = _input._bufferOffsets;
|
|
||||||
const Offsets& strides = _input._bufferStrides;
|
|
||||||
|
|
||||||
const Stream::Format::AttributeMap& attributes = _input._format->getAttributes();
|
|
||||||
auto& inputChannels = _input._format->getChannels();
|
|
||||||
_stats._ISNumInputBufferChanges++;
|
|
||||||
|
|
||||||
GLuint boundVBO = 0;
|
|
||||||
for (auto& channelIt : inputChannels) {
|
|
||||||
const Stream::Format::ChannelMap::value_type::second_type& channel = (channelIt).second;
|
|
||||||
if ((channelIt).first < buffers.size()) {
|
|
||||||
int bufferNum = (channelIt).first;
|
|
||||||
|
|
||||||
if (_input._invalidBuffers.test(bufferNum) || _input._invalidFormat) {
|
|
||||||
// GLuint vbo = gpu::GL41Backend::getBufferID((*buffers[bufferNum]));
|
|
||||||
GLuint vbo = _input._bufferVBOs[bufferNum];
|
|
||||||
if (boundVBO != vbo) {
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
||||||
(void) CHECK_GL_ERROR();
|
|
||||||
boundVBO = vbo;
|
|
||||||
}
|
|
||||||
_input._invalidBuffers[bufferNum] = false;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < channel._slots.size(); i++) {
|
|
||||||
const Stream::Attribute& attrib = attributes.at(channel._slots[i]);
|
|
||||||
GLuint slot = attrib._slot;
|
|
||||||
GLuint count = attrib._element.getLocationScalarCount();
|
|
||||||
uint8_t locationCount = attrib._element.getLocationCount();
|
|
||||||
GLenum type = gl::ELEMENT_TYPE_TO_GL[attrib._element.getType()];
|
|
||||||
// GLenum perLocationStride = strides[bufferNum];
|
|
||||||
GLenum perLocationStride = attrib._element.getLocationSize();
|
|
||||||
GLuint stride = (GLuint)strides[bufferNum];
|
|
||||||
GLuint pointer = (GLuint)(attrib._offset + offsets[bufferNum]);
|
|
||||||
GLboolean isNormalized = attrib._element.isNormalized();
|
|
||||||
|
|
||||||
for (size_t locNum = 0; locNum < locationCount; ++locNum) {
|
|
||||||
glVertexAttribPointer(slot + (GLuint)locNum, count, type, isNormalized, stride,
|
|
||||||
reinterpret_cast<GLvoid*>(pointer + perLocationStride * (GLuint)locNum));
|
|
||||||
glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Support properly the IAttrib version
|
|
||||||
|
|
||||||
(void) CHECK_GL_ERROR();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// everything format related should be in sync now
|
|
||||||
_input._invalidFormat = false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ using namespace gpu;
|
||||||
using namespace gpu::gl41;
|
using namespace gpu::gl41;
|
||||||
|
|
||||||
class GL41Query : public gpu::gl::GLQuery {
|
class GL41Query : public gpu::gl::GLQuery {
|
||||||
using Parent = gpu::gl::GLBuffer;
|
using Parent = gpu::gl::GLQuery;
|
||||||
public:
|
public:
|
||||||
static GLuint allocateQuery() {
|
static GLuint allocateQuery() {
|
||||||
GLuint result;
|
GLuint result;
|
||||||
|
@ -25,7 +25,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
GL41Query(const Query& query)
|
GL41Query(const Query& query)
|
||||||
: gl::GLQuery(query, allocateQuery()) { }
|
: Parent(query, allocateQuery()) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
gl::GLQuery* GL41Backend::syncGPUObject(const Query& query) {
|
gl::GLQuery* GL41Backend::syncGPUObject(const Query& query) {
|
||||||
|
|
149
libraries/gpu-gl/src/gpu/gl45/GL45Backend.cpp
Normal file
149
libraries/gpu-gl/src/gpu/gl45/GL45Backend.cpp
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 10/27/2014.
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
#include "GL45Backend.h"
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <queue>
|
||||||
|
#include <list>
|
||||||
|
#include <functional>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
|
Q_LOGGING_CATEGORY(gpugl45logging, "hifi.gpu.gl45")
|
||||||
|
|
||||||
|
using namespace gpu;
|
||||||
|
using namespace gpu::gl45;
|
||||||
|
|
||||||
|
void GL45Backend::do_draw(Batch& batch, size_t paramOffset) {
|
||||||
|
Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint;
|
||||||
|
GLenum mode = gl::PRIMITIVE_TO_GL[primitiveType];
|
||||||
|
uint32 numVertices = batch._params[paramOffset + 1]._uint;
|
||||||
|
uint32 startVertex = batch._params[paramOffset + 0]._uint;
|
||||||
|
|
||||||
|
if (isStereo()) {
|
||||||
|
setupStereoSide(0);
|
||||||
|
glDrawArrays(mode, startVertex, numVertices);
|
||||||
|
setupStereoSide(1);
|
||||||
|
glDrawArrays(mode, startVertex, numVertices);
|
||||||
|
|
||||||
|
_stats._DSNumTriangles += 2 * numVertices / 3;
|
||||||
|
_stats._DSNumDrawcalls += 2;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
glDrawArrays(mode, startVertex, numVertices);
|
||||||
|
_stats._DSNumTriangles += numVertices / 3;
|
||||||
|
_stats._DSNumDrawcalls++;
|
||||||
|
}
|
||||||
|
_stats._DSNumAPIDrawcalls++;
|
||||||
|
|
||||||
|
(void) CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL45Backend::do_drawIndexed(Batch& batch, size_t paramOffset) {
|
||||||
|
Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint;
|
||||||
|
GLenum mode = gl::PRIMITIVE_TO_GL[primitiveType];
|
||||||
|
uint32 numIndices = batch._params[paramOffset + 1]._uint;
|
||||||
|
uint32 startIndex = batch._params[paramOffset + 0]._uint;
|
||||||
|
|
||||||
|
GLenum glType = gl::ELEMENT_TYPE_TO_GL[_input._indexBufferType];
|
||||||
|
|
||||||
|
auto typeByteSize = TYPE_SIZE[_input._indexBufferType];
|
||||||
|
GLvoid* indexBufferByteOffset = reinterpret_cast<GLvoid*>(startIndex * typeByteSize + _input._indexBufferOffset);
|
||||||
|
|
||||||
|
if (isStereo()) {
|
||||||
|
setupStereoSide(0);
|
||||||
|
glDrawElements(mode, numIndices, glType, indexBufferByteOffset);
|
||||||
|
setupStereoSide(1);
|
||||||
|
glDrawElements(mode, numIndices, glType, indexBufferByteOffset);
|
||||||
|
|
||||||
|
_stats._DSNumTriangles += 2 * numIndices / 3;
|
||||||
|
_stats._DSNumDrawcalls += 2;
|
||||||
|
} else {
|
||||||
|
glDrawElements(mode, numIndices, glType, indexBufferByteOffset);
|
||||||
|
_stats._DSNumTriangles += numIndices / 3;
|
||||||
|
_stats._DSNumDrawcalls++;
|
||||||
|
}
|
||||||
|
_stats._DSNumAPIDrawcalls++;
|
||||||
|
|
||||||
|
(void) CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL45Backend::do_drawInstanced(Batch& batch, size_t paramOffset) {
|
||||||
|
GLint numInstances = batch._params[paramOffset + 4]._uint;
|
||||||
|
Primitive primitiveType = (Primitive)batch._params[paramOffset + 3]._uint;
|
||||||
|
GLenum mode = gl::PRIMITIVE_TO_GL[primitiveType];
|
||||||
|
uint32 numVertices = batch._params[paramOffset + 2]._uint;
|
||||||
|
uint32 startVertex = batch._params[paramOffset + 1]._uint;
|
||||||
|
|
||||||
|
|
||||||
|
if (isStereo()) {
|
||||||
|
GLint trueNumInstances = 2 * numInstances;
|
||||||
|
|
||||||
|
setupStereoSide(0);
|
||||||
|
glDrawArraysInstanced(mode, startVertex, numVertices, numInstances);
|
||||||
|
setupStereoSide(1);
|
||||||
|
glDrawArraysInstanced(mode, startVertex, numVertices, numInstances);
|
||||||
|
|
||||||
|
_stats._DSNumTriangles += (trueNumInstances * numVertices) / 3;
|
||||||
|
_stats._DSNumDrawcalls += trueNumInstances;
|
||||||
|
} else {
|
||||||
|
glDrawArraysInstanced(mode, startVertex, numVertices, numInstances);
|
||||||
|
_stats._DSNumTriangles += (numInstances * numVertices) / 3;
|
||||||
|
_stats._DSNumDrawcalls += numInstances;
|
||||||
|
}
|
||||||
|
_stats._DSNumAPIDrawcalls++;
|
||||||
|
|
||||||
|
(void) CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL45Backend::do_drawIndexedInstanced(Batch& batch, size_t paramOffset) {
|
||||||
|
GLint numInstances = batch._params[paramOffset + 4]._uint;
|
||||||
|
GLenum mode = gl::PRIMITIVE_TO_GL[(Primitive)batch._params[paramOffset + 3]._uint];
|
||||||
|
uint32 numIndices = batch._params[paramOffset + 2]._uint;
|
||||||
|
uint32 startIndex = batch._params[paramOffset + 1]._uint;
|
||||||
|
uint32 startInstance = batch._params[paramOffset + 0]._uint;
|
||||||
|
GLenum glType = gl::ELEMENT_TYPE_TO_GL[_input._indexBufferType];
|
||||||
|
auto typeByteSize = TYPE_SIZE[_input._indexBufferType];
|
||||||
|
GLvoid* indexBufferByteOffset = reinterpret_cast<GLvoid*>(startIndex * typeByteSize + _input._indexBufferOffset);
|
||||||
|
|
||||||
|
if (isStereo()) {
|
||||||
|
GLint trueNumInstances = 2 * numInstances;
|
||||||
|
setupStereoSide(0);
|
||||||
|
glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance);
|
||||||
|
setupStereoSide(1);
|
||||||
|
glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance);
|
||||||
|
_stats._DSNumTriangles += (trueNumInstances * numIndices) / 3;
|
||||||
|
_stats._DSNumDrawcalls += trueNumInstances;
|
||||||
|
} else {
|
||||||
|
glDrawElementsInstancedBaseVertexBaseInstance(mode, numIndices, glType, indexBufferByteOffset, numInstances, 0, startInstance);
|
||||||
|
_stats._DSNumTriangles += (numInstances * numIndices) / 3;
|
||||||
|
_stats._DSNumDrawcalls += numInstances;
|
||||||
|
}
|
||||||
|
|
||||||
|
_stats._DSNumAPIDrawcalls++;
|
||||||
|
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL45Backend::do_multiDrawIndirect(Batch& batch, size_t paramOffset) {
|
||||||
|
uint commandCount = batch._params[paramOffset + 0]._uint;
|
||||||
|
GLenum mode = gl::PRIMITIVE_TO_GL[(Primitive)batch._params[paramOffset + 1]._uint];
|
||||||
|
glMultiDrawArraysIndirect(mode, reinterpret_cast<GLvoid*>(_input._indirectBufferOffset), commandCount, (GLsizei)_input._indirectBufferStride);
|
||||||
|
_stats._DSNumDrawcalls += commandCount;
|
||||||
|
_stats._DSNumAPIDrawcalls++;
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL45Backend::do_multiDrawIndexedIndirect(Batch& batch, size_t paramOffset) {
|
||||||
|
uint commandCount = batch._params[paramOffset + 0]._uint;
|
||||||
|
GLenum mode = gl::PRIMITIVE_TO_GL[(Primitive)batch._params[paramOffset + 1]._uint];
|
||||||
|
GLenum indexType = gl::ELEMENT_TYPE_TO_GL[_input._indexBufferType];
|
||||||
|
glMultiDrawElementsIndirect(mode, indexType, reinterpret_cast<GLvoid*>(_input._indirectBufferOffset), commandCount, (GLsizei)_input._indirectBufferStride);
|
||||||
|
_stats._DSNumDrawcalls += commandCount;
|
||||||
|
_stats._DSNumAPIDrawcalls++;
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
}
|
85
libraries/gpu-gl/src/gpu/gl45/GL45Backend.h
Normal file
85
libraries/gpu-gl/src/gpu/gl45/GL45Backend.h
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
//
|
||||||
|
// GL45Backend.h
|
||||||
|
// libraries/gpu/src/gpu
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 10/27/2014.
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
#ifndef hifi_gpu_45_GL45Backend_h
|
||||||
|
#define hifi_gpu_45_GL45Backend_h
|
||||||
|
|
||||||
|
#include "../gl/GLBackend.h"
|
||||||
|
#include "../gl/GLTexture.h"
|
||||||
|
|
||||||
|
namespace gpu { namespace gl45 {
|
||||||
|
|
||||||
|
class GL45Backend : public gl::GLBackend {
|
||||||
|
using Parent = gl::GLBackend;
|
||||||
|
// Context Backend static interface required
|
||||||
|
friend class Context;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GL45Backend(bool syncCache) : Parent(syncCache) {}
|
||||||
|
GL45Backend() : Parent() {}
|
||||||
|
|
||||||
|
class GL45Texture : public gpu::gl::GLTexture {
|
||||||
|
using Parent = gpu::gl::GLTexture;
|
||||||
|
GLuint allocate(const Texture& texture);
|
||||||
|
public:
|
||||||
|
GL45Texture(const Texture& texture, bool transferrable);
|
||||||
|
GL45Texture(const Texture& texture, GLTexture* original);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void transferMip(uint16_t mipLevel, uint8_t face = 0) const;
|
||||||
|
void allocateStorage() const override;
|
||||||
|
void updateSize() const override;
|
||||||
|
void transfer() const override;
|
||||||
|
void syncSampler() const override;
|
||||||
|
void generateMips() const override;
|
||||||
|
void withPreservedTexture(std::function<void()> f) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
GLuint getFramebufferID(const FramebufferPointer& framebuffer) override;
|
||||||
|
gl::GLFramebuffer* syncGPUObject(const Framebuffer& framebuffer) override;
|
||||||
|
|
||||||
|
GLuint getBufferID(const Buffer& buffer) override;
|
||||||
|
gl::GLBuffer* syncGPUObject(const Buffer& buffer) override;
|
||||||
|
|
||||||
|
GLuint getTextureID(const TexturePointer& texture, bool needTransfer = true) override;
|
||||||
|
gl::GLTexture* syncGPUObject(const TexturePointer& texture, bool sync = true) override;
|
||||||
|
|
||||||
|
GLuint getQueryID(const QueryPointer& query) override;
|
||||||
|
gl::GLQuery* syncGPUObject(const Query& query) override;
|
||||||
|
|
||||||
|
// Draw Stage
|
||||||
|
void do_draw(Batch& batch, size_t paramOffset) override;
|
||||||
|
void do_drawIndexed(Batch& batch, size_t paramOffset) override;
|
||||||
|
void do_drawInstanced(Batch& batch, size_t paramOffset) override;
|
||||||
|
void do_drawIndexedInstanced(Batch& batch, size_t paramOffset) override;
|
||||||
|
void do_multiDrawIndirect(Batch& batch, size_t paramOffset) override;
|
||||||
|
void do_multiDrawIndexedIndirect(Batch& batch, size_t paramOffset) override;
|
||||||
|
|
||||||
|
// Input Stage
|
||||||
|
void updateInput() override;
|
||||||
|
|
||||||
|
// Synchronize the state cache of this Backend with the actual real state of the GL Context
|
||||||
|
void transferTransformState(const Batch& batch) const override;
|
||||||
|
void initTransform() override;
|
||||||
|
void updateTransform(const Batch& batch);
|
||||||
|
void resetTransformStage();
|
||||||
|
|
||||||
|
// Output stage
|
||||||
|
void do_blit(Batch& batch, size_t paramOffset) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} }
|
||||||
|
|
||||||
|
Q_DECLARE_LOGGING_CATEGORY(gpugl45logging)
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
50
libraries/gpu-gl/src/gpu/gl45/GL45BackendBuffer.cpp
Normal file
50
libraries/gpu-gl/src/gpu/gl45/GL45BackendBuffer.cpp
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2016/05/15
|
||||||
|
// Copyright 2013-2016 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
#include "GL45Backend.h"
|
||||||
|
#include "../gl/GLBuffer.h"
|
||||||
|
|
||||||
|
using namespace gpu;
|
||||||
|
using namespace gpu::gl45;
|
||||||
|
|
||||||
|
class GL45Buffer : public gl::GLBuffer {
|
||||||
|
using Parent = gpu::gl::GLBuffer;
|
||||||
|
static GLuint allocate() {
|
||||||
|
GLuint result;
|
||||||
|
glCreateBuffers(1, &result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
GL45Buffer(const Buffer& buffer, GLBuffer* original) : Parent(buffer, allocate()) {
|
||||||
|
glNamedBufferStorage(_buffer, _size, nullptr, GL_DYNAMIC_STORAGE_BIT);
|
||||||
|
if (original && original->_size) {
|
||||||
|
glCopyNamedBufferSubData(original->_buffer, _buffer, 0, 0, std::min(original->_size, _size));
|
||||||
|
}
|
||||||
|
Backend::setGPUObject(buffer, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void transfer() override {
|
||||||
|
Size offset;
|
||||||
|
Size size;
|
||||||
|
Size currentPage { 0 };
|
||||||
|
auto data = _gpuObject.getSysmem().readData();
|
||||||
|
while (_gpuObject.getNextTransferBlock(offset, size, currentPage)) {
|
||||||
|
glNamedBufferSubData(_buffer, (GLintptr)offset, (GLsizeiptr)size, data + offset);
|
||||||
|
}
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
_gpuObject._flags &= ~Buffer::DIRTY;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
GLuint GL45Backend::getBufferID(const Buffer& buffer) {
|
||||||
|
return GL45Buffer::getId<GL45Buffer>(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
gl::GLBuffer* GL45Backend::syncGPUObject(const Buffer& buffer) {
|
||||||
|
return GL45Buffer::sync<GL45Buffer>(buffer);
|
||||||
|
}
|
18
libraries/gpu-gl/src/gpu/gl45/GL45BackendInput.cpp
Normal file
18
libraries/gpu-gl/src/gpu/gl45/GL45BackendInput.cpp
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
//
|
||||||
|
// GL45BackendInput.cpp
|
||||||
|
// libraries/gpu/src/gpu
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 3/8/2015.
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
#include "GL45Backend.h"
|
||||||
|
|
||||||
|
using namespace gpu;
|
||||||
|
using namespace gpu::gl45;
|
||||||
|
|
||||||
|
void GL45Backend::updateInput() {
|
||||||
|
Parent::updateInput();
|
||||||
|
}
|
145
libraries/gpu-gl/src/gpu/gl45/GL45BackendOutput.cpp
Normal file
145
libraries/gpu-gl/src/gpu/gl45/GL45BackendOutput.cpp
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
//
|
||||||
|
// GL45BackendTexture.cpp
|
||||||
|
// libraries/gpu/src/gpu
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 1/19/2015.
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
#include "GL45Backend.h"
|
||||||
|
#include "../gl/GLFramebuffer.h"
|
||||||
|
#include "../gl/GLTexture.h"
|
||||||
|
|
||||||
|
#include <QtGui/QImage>
|
||||||
|
|
||||||
|
namespace gpu { namespace gl45 {
|
||||||
|
|
||||||
|
class GL45Framebuffer : public gl::GLFramebuffer {
|
||||||
|
using Parent = gl::GLFramebuffer;
|
||||||
|
static GLuint allocate() {
|
||||||
|
GLuint result;
|
||||||
|
glCreateFramebuffers(1, &result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
void update() override {
|
||||||
|
gl::GLTexture* gltexture = nullptr;
|
||||||
|
TexturePointer surface;
|
||||||
|
if (_gpuObject.getColorStamps() != _colorStamps) {
|
||||||
|
if (_gpuObject.hasColor()) {
|
||||||
|
_colorBuffers.clear();
|
||||||
|
static const GLenum colorAttachments[] = {
|
||||||
|
GL_COLOR_ATTACHMENT0,
|
||||||
|
GL_COLOR_ATTACHMENT1,
|
||||||
|
GL_COLOR_ATTACHMENT2,
|
||||||
|
GL_COLOR_ATTACHMENT3,
|
||||||
|
GL_COLOR_ATTACHMENT4,
|
||||||
|
GL_COLOR_ATTACHMENT5,
|
||||||
|
GL_COLOR_ATTACHMENT6,
|
||||||
|
GL_COLOR_ATTACHMENT7,
|
||||||
|
GL_COLOR_ATTACHMENT8,
|
||||||
|
GL_COLOR_ATTACHMENT9,
|
||||||
|
GL_COLOR_ATTACHMENT10,
|
||||||
|
GL_COLOR_ATTACHMENT11,
|
||||||
|
GL_COLOR_ATTACHMENT12,
|
||||||
|
GL_COLOR_ATTACHMENT13,
|
||||||
|
GL_COLOR_ATTACHMENT14,
|
||||||
|
GL_COLOR_ATTACHMENT15 };
|
||||||
|
|
||||||
|
int unit = 0;
|
||||||
|
for (auto& b : _gpuObject.getRenderBuffers()) {
|
||||||
|
surface = b._texture;
|
||||||
|
if (surface) {
|
||||||
|
gltexture = gl::GLTexture::sync<GL45Backend::GL45Texture>(surface, false); // Grab the gltexture and don't transfer
|
||||||
|
} else {
|
||||||
|
gltexture = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gltexture) {
|
||||||
|
glNamedFramebufferTexture(_id, colorAttachments[unit], gltexture->_texture, 0);
|
||||||
|
_colorBuffers.push_back(colorAttachments[unit]);
|
||||||
|
} else {
|
||||||
|
glNamedFramebufferTexture(_id, colorAttachments[unit], 0, 0);
|
||||||
|
}
|
||||||
|
unit++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_colorStamps = _gpuObject.getColorStamps();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLenum attachement = GL_DEPTH_STENCIL_ATTACHMENT;
|
||||||
|
if (!_gpuObject.hasStencil()) {
|
||||||
|
attachement = GL_DEPTH_ATTACHMENT;
|
||||||
|
} else if (!_gpuObject.hasDepth()) {
|
||||||
|
attachement = GL_STENCIL_ATTACHMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_gpuObject.getDepthStamp() != _depthStamp) {
|
||||||
|
auto surface = _gpuObject.getDepthStencilBuffer();
|
||||||
|
if (_gpuObject.hasDepthStencil() && surface) {
|
||||||
|
gltexture = gl::GLTexture::sync<GL45Backend::GL45Texture>(surface, false); // Grab the gltexture and don't transfer
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gltexture) {
|
||||||
|
glNamedFramebufferTexture(_id, attachement, gltexture->_texture, 0);
|
||||||
|
} else {
|
||||||
|
glNamedFramebufferTexture(_id, attachement, 0, 0);
|
||||||
|
}
|
||||||
|
_depthStamp = _gpuObject.getDepthStamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Last but not least, define where we draw
|
||||||
|
if (!_colorBuffers.empty()) {
|
||||||
|
glNamedFramebufferDrawBuffers(_id, (GLsizei)_colorBuffers.size(), _colorBuffers.data());
|
||||||
|
} else {
|
||||||
|
glNamedFramebufferDrawBuffer(_id, GL_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now check for completness
|
||||||
|
_status = glCheckNamedFramebufferStatus(_id, GL_DRAW_FRAMEBUFFER);
|
||||||
|
|
||||||
|
// restore the current framebuffer
|
||||||
|
checkStatus(GL_DRAW_FRAMEBUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
GL45Framebuffer(const gpu::Framebuffer& framebuffer)
|
||||||
|
: Parent(framebuffer, allocate()) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
gl::GLFramebuffer* GL45Backend::syncGPUObject(const Framebuffer& framebuffer) {
|
||||||
|
return gl::GLFramebuffer::sync<GL45Framebuffer>(framebuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint GL45Backend::getFramebufferID(const FramebufferPointer& framebuffer) {
|
||||||
|
return framebuffer ? gl::GLFramebuffer::getId<GL45Framebuffer>(*framebuffer) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL45Backend::do_blit(Batch& batch, size_t paramOffset) {
|
||||||
|
auto srcframebuffer = batch._framebuffers.get(batch._params[paramOffset]._uint);
|
||||||
|
Vec4i srcvp;
|
||||||
|
for (auto i = 0; i < 4; ++i) {
|
||||||
|
srcvp[i] = batch._params[paramOffset + 1 + i]._int;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dstframebuffer = batch._framebuffers.get(batch._params[paramOffset + 5]._uint);
|
||||||
|
Vec4i dstvp;
|
||||||
|
for (auto i = 0; i < 4; ++i) {
|
||||||
|
dstvp[i] = batch._params[paramOffset + 6 + i]._int;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign dest framebuffer if not bound already
|
||||||
|
auto destFbo = getFramebufferID(dstframebuffer);
|
||||||
|
auto srcFbo = getFramebufferID(srcframebuffer);
|
||||||
|
glBlitNamedFramebuffer(srcFbo, destFbo,
|
||||||
|
srcvp.x, srcvp.y, srcvp.z, srcvp.w,
|
||||||
|
dstvp.x, dstvp.y, dstvp.z, dstvp.w,
|
||||||
|
GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||||
|
(void) CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
|
||||||
|
} }
|
38
libraries/gpu-gl/src/gpu/gl45/GL45BackendQuery.cpp
Normal file
38
libraries/gpu-gl/src/gpu/gl45/GL45BackendQuery.cpp
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
//
|
||||||
|
// GL45BackendQuery.cpp
|
||||||
|
// libraries/gpu/src/gpu
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 7/7/2015.
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
#include "GL45Backend.h"
|
||||||
|
|
||||||
|
#include "../gl/GLQuery.h"
|
||||||
|
|
||||||
|
namespace gpu { namespace gl45 {
|
||||||
|
|
||||||
|
class GL45Query : public gpu::gl::GLQuery {
|
||||||
|
using Parent = gpu::gl::GLQuery;
|
||||||
|
public:
|
||||||
|
static GLuint allocateQuery() {
|
||||||
|
GLuint result;
|
||||||
|
glCreateQueries(GL_TIME_ELAPSED, 1, &result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
GL45Query(const Query& query)
|
||||||
|
: Parent(query, allocateQuery()) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
gl::GLQuery* GL45Backend::syncGPUObject(const Query& query) {
|
||||||
|
return GL45Query::sync<GL45Query>(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint GL45Backend::getQueryID(const QueryPointer& query) {
|
||||||
|
return GL45Query::getId<GL45Query>(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
} }
|
181
libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp
Normal file
181
libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
//
|
||||||
|
// GL45BackendTexture.cpp
|
||||||
|
// libraries/gpu/src/gpu
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 1/19/2015.
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
#include "GL45Backend.h"
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <QtCore/QThread>
|
||||||
|
|
||||||
|
#include "../gl/GLTexelFormat.h"
|
||||||
|
|
||||||
|
using namespace gpu;
|
||||||
|
using namespace gpu::gl45;
|
||||||
|
|
||||||
|
using GLTexelFormat = gl::GLTexelFormat;
|
||||||
|
using GL45Texture = GL45Backend::GL45Texture;
|
||||||
|
|
||||||
|
GLuint GL45Texture::allocate(const Texture& texture) {
|
||||||
|
Backend::incrementTextureGPUCount();
|
||||||
|
GLuint result;
|
||||||
|
glCreateTextures(getGLTextureType(texture), 1, &result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint GL45Backend::getTextureID(const TexturePointer& texture, bool transfer) {
|
||||||
|
return GL45Texture::getId<GL45Texture>(texture, transfer);
|
||||||
|
}
|
||||||
|
|
||||||
|
gl::GLTexture* GL45Backend::syncGPUObject(const TexturePointer& texture, bool transfer) {
|
||||||
|
return GL45Texture::sync<GL45Texture>(texture, transfer);
|
||||||
|
}
|
||||||
|
|
||||||
|
GL45Backend::GL45Texture::GL45Texture(const Texture& texture, bool transferrable)
|
||||||
|
: gl::GLTexture(texture, allocate(texture), transferrable) {}
|
||||||
|
|
||||||
|
GL45Backend::GL45Texture::GL45Texture(const Texture& texture, GLTexture* original)
|
||||||
|
: gl::GLTexture(texture, allocate(texture), original) {}
|
||||||
|
|
||||||
|
void GL45Backend::GL45Texture::withPreservedTexture(std::function<void()> f) const {
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL45Backend::GL45Texture::generateMips() const {
|
||||||
|
glGenerateTextureMipmap(_id);
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL45Backend::GL45Texture::allocateStorage() const {
|
||||||
|
gl::GLTexelFormat texelFormat = gl::GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat());
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_MAX_LEVEL, _maxMip - _minMip);
|
||||||
|
if (_gpuObject.getTexelFormat().isCompressed()) {
|
||||||
|
qFatal("Compressed textures not yet supported");
|
||||||
|
}
|
||||||
|
// Get the dimensions, accounting for the downgrade level
|
||||||
|
Vec3u dimensions = _gpuObject.evalMipDimensions(_minMip);
|
||||||
|
glTextureStorage2D(_id, usedMipLevels(), texelFormat.internalFormat, dimensions.x, dimensions.y);
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL45Backend::GL45Texture::updateSize() const {
|
||||||
|
setSize(_virtualSize);
|
||||||
|
if (!_id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_gpuObject.getTexelFormat().isCompressed()) {
|
||||||
|
qFatal("Compressed textures not yet supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move content bits from the CPU to the GPU for a given mip / face
|
||||||
|
void GL45Backend::GL45Texture::transferMip(uint16_t mipLevel, uint8_t face) const {
|
||||||
|
auto mip = _gpuObject.accessStoredMipFace(mipLevel, face);
|
||||||
|
gl::GLTexelFormat texelFormat = gl::GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat(), mip->getFormat());
|
||||||
|
auto size = _gpuObject.evalMipDimensions(mipLevel);
|
||||||
|
if (GL_TEXTURE_2D == _target) {
|
||||||
|
glTextureSubImage2D(_id, mipLevel, 0, 0, size.x, size.y, texelFormat.format, texelFormat.type, mip->readData());
|
||||||
|
} else if (GL_TEXTURE_CUBE_MAP == _target) {
|
||||||
|
glTextureSubImage3D(_id, mipLevel, 0, 0, face, size.x, size.y, 1, texelFormat.format, texelFormat.type, mip->readData());
|
||||||
|
} else {
|
||||||
|
Q_ASSERT(false);
|
||||||
|
}
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This should never happen on the main thread
|
||||||
|
// Move content bits from the CPU to the GPU
|
||||||
|
void GL45Backend::GL45Texture::transfer() const {
|
||||||
|
PROFILE_RANGE(__FUNCTION__);
|
||||||
|
//qDebug() << "Transferring texture: " << _privateTexture;
|
||||||
|
// Need to update the content of the GPU object from the source sysmem of the texture
|
||||||
|
if (_contentStamp >= _gpuObject.getDataStamp()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_downsampleSource._texture) {
|
||||||
|
GLuint fbo { 0 };
|
||||||
|
glCreateFramebuffers(1, &fbo);
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
|
||||||
|
// Find the distance between the old min mip and the new one
|
||||||
|
uint16 mipOffset = _minMip - _downsampleSource._minMip;
|
||||||
|
for (uint16 i = _minMip; i <= _maxMip; ++i) {
|
||||||
|
uint16 targetMip = i - _minMip;
|
||||||
|
uint16 sourceMip = targetMip + mipOffset;
|
||||||
|
Vec3u dimensions = _gpuObject.evalMipDimensions(i);
|
||||||
|
for (GLenum target : getFaceTargets(_target)) {
|
||||||
|
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, _downsampleSource._texture, sourceMip);
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
glCopyTextureSubImage2D(_id, targetMip, 0, 0, 0, 0, dimensions.x, dimensions.y);
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||||
|
glDeleteFramebuffers(1, &fbo);
|
||||||
|
} else {
|
||||||
|
// GO through the process of allocating the correct storage and/or update the content
|
||||||
|
switch (_gpuObject.getType()) {
|
||||||
|
case Texture::TEX_2D:
|
||||||
|
{
|
||||||
|
for (uint16_t i = _minMip; i <= _maxMip; ++i) {
|
||||||
|
if (_gpuObject.isStoredMipFaceAvailable(i)) {
|
||||||
|
transferMip(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Texture::TEX_CUBE:
|
||||||
|
// transfer pixels from each faces
|
||||||
|
for (uint8_t f = 0; f < CUBE_NUM_FACES; f++) {
|
||||||
|
for (uint16_t i = 0; i < Sampler::MAX_MIP_LEVEL; ++i) {
|
||||||
|
if (_gpuObject.isStoredMipFaceAvailable(i, f)) {
|
||||||
|
transferMip(i, f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
qCWarning(gpugl45logging) << __FUNCTION__ << " case for Texture Type " << _gpuObject.getType() << " not supported";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_gpuObject.isAutogenerateMips()) {
|
||||||
|
glGenerateTextureMipmap(_id);
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL45Backend::GL45Texture::syncSampler() const {
|
||||||
|
const Sampler& sampler = _gpuObject.getSampler();
|
||||||
|
|
||||||
|
const auto& fm = FILTER_MODES[sampler.getFilter()];
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_MIN_FILTER, fm.minFilter);
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_MAG_FILTER, fm.magFilter);
|
||||||
|
|
||||||
|
if (sampler.doComparison()) {
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_COMPARE_FUNC, gl::COMPARISON_TO_GL[sampler.getComparisonFunction()]);
|
||||||
|
} else {
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_WRAP_S, WRAP_MODES[sampler.getWrapModeU()]);
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_WRAP_T, WRAP_MODES[sampler.getWrapModeV()]);
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_WRAP_R, WRAP_MODES[sampler.getWrapModeW()]);
|
||||||
|
glTextureParameterfv(_id, GL_TEXTURE_BORDER_COLOR, (const float*)&sampler.getBorderColor());
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, (uint16)sampler.getMipOffset());
|
||||||
|
glTextureParameterf(_id, GL_TEXTURE_MIN_LOD, (float)sampler.getMinMip());
|
||||||
|
glTextureParameterf(_id, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip()));
|
||||||
|
glTextureParameterf(_id, GL_TEXTURE_MAX_ANISOTROPY_EXT, sampler.getMaxAnisotropy());
|
||||||
|
}
|
||||||
|
|
71
libraries/gpu-gl/src/gpu/gl45/GL45BackendTransform.cpp
Normal file
71
libraries/gpu-gl/src/gpu/gl45/GL45BackendTransform.cpp
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
//
|
||||||
|
// GL45BackendTransform.cpp
|
||||||
|
// libraries/gpu/src/gpu
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 3/8/2015.
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
#include "GL45Backend.h"
|
||||||
|
|
||||||
|
using namespace gpu;
|
||||||
|
using namespace gpu::gl45;
|
||||||
|
|
||||||
|
void GL45Backend::initTransform() {
|
||||||
|
GLuint transformBuffers[3];
|
||||||
|
glCreateBuffers(3, transformBuffers);
|
||||||
|
_transform._objectBuffer = transformBuffers[0];
|
||||||
|
_transform._cameraBuffer = transformBuffers[1];
|
||||||
|
_transform._drawCallInfoBuffer = transformBuffers[2];
|
||||||
|
glCreateTextures(GL_TEXTURE_BUFFER, 1, &_transform._objectBufferTexture);
|
||||||
|
size_t cameraSize = sizeof(TransformStageState::CameraBufferElement);
|
||||||
|
while (_transform._cameraUboSize < cameraSize) {
|
||||||
|
_transform._cameraUboSize += _uboAlignment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL45Backend::transferTransformState(const Batch& batch) const {
|
||||||
|
// FIXME not thread safe
|
||||||
|
static std::vector<uint8_t> bufferData;
|
||||||
|
if (!_transform._cameras.empty()) {
|
||||||
|
bufferData.resize(_transform._cameraUboSize * _transform._cameras.size());
|
||||||
|
for (size_t i = 0; i < _transform._cameras.size(); ++i) {
|
||||||
|
memcpy(bufferData.data() + (_transform._cameraUboSize * i), &_transform._cameras[i], sizeof(TransformStageState::CameraBufferElement));
|
||||||
|
}
|
||||||
|
glNamedBufferData(_transform._cameraBuffer, bufferData.size(), bufferData.data(), GL_STREAM_DRAW);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!batch._objects.empty()) {
|
||||||
|
auto byteSize = batch._objects.size() * sizeof(Batch::TransformObject);
|
||||||
|
bufferData.resize(byteSize);
|
||||||
|
memcpy(bufferData.data(), batch._objects.data(), byteSize);
|
||||||
|
glNamedBufferData(_transform._objectBuffer, bufferData.size(), bufferData.data(), GL_STREAM_DRAW);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!batch._namedData.empty()) {
|
||||||
|
bufferData.clear();
|
||||||
|
for (auto& data : batch._namedData) {
|
||||||
|
auto currentSize = bufferData.size();
|
||||||
|
auto bytesToCopy = data.second.drawCallInfos.size() * sizeof(Batch::DrawCallInfo);
|
||||||
|
bufferData.resize(currentSize + bytesToCopy);
|
||||||
|
memcpy(bufferData.data() + currentSize, data.second.drawCallInfos.data(), bytesToCopy);
|
||||||
|
_transform._drawCallInfoOffsets[data.first] = (GLvoid*)currentSize;
|
||||||
|
}
|
||||||
|
glNamedBufferData(_transform._drawCallInfoBuffer, bufferData.size(), bufferData.data(), GL_STREAM_DRAW);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef GPU_SSBO_DRAW_CALL_INFO
|
||||||
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, TRANSFORM_OBJECT_SLOT, _transform._objectBuffer);
|
||||||
|
#else
|
||||||
|
glTextureBuffer(_transform._objectBufferTexture, GL_RGBA32F, _transform._objectBuffer);
|
||||||
|
glActiveTexture(GL_TEXTURE0 + TRANSFORM_OBJECT_SLOT);
|
||||||
|
glBindTexture(GL_TEXTURE_BUFFER, _transform._objectBufferTexture);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
// Make sure the current Camera offset is unknown before render Draw
|
||||||
|
_transform._currentCameraOffset = INVALID_OFFSET;
|
||||||
|
}
|
54
libraries/gpu/src/gpu/null/NullBackend.h
Normal file
54
libraries/gpu/src/gpu/null/NullBackend.h
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2016/05/16
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
#ifndef hifi_gpu_Null_Backend_h
|
||||||
|
#define hifi_gpu_Null_Backend_h
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <functional>
|
||||||
|
#include <bitset>
|
||||||
|
#include <queue>
|
||||||
|
#include <utility>
|
||||||
|
#include <list>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
#include <QtCore/QLoggingCategory>
|
||||||
|
|
||||||
|
#include "../Context.h"
|
||||||
|
|
||||||
|
namespace gpu { namespace null {
|
||||||
|
|
||||||
|
class Backend : public gpu::Backend {
|
||||||
|
using Parent = gpu::Backend;
|
||||||
|
// Context Backend static interface required
|
||||||
|
friend class gpu::Context;
|
||||||
|
static void init() {}
|
||||||
|
static gpu::Backend* createBackend() { return new Backend(); }
|
||||||
|
static bool makeProgram(Shader& shader, const Shader::BindingSet& slotBindings) { return true; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit Backend(bool syncCache) : Parent() { }
|
||||||
|
Backend() : Parent() { }
|
||||||
|
public:
|
||||||
|
~Backend() { }
|
||||||
|
|
||||||
|
void render(Batch& batch) final { }
|
||||||
|
|
||||||
|
// This call synchronize the Full Backend cache with the current GLState
|
||||||
|
// THis is only intended to be used when mixing raw gl calls with the gpu api usage in order to sync
|
||||||
|
// the gpu::Backend state with the true gl state which has probably been messed up by these ugly naked gl calls
|
||||||
|
// Let's try to avoid to do that as much as possible!
|
||||||
|
void syncCache() final { }
|
||||||
|
|
||||||
|
// This is the ugly "download the pixels to sysmem for taking a snapshot"
|
||||||
|
// Just avoid using it, it's ugly and will break performances
|
||||||
|
virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) final { }
|
||||||
|
};
|
||||||
|
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
|
@ -39,6 +39,9 @@ const quint64 NSECS_PER_MSEC = 1000000;
|
||||||
const quint64 USECS_PER_MSEC = 1000;
|
const quint64 USECS_PER_MSEC = 1000;
|
||||||
const quint64 MSECS_PER_SECOND = 1000;
|
const quint64 MSECS_PER_SECOND = 1000;
|
||||||
const quint64 USECS_PER_SECOND = USECS_PER_MSEC * MSECS_PER_SECOND;
|
const quint64 USECS_PER_SECOND = USECS_PER_MSEC * MSECS_PER_SECOND;
|
||||||
|
const quint64 SECS_PER_MINUTE = 60;
|
||||||
|
const quint64 MINS_PER_HOUR = 60;
|
||||||
|
const quint64 SECS_PER_HOUR = SECS_PER_MINUTE * MINS_PER_HOUR;
|
||||||
|
|
||||||
const int BITS_IN_BYTE = 8;
|
const int BITS_IN_BYTE = 8;
|
||||||
const int BYTES_PER_KILOBYTE = 1000;
|
const int BYTES_PER_KILOBYTE = 1000;
|
||||||
|
|
|
@ -141,7 +141,9 @@ CameraManager = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
that.enable = function() {
|
that.enable = function() {
|
||||||
if (Camera.mode == "independent" || that.enabled) return;
|
if (Camera.mode == "independent" || that.enabled || HMD.active) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < CAPTURED_KEYS.length; i++) {
|
for (var i = 0; i < CAPTURED_KEYS.length; i++) {
|
||||||
Controller.captureKeyEvents({
|
Controller.captureKeyEvents({
|
||||||
|
@ -179,7 +181,9 @@ CameraManager = function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
that.disable = function(ignoreCamera) {
|
that.disable = function(ignoreCamera) {
|
||||||
if (!that.enabled) return;
|
if (!that.enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < CAPTURED_KEYS.length; i++) {
|
for (var i = 0; i < CAPTURED_KEYS.length; i++) {
|
||||||
Controller.releaseKeyEvents({
|
Controller.releaseKeyEvents({
|
||||||
|
@ -352,27 +356,21 @@ CameraManager = function() {
|
||||||
that.mousePressEvent = function(event) {
|
that.mousePressEvent = function(event) {
|
||||||
|
|
||||||
if (cameraTool.mousePressEvent(event)) {
|
if (cameraTool.mousePressEvent(event)) {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!that.enabled) {
|
||||||
if (!that.enabled) return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (event.isRightButton || (event.isLeftButton && event.isControl && !event.isShifted)) {
|
if (event.isRightButton || (event.isLeftButton && event.isControl && !event.isShifted)) {
|
||||||
|
|
||||||
that.mode = MODE_ORBIT;
|
that.mode = MODE_ORBIT;
|
||||||
} else if (event.isMiddleButton || (event.isLeftButton && event.isControl && event.isShifted)) {
|
} else if (event.isMiddleButton || (event.isLeftButton && event.isControl && event.isShifted)) {
|
||||||
|
|
||||||
|
|
||||||
that.mode = MODE_PAN;
|
that.mode = MODE_PAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (that.mode !== MODE_INACTIVE) {
|
if (that.mode !== MODE_INACTIVE) {
|
||||||
|
|
||||||
|
|
||||||
hasDragged = false;
|
hasDragged = false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,7 +379,9 @@ CameraManager = function() {
|
||||||
|
|
||||||
that.mouseReleaseEvent = function(event) {
|
that.mouseReleaseEvent = function(event) {
|
||||||
|
|
||||||
if (!that.enabled) return;
|
if (!that.enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
that.mode = MODE_INACTIVE;
|
that.mode = MODE_INACTIVE;
|
||||||
Reticle.setVisible(true);
|
Reticle.setVisible(true);
|
||||||
|
@ -403,7 +403,9 @@ CameraManager = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
that.wheelEvent = function(event) {
|
that.wheelEvent = function(event) {
|
||||||
if (!that.enabled) return;
|
if (!that.enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var dZoom = -event.delta * SCROLL_SENSITIVITY;
|
var dZoom = -event.delta * SCROLL_SENSITIVITY;
|
||||||
|
|
||||||
|
@ -459,8 +461,12 @@ CameraManager = function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeDegrees(degrees) {
|
function normalizeDegrees(degrees) {
|
||||||
while (degrees > 180) degrees -= 360;
|
while (degrees > 180) {
|
||||||
while (degrees < -180) degrees += 360;
|
degrees -= 360;
|
||||||
|
}
|
||||||
|
while (degrees < -180) {
|
||||||
|
degrees += 360;
|
||||||
|
}
|
||||||
return degrees;
|
return degrees;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,7 +489,6 @@ CameraManager = function() {
|
||||||
that.targetZoomDistance = clamp(that.targetZoomDistance, MIN_ZOOM_DISTANCE, MAX_ZOOM_DISTANCE);
|
that.targetZoomDistance = clamp(that.targetZoomDistance, MIN_ZOOM_DISTANCE, MAX_ZOOM_DISTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (easing) {
|
if (easing) {
|
||||||
easingTime = Math.min(EASE_TIME, easingTime + dt);
|
easingTime = Math.min(EASE_TIME, easingTime + dt);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
// 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
|
||||||
//
|
//
|
||||||
|
|
||||||
var PopUpMenu = function(properties) {
|
var PopUpMenu = function (properties) {
|
||||||
var value = properties.value,
|
var value = properties.value,
|
||||||
promptOverlay,
|
promptOverlay,
|
||||||
valueOverlay,
|
valueOverlay,
|
||||||
|
@ -217,7 +217,7 @@ var PopUpMenu = function(properties) {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
var usersWindow = (function() {
|
var usersWindow = (function () {
|
||||||
|
|
||||||
var baseURL = Script.resolvePath("assets/images/tools/"),
|
var baseURL = Script.resolvePath("assets/images/tools/"),
|
||||||
WINDOW_WIDTH = 260,
|
WINDOW_WIDTH = 260,
|
||||||
|
@ -253,11 +253,7 @@ var usersWindow = (function() {
|
||||||
WINDOW_BORDER_BOTTOM_MARGIN = WINDOW_BASE_MARGIN,
|
WINDOW_BORDER_BOTTOM_MARGIN = WINDOW_BASE_MARGIN,
|
||||||
WINDOW_BORDER_LEFT_MARGIN = WINDOW_BASE_MARGIN,
|
WINDOW_BORDER_LEFT_MARGIN = WINDOW_BASE_MARGIN,
|
||||||
WINDOW_BORDER_RADIUS = 4,
|
WINDOW_BORDER_RADIUS = 4,
|
||||||
WINDOW_BORDER_COLOR = {
|
WINDOW_BORDER_COLOR = { red: 255, green: 255, blue: 255 },
|
||||||
red: 255,
|
|
||||||
green: 255,
|
|
||||||
blue: 255
|
|
||||||
},
|
|
||||||
WINDOW_BORDER_ALPHA = 0.5,
|
WINDOW_BORDER_ALPHA = 0.5,
|
||||||
windowBorder,
|
windowBorder,
|
||||||
|
|
||||||
|
@ -363,30 +359,31 @@ var usersWindow = (function() {
|
||||||
usersTimer = null,
|
usersTimer = null,
|
||||||
USERS_UPDATE_TIMEOUT = 5000, // ms = 5s
|
USERS_UPDATE_TIMEOUT = 5000, // ms = 5s
|
||||||
|
|
||||||
|
showMe,
|
||||||
myVisibility,
|
myVisibility,
|
||||||
|
|
||||||
MENU_NAME = "Tools",
|
MENU_NAME = "View",
|
||||||
MENU_ITEM = "Users Online",
|
MENU_ITEM = "Users Online",
|
||||||
MENU_ITEM_AFTER = "Chat...",
|
MENU_ITEM_AFTER = "Overlays",
|
||||||
|
|
||||||
|
SETTING_USERS_SHOW_ME = "UsersWindow.ShowMe",
|
||||||
|
SETTING_USERS_VISIBLE_TO = "UsersWindow.VisibleTo",
|
||||||
SETTING_USERS_WINDOW_MINIMIZED = "UsersWindow.Minimized",
|
SETTING_USERS_WINDOW_MINIMIZED = "UsersWindow.Minimized",
|
||||||
SETINGS_USERS_WINDOW_OFFSET = "UsersWindow.Offset",
|
SETTING_USERS_WINDOW_OFFSET = "UsersWindow.Offset",
|
||||||
// +ve x, y values are offset from left, top of screen; -ve from right, bottom.
|
// +ve x, y values are offset from left, top of screen; -ve from right, bottom.
|
||||||
|
|
||||||
|
isLoggedIn = false,
|
||||||
isVisible = true,
|
isVisible = true,
|
||||||
isMinimized = false,
|
isMinimized = true,
|
||||||
isBorderVisible = false,
|
isBorderVisible = false,
|
||||||
|
|
||||||
viewport,
|
viewport,
|
||||||
isMirrorDisplay = false,
|
isMirrorDisplay = false,
|
||||||
isFullscreenMirror = false,
|
isFullscreenMirror = false,
|
||||||
|
|
||||||
windowPosition = {}, // Bottom left corner of window pane.
|
windowPosition = {}, // Bottom left corner of window pane.
|
||||||
isMovingWindow = false,
|
isMovingWindow = false,
|
||||||
movingClickOffset = {
|
movingClickOffset = { x: 0, y: 0 },
|
||||||
x: 0,
|
|
||||||
y: 0
|
|
||||||
},
|
|
||||||
|
|
||||||
isUsingScrollbars = false,
|
isUsingScrollbars = false,
|
||||||
isMovingScrollbar = false,
|
isMovingScrollbar = false,
|
||||||
|
@ -395,6 +392,12 @@ var usersWindow = (function() {
|
||||||
scrollbarBarClickedAt, // 0.0 .. 1.0
|
scrollbarBarClickedAt, // 0.0 .. 1.0
|
||||||
scrollbarValue = 0.0; // 0.0 .. 1.0
|
scrollbarValue = 0.0; // 0.0 .. 1.0
|
||||||
|
|
||||||
|
function isValueTrue(value) {
|
||||||
|
// Work around Boolean Settings values being read as string when Interface starts up but as Booleans when re-read after
|
||||||
|
// Being written if refresh script.
|
||||||
|
return value === true || value === "true";
|
||||||
|
}
|
||||||
|
|
||||||
function calculateWindowHeight() {
|
function calculateWindowHeight() {
|
||||||
var AUDIO_METER_HEIGHT = 52,
|
var AUDIO_METER_HEIGHT = 52,
|
||||||
MIRROR_HEIGHT = 220,
|
MIRROR_HEIGHT = 220,
|
||||||
|
@ -408,7 +411,9 @@ var usersWindow = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reserve space for title, friends button, and option controls
|
// Reserve space for title, friends button, and option controls
|
||||||
nonUsersHeight = WINDOW_MARGIN + windowLineHeight + FRIENDS_BUTTON_SPACER + FRIENDS_BUTTON_HEIGHT + DISPLAY_SPACER + windowLineHeight + VISIBILITY_SPACER + windowLineHeight + WINDOW_BASE_MARGIN;
|
nonUsersHeight = WINDOW_MARGIN + windowLineHeight + FRIENDS_BUTTON_SPACER + FRIENDS_BUTTON_HEIGHT + DISPLAY_SPACER
|
||||||
|
+ windowLineHeight + VISIBILITY_SPACER
|
||||||
|
+ windowLineHeight + WINDOW_BASE_MARGIN;
|
||||||
|
|
||||||
// Limit window to height of viewport above window position minus VU meter and mirror if displayed
|
// Limit window to height of viewport above window position minus VU meter and mirror if displayed
|
||||||
windowHeight = linesOfUsers.length * windowLineHeight - windowLineSpacing + nonUsersHeight;
|
windowHeight = linesOfUsers.length * windowLineHeight - windowLineSpacing + nonUsersHeight;
|
||||||
|
@ -461,14 +466,17 @@ var usersWindow = (function() {
|
||||||
x: scrollbarBackgroundPosition.x,
|
x: scrollbarBackgroundPosition.x,
|
||||||
y: scrollbarBackgroundPosition.y
|
y: scrollbarBackgroundPosition.y
|
||||||
});
|
});
|
||||||
scrollbarBarPosition.y = scrollbarBackgroundPosition.y + 1 + scrollbarValue * (scrollbarBackgroundHeight - scrollbarBarHeight - 2);
|
scrollbarBarPosition.y = scrollbarBackgroundPosition.y + 1
|
||||||
|
+ scrollbarValue * (scrollbarBackgroundHeight - scrollbarBarHeight - 2);
|
||||||
Overlays.editOverlay(scrollbarBar, {
|
Overlays.editOverlay(scrollbarBar, {
|
||||||
x: scrollbarBackgroundPosition.x + 1,
|
x: scrollbarBackgroundPosition.x + 1,
|
||||||
y: scrollbarBarPosition.y
|
y: scrollbarBarPosition.y
|
||||||
});
|
});
|
||||||
|
|
||||||
x = windowLeft + WINDOW_MARGIN;
|
x = windowLeft + WINDOW_MARGIN;
|
||||||
y = windowPosition.y - FRIENDS_BUTTON_HEIGHT - DISPLAY_SPACER - windowLineHeight - VISIBILITY_SPACER - windowLineHeight - WINDOW_BASE_MARGIN;
|
y = windowPosition.y - FRIENDS_BUTTON_HEIGHT - DISPLAY_SPACER
|
||||||
|
- windowLineHeight - VISIBILITY_SPACER
|
||||||
|
- windowLineHeight - WINDOW_BASE_MARGIN;
|
||||||
Overlays.editOverlay(friendsButton, {
|
Overlays.editOverlay(friendsButton, {
|
||||||
x: x,
|
x: x,
|
||||||
y: y
|
y: y
|
||||||
|
@ -519,13 +527,13 @@ var usersWindow = (function() {
|
||||||
scrollbarBackgroundHeight = numUsersToDisplay * windowLineHeight - windowLineSpacing / 2;
|
scrollbarBackgroundHeight = numUsersToDisplay * windowLineHeight - windowLineSpacing / 2;
|
||||||
Overlays.editOverlay(scrollbarBackground, {
|
Overlays.editOverlay(scrollbarBackground, {
|
||||||
height: scrollbarBackgroundHeight,
|
height: scrollbarBackgroundHeight,
|
||||||
visible: isUsingScrollbars
|
visible: isLoggedIn && isUsingScrollbars
|
||||||
});
|
});
|
||||||
scrollbarBarHeight = Math.max(numUsersToDisplay / linesOfUsers.length * scrollbarBackgroundHeight,
|
scrollbarBarHeight = Math.max(numUsersToDisplay / linesOfUsers.length * scrollbarBackgroundHeight,
|
||||||
SCROLLBAR_BAR_MIN_HEIGHT);
|
SCROLLBAR_BAR_MIN_HEIGHT);
|
||||||
Overlays.editOverlay(scrollbarBar, {
|
Overlays.editOverlay(scrollbarBar, {
|
||||||
height: scrollbarBarHeight,
|
height: scrollbarBarHeight,
|
||||||
visible: isUsingScrollbars
|
visible: isLoggedIn && isUsingScrollbars
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -543,10 +551,45 @@ var usersWindow = (function() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateOverlayVisibility() {
|
||||||
|
Overlays.editOverlay(windowBorder, {
|
||||||
|
visible: isLoggedIn && isVisible && isBorderVisible
|
||||||
|
});
|
||||||
|
Overlays.editOverlay(windowPane, {
|
||||||
|
visible: isLoggedIn && isVisible
|
||||||
|
});
|
||||||
|
Overlays.editOverlay(windowHeading, {
|
||||||
|
visible: isLoggedIn && isVisible
|
||||||
|
});
|
||||||
|
Overlays.editOverlay(minimizeButton, {
|
||||||
|
visible: isLoggedIn && isVisible
|
||||||
|
});
|
||||||
|
Overlays.editOverlay(scrollbarBackground, {
|
||||||
|
visible: isLoggedIn && isVisible && isUsingScrollbars && !isMinimized
|
||||||
|
});
|
||||||
|
Overlays.editOverlay(scrollbarBar, {
|
||||||
|
visible: isLoggedIn && isVisible && isUsingScrollbars && !isMinimized
|
||||||
|
});
|
||||||
|
Overlays.editOverlay(friendsButton, {
|
||||||
|
visible: isLoggedIn && isVisible && !isMinimized
|
||||||
|
});
|
||||||
|
displayControl.setVisible(isLoggedIn && isVisible && !isMinimized);
|
||||||
|
visibilityControl.setVisible(isLoggedIn && isVisible && !isMinimized);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkLoggedIn() {
|
||||||
|
var wasLoggedIn = isLoggedIn;
|
||||||
|
|
||||||
|
isLoggedIn = Account.isLoggedIn();
|
||||||
|
if (isLoggedIn !== wasLoggedIn) {
|
||||||
|
updateOverlayVisibility();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function pollUsers() {
|
function pollUsers() {
|
||||||
var url = API_URL;
|
var url = API_URL;
|
||||||
|
|
||||||
if (displayControl.getValue() === DISPLAY_FRIENDS) {
|
if (showMe === DISPLAY_FRIENDS) {
|
||||||
url += API_FRIENDS_FILTER;
|
url += API_FRIENDS_FILTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -556,36 +599,9 @@ var usersWindow = (function() {
|
||||||
usersRequest.ontimeout = pollUsersTimedOut;
|
usersRequest.ontimeout = pollUsersTimedOut;
|
||||||
usersRequest.onreadystatechange = processUsers;
|
usersRequest.onreadystatechange = processUsers;
|
||||||
usersRequest.send();
|
usersRequest.send();
|
||||||
checkLoggedIn();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var loggedIn = false;
|
processUsers = function () {
|
||||||
|
|
||||||
function checkLoggedIn() {
|
|
||||||
loggedIn = Account.isLoggedIn();
|
|
||||||
if (loggedIn === false) {
|
|
||||||
Overlays.editOverlay(friendsButton, {
|
|
||||||
visible: false
|
|
||||||
});
|
|
||||||
visibilityControl.setVisible(false);
|
|
||||||
displayControl.setVisible(false);
|
|
||||||
} else {
|
|
||||||
if (isMinimized === true) {
|
|
||||||
loggedIn = true;
|
|
||||||
return
|
|
||||||
}
|
|
||||||
Overlays.editOverlay(friendsButton, {
|
|
||||||
visible: true
|
|
||||||
});
|
|
||||||
visibilityControl.setVisible(true);
|
|
||||||
displayControl.setVisible(true);
|
|
||||||
loggedIn = true;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
processUsers = function() {
|
|
||||||
var response,
|
var response,
|
||||||
myUsername,
|
myUsername,
|
||||||
user,
|
user,
|
||||||
|
@ -628,6 +644,8 @@ var usersWindow = (function() {
|
||||||
updateUsersDisplay();
|
updateUsersDisplay();
|
||||||
updateOverlayPositions();
|
updateOverlayPositions();
|
||||||
|
|
||||||
|
checkLoggedIn();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
print("Error: Request for users status returned " + usersRequest.status + " " + usersRequest.statusText);
|
print("Error: Request for users status returned " + usersRequest.status + " " + usersRequest.statusText);
|
||||||
usersTimer = Script.setTimeout(pollUsers, HTTP_GET_TIMEOUT); // Try again after a longer delay.
|
usersTimer = Script.setTimeout(pollUsers, HTTP_GET_TIMEOUT); // Try again after a longer delay.
|
||||||
|
@ -638,41 +656,11 @@ var usersWindow = (function() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pollUsersTimedOut = function() {
|
pollUsersTimedOut = function () {
|
||||||
print("Error: Request for users status timed out");
|
print("Error: Request for users status timed out");
|
||||||
usersTimer = Script.setTimeout(pollUsers, HTTP_GET_TIMEOUT); // Try again after a longer delay.
|
usersTimer = Script.setTimeout(pollUsers, HTTP_GET_TIMEOUT); // Try again after a longer delay.
|
||||||
};
|
};
|
||||||
|
|
||||||
function updateOverlayVisibility() {
|
|
||||||
Overlays.editOverlay(windowBorder, {
|
|
||||||
visible: isVisible && isBorderVisible
|
|
||||||
});
|
|
||||||
Overlays.editOverlay(windowPane, {
|
|
||||||
visible: isVisible
|
|
||||||
});
|
|
||||||
Overlays.editOverlay(windowHeading, {
|
|
||||||
visible: isVisible
|
|
||||||
});
|
|
||||||
Overlays.editOverlay(minimizeButton, {
|
|
||||||
visible: isVisible
|
|
||||||
});
|
|
||||||
Overlays.editOverlay(scrollbarBackground, {
|
|
||||||
visible: isVisible && isUsingScrollbars && !isMinimized
|
|
||||||
});
|
|
||||||
Overlays.editOverlay(scrollbarBar, {
|
|
||||||
visible: isVisible && isUsingScrollbars && !isMinimized
|
|
||||||
});
|
|
||||||
|
|
||||||
if (loggedIn === true) {
|
|
||||||
Overlays.editOverlay(friendsButton, {
|
|
||||||
visible: isVisible && !isMinimized
|
|
||||||
});
|
|
||||||
displayControl.setVisible(isVisible && !isMinimized);
|
|
||||||
visibilityControl.setVisible(isVisible && !isMinimized);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function setVisible(visible) {
|
function setVisible(visible) {
|
||||||
isVisible = visible;
|
isVisible = visible;
|
||||||
|
|
||||||
|
@ -686,7 +674,6 @@ var usersWindow = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
updateOverlayVisibility();
|
updateOverlayVisibility();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setMinimized(minimized) {
|
function setMinimized(minimized) {
|
||||||
|
@ -697,6 +684,7 @@ var usersWindow = (function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
updateOverlayVisibility();
|
updateOverlayVisibility();
|
||||||
|
Settings.setValue(SETTING_USERS_WINDOW_MINIMIZED, isMinimized);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMenuItemEvent(event) {
|
function onMenuItemEvent(event) {
|
||||||
|
@ -707,9 +695,11 @@ var usersWindow = (function() {
|
||||||
|
|
||||||
function onFindableByChanged(event) {
|
function onFindableByChanged(event) {
|
||||||
if (VISIBILITY_VALUES.indexOf(event) !== -1) {
|
if (VISIBILITY_VALUES.indexOf(event) !== -1) {
|
||||||
|
myVisibility = event;
|
||||||
visibilityControl.setValue(event);
|
visibilityControl.setValue(event);
|
||||||
|
Settings.setValue(SETTING_USERS_VISIBLE_TO, myVisibility);
|
||||||
} else {
|
} else {
|
||||||
print("Error: Unrecognized onFindableByChanged value: " + myVisibility);
|
print("Error: Unrecognized onFindableByChanged value: " + event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -739,11 +729,15 @@ var usersWindow = (function() {
|
||||||
usersTimer = null;
|
usersTimer = null;
|
||||||
}
|
}
|
||||||
pollUsers();
|
pollUsers();
|
||||||
|
showMe = displayControl.getValue();
|
||||||
|
Settings.setValue(SETTING_USERS_SHOW_ME, showMe);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (visibilityControl.handleClick(clickedOverlay)) {
|
if (visibilityControl.handleClick(clickedOverlay)) {
|
||||||
GlobalServices.findableBy = visibilityControl.getValue();
|
myVisibility = visibilityControl.getValue();
|
||||||
|
GlobalServices.findableBy = myVisibility;
|
||||||
|
Settings.setValue(SETTING_USERS_VISIBLE_TO, myVisibility);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -763,7 +757,9 @@ var usersWindow = (function() {
|
||||||
|
|
||||||
userClicked = firstUserToDisplay + lineClicked;
|
userClicked = firstUserToDisplay + lineClicked;
|
||||||
|
|
||||||
if (0 <= userClicked && userClicked < linesOfUsers.length && 0 <= overlayX && overlayX <= usersOnline[linesOfUsers[userClicked]].textWidth) {
|
if (0 <= userClicked && userClicked < linesOfUsers.length && 0 <= overlayX
|
||||||
|
&& overlayX <= usersOnline[linesOfUsers[userClicked]].textWidth) {
|
||||||
|
//print("Go to " + usersOnline[linesOfUsers[userClicked]].username);
|
||||||
location.goToUser(usersOnline[linesOfUsers[userClicked]].username);
|
location.goToUser(usersOnline[linesOfUsers[userClicked]].username);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -831,8 +827,12 @@ var usersWindow = (function() {
|
||||||
var isVisible;
|
var isVisible;
|
||||||
|
|
||||||
if (isMovingScrollbar) {
|
if (isMovingScrollbar) {
|
||||||
if (scrollbarBackgroundPosition.x - WINDOW_MARGIN <= event.x && event.x <= scrollbarBackgroundPosition.x + SCROLLBAR_BACKGROUND_WIDTH + WINDOW_MARGIN && scrollbarBackgroundPosition.y - WINDOW_MARGIN <= event.y && event.y <= scrollbarBackgroundPosition.y + scrollbarBackgroundHeight + WINDOW_MARGIN) {
|
if (scrollbarBackgroundPosition.x - WINDOW_MARGIN <= event.x
|
||||||
scrollbarValue = (event.y - scrollbarBarClickedAt * scrollbarBarHeight - scrollbarBackgroundPosition.y) / (scrollbarBackgroundHeight - scrollbarBarHeight - 2);
|
&& event.x <= scrollbarBackgroundPosition.x + SCROLLBAR_BACKGROUND_WIDTH + WINDOW_MARGIN
|
||||||
|
&& scrollbarBackgroundPosition.y - WINDOW_MARGIN <= event.y
|
||||||
|
&& event.y <= scrollbarBackgroundPosition.y + scrollbarBackgroundHeight + WINDOW_MARGIN) {
|
||||||
|
scrollbarValue = (event.y - scrollbarBarClickedAt * scrollbarBarHeight - scrollbarBackgroundPosition.y)
|
||||||
|
/ (scrollbarBackgroundHeight - scrollbarBarHeight - 2);
|
||||||
scrollbarValue = Math.min(Math.max(scrollbarValue, 0.0), 1.0);
|
scrollbarValue = Math.min(Math.max(scrollbarValue, 0.0), 1.0);
|
||||||
firstUserToDisplay = Math.floor(scrollbarValue * (linesOfUsers.length - numUsersToDisplay));
|
firstUserToDisplay = Math.floor(scrollbarValue * (linesOfUsers.length - numUsersToDisplay));
|
||||||
updateOverlayPositions();
|
updateOverlayPositions();
|
||||||
|
@ -858,9 +858,13 @@ var usersWindow = (function() {
|
||||||
|
|
||||||
isVisible = isBorderVisible;
|
isVisible = isBorderVisible;
|
||||||
if (isVisible) {
|
if (isVisible) {
|
||||||
isVisible = windowPosition.x - WINDOW_BORDER_LEFT_MARGIN <= event.x && event.x <= windowPosition.x - WINDOW_BORDER_LEFT_MARGIN + WINDOW_BORDER_WIDTH && windowPosition.y - windowHeight - WINDOW_BORDER_TOP_MARGIN <= event.y && event.y <= windowPosition.y + WINDOW_BORDER_BOTTOM_MARGIN;
|
isVisible = windowPosition.x - WINDOW_BORDER_LEFT_MARGIN <= event.x
|
||||||
|
&& event.x <= windowPosition.x - WINDOW_BORDER_LEFT_MARGIN + WINDOW_BORDER_WIDTH
|
||||||
|
&& windowPosition.y - windowHeight - WINDOW_BORDER_TOP_MARGIN <= event.y
|
||||||
|
&& event.y <= windowPosition.y + WINDOW_BORDER_BOTTOM_MARGIN;
|
||||||
} else {
|
} else {
|
||||||
isVisible = windowPosition.x <= event.x && event.x <= windowPosition.x + WINDOW_WIDTH && windowPosition.y - windowHeight <= event.y && event.y <= windowPosition.y;
|
isVisible = windowPosition.x <= event.x && event.x <= windowPosition.x + WINDOW_WIDTH
|
||||||
|
&& windowPosition.y - windowHeight <= event.y && event.y <= windowPosition.y;
|
||||||
}
|
}
|
||||||
if (isVisible !== isBorderVisible) {
|
if (isVisible !== isBorderVisible) {
|
||||||
isBorderVisible = isVisible;
|
isBorderVisible = isVisible;
|
||||||
|
@ -883,9 +887,11 @@ var usersWindow = (function() {
|
||||||
|
|
||||||
if (isMovingWindow) {
|
if (isMovingWindow) {
|
||||||
// Save offset of bottom of window to nearest edge of the window.
|
// Save offset of bottom of window to nearest edge of the window.
|
||||||
offset.x = (windowPosition.x + WINDOW_WIDTH / 2 < viewport.x / 2) ? windowPosition.x : windowPosition.x - viewport.x;
|
offset.x = (windowPosition.x + WINDOW_WIDTH / 2 < viewport.x / 2)
|
||||||
offset.y = (windowPosition.y < viewport.y / 2) ? windowPosition.y : windowPosition.y - viewport.y;
|
? windowPosition.x : windowPosition.x - viewport.x;
|
||||||
Settings.setValue(SETINGS_USERS_WINDOW_OFFSET, JSON.stringify(offset));
|
offset.y = (windowPosition.y < viewport.y / 2)
|
||||||
|
? windowPosition.y : windowPosition.y - viewport.y;
|
||||||
|
Settings.setValue(SETTING_USERS_WINDOW_OFFSET, JSON.stringify(offset));
|
||||||
isMovingWindow = false;
|
isMovingWindow = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -901,7 +907,8 @@ var usersWindow = (function() {
|
||||||
isMirrorDisplay = Menu.isOptionChecked(MIRROR_MENU_ITEM);
|
isMirrorDisplay = Menu.isOptionChecked(MIRROR_MENU_ITEM);
|
||||||
isFullscreenMirror = Menu.isOptionChecked(FULLSCREEN_MIRROR_MENU_ITEM);
|
isFullscreenMirror = Menu.isOptionChecked(FULLSCREEN_MIRROR_MENU_ITEM);
|
||||||
|
|
||||||
if (viewport.y !== oldViewport.y || isMirrorDisplay !== oldIsMirrorDisplay || isFullscreenMirror !== oldIsFullscreenMirror) {
|
if (viewport.y !== oldViewport.y || isMirrorDisplay !== oldIsMirrorDisplay
|
||||||
|
|| isFullscreenMirror !== oldIsFullscreenMirror) {
|
||||||
calculateWindowHeight();
|
calculateWindowHeight();
|
||||||
updateUsersDisplay();
|
updateUsersDisplay();
|
||||||
}
|
}
|
||||||
|
@ -940,9 +947,9 @@ var usersWindow = (function() {
|
||||||
|
|
||||||
viewport = Controller.getViewportDimensions();
|
viewport = Controller.getViewportDimensions();
|
||||||
|
|
||||||
offsetSetting = Settings.getValue(SETINGS_USERS_WINDOW_OFFSET);
|
offsetSetting = Settings.getValue(SETTING_USERS_WINDOW_OFFSET);
|
||||||
if (offsetSetting !== "") {
|
if (offsetSetting !== "") {
|
||||||
offset = JSON.parse(Settings.getValue(SETINGS_USERS_WINDOW_OFFSET));
|
offset = JSON.parse(Settings.getValue(SETTING_USERS_WINDOW_OFFSET));
|
||||||
}
|
}
|
||||||
if (offset.hasOwnProperty("x") && offset.hasOwnProperty("y")) {
|
if (offset.hasOwnProperty("x") && offset.hasOwnProperty("y")) {
|
||||||
windowPosition.x = offset.x < 0 ? viewport.x + offset.x : offset.x;
|
windowPosition.x = offset.x < 0 ? viewport.x + offset.x : offset.x;
|
||||||
|
@ -951,8 +958,8 @@ var usersWindow = (function() {
|
||||||
} else {
|
} else {
|
||||||
hmdViewport = Controller.getRecommendedOverlayRect();
|
hmdViewport = Controller.getRecommendedOverlayRect();
|
||||||
windowPosition = {
|
windowPosition = {
|
||||||
x: (viewport.x - hmdViewport.width) / 2, // HMD viewport is narrower than screen.
|
x: (viewport.x - hmdViewport.width) / 2, // HMD viewport is narrower than screen.
|
||||||
y: hmdViewport.height // HMD viewport starts at top of screen but only extends down so far.
|
y: hmdViewport.height // HMD viewport starts at top of screen but only extends down so far.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -960,13 +967,13 @@ var usersWindow = (function() {
|
||||||
|
|
||||||
windowBorder = Overlays.addOverlay("rectangle", {
|
windowBorder = Overlays.addOverlay("rectangle", {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: viewport.y, // Start up off-screen
|
y: viewport.y, // Start up off-screen
|
||||||
width: WINDOW_BORDER_WIDTH,
|
width: WINDOW_BORDER_WIDTH,
|
||||||
height: windowBorderHeight,
|
height: windowBorderHeight,
|
||||||
radius: WINDOW_BORDER_RADIUS,
|
radius: WINDOW_BORDER_RADIUS,
|
||||||
color: WINDOW_BORDER_COLOR,
|
color: WINDOW_BORDER_COLOR,
|
||||||
alpha: WINDOW_BORDER_ALPHA,
|
alpha: WINDOW_BORDER_ALPHA,
|
||||||
visible: isVisible && isBorderVisible
|
visible: false
|
||||||
});
|
});
|
||||||
|
|
||||||
windowPane = Overlays.addOverlay("text", {
|
windowPane = Overlays.addOverlay("text", {
|
||||||
|
@ -982,7 +989,7 @@ var usersWindow = (function() {
|
||||||
backgroundAlpha: WINDOW_BACKGROUND_ALPHA,
|
backgroundAlpha: WINDOW_BACKGROUND_ALPHA,
|
||||||
text: "",
|
text: "",
|
||||||
font: WINDOW_FONT,
|
font: WINDOW_FONT,
|
||||||
visible: isVisible
|
visible: false
|
||||||
});
|
});
|
||||||
|
|
||||||
windowHeading = Overlays.addOverlay("text", {
|
windowHeading = Overlays.addOverlay("text", {
|
||||||
|
@ -997,7 +1004,7 @@ var usersWindow = (function() {
|
||||||
backgroundAlpha: 0.0,
|
backgroundAlpha: 0.0,
|
||||||
text: "No users online",
|
text: "No users online",
|
||||||
font: WINDOW_FONT,
|
font: WINDOW_FONT,
|
||||||
visible: isVisible && !isMinimized
|
visible: false
|
||||||
});
|
});
|
||||||
|
|
||||||
minimizeButton = Overlays.addOverlay("image", {
|
minimizeButton = Overlays.addOverlay("image", {
|
||||||
|
@ -1014,7 +1021,7 @@ var usersWindow = (function() {
|
||||||
},
|
},
|
||||||
color: MIN_MAX_BUTTON_COLOR,
|
color: MIN_MAX_BUTTON_COLOR,
|
||||||
alpha: MIN_MAX_BUTTON_ALPHA,
|
alpha: MIN_MAX_BUTTON_ALPHA,
|
||||||
visible: isVisible && !isMinimized
|
visible: false
|
||||||
});
|
});
|
||||||
|
|
||||||
scrollbarBackgroundPosition = {
|
scrollbarBackgroundPosition = {
|
||||||
|
@ -1029,7 +1036,7 @@ var usersWindow = (function() {
|
||||||
backgroundColor: SCROLLBAR_BACKGROUND_COLOR,
|
backgroundColor: SCROLLBAR_BACKGROUND_COLOR,
|
||||||
backgroundAlpha: SCROLLBAR_BACKGROUND_ALPHA,
|
backgroundAlpha: SCROLLBAR_BACKGROUND_ALPHA,
|
||||||
text: "",
|
text: "",
|
||||||
visible: isVisible && isUsingScrollbars && !isMinimized
|
visible: false
|
||||||
});
|
});
|
||||||
|
|
||||||
scrollbarBarPosition = {
|
scrollbarBarPosition = {
|
||||||
|
@ -1044,7 +1051,7 @@ var usersWindow = (function() {
|
||||||
backgroundColor: SCROLLBAR_BAR_COLOR,
|
backgroundColor: SCROLLBAR_BAR_COLOR,
|
||||||
backgroundAlpha: SCROLLBAR_BAR_ALPHA,
|
backgroundAlpha: SCROLLBAR_BAR_ALPHA,
|
||||||
text: "",
|
text: "",
|
||||||
visible: isVisible && isUsingScrollbars && !isMinimized
|
visible: false
|
||||||
});
|
});
|
||||||
|
|
||||||
friendsButton = Overlays.addOverlay("image", {
|
friendsButton = Overlays.addOverlay("image", {
|
||||||
|
@ -1060,12 +1067,18 @@ var usersWindow = (function() {
|
||||||
height: FRIENDS_BUTTON_SVG_HEIGHT
|
height: FRIENDS_BUTTON_SVG_HEIGHT
|
||||||
},
|
},
|
||||||
color: FRIENDS_BUTTON_COLOR,
|
color: FRIENDS_BUTTON_COLOR,
|
||||||
alpha: FRIENDS_BUTTON_ALPHA
|
alpha: FRIENDS_BUTTON_ALPHA,
|
||||||
|
visible: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
showMe = Settings.getValue(SETTING_USERS_SHOW_ME, "");
|
||||||
|
if (DISPLAY_VALUES.indexOf(showMe) === -1) {
|
||||||
|
showMe = DISPLAY_EVERYONE;
|
||||||
|
}
|
||||||
|
|
||||||
displayControl = new PopUpMenu({
|
displayControl = new PopUpMenu({
|
||||||
prompt: DISPLAY_PROMPT,
|
prompt: DISPLAY_PROMPT,
|
||||||
value: DISPLAY_VALUES[0],
|
value: showMe,
|
||||||
values: DISPLAY_VALUES,
|
values: DISPLAY_VALUES,
|
||||||
displayValues: DISPLAY_DISPLAY_VALUES,
|
displayValues: DISPLAY_DISPLAY_VALUES,
|
||||||
x: 0,
|
x: 0,
|
||||||
|
@ -1087,13 +1100,12 @@ var usersWindow = (function() {
|
||||||
popupBackgroundAlpha: DISPLAY_OPTIONS_BACKGROUND_ALPHA,
|
popupBackgroundAlpha: DISPLAY_OPTIONS_BACKGROUND_ALPHA,
|
||||||
buttonColor: MIN_MAX_BUTTON_COLOR,
|
buttonColor: MIN_MAX_BUTTON_COLOR,
|
||||||
buttonAlpha: MIN_MAX_BUTTON_ALPHA,
|
buttonAlpha: MIN_MAX_BUTTON_ALPHA,
|
||||||
visible: isVisible && !isMinimized
|
visible: false
|
||||||
});
|
});
|
||||||
|
|
||||||
myVisibility = GlobalServices.findableBy;
|
myVisibility = Settings.getValue(SETTING_USERS_VISIBLE_TO, "");
|
||||||
if (VISIBILITY_VALUES.indexOf(myVisibility) === -1) {
|
if (VISIBILITY_VALUES.indexOf(myVisibility) === -1) {
|
||||||
print("Error: Unrecognized findableBy value: " + myVisibility);
|
myVisibility = VISIBILITY_FRIENDS;
|
||||||
myVisibility = VISIBILITY_ALL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
visibilityControl = new PopUpMenu({
|
visibilityControl = new PopUpMenu({
|
||||||
|
@ -1120,14 +1132,9 @@ var usersWindow = (function() {
|
||||||
popupBackgroundAlpha: DISPLAY_OPTIONS_BACKGROUND_ALPHA,
|
popupBackgroundAlpha: DISPLAY_OPTIONS_BACKGROUND_ALPHA,
|
||||||
buttonColor: MIN_MAX_BUTTON_COLOR,
|
buttonColor: MIN_MAX_BUTTON_COLOR,
|
||||||
buttonAlpha: MIN_MAX_BUTTON_ALPHA,
|
buttonAlpha: MIN_MAX_BUTTON_ALPHA,
|
||||||
visible: isVisible && !isMinimized
|
visible: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
Script.setTimeout(function() {
|
|
||||||
checkLoggedIn()
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
Controller.mousePressEvent.connect(onMousePressEvent);
|
Controller.mousePressEvent.connect(onMousePressEvent);
|
||||||
Controller.mouseMoveEvent.connect(onMouseMoveEvent);
|
Controller.mouseMoveEvent.connect(onMouseMoveEvent);
|
||||||
Controller.mouseReleaseEvent.connect(onMouseReleaseEvent);
|
Controller.mouseReleaseEvent.connect(onMouseReleaseEvent);
|
||||||
|
@ -1148,12 +1155,10 @@ var usersWindow = (function() {
|
||||||
pollUsers();
|
pollUsers();
|
||||||
|
|
||||||
// Set minimized at end - setup code does not handle `minimized == false` correctly
|
// Set minimized at end - setup code does not handle `minimized == false` correctly
|
||||||
setMinimized(Settings.getValue(SETTING_USERS_WINDOW_MINIMIZED, false));
|
setMinimized(isValueTrue(Settings.getValue(SETTING_USERS_WINDOW_MINIMIZED, false)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function tearDown() {
|
function tearDown() {
|
||||||
Settings.setValue(SETTING_USERS_WINDOW_MINIMIZED, isMinimized);
|
|
||||||
|
|
||||||
Menu.removeMenuItem(MENU_NAME, MENU_ITEM);
|
Menu.removeMenuItem(MENU_NAME, MENU_ITEM);
|
||||||
|
|
||||||
Script.clearTimeout(usersTimer);
|
Script.clearTimeout(usersTimer);
|
||||||
|
@ -1170,4 +1175,4 @@ var usersWindow = (function() {
|
||||||
|
|
||||||
setUp();
|
setUp();
|
||||||
Script.scriptEnding.connect(tearDown);
|
Script.scriptEnding.connect(tearDown);
|
||||||
}());
|
}());
|
||||||
|
|
187
tests/gpu-test/src/TestFbx.cpp
Normal file
187
tests/gpu-test/src/TestFbx.cpp
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2016/05/16
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "TestFbx.h"
|
||||||
|
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
|
#include <QtCore/QFile>
|
||||||
|
|
||||||
|
#include <FBXReader.h>
|
||||||
|
|
||||||
|
struct MyVertex {
|
||||||
|
vec3 position;
|
||||||
|
vec2 texCoords;
|
||||||
|
vec3 normal;
|
||||||
|
uint32_t color;
|
||||||
|
|
||||||
|
static gpu::Stream::FormatPointer getVertexFormat() {
|
||||||
|
static const gpu::Element POSITION_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ };
|
||||||
|
static const gpu::Element TEXTURE_ELEMENT { gpu::VEC2, gpu::FLOAT, gpu::UV };
|
||||||
|
static const gpu::Element NORMAL_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ };
|
||||||
|
static const gpu::Element COLOR_ELEMENT { gpu::VEC4, gpu::NUINT8, gpu::RGBA };
|
||||||
|
gpu::Stream::FormatPointer vertexFormat { std::make_shared<gpu::Stream::Format>() };
|
||||||
|
vertexFormat->setAttribute(gpu::Stream::POSITION, 0, POSITION_ELEMENT, offsetof(MyVertex, position));
|
||||||
|
vertexFormat->setAttribute(gpu::Stream::TEXCOORD, 0, TEXTURE_ELEMENT, offsetof(MyVertex, texCoords));
|
||||||
|
vertexFormat->setAttribute(gpu::Stream::COLOR, 0, COLOR_ELEMENT, offsetof(MyVertex, color));
|
||||||
|
vertexFormat->setAttribute(gpu::Stream::NORMAL, 0, NORMAL_ELEMENT, offsetof(MyVertex, normal));
|
||||||
|
return vertexFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Part {
|
||||||
|
size_t baseVertex;
|
||||||
|
size_t baseIndex;
|
||||||
|
size_t materialId;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DrawElementsIndirectCommand {
|
||||||
|
uint count { 0 };
|
||||||
|
uint instanceCount { 1 };
|
||||||
|
uint firstIndex { 0 };
|
||||||
|
uint baseVertex { 0 };
|
||||||
|
uint baseInstance { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class FileDownloader : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit FileDownloader(QUrl imageUrl, QObject *parent = 0) : QObject(parent) {
|
||||||
|
connect(&m_WebCtrl, SIGNAL(finished(QNetworkReply*)), this, SLOT(fileDownloaded(QNetworkReply*)));
|
||||||
|
QNetworkRequest request(imageUrl);
|
||||||
|
m_WebCtrl.get(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~FileDownloader() {}
|
||||||
|
|
||||||
|
const QByteArray& downloadedData() const {
|
||||||
|
return m_DownloadedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void downloaded();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void fileDownloaded(QNetworkReply* pReply) {
|
||||||
|
m_DownloadedData = pReply->readAll();
|
||||||
|
pReply->deleteLater();
|
||||||
|
emit downloaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QNetworkAccessManager m_WebCtrl;
|
||||||
|
QByteArray m_DownloadedData;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static const QUrl TEST_ASSET = QString("https://s3.amazonaws.com/DreamingContent/assets/models/tardis/console.fbx");
|
||||||
|
static const mat4 TEST_ASSET_TRANSFORM = glm::translate(mat4(), vec3(0, -1.5f, 0)) * glm::scale(mat4(), vec3(0.01f));
|
||||||
|
//static const QUrl TEST_ASSET = QString("https://s3.amazonaws.com/DreamingContent/assets/simple/SimpleMilitary/Models/Vehicles/tank_02_c.fbx");
|
||||||
|
//static const mat4 TEST_ASSET_TRANSFORM = glm::translate(mat4(), vec3(0, -0.5f, 0)) * glm::scale(mat4(), vec3(0.1f));
|
||||||
|
|
||||||
|
TestFbx::TestFbx(const render::ShapePlumberPointer& shapePlumber) : _shapePlumber(shapePlumber) {
|
||||||
|
FileDownloader* downloader = new FileDownloader(TEST_ASSET, qApp);
|
||||||
|
QObject::connect(downloader, &FileDownloader::downloaded, [this, downloader] {
|
||||||
|
parseFbx(downloader->downloadedData());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TestFbx::isReady() const {
|
||||||
|
return _partCount != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestFbx::parseFbx(const QByteArray& fbxData) {
|
||||||
|
QVariantHash mapping;
|
||||||
|
FBXGeometry* fbx = readFBX(fbxData, mapping);
|
||||||
|
size_t totalVertexCount = 0;
|
||||||
|
size_t totalIndexCount = 0;
|
||||||
|
size_t totalPartCount = 0;
|
||||||
|
size_t highestIndex = 0;
|
||||||
|
for (const auto& mesh : fbx->meshes) {
|
||||||
|
size_t vertexCount = mesh.vertices.size();
|
||||||
|
totalVertexCount += mesh.vertices.size();
|
||||||
|
highestIndex = std::max(highestIndex, vertexCount);
|
||||||
|
totalPartCount += mesh.parts.size();
|
||||||
|
for (const auto& part : mesh.parts) {
|
||||||
|
totalIndexCount += part.quadTrianglesIndices.size();
|
||||||
|
totalIndexCount += part.triangleIndices.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size_t baseVertex = 0;
|
||||||
|
std::vector<MyVertex> vertices;
|
||||||
|
vertices.reserve(totalVertexCount);
|
||||||
|
std::vector<uint16_t> indices;
|
||||||
|
indices.reserve(totalIndexCount);
|
||||||
|
std::vector<DrawElementsIndirectCommand> parts;
|
||||||
|
parts.reserve(totalPartCount);
|
||||||
|
_partCount = totalPartCount;
|
||||||
|
for (const auto& mesh : fbx->meshes) {
|
||||||
|
baseVertex = vertices.size();
|
||||||
|
|
||||||
|
vec3 color;
|
||||||
|
for (const auto& part : mesh.parts) {
|
||||||
|
DrawElementsIndirectCommand partIndirect;
|
||||||
|
partIndirect.baseVertex = (uint)baseVertex;
|
||||||
|
partIndirect.firstIndex = (uint)indices.size();
|
||||||
|
partIndirect.baseInstance = (uint)parts.size();
|
||||||
|
_partTransforms.push_back(mesh.modelTransform);
|
||||||
|
auto material = fbx->materials[part.materialID];
|
||||||
|
color = material.diffuseColor;
|
||||||
|
for (auto index : part.quadTrianglesIndices) {
|
||||||
|
indices.push_back(index);
|
||||||
|
}
|
||||||
|
for (auto index : part.triangleIndices) {
|
||||||
|
indices.push_back(index);
|
||||||
|
}
|
||||||
|
size_t triangles = (indices.size() - partIndirect.firstIndex);
|
||||||
|
Q_ASSERT(0 == (triangles % 3));
|
||||||
|
//triangles /= 3;
|
||||||
|
partIndirect.count = (uint)triangles;
|
||||||
|
parts.push_back(partIndirect);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t vertexCount = mesh.vertices.size();
|
||||||
|
for (size_t i = 0; i < vertexCount; ++i) {
|
||||||
|
MyVertex vertex;
|
||||||
|
vertex.position = mesh.vertices[(int)i];
|
||||||
|
vec3 n = mesh.normals[(int)i];
|
||||||
|
vertex.normal = n;
|
||||||
|
vertex.texCoords = mesh.texCoords[(int)i];
|
||||||
|
vertex.color = toCompactColor(vec4(color, 1));
|
||||||
|
vertices.push_back(vertex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_vertexBuffer->append(vertices);
|
||||||
|
_indexBuffer->append(indices);
|
||||||
|
_indirectBuffer->append(parts);
|
||||||
|
delete fbx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestFbx::renderTest(size_t testId, RenderArgs* args) {
|
||||||
|
gpu::Batch& batch = *(args->_batch);
|
||||||
|
//pipeline->pipeline
|
||||||
|
if (_partCount) {
|
||||||
|
for (size_t i = 0; i < _partCount; ++i) {
|
||||||
|
batch.setModelTransform(TEST_ASSET_TRANSFORM * _partTransforms[i]);
|
||||||
|
batch.setupNamedCalls(__FUNCTION__, [this](gpu::Batch& batch, gpu::Batch::NamedBatchData&) {
|
||||||
|
RenderArgs args; args._batch = &batch;
|
||||||
|
_shapePlumber->pickPipeline(&args, render::ShapeKey());
|
||||||
|
batch.setInputBuffer(0, _vertexBuffer, 0, sizeof(MyVertex));
|
||||||
|
batch.setIndexBuffer(gpu::UINT16, _indexBuffer, 0);
|
||||||
|
batch.setInputFormat(MyVertex::getVertexFormat());
|
||||||
|
batch.setIndirectBuffer(_indirectBuffer, 0);
|
||||||
|
batch.multiDrawIndexedIndirect((uint)_partCount, gpu::TRIANGLES);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "TestFbx.moc"
|
35
tests/gpu-test/src/TestFbx.h
Normal file
35
tests/gpu-test/src/TestFbx.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2016/05/16
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "TestHelpers.h"
|
||||||
|
|
||||||
|
#include <render/ShapePipeline.h>
|
||||||
|
|
||||||
|
class FBXGeometry;
|
||||||
|
|
||||||
|
class TestFbx : public GpuTestBase {
|
||||||
|
size_t _partCount { 0 };
|
||||||
|
model::Material _material;
|
||||||
|
render::ShapeKey _shapeKey;
|
||||||
|
std::vector<mat4> _partTransforms;
|
||||||
|
render::ShapePlumberPointer _shapePlumber;
|
||||||
|
gpu::Stream::FormatPointer _vertexFormat { std::make_shared<gpu::Stream::Format>() };
|
||||||
|
gpu::BufferPointer _vertexBuffer { std::make_shared<gpu::Buffer>() };
|
||||||
|
gpu::BufferPointer _indexBuffer { std::make_shared<gpu::Buffer>() };
|
||||||
|
gpu::BufferPointer _indirectBuffer { std::make_shared<gpu::Buffer>() };
|
||||||
|
public:
|
||||||
|
TestFbx(const render::ShapePlumberPointer& shapePlumber);
|
||||||
|
bool isReady() const override;
|
||||||
|
void renderTest(size_t test, RenderArgs* args) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void parseFbx(const QByteArray& fbxData);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
54
tests/gpu-test/src/TestFloorGrid.cpp
Normal file
54
tests/gpu-test/src/TestFloorGrid.cpp
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2016/05/16
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "TestFloorGrid.h"
|
||||||
|
|
||||||
|
|
||||||
|
TestFloorGrid::TestFloorGrid() {
|
||||||
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
|
// Render grid on xz plane (not the optimal way to do things, but w/e)
|
||||||
|
// Note: GeometryCache::renderGrid will *not* work, as it is apparenly unaffected by batch rotations and renders xy only
|
||||||
|
static const std::string GRID_INSTANCE = "Grid";
|
||||||
|
static auto compactColor1 = toCompactColor(vec4 { 0.35f, 0.25f, 0.15f, 1.0f });
|
||||||
|
static auto compactColor2 = toCompactColor(vec4 { 0.15f, 0.25f, 0.35f, 1.0f });
|
||||||
|
static std::vector<glm::mat4> transforms;
|
||||||
|
static gpu::BufferPointer colorBuffer;
|
||||||
|
if (!transforms.empty()) {
|
||||||
|
transforms.reserve(200);
|
||||||
|
colorBuffer = std::make_shared<gpu::Buffer>();
|
||||||
|
for (int i = 0; i < 100; ++i) {
|
||||||
|
{
|
||||||
|
glm::mat4 transform = glm::translate(mat4(), vec3(0, -1, -50 + i));
|
||||||
|
transform = glm::scale(transform, vec3(100, 1, 1));
|
||||||
|
transforms.push_back(transform);
|
||||||
|
colorBuffer->append(compactColor1);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
glm::mat4 transform = glm::mat4_cast(quat(vec3(0, PI / 2.0f, 0)));
|
||||||
|
transform = glm::translate(transform, vec3(0, -1, -50 + i));
|
||||||
|
transform = glm::scale(transform, vec3(100, 1, 1));
|
||||||
|
transforms.push_back(transform);
|
||||||
|
colorBuffer->append(compactColor2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestFloorGrid::renderTest(size_t testId, RenderArgs* args) {
|
||||||
|
//gpu::Batch& batch = *(args->_batch);
|
||||||
|
//auto pipeline = geometryCache->getSimplePipeline();
|
||||||
|
//for (auto& transform : transforms) {
|
||||||
|
// batch.setModelTransform(transform);
|
||||||
|
// batch.setupNamedCalls(GRID_INSTANCE, [=](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
||||||
|
// batch.setPipeline(_pipeline);
|
||||||
|
// geometryCache->renderWireShapeInstances(batch, GeometryCache::Line, data.count(), colorBuffer);
|
||||||
|
// });
|
||||||
|
//}
|
||||||
|
}
|
26
tests/gpu-test/src/TestFloorGrid.h
Normal file
26
tests/gpu-test/src/TestFloorGrid.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2016/05/16
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <GLMHelpers.h>
|
||||||
|
#include <Transform.h>
|
||||||
|
|
||||||
|
#include <gpu/Resource.h>
|
||||||
|
#include <gpu/Stream.h>
|
||||||
|
|
||||||
|
#include "TestHelpers.h"
|
||||||
|
|
||||||
|
class TestFloorGrid : public GpuTestBase {
|
||||||
|
public:
|
||||||
|
TestFloorGrid();
|
||||||
|
void renderTest(size_t testId, RenderArgs* args) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
88
tests/gpu-test/src/TestFloorTexture.cpp
Normal file
88
tests/gpu-test/src/TestFloorTexture.cpp
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2016/05/16
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "TestFloorTexture.h"
|
||||||
|
|
||||||
|
struct Vertex {
|
||||||
|
vec4 position;
|
||||||
|
vec4 texture;
|
||||||
|
vec4 normal;
|
||||||
|
vec4 color;
|
||||||
|
};
|
||||||
|
static const uint TEXTURE_OFFSET = offsetof(Vertex, texture);
|
||||||
|
static const uint NORMAL_OFFSET = offsetof(Vertex, normal);
|
||||||
|
static const uint POSITION_OFFSET = offsetof(Vertex, position);
|
||||||
|
static const uint COLOR_OFFSET = offsetof(Vertex, color);
|
||||||
|
static const gpu::Element POSITION_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ };
|
||||||
|
static const gpu::Element TEXTURE_ELEMENT { gpu::VEC2, gpu::FLOAT, gpu::UV };
|
||||||
|
static const gpu::Element NORMAL_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ };
|
||||||
|
static const gpu::Element COLOR_ELEMENT { gpu::VEC4, gpu::FLOAT, gpu::RGBA };
|
||||||
|
|
||||||
|
FloorTextureTest::FloorTextureTest() {
|
||||||
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
|
std::vector<Vertex> vertices;
|
||||||
|
const int MINX = -1000;
|
||||||
|
const int MAXX = 1000;
|
||||||
|
|
||||||
|
vertices.push_back({
|
||||||
|
vec4(MAXX, 0, MAXX, 1),
|
||||||
|
vec4(MAXX, MAXX, 0, 0),
|
||||||
|
vec4(0, 1, 0, 1),
|
||||||
|
vec4(1),
|
||||||
|
});
|
||||||
|
|
||||||
|
vertices.push_back({
|
||||||
|
vec4(MAXX, 0, MINX, 1),
|
||||||
|
vec4(MAXX, 0, 0, 0),
|
||||||
|
vec4(0, 1, 0, 1),
|
||||||
|
vec4(1),
|
||||||
|
});
|
||||||
|
|
||||||
|
vertices.push_back({
|
||||||
|
vec4(MINX, 0, MINX, 1),
|
||||||
|
vec4(0, 0, 0, 0),
|
||||||
|
vec4(0, 1, 0, 1),
|
||||||
|
vec4(1),
|
||||||
|
});
|
||||||
|
|
||||||
|
vertices.push_back({
|
||||||
|
vec4(MINX, 0, MAXX, 1),
|
||||||
|
vec4(0, MAXX, 0, 0),
|
||||||
|
vec4(0, 1, 0, 1),
|
||||||
|
vec4(1),
|
||||||
|
});
|
||||||
|
|
||||||
|
vertexBuffer->append(vertices);
|
||||||
|
indexBuffer->append(std::vector<uint16_t>({ 0, 1, 2, 2, 3, 0 }));
|
||||||
|
texture = DependencyManager::get<TextureCache>()->getImageTexture("C:/Users/bdavis/Git/openvr/samples/bin/cube_texture.png");
|
||||||
|
//texture = DependencyManager::get<TextureCache>()->getImageTexture("H:/test.png");
|
||||||
|
//texture = DependencyManager::get<TextureCache>()->getImageTexture("H:/crate_blue.fbm/lambert8SG_Normal_OpenGL.png");
|
||||||
|
vertexFormat->setAttribute(gpu::Stream::POSITION, 0, POSITION_ELEMENT, POSITION_OFFSET);
|
||||||
|
vertexFormat->setAttribute(gpu::Stream::TEXCOORD, 0, TEXTURE_ELEMENT, TEXTURE_OFFSET);
|
||||||
|
vertexFormat->setAttribute(gpu::Stream::COLOR, 0, COLOR_ELEMENT, COLOR_OFFSET);
|
||||||
|
vertexFormat->setAttribute(gpu::Stream::NORMAL, 0, NORMAL_ELEMENT, NORMAL_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FloorTextureTest::renderTest(size_t testId, RenderArgs* args) {
|
||||||
|
gpu::Batch& batch = *(args->_batch);
|
||||||
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
|
static auto start = usecTimestampNow();
|
||||||
|
auto now = usecTimestampNow();
|
||||||
|
if ((now - start) > USECS_PER_SECOND * 1) {
|
||||||
|
start = now;
|
||||||
|
texture->incremementMinMip();
|
||||||
|
}
|
||||||
|
|
||||||
|
geometryCache->bindSimpleProgram(batch, true, true, true);
|
||||||
|
batch.setInputBuffer(0, vertexBuffer, 0, sizeof(Vertex));
|
||||||
|
batch.setInputFormat(vertexFormat);
|
||||||
|
batch.setIndexBuffer(gpu::UINT16, indexBuffer, 0);
|
||||||
|
batch.setResourceTexture(0, texture);
|
||||||
|
batch.setModelTransform(glm::translate(glm::mat4(), vec3(0, -0.1, 0)));
|
||||||
|
batch.drawIndexed(gpu::TRIANGLES, 6, 0);
|
||||||
|
}
|
22
tests/gpu-test/src/TestFloorTexture.h
Normal file
22
tests/gpu-test/src/TestFloorTexture.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2016/05/16
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "TestHelpers.h"
|
||||||
|
|
||||||
|
class FloorTextureTest : public GpuTestBase {
|
||||||
|
gpu::BufferPointer vertexBuffer { std::make_shared<gpu::Buffer>() };
|
||||||
|
gpu::BufferPointer indexBuffer { std::make_shared<gpu::Buffer>() };
|
||||||
|
gpu::Stream::FormatPointer vertexFormat { std::make_shared<gpu::Stream::Format>() };
|
||||||
|
gpu::TexturePointer texture;
|
||||||
|
public:
|
||||||
|
FloorTextureTest();
|
||||||
|
void renderTest(size_t testId, RenderArgs* args) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,9 @@
|
||||||
#include <render/CullTask.h>
|
#include <render/CullTask.h>
|
||||||
|
|
||||||
#include "TestWindow.h"
|
#include "TestWindow.h"
|
||||||
|
#include "TestFbx.h"
|
||||||
|
#include "TestFloorGrid.h"
|
||||||
|
#include "TestFloorTexture.h"
|
||||||
#include "TestInstancedShapes.h"
|
#include "TestInstancedShapes.h"
|
||||||
#include "TestShapes.h"
|
#include "TestShapes.h"
|
||||||
|
|
||||||
|
@ -90,8 +93,8 @@ class MyTestWindow : public TestWindow {
|
||||||
#endif
|
#endif
|
||||||
updateCamera();
|
updateCamera();
|
||||||
_testBuilders = TestBuilders({
|
_testBuilders = TestBuilders({
|
||||||
//[this] { return new TestFbx(_shapePlumber); },
|
[this] { return new TestFbx(_shapePlumber); },
|
||||||
[] { return new TestShapes(); },
|
[] { return new TestInstancedShapes(); },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
<@include gpu/Config.slh@>
|
|
||||||
<$VERSION_HEADER$>
|
|
||||||
// Generated on <$_SCRIBE_DATE$>
|
|
||||||
//
|
|
||||||
// simple.frag
|
|
||||||
// fragment shader
|
|
||||||
//
|
|
||||||
// Created by Andrzej Kapolka on 9/15/14.
|
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
<@include DeferredBufferWrite.slh@>
|
|
||||||
<@include model/Material.slh@>
|
|
||||||
|
|
||||||
// the interpolated normal
|
|
||||||
in vec3 _normal;
|
|
||||||
in vec3 _color;
|
|
||||||
|
|
||||||
void main(void) {
|
|
||||||
packDeferredFragment(
|
|
||||||
normalize(_normal.xyz),
|
|
||||||
1.0,
|
|
||||||
_color.rgb,
|
|
||||||
DEFAULT_ROUGHNESS, DEFAULT_METALLIC, DEFAULT_EMISSIVE, DEFAULT_OCCLUSION, DEFAULT_SCATTERING);
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
<@include gpu/Config.slh@>
|
|
||||||
<$VERSION_HEADER$>
|
|
||||||
// Generated on <$_SCRIBE_DATE$>
|
|
||||||
//
|
|
||||||
// simple.vert
|
|
||||||
// vertex shader
|
|
||||||
//
|
|
||||||
// Created by Andrzej Kapolka on 9/15/14.
|
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
<@include gpu/Inputs.slh@>
|
|
||||||
|
|
||||||
<@include gpu/Transform.slh@>
|
|
||||||
|
|
||||||
<$declareStandardTransform()$>
|
|
||||||
|
|
||||||
// the interpolated normal
|
|
||||||
out vec3 _normal;
|
|
||||||
out vec3 _color;
|
|
||||||
out vec2 _texCoord0;
|
|
||||||
|
|
||||||
void main(void) {
|
|
||||||
_color = inColor.rgb;
|
|
||||||
_texCoord0 = inTexCoord0.st;
|
|
||||||
|
|
||||||
// standard transform
|
|
||||||
TransformCamera cam = getTransformCamera();
|
|
||||||
TransformObject obj = getTransformObject();
|
|
||||||
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
|
|
||||||
<$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$>
|
|
||||||
_normal = vec3(0.0, 0.0, 1.0);
|
|
||||||
}
|
|
Loading…
Reference in a new issue