mirror of
https://github.com/JulianGro/overte.git
synced 2025-05-08 06:30:07 +02:00
Initial effort to reorganize the startup code.
This is intended to make things like plugin initialization more sane, and make Qt happier. Qt wants QApplication to start as soon as possible, but our code's attempt to load the entire world in the Application constructor doesn't quite mesh with this. This is an effort to first create Application much earlier, and do as little as possible in the constructor, moving almost all initialization to a later init function. A later stage would be to split the giant mess of init code into more digestible sections that run in some sort of logical order.
This commit is contained in:
parent
85a9987af5
commit
059600e8d4
3 changed files with 87 additions and 25 deletions
|
@ -724,7 +724,7 @@ extern DisplayPluginList getDisplayPlugins();
|
||||||
extern InputPluginList getInputPlugins();
|
extern InputPluginList getInputPlugins();
|
||||||
extern void saveInputPluginSettings(const InputPluginList& plugins);
|
extern void saveInputPluginSettings(const InputPluginList& plugins);
|
||||||
|
|
||||||
bool setupEssentials(int& argc, char** argv, const QCommandLineParser& parser, bool runningMarkerExisted) {
|
bool setupEssentials(const QCommandLineParser& parser, bool runningMarkerExisted) {
|
||||||
qInstallMessageHandler(messageHandler);
|
qInstallMessageHandler(messageHandler);
|
||||||
|
|
||||||
|
|
||||||
|
@ -743,6 +743,7 @@ bool setupEssentials(int& argc, char** argv, const QCommandLineParser& parser, b
|
||||||
|
|
||||||
bool previousSessionCrashed { false };
|
bool previousSessionCrashed { false };
|
||||||
if (!inTestMode) {
|
if (!inTestMode) {
|
||||||
|
// TODO: FIX
|
||||||
previousSessionCrashed = CrashRecoveryHandler::checkForResetSettings(runningMarkerExisted, suppressPrompt);
|
previousSessionCrashed = CrashRecoveryHandler::checkForResetSettings(runningMarkerExisted, suppressPrompt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -764,6 +765,7 @@ bool setupEssentials(int& argc, char** argv, const QCommandLineParser& parser, b
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tell the plugin manager about our statically linked plugins
|
// Tell the plugin manager about our statically linked plugins
|
||||||
|
DependencyManager::set<PathUtils>();
|
||||||
DependencyManager::set<ScriptInitializers>();
|
DependencyManager::set<ScriptInitializers>();
|
||||||
DependencyManager::set<PluginManager>();
|
DependencyManager::set<PluginManager>();
|
||||||
auto pluginManager = PluginManager::getInstance();
|
auto pluginManager = PluginManager::getInstance();
|
||||||
|
@ -777,6 +779,7 @@ bool setupEssentials(int& argc, char** argv, const QCommandLineParser& parser, b
|
||||||
oculusPlatform->init();
|
oculusPlatform->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PROFILE_SET_THREAD_NAME("Main Thread");
|
PROFILE_SET_THREAD_NAME("Main Thread");
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
|
@ -993,8 +996,7 @@ bool Application::initMenu() {
|
||||||
Application::Application(
|
Application::Application(
|
||||||
int& argc, char** argv,
|
int& argc, char** argv,
|
||||||
const QCommandLineParser& parser,
|
const QCommandLineParser& parser,
|
||||||
QElapsedTimer& startupTimer,
|
QElapsedTimer& startupTimer
|
||||||
bool runningMarkerExisted
|
|
||||||
) :
|
) :
|
||||||
QApplication(argc, argv),
|
QApplication(argc, argv),
|
||||||
_window(new MainWindow(desktop())),
|
_window(new MainWindow(desktop())),
|
||||||
|
@ -1004,7 +1006,7 @@ Application::Application(
|
||||||
#ifndef Q_OS_ANDROID
|
#ifndef Q_OS_ANDROID
|
||||||
_logger(new FileLogger(this)),
|
_logger(new FileLogger(this)),
|
||||||
#endif
|
#endif
|
||||||
_previousSessionCrashed(setupEssentials(argc, argv, parser, runningMarkerExisted)),
|
_previousSessionCrashed(setupEssentials(parser, false)),
|
||||||
_entitySimulation(std::make_shared<PhysicalEntitySimulation>()),
|
_entitySimulation(std::make_shared<PhysicalEntitySimulation>()),
|
||||||
_physicsEngine(std::make_shared<PhysicsEngine>(Vectors::ZERO)),
|
_physicsEngine(std::make_shared<PhysicsEngine>(Vectors::ZERO)),
|
||||||
_entityClipboard(std::make_shared<EntityTree>()),
|
_entityClipboard(std::make_shared<EntityTree>()),
|
||||||
|
@ -1032,12 +1034,22 @@ Application::Application(
|
||||||
_snapshotSound(nullptr),
|
_snapshotSound(nullptr),
|
||||||
_sampleSound(nullptr)
|
_sampleSound(nullptr)
|
||||||
{
|
{
|
||||||
auto steamClient = PluginManager::getInstance()->getSteamClientPlugin();
|
|
||||||
setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning()));
|
|
||||||
setProperty(hifi::properties::CRASHED, _previousSessionCrashed);
|
setProperty(hifi::properties::CRASHED, _previousSessionCrashed);
|
||||||
|
|
||||||
LogHandler::getInstance().moveToThread(thread());
|
LogHandler::getInstance().moveToThread(thread());
|
||||||
LogHandler::getInstance().setupRepeatedMessageFlusher();
|
LogHandler::getInstance().setupRepeatedMessageFlusher();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::initialize(const QCommandLineParser &parser) {
|
||||||
|
|
||||||
|
//qCDebug(interfaceapp) << "Setting up essentials";
|
||||||
|
//setupEssentials(parser, _previousSessionCrashed);
|
||||||
|
qCDebug(interfaceapp) << "Initializing application";
|
||||||
|
|
||||||
|
|
||||||
|
auto steamClient = PluginManager::getInstance()->getSteamClientPlugin();
|
||||||
|
setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning()));
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
if (parser.isSet("testScript")) {
|
if (parser.isSet("testScript")) {
|
||||||
|
@ -2375,7 +2387,7 @@ Application::Application(
|
||||||
|
|
||||||
connect(this, &Application::applicationStateChanged, this, &Application::activeChanged);
|
connect(this, &Application::applicationStateChanged, this, &Application::activeChanged);
|
||||||
connect(_window, SIGNAL(windowMinimizedChanged(bool)), this, SLOT(windowMinimizedChanged(bool)));
|
connect(_window, SIGNAL(windowMinimizedChanged(bool)), this, SLOT(windowMinimizedChanged(bool)));
|
||||||
qCDebug(interfaceapp, "Startup time: %4.2f seconds.", (double)startupTimer.elapsed() / 1000.0);
|
qCDebug(interfaceapp, "Startup time: %4.2f seconds.", (double)_sessionRunTimer.elapsed() / 1000.0);
|
||||||
|
|
||||||
EntityTreeRenderer::setEntitiesShouldFadeFunction([this]() {
|
EntityTreeRenderer::setEntitiesShouldFadeFunction([this]() {
|
||||||
SharedNodePointer entityServerNode = DependencyManager::get<NodeList>()->soloNodeOfType(NodeType::EntityServer);
|
SharedNodePointer entityServerNode = DependencyManager::get<NodeList>()->soloNodeOfType(NodeType::EntityServer);
|
||||||
|
@ -4201,7 +4213,9 @@ bool Application::handleFileOpenEvent(QFileOpenEvent* fileEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::notify(QObject * object, QEvent * event) {
|
bool Application::notify(QObject * object, QEvent * event) {
|
||||||
if (thread() == QThread::currentThread()) {
|
if (thread() == QThread::currentThread() && _profilingInitialized ) {
|
||||||
|
// _profilingInitialized gets set once we're reading for profiling.
|
||||||
|
// this prevents a deadlock due to profiling not working yet
|
||||||
PROFILE_RANGE_IF_LONGER(app, "notify", 2)
|
PROFILE_RANGE_IF_LONGER(app, "notify", 2)
|
||||||
return QApplication::notify(object, event);
|
return QApplication::notify(object, event);
|
||||||
}
|
}
|
||||||
|
@ -8762,7 +8776,11 @@ void Application::sendLambdaEvent(const std::function<void()>& f) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::initPlugins(const QCommandLineParser& parser) {
|
void Application::configurePlugins(const QCommandLineParser& parser) {
|
||||||
|
// This must be a member function -- PluginManager must exist, and for that
|
||||||
|
// QApplication must exist, or it can't find the plugin path, as QCoreApplication:applicationDirPath
|
||||||
|
// won't work yet.
|
||||||
|
|
||||||
if (parser.isSet("display")) {
|
if (parser.isSet("display")) {
|
||||||
auto preferredDisplays = parser.value("display").split(',', Qt::SkipEmptyParts);
|
auto preferredDisplays = parser.value("display").split(',', Qt::SkipEmptyParts);
|
||||||
qInfo() << "Setting prefered display plugins:" << preferredDisplays;
|
qInfo() << "Setting prefered display plugins:" << preferredDisplays;
|
||||||
|
@ -8780,6 +8798,7 @@ void Application::initPlugins(const QCommandLineParser& parser) {
|
||||||
qInfo() << "Disabling following input plugins:" << disabledInputs;
|
qInfo() << "Disabling following input plugins:" << disabledInputs;
|
||||||
PluginManager::getInstance()->disableInputs(disabledInputs);
|
PluginManager::getInstance()->disableInputs(disabledInputs);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::shutdownPlugins() {
|
void Application::shutdownPlugins() {
|
||||||
|
|
|
@ -123,6 +123,19 @@ class Application : public QApplication,
|
||||||
friend class OctreePacketProcessor;
|
friend class OctreePacketProcessor;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Initialize everything
|
||||||
|
*
|
||||||
|
* This is a QApplication, and for Qt reasons it's desirable to create this object
|
||||||
|
* as early as possible. Without that some Qt functions don't work, like QCoreApplication::applicationDirPath()
|
||||||
|
*
|
||||||
|
* So we keep the constructor as minimal as possible, and do the rest of the work in
|
||||||
|
* this function.
|
||||||
|
*/
|
||||||
|
void initialize(const QCommandLineParser &parser);
|
||||||
|
|
||||||
|
void setPreviousSessionCrashed(bool value) { _previousSessionCrashed = value; }
|
||||||
|
|
||||||
// virtual functions required for PluginContainer
|
// virtual functions required for PluginContainer
|
||||||
virtual ui::Menu* getPrimaryMenu() override;
|
virtual ui::Menu* getPrimaryMenu() override;
|
||||||
virtual void requestReset() override { resetSensors(false); }
|
virtual void requestReset() override { resetSensors(false); }
|
||||||
|
@ -136,14 +149,13 @@ public:
|
||||||
virtual DisplayPluginPointer getActiveDisplayPlugin() const override;
|
virtual DisplayPluginPointer getActiveDisplayPlugin() const override;
|
||||||
|
|
||||||
// FIXME? Empty methods, do we still need them?
|
// FIXME? Empty methods, do we still need them?
|
||||||
static void initPlugins(const QCommandLineParser& parser);
|
void configurePlugins(const QCommandLineParser& parser);
|
||||||
static void shutdownPlugins();
|
static void shutdownPlugins();
|
||||||
|
|
||||||
Application(
|
Application(
|
||||||
int& argc, char** argv,
|
int& argc, char** argv,
|
||||||
const QCommandLineParser& parser,
|
const QCommandLineParser& parser,
|
||||||
QElapsedTimer& startup_time,
|
QElapsedTimer& startup_time
|
||||||
bool runningMarkerExisted
|
|
||||||
);
|
);
|
||||||
~Application();
|
~Application();
|
||||||
|
|
||||||
|
@ -860,5 +872,7 @@ private:
|
||||||
bool _crashOnShutdown { false };
|
bool _crashOnShutdown { false };
|
||||||
|
|
||||||
DiscordPresence* _discordPresence{ nullptr };
|
DiscordPresence* _discordPresence{ nullptr };
|
||||||
|
|
||||||
|
bool _profilingInitialized { false };
|
||||||
};
|
};
|
||||||
#endif // hifi_Application_h
|
#endif // hifi_Application_h
|
||||||
|
|
|
@ -68,6 +68,18 @@ int main(int argc, const char* argv[]) {
|
||||||
// Journald by default in user applications is probably a bit too modern still.
|
// Journald by default in user applications is probably a bit too modern still.
|
||||||
LogHandler::getInstance().setShouldUseJournald(false);
|
LogHandler::getInstance().setShouldUseJournald(false);
|
||||||
|
|
||||||
|
|
||||||
|
// Extend argv to enable WebGL rendering
|
||||||
|
std::vector<const char*> argvExtended(&argv[0], &argv[argc]);
|
||||||
|
argvExtended.push_back("--ignore-gpu-blocklist");
|
||||||
|
#ifdef Q_OS_ANDROID
|
||||||
|
argvExtended.push_back("--suppress-settings-reset");
|
||||||
|
#endif
|
||||||
|
int argcExtended = (int)argvExtended.size();
|
||||||
|
|
||||||
|
QElapsedTimer startupTime;
|
||||||
|
startupTime.start();
|
||||||
|
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
parser.setApplicationDescription("Overte -- A free/libre and open-source virtual worlds client");
|
parser.setApplicationDescription("Overte -- A free/libre and open-source virtual worlds client");
|
||||||
QCommandLineOption helpOption = parser.addHelpOption();
|
QCommandLineOption helpOption = parser.addHelpOption();
|
||||||
|
@ -246,6 +258,15 @@ int main(int argc, const char* argv[]) {
|
||||||
"Logging options, comma separated: color,nocolor,process_id,thread_id,milliseconds,keep_repeats,journald,nojournald",
|
"Logging options, comma separated: color,nocolor,process_id,thread_id,milliseconds,keep_repeats,journald,nojournald",
|
||||||
"options"
|
"options"
|
||||||
);
|
);
|
||||||
|
QCommandLineOption abortAfterStartupOption(
|
||||||
|
"abortAfterStartup",
|
||||||
|
"Debug option. Aborts right after startup."
|
||||||
|
);
|
||||||
|
QCommandLineOption abortAfterInitOption(
|
||||||
|
"abortAfterInit",
|
||||||
|
"Debug option. Aborts after initialization, right before the program starts running the event loop."
|
||||||
|
);
|
||||||
|
|
||||||
// "--qmljsdebugger", which appears in output from "--help-all".
|
// "--qmljsdebugger", which appears in output from "--help-all".
|
||||||
// Those below don't seem to be optional.
|
// Those below don't seem to be optional.
|
||||||
// --ignore-gpu-blacklist
|
// --ignore-gpu-blacklist
|
||||||
|
@ -288,6 +309,9 @@ int main(int argc, const char* argv[]) {
|
||||||
parser.addOption(quitWhenFinishedOption);
|
parser.addOption(quitWhenFinishedOption);
|
||||||
parser.addOption(fastHeartbeatOption);
|
parser.addOption(fastHeartbeatOption);
|
||||||
parser.addOption(logOption);
|
parser.addOption(logOption);
|
||||||
|
parser.addOption(abortAfterStartupOption);
|
||||||
|
parser.addOption(abortAfterInitOption);
|
||||||
|
|
||||||
|
|
||||||
QString applicationPath;
|
QString applicationPath;
|
||||||
// A temporary application instance is needed to get the location of the running executable
|
// A temporary application instance is needed to get the location of the running executable
|
||||||
|
@ -310,6 +334,16 @@ int main(int argc, const char* argv[]) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: We need settings for Application, but Settings needs an Application
|
||||||
|
// to handle events. Needs splitting into two parts: enough initialization
|
||||||
|
// for Application to work, and then thread start afterwards.
|
||||||
|
Setting::init();
|
||||||
|
Application app(argcExtended, const_cast<char**>(argvExtended.data()), parser, startupTime);
|
||||||
|
|
||||||
|
if (parser.isSet("abortAfterStartup")) {
|
||||||
|
return 99;
|
||||||
|
}
|
||||||
|
|
||||||
// We want to configure the logging system as early as possible
|
// We want to configure the logging system as early as possible
|
||||||
auto& logHandler = LogHandler::getInstance();
|
auto& logHandler = LogHandler::getInstance();
|
||||||
|
|
||||||
|
@ -407,10 +441,9 @@ int main(int argc, const char* argv[]) {
|
||||||
QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
|
QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QElapsedTimer startupTime;
|
|
||||||
startupTime.start();
|
|
||||||
|
|
||||||
Setting::init();
|
|
||||||
|
|
||||||
|
|
||||||
// Instance UserActivityLogger now that the settings are loaded
|
// Instance UserActivityLogger now that the settings are loaded
|
||||||
auto& ual = UserActivityLogger::getInstance();
|
auto& ual = UserActivityLogger::getInstance();
|
||||||
|
@ -548,7 +581,7 @@ int main(int argc, const char* argv[]) {
|
||||||
// Oculus initialization MUST PRECEDE OpenGL context creation.
|
// Oculus initialization MUST PRECEDE OpenGL context creation.
|
||||||
// The nature of the Application constructor means this has to be either here,
|
// The nature of the Application constructor means this has to be either here,
|
||||||
// or in the main window ctor, before GL startup.
|
// or in the main window ctor, before GL startup.
|
||||||
Application::initPlugins(parser);
|
app.configurePlugins(parser);
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
// If we're running in steam mode, we need to do an explicit check to ensure we're up to the required min spec
|
// If we're running in steam mode, we need to do an explicit check to ensure we're up to the required min spec
|
||||||
|
@ -586,17 +619,10 @@ int main(int argc, const char* argv[]) {
|
||||||
SandboxUtils::runLocalSandbox(serverContentPath, true, noUpdater);
|
SandboxUtils::runLocalSandbox(serverContentPath, true, noUpdater);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extend argv to enable WebGL rendering
|
|
||||||
std::vector<const char*> argvExtended(&argv[0], &argv[argc]);
|
|
||||||
argvExtended.push_back("--ignore-gpu-blocklist");
|
|
||||||
#ifdef Q_OS_ANDROID
|
|
||||||
argvExtended.push_back("--suppress-settings-reset");
|
|
||||||
#endif
|
|
||||||
int argcExtended = (int)argvExtended.size();
|
|
||||||
|
|
||||||
PROFILE_SYNC_END(startup, "main startup", "");
|
PROFILE_SYNC_END(startup, "main startup", "");
|
||||||
PROFILE_SYNC_BEGIN(startup, "app full ctor", "");
|
PROFILE_SYNC_BEGIN(startup, "app full ctor", "");
|
||||||
Application app(argcExtended, const_cast<char**>(argvExtended.data()), parser, startupTime, runningMarkerExisted);
|
app.setPreviousSessionCrashed(runningMarkerExisted);
|
||||||
|
app.initialize(parser);
|
||||||
PROFILE_SYNC_END(startup, "app full ctor", "");
|
PROFILE_SYNC_END(startup, "app full ctor", "");
|
||||||
|
|
||||||
#if defined(Q_OS_LINUX)
|
#if defined(Q_OS_LINUX)
|
||||||
|
@ -664,6 +690,9 @@ int main(int argc, const char* argv[]) {
|
||||||
translator.load("i18n/interface_en");
|
translator.load("i18n/interface_en");
|
||||||
app.installTranslator(&translator);
|
app.installTranslator(&translator);
|
||||||
qCDebug(interfaceapp, "Created QT Application.");
|
qCDebug(interfaceapp, "Created QT Application.");
|
||||||
|
if (parser.isSet("abortAfterInit")) {
|
||||||
|
return 99;
|
||||||
|
}
|
||||||
exitCode = app.exec();
|
exitCode = app.exec();
|
||||||
server.close();
|
server.close();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue