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)
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(
"=");
469 pcloptions.push_back({key, value});
474 return CommandLineOk;
482 std::string profileToString(QSurfaceFormat::OpenGLContextProfile _profile)
484 if(_profile == QSurfaceFormat::CompatibilityProfile)
485 return "CompatibilityProfile";
487 if(_profile == QSurfaceFormat::CoreProfile)
488 return "CoreProfile";
490 if(_profile == QSurfaceFormat::NoProfile)
498 bool verifySpecificContextFormat(QSurfaceFormat format, QSurfaceFormat* resultingFormat =
nullptr)
501 QSurfaceFormat::setDefaultFormat(format);
505 QApplication tempApp(tempArgC,
nullptr);
506 QOffscreenSurface *surface =
new QOffscreenSurface();
509 auto shareContext = QOpenGLContext::globalShareContext();
512 std::cerr <<
"Error: Apparently no GL context was created!" << std::endl;
517 shareContext->makeCurrent(surface);
521 auto resultFormat = QOpenGLContext::globalShareContext()->format();
524 if(resultingFormat !=
nullptr)
525 *resultingFormat = resultFormat;
527 auto curVersion = resultFormat.version();
530 auto reqProfileString = profileToString(format.profile());
533 auto curProfileString = profileToString(resultFormat.profile());
537 auto reqVersionInt = format.version().first * 10 + format.version().second;
538 auto curVersionInt = curVersion.first * 10 + curVersion.second;
546 if(curVersionInt < 32 && resultFormat.profile() == QSurfaceFormat::CoreProfile)
548 std::cerr <<
"Warning: Got an OpenGL core context with OpengGL version < 3.2 (" << curVersion.first <<
"." << curVersion.second <<
")! This should not be possible." << std::endl;
554 if(curVersionInt < reqVersionInt ||
555 format.profile()!= resultFormat.profile() )
557 std::cout <<
"[OpenGL context] Requested: " 558 << format.version().first <<
"." << format.version().second <<
" (" << reqProfileString <<
")" 559 <<
", Actually created: " 560 << curVersion.first <<
"." << curVersion.second <<
" (" << curProfileString <<
")" 565 std::cout <<
"[OpenGL context] Successfully created OpenGL context with version " << curVersion.first <<
"." 566 << curVersion.second <<
" (" << curProfileString <<
")." << std::endl;
572 QSurfaceFormat createFormat(QSurfaceFormat::OpenGLContextProfile _profile,
int _glMajor,
int _glMinor,
int _multisamplingSamples,
bool _stereo,
bool _debugContext)
574 QSurfaceFormat format;
575 format.setVersion(_glMajor, _glMinor);
576 format.setProfile(_profile);
577 format.setSamples(_multisamplingSamples);
578 format.setStereo(_stereo);
579 if(_profile != QSurfaceFormat::CoreProfile)
580 format.setOption(QSurfaceFormat::DeprecatedFunctions);
582 format.setOption(format.options() | QSurfaceFormat::DebugContext);
592 QSurfaceFormat getContextFormat()
594 auto reqProfile = OpenFlipper::Options::coreProfile() ? QSurfaceFormat::CoreProfile : QSurfaceFormat::CompatibilityProfile;
595 QPair<int,int> reqVersion = OpenFlipper::Options::glVersion();
596 auto reqSamples = OpenFlipper::Options::samples();
597 auto reqStereo = OpenFlipper::Options::glStereo();
598 bool debugContext = OpenFlipper::Options::debug();
619 QSurfaceFormat resultFormat;
622 std::cout <<
"[OpenGL context] Trying to create a " << reqVersion.first <<
"." << reqVersion.second <<
" " << profileToString(reqProfile) <<
" context (default from settings)..." << std::endl;
623 bool success = verifySpecificContextFormat(createFormat(reqProfile, reqVersion.first, reqVersion.second, reqSamples, reqStereo, debugContext), &resultFormat);
628 std::cout <<
"[OpenGL context] Trying to create a 4.4 compat context..." << std::endl;
629 success = verifySpecificContextFormat(createFormat(QSurfaceFormat::CompatibilityProfile, 4, 4, reqSamples, reqStereo, debugContext), &resultFormat);
633 std::cout <<
"[OpenGL context] Trying to create a 3.2 core context..." << std::endl;
634 success = verifySpecificContextFormat(createFormat(QSurfaceFormat::CoreProfile, 3, 2, reqSamples, reqStereo, debugContext), &resultFormat);
637 std::cerr <<
"[OpenGL context] Warning: Could not create any of the requested GL contexts." << std::endl;
638 std::cerr <<
"[OpenGL context] The following context (proposed by the graphics driver) will be created:" << std::endl;
639 std::cerr <<
"[OpenGL context] Profile: " << profileToString(resultFormat.profile()) <<
", Version: " 640 << resultFormat.version().first <<
"." << resultFormat.version().second << std::endl;
641 std::cerr <<
"[OpenGL context] Please consider setting a supported OpenGL version and profile in the Options dialog." << std::endl;
651 int main(
int argc,
char **argv)
656 for (
int i = 0; i < argc; i++) {
657 if(strlen(argv[i]) > 4) {
658 if( ( (argv[i])[0] ==
'-' ) &&
659 ( (argv[i])[1] ==
'p' ) &&
660 ( (argv[i])[2] ==
's' ) &&
661 ( (argv[i])[3] ==
'n' ) ) {
663 argv[i] = (
char *)
"";
668 OpenFlipper::Options::argc(&argc);
669 OpenFlipper::Options::argv(&argv);
672 QCoreApplication::setOrganizationName(
"VCI");
673 QCoreApplication::setApplicationName(
TOSTRING(PRODUCT_STRING));
674 QCoreApplication::setApplicationVersion(OpenFlipper::Options::coreVersion());
677 QCoreApplication* coreApp =
new QCoreApplication(argc, argv);
679 OpenFlipper::Options::initializeSettings();
681 QCommandLineParser parser;
682 QString errorMessage;
685 switch (parseCommandLine(parser, &errorMessage)) {
688 case CommandLineError:
689 fputs(qPrintable(errorMessage), stderr);
690 fputs(
"\n\n", stderr);
691 fputs(qPrintable(parser.helpText()), stderr);
693 case CommandLineVersionRequested:
694 printf(
"%s %s\n", qPrintable(QCoreApplication::applicationName()),
695 qPrintable(QCoreApplication::applicationVersion()));
697 case CommandLineHelpRequested:
713 #ifndef NO_CATCH_SIGSEGV 715 std::signal(SIGSEGV, segfaultHandling);
718 OpenFlipper::Options::windowTitle(
TOSTRING(PRODUCT_STRING)
" v" + OpenFlipper::Options::coreVersion());
720 if ( !OpenFlipper::Options::nogui() ) {
723 QApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
724 QApplication::setColorSpec( QApplication::CustomColor );
730 QSurfaceFormat resultFormat = getContextFormat();
733 OpenFlipper::Options::samples(resultFormat.samples(),
true);
734 OpenFlipper::Options::glStereo(resultFormat.stereo(),
true);
735 OpenFlipper::Options::glVersion(resultFormat.version(),
true);
736 OpenFlipper::Options::coreProfile(resultFormat.profile() == QSurfaceFormat::CoreProfile,
true);
739 QSurfaceFormat::setDefaultFormat(resultFormat);
740 QApplication app(argc, argv);
741 QOffscreenSurface *surface =
new QOffscreenSurface();
745 QOpenGLContext::globalShareContext()->makeCurrent(surface);
750 if ( !QGLFormat::hasOpenGL() ) {
751 std::cerr <<
"This system has no OpenGL support.\n";
757 #ifdef PYTHON_ENABLED 763 if (tLang ==
"locale")
764 tLang = QLocale::system().name();
767 QTranslator qtTranslator;
768 qtTranslator.load(
"qt_" + tLang, QLibraryInfo::location(QLibraryInfo::TranslationsPath));
769 app.installTranslator(&qtTranslator);
772 QString translationDir = OpenFlipper::Options::translationsDirStr() + QDir::separator();
773 QDir dir(translationDir);
774 dir.setFilter(QDir::Files);
776 QFileInfoList list = dir.entryInfoList();
778 for (
int i = 0; i < list.size(); ++i) {
779 QFileInfo fileInfo = list.at(i);
781 if ( fileInfo.baseName().contains(tLang) ){
782 QTranslator* myAppTranslator =
new QTranslator();
784 if ( myAppTranslator->load( fileInfo.filePath() ) )
786 app.installTranslator(myAppTranslator);
789 delete myAppTranslator;
801 const QStringList positionalArguments = parser.positionalArguments();
803 for (
auto file: positionalArguments ) {
811 QCoreApplication app(argc,argv);
817 #ifdef PYTHON_ENABLED 824 const QStringList positionalArguments = parser.positionalArguments();
826 for (
auto file: positionalArguments ) {
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
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...
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.
DLLEXPORT void setPluginCommandLineOptions(QVector< QPair< QString, QString >> const &_pluginCommandLineOptions)
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
#define TOSTRING(x)
QSettings object containing all program settings of OpenFlipper.
std::string description() const
void init()
Second initialization stage.