mirror of
https://github.com/lubosz/overte.git
synced 2025-04-07 15:22:09 +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 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);
|
||||
|
||||
|
||||
|
@ -743,6 +743,7 @@ bool setupEssentials(int& argc, char** argv, const QCommandLineParser& parser, b
|
|||
|
||||
bool previousSessionCrashed { false };
|
||||
if (!inTestMode) {
|
||||
// TODO: FIX
|
||||
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
|
||||
DependencyManager::set<PathUtils>();
|
||||
DependencyManager::set<ScriptInitializers>();
|
||||
DependencyManager::set<PluginManager>();
|
||||
auto pluginManager = PluginManager::getInstance();
|
||||
|
@ -777,6 +779,7 @@ bool setupEssentials(int& argc, char** argv, const QCommandLineParser& parser, b
|
|||
oculusPlatform->init();
|
||||
}
|
||||
|
||||
|
||||
PROFILE_SET_THREAD_NAME("Main Thread");
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
|
@ -993,8 +996,7 @@ bool Application::initMenu() {
|
|||
Application::Application(
|
||||
int& argc, char** argv,
|
||||
const QCommandLineParser& parser,
|
||||
QElapsedTimer& startupTimer,
|
||||
bool runningMarkerExisted
|
||||
QElapsedTimer& startupTimer
|
||||
) :
|
||||
QApplication(argc, argv),
|
||||
_window(new MainWindow(desktop())),
|
||||
|
@ -1004,7 +1006,7 @@ Application::Application(
|
|||
#ifndef Q_OS_ANDROID
|
||||
_logger(new FileLogger(this)),
|
||||
#endif
|
||||
_previousSessionCrashed(setupEssentials(argc, argv, parser, runningMarkerExisted)),
|
||||
_previousSessionCrashed(setupEssentials(parser, false)),
|
||||
_entitySimulation(std::make_shared<PhysicalEntitySimulation>()),
|
||||
_physicsEngine(std::make_shared<PhysicsEngine>(Vectors::ZERO)),
|
||||
_entityClipboard(std::make_shared<EntityTree>()),
|
||||
|
@ -1032,12 +1034,22 @@ Application::Application(
|
|||
_snapshotSound(nullptr),
|
||||
_sampleSound(nullptr)
|
||||
{
|
||||
auto steamClient = PluginManager::getInstance()->getSteamClientPlugin();
|
||||
setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning()));
|
||||
setProperty(hifi::properties::CRASHED, _previousSessionCrashed);
|
||||
|
||||
LogHandler::getInstance().moveToThread(thread());
|
||||
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")) {
|
||||
|
@ -2375,7 +2387,7 @@ Application::Application(
|
|||
|
||||
connect(this, &Application::applicationStateChanged, this, &Application::activeChanged);
|
||||
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]() {
|
||||
SharedNodePointer entityServerNode = DependencyManager::get<NodeList>()->soloNodeOfType(NodeType::EntityServer);
|
||||
|
@ -4201,7 +4213,9 @@ bool Application::handleFileOpenEvent(QFileOpenEvent* fileEvent) {
|
|||
}
|
||||
|
||||
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)
|
||||
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")) {
|
||||
auto preferredDisplays = parser.value("display").split(',', Qt::SkipEmptyParts);
|
||||
qInfo() << "Setting prefered display plugins:" << preferredDisplays;
|
||||
|
@ -8780,6 +8798,7 @@ void Application::initPlugins(const QCommandLineParser& parser) {
|
|||
qInfo() << "Disabling following input plugins:" << disabledInputs;
|
||||
PluginManager::getInstance()->disableInputs(disabledInputs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Application::shutdownPlugins() {
|
||||
|
|
|
@ -123,6 +123,19 @@ class Application : public QApplication,
|
|||
friend class OctreePacketProcessor;
|
||||
|
||||
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 ui::Menu* getPrimaryMenu() override;
|
||||
virtual void requestReset() override { resetSensors(false); }
|
||||
|
@ -136,14 +149,13 @@ public:
|
|||
virtual DisplayPluginPointer getActiveDisplayPlugin() const override;
|
||||
|
||||
// FIXME? Empty methods, do we still need them?
|
||||
static void initPlugins(const QCommandLineParser& parser);
|
||||
void configurePlugins(const QCommandLineParser& parser);
|
||||
static void shutdownPlugins();
|
||||
|
||||
Application(
|
||||
int& argc, char** argv,
|
||||
const QCommandLineParser& parser,
|
||||
QElapsedTimer& startup_time,
|
||||
bool runningMarkerExisted
|
||||
QElapsedTimer& startup_time
|
||||
);
|
||||
~Application();
|
||||
|
||||
|
@ -860,5 +872,7 @@ private:
|
|||
bool _crashOnShutdown { false };
|
||||
|
||||
DiscordPresence* _discordPresence{ nullptr };
|
||||
|
||||
bool _profilingInitialized { false };
|
||||
};
|
||||
#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.
|
||||
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;
|
||||
parser.setApplicationDescription("Overte -- A free/libre and open-source virtual worlds client");
|
||||
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",
|
||||
"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".
|
||||
// Those below don't seem to be optional.
|
||||
// --ignore-gpu-blacklist
|
||||
|
@ -288,6 +309,9 @@ int main(int argc, const char* argv[]) {
|
|||
parser.addOption(quitWhenFinishedOption);
|
||||
parser.addOption(fastHeartbeatOption);
|
||||
parser.addOption(logOption);
|
||||
parser.addOption(abortAfterStartupOption);
|
||||
parser.addOption(abortAfterInitOption);
|
||||
|
||||
|
||||
QString applicationPath;
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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
|
||||
auto& logHandler = LogHandler::getInstance();
|
||||
|
||||
|
@ -407,10 +441,9 @@ int main(int argc, const char* argv[]) {
|
|||
QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
|
||||
#endif
|
||||
|
||||
QElapsedTimer startupTime;
|
||||
startupTime.start();
|
||||
|
||||
Setting::init();
|
||||
|
||||
|
||||
|
||||
// Instance UserActivityLogger now that the settings are loaded
|
||||
auto& ual = UserActivityLogger::getInstance();
|
||||
|
@ -548,7 +581,7 @@ int main(int argc, const char* argv[]) {
|
|||
// Oculus initialization MUST PRECEDE OpenGL context creation.
|
||||
// The nature of the Application constructor means this has to be either here,
|
||||
// or in the main window ctor, before GL startup.
|
||||
Application::initPlugins(parser);
|
||||
app.configurePlugins(parser);
|
||||
|
||||
#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
|
||||
|
@ -586,17 +619,10 @@ int main(int argc, const char* argv[]) {
|
|||
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_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", "");
|
||||
|
||||
#if defined(Q_OS_LINUX)
|
||||
|
@ -664,6 +690,9 @@ int main(int argc, const char* argv[]) {
|
|||
translator.load("i18n/interface_en");
|
||||
app.installTranslator(&translator);
|
||||
qCDebug(interfaceapp, "Created QT Application.");
|
||||
if (parser.isSet("abortAfterInit")) {
|
||||
return 99;
|
||||
}
|
||||
exitCode = app.exec();
|
||||
server.close();
|
||||
|
||||
|
|
Loading…
Reference in a new issue