49 #include "common/glew_wrappers.hh" 50 #include "OpenFlipper/BasePlugin/PluginFunctionsCore.hh" 59 #include <QCommandLineParser> 70 #include <PythonInterpreter/PythonInterpreter.hh> 85 #include "StackWalker/StackWalker.hh" 91 virtual void OnOutput(LPCSTR szText)
override 94 std::ofstream crashFile;
95 QString crashName = OpenFlipper::Options::configDirStr() + QDir::separator() +
"CrashDump.txt";
96 crashFile.open(crashName.toLatin1(),std::ios::out | std::ios::app);
101 StackWalker::OnOutput(szText);
116 void connect_console()
118 FILE* check = freopen(
"CONIN$",
"r", stdin);
120 std::cerr <<
"Error reopening stdin" << std::endl;
122 check = freopen(
"CONOUT$",
"w", stdout);
124 std::cerr <<
"Error reopening stdout" << std::endl;
126 check = freopen(
"CONOUT$",
"w", stderr);
128 std::cerr <<
"Error reopening stderr" << std::endl;
141 if (AttachConsole(-1))
156 if (OpenFlipper::Options::logToConsole())
173 #if defined(__GLIBCXX__) || defined(__GLIBCPP__) 176 std::string demangle(
const std::string& _symbol)
179 char* demangled = abi::__cxa_demangle(_symbol.c_str(),
nullptr,
nullptr, &status);
181 std::string result{demangled};
196 std::string demangle(
const std::string& _symbol)
207 int size = backtrace(addresses, 20);
208 strings = backtrace_symbols(addresses, size);
209 std::cerr <<
"Stack frames: " << size << std::endl;
212 std::regex line_format{R
"(^\s*(.+)\((([^()]+)?\+(0x[0-9a-f]+))?\)\s+\[(0x[0-9a-f]+)\]\s*$)"}; 213 for(
int i = 0; i < size; i++) {
214 std::string line{strings[i]};
216 std::regex_match(line, match, line_format);
217 if (!match.empty()) {
218 auto file_name = match[1].str();
219 auto symbol = demangle(match[3].str());
220 auto offset = match[4].str();
221 auto address = match[5].str();
222 std::cerr << i <<
":";
223 if (!file_name.empty()) std::cerr <<
" " << file_name <<
" ::";
224 if (!symbol.empty()) std::cerr <<
" " << symbol;
225 if (!offset.empty()) std::cerr <<
" (+" << offset <<
")";
226 if (!address.empty()) std::cerr <<
" [" << address <<
"]";
227 std::cerr << std::endl;
240 void segfaultHandling (
int) {
243 std::signal(SIGSEGV, SIG_DFL);
246 std::cerr <<
"\n" << std::endl;
247 std::cerr <<
"\n" << std::endl;
248 std::cerr <<
"\33[31m" <<
"=====================================================" << std::endl;
249 std::cerr <<
"\33[31m" <<
"OpenFlipper or one of its plugins caused a Segfault." << std::endl;
250 std::cerr <<
"\33[31m" <<
"This should not happen,... Sorry :-(" << std::endl;
251 std::cerr <<
"\33[31m" <<
"=====================================================" << std::endl;
252 std::cerr <<
"\n" << std::endl;
256 std::cerr <<
"\33[0m" <<
"Trying a backtrace to show what happened last: " << std::endl;
259 std::cerr <<
"\n" << std::endl;
260 std::cerr <<
"Backtrace completed, trying to abort now ..." << std::endl;
265 StackWalkerToConsole sw;
270 std::cerr <<
"Trying to get additional information (This might fail if the memory is corrupted)." << std::endl;
272 if (OpenFlipper::Options::gui()) {
273 for (
unsigned int i = 0 ; i < 4 ; ++i) {
281 enum CommandLineParseResult
285 CommandLineVersionRequested,
286 CommandLineHelpRequested
290 bool openPolyMeshes =
false;
291 bool remoteControl =
false;
294 CommandLineParseResult parseCommandLine(QCommandLineParser &parser, QString *errorMessage) {
299 int QtVersionMajor, QtVersionMinor, QtVersionPatch;
300 if(sscanf(qVersion(),
"%1d.%1d.%1d",&QtVersionMajor, &QtVersionMinor, &QtVersionPatch) == 3)
302 if(QtVersionMajor == 5 && QtVersionMinor >= 7)
304 if(QtVersionPatch < 2)
306 std::cerr <<
"The used Qt Version does not support stereo mode. Disabling stereo mode." << std::endl;
307 OpenFlipper::Options::stereo(
false);
310 std::cerr <<
"Stereo Mode has not been tested for the used Qt Version." << std::endl;
317 parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
320 QCommandLineOption debugOption(QStringList() <<
"d" <<
"debug",QCoreApplication::translate(
"main",
"Enable debugging mode"));
321 parser.addOption(debugOption);
323 QCommandLineOption stereoOption(
"disable-stereo",QCoreApplication::translate(
"main",
"Disable stereo mode"));
324 parser.addOption(stereoOption);
326 QCommandLineOption batchOption(QStringList() <<
"b" <<
"batch",QCoreApplication::translate(
"main",
"Batch mode, you have to provide a script for execution"));
327 parser.addOption(batchOption);
329 QCommandLineOption logConsoleOption(QStringList() <<
"c" <<
"log-to-console",QCoreApplication::translate(
"main",
"Write logger window contents to console"));
330 parser.addOption(logConsoleOption);
332 QCommandLineOption remoteControlOption(
"remote-control",QCoreApplication::translate(
"main",
"Batch mode accepting remote connections"));
333 parser.addOption(remoteControlOption);
335 QCommandLineOption fulscreenOption(QStringList() <<
"f" <<
"fullscreen",QCoreApplication::translate(
"main",
"Start in fullscreen mode"));
336 parser.addOption(fulscreenOption);
338 QCommandLineOption hideLoggerOption(QStringList() <<
"l" <<
"hide-logger",QCoreApplication::translate(
"main",
"Start with hidden log window"));
339 parser.addOption(hideLoggerOption);
341 QCommandLineOption hideToolboxOption(QStringList() <<
"t" <<
"hide-toolbox",QCoreApplication::translate(
"main",
"Start with hidden toolbox"));
342 parser.addOption(hideToolboxOption);
344 QCommandLineOption noSplashOption(
"no-splash",QCoreApplication::translate(
"main",
"Hide splash screen"));
345 parser.addOption(noSplashOption);
347 QCommandLineOption polyMeshOption(
"p",QCoreApplication::translate(
"main",
"Open files as PolyMeshes"));
348 parser.addOption(polyMeshOption);
350 QCommandLineOption remotePortOption(
"remote-port",QCoreApplication::translate(
"main",
"Remote port"),
"portnumber");
351 parser.addOption(remotePortOption);
353 QCommandLineOption coreProfileOption(
"core-profile",QCoreApplication::translate(
"main",
"OpenGL Core Profile Mode"));
354 parser.addOption(coreProfileOption);
356 QCommandLineOption glVersionOption(
"glVersion",QCoreApplication::translate(
"main",
"Request OpenGL version <major>.<minor> "),QCoreApplication::translate(
"main",
"< 1.0 | 1.1 | ... | 4.6 >"));
357 parser.addOption(glVersionOption);
359 QCommandLineOption samplesOption(
"samples",QCoreApplication::translate(
"main",
"Overwrite multisampling sample count"),QCoreApplication::translate(
"main",
"< 0 | 1 | 2 | ... | 16 >"));
360 parser.addOption(samplesOption);
362 QCommandLineOption glStereoOption(
"glStereo",QCoreApplication::translate(
"main",
"Overwrite OpenGL Stereo setting"),QCoreApplication::translate(
"main",
"< true | false >"));
363 parser.addOption(glStereoOption);
365 QCommandLineOption profileOption(
"profile",QCoreApplication::translate(
"main",
"Request OpenGL context profile <profile> with profile set as compat or core"),QCoreApplication::translate(
"main",
"< compat | core >"));
366 parser.addOption(profileOption);
368 QCommandLineOption pluginOptionsOption(QStringList() <<
"o" <<
"pluginoptions",QCoreApplication::translate(
"main",
"Pass options to plugins"),
"key1=value1;key2=value2;...");
369 parser.addOption(pluginOptionsOption);
371 const QCommandLineOption helpOption = parser.addHelpOption();
372 const QCommandLineOption versionOption = parser.addVersionOption();
376 if (!parser.parse(QCoreApplication::arguments())) {
377 *errorMessage = parser.errorText();
378 return CommandLineError;
381 if (parser.isSet(helpOption))
382 return CommandLineHelpRequested;
384 if (parser.isSet(versionOption))
385 return CommandLineVersionRequested;
387 if (parser.isSet(debugOption)) {
388 OpenFlipper::Options::debug(
true);
391 if (parser.isSet(stereoOption)) {
392 OpenFlipper::Options::stereo(
false);
395 if (parser.isSet(batchOption)) {
396 OpenFlipper::Options::nogui(
true);
399 if (parser.isSet(logConsoleOption)) {
400 OpenFlipper::Options::logToConsole(
true);
403 if (parser.isSet(remoteControlOption)) {
404 OpenFlipper::Options::remoteControl(
true);
407 if (parser.isSet(fulscreenOption)) {
411 if (parser.isSet(hideLoggerOption)) {
412 OpenFlipper::Options::loggerState(OpenFlipper::Options::Hidden);
415 if (parser.isSet(hideToolboxOption)) {
419 if (parser.isSet(noSplashOption)) {
423 if (parser.isSet(polyMeshOption)) {
424 openPolyMeshes =
true;
427 if (parser.isSet(remotePortOption)) {
428 const QString port = parser.value(
"remote-port");
429 std::cerr <<
"Got port option : " << port.toStdString() << std::endl;
430 OpenFlipper::Options::remoteControl(port.toInt());
432 if(parser.isSet(
"samples"))
433 OpenFlipper::Options::samples(parser.value(
"samples").toInt(),
true);
434 if(parser.isSet(
"glVersion"))
436 QStringList values = parser.value(
"glVersion").split(
".");
437 QPair<int,int> version(
440 OpenFlipper::Options::glVersion(version,
true);
443 if(parser.isSet(
"glStereo"))
444 OpenFlipper::Options::glStereo(parser.value(
"glStereo")==
"true");
446 if(parser.value(profileOption)==
"core")
448 OpenFlipper::Options::coreProfile(
true,
true);
452 if(parser.value(profileOption)==
"compat")
454 OpenFlipper::Options::coreProfile(
false,
true);
457 if(parser.isSet(coreProfileOption)) {
458 OpenFlipper::Options::coreProfile(
true,
true);
460 if(parser.isSet(pluginOptionsOption))
462 QStringList poptions = parser.value(pluginOptionsOption).split(
";");
463 QVector<QPair<QString, QString>> pcloptions;
464 for(
auto s : poptions)
466 auto kvp = s.split(
"=");
474 pcloptions.push_back({key, value});
479 return CommandLineOk;
487 std::string profileToString(QSurfaceFormat::OpenGLContextProfile _profile)
489 if(_profile == QSurfaceFormat::CompatibilityProfile)
490 return "CompatibilityProfile";
492 if(_profile == QSurfaceFormat::CoreProfile)
493 return "CoreProfile";
495 if(_profile == QSurfaceFormat::NoProfile)
503 bool verifySpecificContextFormat(QSurfaceFormat format, QSurfaceFormat* resultingFormat =
nullptr)
506 QSurfaceFormat::setDefaultFormat(format);
510 QApplication tempApp(tempArgC,
nullptr);
511 QOffscreenSurface *surface =
new QOffscreenSurface();
514 auto shareContext = QOpenGLContext::globalShareContext();
517 std::cerr <<
"Error: Apparently no GL context was created!" << std::endl;
522 shareContext->makeCurrent(surface);
526 auto resultFormat = QOpenGLContext::globalShareContext()->format();
529 if(resultingFormat !=
nullptr)
530 *resultingFormat = resultFormat;
532 auto curVersion = resultFormat.version();
535 auto reqProfileString = profileToString(format.profile());
538 auto curProfileString = profileToString(resultFormat.profile());
542 auto reqVersionInt = format.version().first * 10 + format.version().second;
543 auto curVersionInt = curVersion.first * 10 + curVersion.second;
551 if(curVersionInt < 32 && resultFormat.profile() == QSurfaceFormat::CoreProfile)
553 std::cerr <<
"Warning: Got an OpenGL core context with OpengGL version < 3.2 (" << curVersion.first <<
"." << curVersion.second <<
")! This should not be possible." << std::endl;
559 if(curVersionInt < reqVersionInt ||
560 format.profile()!= resultFormat.profile() )
562 std::cout <<
"[OpenGL context] Requested: " 563 << format.version().first <<
"." << format.version().second <<
" (" << reqProfileString <<
")" 564 <<
", Actually created: " 565 << curVersion.first <<
"." << curVersion.second <<
" (" << curProfileString <<
")" 570 std::cout <<
"[OpenGL context] Successfully created OpenGL context with version " << curVersion.first <<
"." 571 << curVersion.second <<
" (" << curProfileString <<
")." << std::endl;
577 QSurfaceFormat createFormat(QSurfaceFormat::OpenGLContextProfile _profile,
int _glMajor,
int _glMinor,
int _multisamplingSamples,
bool _stereo,
bool _debugContext)
579 QSurfaceFormat format;
580 format.setVersion(_glMajor, _glMinor);
581 format.setProfile(_profile);
582 format.setSamples(_multisamplingSamples);
583 format.setStereo(_stereo);
584 if(_profile != QSurfaceFormat::CoreProfile)
585 format.setOption(QSurfaceFormat::DeprecatedFunctions);
587 format.setOption(format.options() | QSurfaceFormat::DebugContext);
597 QSurfaceFormat getContextFormat()
599 auto reqProfile = OpenFlipper::Options::coreProfile() ? QSurfaceFormat::CoreProfile : QSurfaceFormat::CompatibilityProfile;
600 QPair<int,int> reqVersion = OpenFlipper::Options::glVersion();
601 auto reqSamples = OpenFlipper::Options::samples();
602 auto reqStereo = OpenFlipper::Options::glStereo();
603 bool debugContext = OpenFlipper::Options::debug();
624 QSurfaceFormat resultFormat;
627 std::cout <<
"[OpenGL context] Trying to create a " << reqVersion.first <<
"." << reqVersion.second <<
" " << profileToString(reqProfile) <<
" context (default from settings)..." << std::endl;
628 bool success = verifySpecificContextFormat(createFormat(reqProfile, reqVersion.first, reqVersion.second, reqSamples, reqStereo, debugContext), &resultFormat);
633 std::cout <<
"[OpenGL context] Trying to create a 4.4 compat context..." << std::endl;
634 success = verifySpecificContextFormat(createFormat(QSurfaceFormat::CompatibilityProfile, 4, 4, reqSamples, reqStereo, debugContext), &resultFormat);
638 std::cout <<
"[OpenGL context] Trying to create a 3.2 core context..." << std::endl;
639 success = verifySpecificContextFormat(createFormat(QSurfaceFormat::CoreProfile, 3, 2, reqSamples, reqStereo, debugContext), &resultFormat);
642 std::cerr <<
"[OpenGL context] Warning: Could not create any of the requested GL contexts." << std::endl;
643 std::cerr <<
"[OpenGL context] The following context (proposed by the graphics driver) will be created:" << std::endl;
644 std::cerr <<
"[OpenGL context] Profile: " << profileToString(resultFormat.profile()) <<
", Version: " 645 << resultFormat.version().first <<
"." << resultFormat.version().second << std::endl;
646 std::cerr <<
"[OpenGL context] Please consider setting a supported OpenGL version and profile in the Options dialog." << std::endl;
656 int main(
int argc,
char **argv)
661 for (
int i = 0; i < argc; i++) {
662 if(strlen(argv[i]) > 4) {
663 if( ( (argv[i])[0] ==
'-' ) &&
664 ( (argv[i])[1] ==
'p' ) &&
665 ( (argv[i])[2] ==
's' ) &&
666 ( (argv[i])[3] ==
'n' ) ) {
668 argv[i] = (
char *)
"";
673 OpenFlipper::Options::argc(&argc);
674 OpenFlipper::Options::argv(&argv);
677 QCoreApplication::setOrganizationName(
"VCI");
678 QCoreApplication::setApplicationName(
TOSTRING(PRODUCT_STRING));
679 QCoreApplication::setApplicationVersion(OpenFlipper::Options::coreVersion());
682 QCoreApplication* coreApp =
new QCoreApplication(argc, argv);
684 OpenFlipper::Options::initializeSettings();
686 QCommandLineParser parser;
687 QString errorMessage;
690 switch (parseCommandLine(parser, &errorMessage)) {
693 case CommandLineError:
694 fputs(qPrintable(errorMessage), stderr);
695 fputs(
"\n\n", stderr);
696 fputs(qPrintable(parser.helpText()), stderr);
698 case CommandLineVersionRequested:
699 printf(
"%s %s\n", qPrintable(QCoreApplication::applicationName()),
700 qPrintable(QCoreApplication::applicationVersion()));
702 case CommandLineHelpRequested:
718 #ifndef NO_CATCH_SIGSEGV 720 std::signal(SIGSEGV, segfaultHandling);
723 OpenFlipper::Options::windowTitle(
TOSTRING(PRODUCT_STRING)
" v" + OpenFlipper::Options::coreVersion());
725 if ( !OpenFlipper::Options::nogui() ) {
728 QApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
729 QApplication::setColorSpec( QApplication::CustomColor );
735 QSurfaceFormat resultFormat = getContextFormat();
738 OpenFlipper::Options::samples(resultFormat.samples(),
true);
739 OpenFlipper::Options::glStereo(resultFormat.stereo(),
true);
740 OpenFlipper::Options::glVersion(resultFormat.version(),
true);
741 OpenFlipper::Options::coreProfile(resultFormat.profile() == QSurfaceFormat::CoreProfile,
true);
744 QSurfaceFormat::setDefaultFormat(resultFormat);
745 QApplication app(argc, argv);
746 QOffscreenSurface *surface =
new QOffscreenSurface();
750 QOpenGLContext::globalShareContext()->makeCurrent(surface);
755 if ( !QGLFormat::hasOpenGL() ) {
756 std::cerr <<
"This system has no OpenGL support.\n";
762 #ifdef PYTHON_ENABLED 768 if (tLang ==
"locale")
769 tLang = QLocale::system().name();
772 QTranslator qtTranslator;
773 qtTranslator.load(
"qt_" + tLang, QLibraryInfo::location(QLibraryInfo::TranslationsPath));
774 app.installTranslator(&qtTranslator);
777 QString translationDir = OpenFlipper::Options::translationsDirStr() + QDir::separator();
778 QDir dir(translationDir);
779 dir.setFilter(QDir::Files);
781 QFileInfoList list = dir.entryInfoList();
783 for (
int i = 0; i < list.size(); ++i) {
784 QFileInfo fileInfo = list.at(i);
786 if ( fileInfo.baseName().contains(tLang) ){
787 QTranslator* myAppTranslator =
new QTranslator();
789 if ( myAppTranslator->load( fileInfo.filePath() ) )
791 app.installTranslator(myAppTranslator);
794 delete myAppTranslator;
806 const QStringList positionalArguments = parser.positionalArguments();
808 for (
auto file: positionalArguments ) {
816 QCoreApplication app(argc,argv);
822 #ifdef PYTHON_ENABLED 829 const QStringList positionalArguments = parser.positionalArguments();
831 for (
auto file: positionalArguments ) {
void commandLineOpen(const QString &_filename, bool _asPolyMesh)
Load an object from the commandline on application start.
ACG::SceneGraph::DrawModes::DrawMode drawMode(int _viewer)
Get the current draw Mode of a Viewer.
std::string description() const
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
#define TOSTRING(x)
QSettings object containing all program settings of OpenFlipper.
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
DLLEXPORT void setPluginCommandLineOptions(QVector< QPair< QString, QString >> const &_pluginCommandLineOptions)
void init()
Second initialization stage.