VBO override option; argv parsing using getopt
* added -vbo option to override autodetection of OpenGL VBO extension * refactored argument parsing to use getopt() * fixed failing UTsdev-ui
parent
1f565fdf38
commit
bc859c4c59
218
src/app/app.cpp
218
src/app/app.cpp
|
@ -39,6 +39,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <libintl.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
|
||||
|
||||
#ifdef OPENAL_SOUND
|
||||
|
@ -195,101 +196,130 @@ CEventQueue* CApplication::GetEventQueue()
|
|||
CSoundInterface* CApplication::GetSound()
|
||||
{
|
||||
return m_sound;
|
||||
|
||||
for (int i = 0; i < PCNT_MAX; ++i)
|
||||
{
|
||||
DestroyTimeStamp(m_performanceCounters[i][0]);
|
||||
DestroyTimeStamp(m_performanceCounters[i][1]);
|
||||
}
|
||||
}
|
||||
|
||||
ParseArgsStatus CApplication::ParseArguments(int argc, char *argv[])
|
||||
{
|
||||
bool waitDataDir = false;
|
||||
bool waitLogLevel = false;
|
||||
bool waitLanguage = false;
|
||||
|
||||
for (int i = 1; i < argc; ++i)
|
||||
enum OptionType
|
||||
{
|
||||
std::string arg = argv[i];
|
||||
OPT_HELP = 1,
|
||||
OPT_DEBUG,
|
||||
OPT_DATADIR,
|
||||
OPT_LOGLEVEL,
|
||||
OPT_LANGUAGE,
|
||||
OPT_VBO
|
||||
};
|
||||
|
||||
if (waitDataDir)
|
||||
option options[] =
|
||||
{
|
||||
waitDataDir = false;
|
||||
m_dataPath = arg;
|
||||
GetLogger()->Info("Using custom data dir: '%s'\n", m_dataPath.c_str());
|
||||
continue;
|
||||
}
|
||||
{ "help", no_argument, nullptr, OPT_HELP },
|
||||
{ "debug", no_argument, nullptr, OPT_DEBUG },
|
||||
{ "datadir", required_argument, nullptr, OPT_DATADIR },
|
||||
{ "loglevel", required_argument, nullptr, OPT_LOGLEVEL },
|
||||
{ "language", required_argument, nullptr, OPT_LANGUAGE },
|
||||
{ "vbo", required_argument, nullptr, OPT_VBO }
|
||||
};
|
||||
|
||||
if (waitLogLevel)
|
||||
opterr = 0;
|
||||
|
||||
int c = 0;
|
||||
int index = -1;
|
||||
while ((c = getopt_long_only(argc, argv, "", options, &index)) != -1)
|
||||
{
|
||||
waitLogLevel = false;
|
||||
if (arg == "trace")
|
||||
GetLogger()->SetLogLevel(LOG_TRACE);
|
||||
else if (arg == "debug")
|
||||
GetLogger()->SetLogLevel(LOG_DEBUG);
|
||||
else if (arg == "info")
|
||||
GetLogger()->SetLogLevel(LOG_INFO);
|
||||
else if (arg == "warn")
|
||||
GetLogger()->SetLogLevel(LOG_WARN);
|
||||
else if (arg == "error")
|
||||
GetLogger()->SetLogLevel(LOG_ERROR);
|
||||
else if (arg == "none")
|
||||
GetLogger()->SetLogLevel(LOG_NONE);
|
||||
if (c == '?')
|
||||
{
|
||||
if (optopt == 0)
|
||||
GetLogger()->Error("Invalid argument: %s\n", argv[optind-1]);
|
||||
else
|
||||
return PARSE_ARGS_FAIL;
|
||||
continue;
|
||||
}
|
||||
GetLogger()->Error("Expected argument for option: %s\n", argv[optind-1]);
|
||||
|
||||
if (waitLanguage)
|
||||
{
|
||||
waitLanguage = false;
|
||||
if (arg == "en")
|
||||
m_language = LANGUAGE_ENGLISH;
|
||||
else if (arg == "de")
|
||||
m_language = LANGUAGE_GERMAN;
|
||||
else if (arg == "fr")
|
||||
m_language = LANGUAGE_FRENCH;
|
||||
else if (arg == "pl")
|
||||
m_language = LANGUAGE_POLISH;
|
||||
else
|
||||
return PARSE_ARGS_FAIL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg == "-debug")
|
||||
{
|
||||
SetDebugMode(true);
|
||||
}
|
||||
else if (arg == "-loglevel")
|
||||
{
|
||||
waitLogLevel = true;
|
||||
}
|
||||
else if (arg == "-datadir")
|
||||
{
|
||||
waitDataDir = true;
|
||||
}
|
||||
else if (arg == "-language")
|
||||
{
|
||||
waitLanguage = true;
|
||||
}
|
||||
else if (arg == "-help")
|
||||
{
|
||||
GetLogger()->Message("\n");
|
||||
GetLogger()->Message("Colobot %s (%s)\n",COLOBOT_CODENAME,COLOBOT_VERSION);
|
||||
GetLogger()->Message("\n");
|
||||
GetLogger()->Message("List of available options:\n");
|
||||
GetLogger()->Message(" -help this help\n");
|
||||
GetLogger()->Message(" -datadir path set custom data directory path\n");
|
||||
GetLogger()->Message(" -debug enable debug mode (more info printed in logs)\n");
|
||||
GetLogger()->Message(" -loglevel level set log level to level (one of: trace, debug, info, warn, error, none)\n");
|
||||
GetLogger()->Message(" -language lang set language (one of: en, de, fr, pl)\n");
|
||||
return PARSE_ARGS_HELP;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_exitCode = 1;
|
||||
return PARSE_ARGS_FAIL;
|
||||
}
|
||||
|
||||
index = -1;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case OPT_HELP:
|
||||
{
|
||||
GetLogger()->Message("\n");
|
||||
GetLogger()->Message("Colobot %s (%s)\n", COLOBOT_CODENAME, COLOBOT_VERSION);
|
||||
GetLogger()->Message("\n");
|
||||
GetLogger()->Message("List of available options:\n");
|
||||
GetLogger()->Message(" -help this help\n");
|
||||
GetLogger()->Message(" -debug enable debug mode (more info printed in logs)\n");
|
||||
GetLogger()->Message(" -datadir path set custom data directory path\n");
|
||||
GetLogger()->Message(" -loglevel level set log level to level (one of: trace, debug, info, warn, error, none)\n");
|
||||
GetLogger()->Message(" -language lang set language (one of: en, de, fr, pl)\n");
|
||||
GetLogger()->Message(" -vbo mode set OpenGL VBO mode (one of: auto, enable, disable)\n");
|
||||
return PARSE_ARGS_HELP;
|
||||
}
|
||||
case OPT_DEBUG:
|
||||
{
|
||||
SetDebugMode(true);
|
||||
break;
|
||||
}
|
||||
case OPT_DATADIR:
|
||||
{
|
||||
m_dataPath = optarg;
|
||||
GetLogger()->Info("Using custom data dir: '%s'\n", m_dataPath.c_str());
|
||||
break;
|
||||
}
|
||||
case OPT_LOGLEVEL:
|
||||
{
|
||||
LogLevel logLevel;
|
||||
if (! CLogger::ParseLogLevel(optarg, logLevel))
|
||||
{
|
||||
GetLogger()->Error("Invalid log level: \"%s\"\n", optarg);
|
||||
return PARSE_ARGS_FAIL;
|
||||
}
|
||||
|
||||
// Args not given?
|
||||
if (waitDataDir || waitLogLevel || waitLanguage)
|
||||
GetLogger()->Message("[*****] Log level changed to %s\n", optarg);
|
||||
GetLogger()->SetLogLevel(logLevel);
|
||||
break;
|
||||
}
|
||||
case OPT_LANGUAGE:
|
||||
{
|
||||
Language language;
|
||||
if (! ParseLanguage(optarg, language))
|
||||
{
|
||||
GetLogger()->Error("Invalid language: \"%s\"\n", optarg);
|
||||
return PARSE_ARGS_FAIL;
|
||||
}
|
||||
|
||||
GetLogger()->Info("Using language %s\n", optarg);
|
||||
m_language = language;
|
||||
break;
|
||||
}
|
||||
case OPT_VBO:
|
||||
{
|
||||
std::string vbo;
|
||||
vbo = optarg;
|
||||
if (vbo == "auto")
|
||||
m_deviceConfig.vboMode = Gfx::VBO_MODE_AUTO;
|
||||
else if (vbo == "enable")
|
||||
m_deviceConfig.vboMode = Gfx::VBO_MODE_ENABLE;
|
||||
else if (vbo == "disable")
|
||||
m_deviceConfig.vboMode = Gfx::VBO_MODE_DISABLE;
|
||||
else
|
||||
{
|
||||
GetLogger()->Error("Invalid vbo mode: \"%s\"\n", optarg);
|
||||
return PARSE_ARGS_FAIL;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(false); // should never get here
|
||||
}
|
||||
}
|
||||
|
||||
return PARSE_ARGS_OK;
|
||||
}
|
||||
|
@ -379,14 +409,16 @@ bool CApplication::Create()
|
|||
|
||||
// load settings from profile
|
||||
int iValue;
|
||||
if ( GetProfile().GetLocalProfileInt("Setup", "Resolution", iValue) ) {
|
||||
if ( GetProfile().GetLocalProfileInt("Setup", "Resolution", iValue) )
|
||||
{
|
||||
std::vector<Math::IntPoint> modes;
|
||||
GetVideoResolutionList(modes, true, true);
|
||||
if (static_cast<unsigned int>(iValue) < modes.size())
|
||||
m_deviceConfig.size = modes.at(iValue);
|
||||
}
|
||||
|
||||
if ( GetProfile().GetLocalProfileInt("Setup", "Fullscreen", iValue) ) {
|
||||
if ( GetProfile().GetLocalProfileInt("Setup", "Fullscreen", iValue) )
|
||||
{
|
||||
m_deviceConfig.fullScreen = (iValue == 1);
|
||||
}
|
||||
|
||||
|
@ -1503,6 +1535,32 @@ char CApplication::GetLanguageChar()
|
|||
return langChar;
|
||||
}
|
||||
|
||||
bool CApplication::ParseLanguage(const std::string& str, Language& language)
|
||||
{
|
||||
if (str == "en")
|
||||
{
|
||||
language = LANGUAGE_ENGLISH;
|
||||
return true;
|
||||
}
|
||||
else if (str == "de")
|
||||
{
|
||||
language = LANGUAGE_GERMAN;
|
||||
return true;
|
||||
}
|
||||
else if (str == "fr")
|
||||
{
|
||||
language = LANGUAGE_FRENCH;
|
||||
return true;
|
||||
}
|
||||
else if (str == "pl")
|
||||
{
|
||||
language = LANGUAGE_POLISH;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CApplication::SetLanguage(Language language)
|
||||
{
|
||||
m_language = language;
|
||||
|
|
|
@ -327,6 +327,7 @@ public:
|
|||
Language GetLanguage();
|
||||
char GetLanguageChar();
|
||||
void SetLanguage(Language language);
|
||||
static bool ParseLanguage(const std::string& str, Language& language);
|
||||
//@}
|
||||
|
||||
//! Management of sleep in main loop (lowers CPU usage)
|
||||
|
|
|
@ -36,25 +36,37 @@ CLogger::~CLogger()
|
|||
}
|
||||
|
||||
|
||||
void CLogger::Log(LogType type, const char *str, va_list args)
|
||||
void CLogger::Log(LogLevel type, const char* str, va_list args)
|
||||
{
|
||||
if (type < mLogLevel)
|
||||
return;
|
||||
|
||||
switch (type) {
|
||||
case LOG_TRACE: fprintf(IsOpened() ? mFile : stderr, "[TRACE]: "); break;
|
||||
case LOG_DEBUG: fprintf(IsOpened() ? mFile : stderr, "[DEBUG]: "); break;
|
||||
case LOG_WARN: fprintf(IsOpened() ? mFile : stderr, "[WARN]: "); break;
|
||||
case LOG_INFO: fprintf(IsOpened() ? mFile : stderr, "[INFO]: "); break;
|
||||
case LOG_ERROR: fprintf(IsOpened() ? mFile : stderr, "[ERROR]: "); break;
|
||||
default: break;
|
||||
switch (type)
|
||||
{
|
||||
case LOG_TRACE:
|
||||
fprintf(IsOpened() ? mFile : stderr, "[TRACE]: ");
|
||||
break;
|
||||
case LOG_DEBUG:
|
||||
fprintf(IsOpened() ? mFile : stderr, "[DEBUG]: ");
|
||||
break;
|
||||
case LOG_WARN:
|
||||
fprintf(IsOpened() ? mFile : stderr, "[WARN]: ");
|
||||
break;
|
||||
case LOG_INFO:
|
||||
fprintf(IsOpened() ? mFile : stderr, "[INFO]: ");
|
||||
break;
|
||||
case LOG_ERROR:
|
||||
fprintf(IsOpened() ? mFile : stderr, "[ERROR]: ");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
vfprintf(IsOpened() ? mFile : stderr, str, args);
|
||||
}
|
||||
|
||||
|
||||
void CLogger::Trace(const char *str, ...)
|
||||
void CLogger::Trace(const char* str, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, str);
|
||||
|
@ -63,7 +75,7 @@ void CLogger::Trace(const char *str, ...)
|
|||
}
|
||||
|
||||
|
||||
void CLogger::Debug(const char *str, ...)
|
||||
void CLogger::Debug(const char* str, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, str);
|
||||
|
@ -72,7 +84,7 @@ void CLogger::Debug(const char *str, ...)
|
|||
}
|
||||
|
||||
|
||||
void CLogger::Info(const char *str, ...)
|
||||
void CLogger::Info(const char* str, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, str);
|
||||
|
@ -81,7 +93,7 @@ void CLogger::Info(const char *str, ...)
|
|||
}
|
||||
|
||||
|
||||
void CLogger::Warn(const char *str, ...)
|
||||
void CLogger::Warn(const char* str, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, str);
|
||||
|
@ -90,7 +102,7 @@ void CLogger::Warn(const char *str, ...)
|
|||
}
|
||||
|
||||
|
||||
void CLogger::Error(const char *str, ...)
|
||||
void CLogger::Error(const char* str, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, str);
|
||||
|
@ -99,7 +111,7 @@ void CLogger::Error(const char *str, ...)
|
|||
}
|
||||
|
||||
|
||||
void CLogger::Message(const char *str, ...)
|
||||
void CLogger::Message(const char* str, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, str);
|
||||
|
@ -118,6 +130,7 @@ void CLogger::SetOutputFile(std::string filename)
|
|||
void CLogger::Open()
|
||||
{
|
||||
mFile = fopen(mFilename.c_str(), "w");
|
||||
|
||||
if (mFile == NULL)
|
||||
fprintf(stderr, "Could not create file %s\n", mFilename.c_str());
|
||||
}
|
||||
|
@ -136,6 +149,45 @@ bool CLogger::IsOpened()
|
|||
}
|
||||
|
||||
|
||||
void CLogger::SetLogLevel(LogType type) {
|
||||
void CLogger::SetLogLevel(LogLevel type)
|
||||
{
|
||||
mLogLevel = type;
|
||||
}
|
||||
|
||||
|
||||
bool CLogger::ParseLogLevel(const std::string& str, LogLevel& logLevel)
|
||||
{
|
||||
if (str == "trace")
|
||||
{
|
||||
logLevel = LOG_TRACE;
|
||||
return true;
|
||||
}
|
||||
else if (str == "debug")
|
||||
{
|
||||
logLevel = LOG_DEBUG;
|
||||
return true;
|
||||
}
|
||||
else if (str == "info")
|
||||
{
|
||||
logLevel = LOG_INFO;
|
||||
return true;
|
||||
}
|
||||
else if (str == "warn")
|
||||
{
|
||||
logLevel = LOG_WARN;
|
||||
return true;
|
||||
}
|
||||
else if (str == "error")
|
||||
{
|
||||
logLevel = LOG_ERROR;
|
||||
return true;
|
||||
}
|
||||
else if (str == "none")
|
||||
{
|
||||
logLevel = LOG_NONE;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,10 +31,10 @@
|
|||
|
||||
/**
|
||||
* \public
|
||||
* \enum LogType common/logger.h
|
||||
* \enum LogLevel common/logger.h
|
||||
* \brief Enum representing log level
|
||||
**/
|
||||
enum LogType
|
||||
enum LogLevel
|
||||
{
|
||||
LOG_TRACE = 1, /*!< lowest level, execution tracing */
|
||||
LOG_DEBUG = 2, /*!< debugging messages */
|
||||
|
@ -53,7 +53,7 @@ enum LogType
|
|||
*/
|
||||
class CLogger : public CSingleton<CLogger>
|
||||
{
|
||||
public:
|
||||
public:
|
||||
CLogger();
|
||||
~CLogger();
|
||||
|
||||
|
@ -101,17 +101,26 @@ class CLogger : public CSingleton<CLogger>
|
|||
/** Set log level. Logs with level below will not be shown
|
||||
* \param level - minimum log level to write
|
||||
*/
|
||||
void SetLogLevel(LogType level);
|
||||
void SetLogLevel(LogLevel level);
|
||||
|
||||
private:
|
||||
/** Parses string as a log level
|
||||
* \param str string to parse
|
||||
* \param logLevel result log level
|
||||
*
|
||||
* Valid values are "trace", "debug", "info", "warn", "error" and "none".
|
||||
* On invalid value, returns \c false.
|
||||
*/
|
||||
static bool ParseLogLevel(const std::string& str, LogLevel& logLevel);
|
||||
|
||||
private:
|
||||
std::string mFilename;
|
||||
FILE *mFile;
|
||||
LogType mLogLevel;
|
||||
LogLevel mLogLevel;
|
||||
|
||||
void Open();
|
||||
void Close();
|
||||
bool IsOpened();
|
||||
void Log(LogType type, const char* str, va_list args);
|
||||
void Log(LogLevel type, const char* str, va_list args);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -51,6 +51,8 @@ void GLDeviceConfig::LoadDefault()
|
|||
greenSize = 8;
|
||||
alphaSize = 8;
|
||||
depthSize = 24;
|
||||
|
||||
vboMode = VBO_MODE_AUTO;
|
||||
}
|
||||
|
||||
|
||||
|
@ -99,12 +101,27 @@ bool CGLDevice::Create()
|
|||
if (!m_multitextureAvailable)
|
||||
GetLogger()->Warn("GLEW reports multitexturing not supported - graphics quality will be degraded!\n");
|
||||
|
||||
if (m_config.vboMode == VBO_MODE_ENABLE)
|
||||
{
|
||||
GetLogger()->Info("VBO enabled by override - using VBOs\n");
|
||||
m_vboAvailable = true;
|
||||
}
|
||||
else if (m_config.vboMode == VBO_MODE_DISABLE)
|
||||
{
|
||||
GetLogger()->Info("VBO disabled by override - using display lists\n");
|
||||
m_vboAvailable = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
GetLogger()->Info("Auto-detecting VBO support\n");
|
||||
m_vboAvailable = glewIsSupported("GL_ARB_vertex_buffer_object");
|
||||
|
||||
if (m_vboAvailable)
|
||||
GetLogger()->Info("Detected ARB_vertex_buffer_object extension - using VBOs\n");
|
||||
else
|
||||
GetLogger()->Info("No ARB_vertex_buffer_object extension present - using display lists\n");
|
||||
}
|
||||
}
|
||||
|
||||
// This is mostly done in all modern hardware by default
|
||||
// DirectX doesn't even allow the option to turn off perspective correction anymore
|
||||
|
|
|
@ -33,6 +33,17 @@
|
|||
// Graphics module namespace
|
||||
namespace Gfx {
|
||||
|
||||
/**
|
||||
\enum VBOMode
|
||||
\brief VBO autodetect/override
|
||||
*/
|
||||
enum VBOMode
|
||||
{
|
||||
VBO_MODE_ENABLE, //! < override: enable
|
||||
VBO_MODE_DISABLE, //! < override: disable
|
||||
VBO_MODE_AUTO //! < autodetect
|
||||
};
|
||||
|
||||
/**
|
||||
\struct GLDeviceConfig
|
||||
\brief Additional config with OpenGL-specific settings */
|
||||
|
@ -52,6 +63,9 @@ struct GLDeviceConfig : public DeviceConfig
|
|||
//! Force hardware acceleration (video mode set will fail on lack of hw accel)
|
||||
bool hardwareAccel;
|
||||
|
||||
//! VBO override/autodetect
|
||||
VBOMode vboMode;
|
||||
|
||||
//! Constructor calls LoadDefaults()
|
||||
GLDeviceConfig();
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ TEST_F(LightManagerUT, LightSorting_IncludeTypesAreIncluded)
|
|||
AddLight(2, LIGHT_PRI_LOW, true, true, Math::Vector(0.0f, 0.0f, 0.0f), ENG_OBJTYPE_TERRAIN, ENG_OBJTYPE_NULL);
|
||||
AddLight(3, LIGHT_PRI_LOW, true, true, Math::Vector(0.0f, 0.0f, 0.0f), ENG_OBJTYPE_QUARTZ, ENG_OBJTYPE_NULL);
|
||||
|
||||
std::vector<int> expectedLights = { 2, 1 };
|
||||
std::vector<int> expectedLights = { 1, 2 };
|
||||
CheckLightSorting(ENG_OBJTYPE_TERRAIN, expectedLights);
|
||||
}
|
||||
|
||||
|
@ -124,7 +124,7 @@ TEST_F(LightManagerUT, LightSorting_ExcludeTypesAreExcluded)
|
|||
AddLight(2, LIGHT_PRI_LOW, true, true, Math::Vector(0.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_TERRAIN);
|
||||
AddLight(3, LIGHT_PRI_LOW, true, true, Math::Vector(0.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_QUARTZ);
|
||||
|
||||
std::vector<int> expectedLights = { 3, 1 };
|
||||
std::vector<int> expectedLights = { 1, 3 };
|
||||
CheckLightSorting(ENG_OBJTYPE_TERRAIN, expectedLights);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue