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 UTs
dev-ui
Piotr Dziwinski 2013-03-10 15:44:21 +01:00
parent 1f565fdf38
commit bc859c4c59
7 changed files with 316 additions and 165 deletions

View File

@ -39,6 +39,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <libintl.h> #include <libintl.h>
#include <unistd.h> #include <unistd.h>
#include <getopt.h>
#ifdef OPENAL_SOUND #ifdef OPENAL_SOUND
@ -195,101 +196,130 @@ CEventQueue* CApplication::GetEventQueue()
CSoundInterface* CApplication::GetSound() CSoundInterface* CApplication::GetSound()
{ {
return m_sound; 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[]) ParseArgsStatus CApplication::ParseArguments(int argc, char *argv[])
{ {
bool waitDataDir = false; enum OptionType
bool waitLogLevel = false;
bool waitLanguage = false;
for (int i = 1; i < argc; ++i)
{ {
std::string arg = argv[i]; OPT_HELP = 1,
OPT_DEBUG,
OPT_DATADIR,
OPT_LOGLEVEL,
OPT_LANGUAGE,
OPT_VBO
};
if (waitDataDir) option options[] =
{ {
waitDataDir = false; { "help", no_argument, nullptr, OPT_HELP },
m_dataPath = arg; { "debug", no_argument, nullptr, OPT_DEBUG },
GetLogger()->Info("Using custom data dir: '%s'\n", m_dataPath.c_str()); { "datadir", required_argument, nullptr, OPT_DATADIR },
continue; { "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 (c == '?')
if (arg == "trace") {
GetLogger()->SetLogLevel(LOG_TRACE); if (optopt == 0)
else if (arg == "debug") GetLogger()->Error("Invalid argument: %s\n", argv[optind-1]);
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);
else else
GetLogger()->Error("Expected argument for option: %s\n", argv[optind-1]);
m_exitCode = 1;
return PARSE_ARGS_FAIL; return PARSE_ARGS_FAIL;
continue;
} }
if (waitLanguage) index = -1;
{
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") switch (c)
{ {
SetDebugMode(true); case OPT_HELP:
}
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("\n");
GetLogger()->Message("Colobot %s (%s)\n", COLOBOT_CODENAME, COLOBOT_VERSION); GetLogger()->Message("Colobot %s (%s)\n", COLOBOT_CODENAME, COLOBOT_VERSION);
GetLogger()->Message("\n"); GetLogger()->Message("\n");
GetLogger()->Message("List of available options:\n"); GetLogger()->Message("List of available options:\n");
GetLogger()->Message(" -help this help\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(" -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(" -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(" -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; return PARSE_ARGS_HELP;
} }
else case OPT_DEBUG:
{ {
m_exitCode = 1; SetDebugMode(true);
return PARSE_ARGS_FAIL; 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? GetLogger()->Message("[*****] Log level changed to %s\n", optarg);
if (waitDataDir || waitLogLevel || waitLanguage) GetLogger()->SetLogLevel(logLevel);
break;
}
case OPT_LANGUAGE:
{
Language language;
if (! ParseLanguage(optarg, language))
{
GetLogger()->Error("Invalid language: \"%s\"\n", optarg);
return PARSE_ARGS_FAIL; 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; return PARSE_ARGS_OK;
} }
@ -379,14 +409,16 @@ bool CApplication::Create()
// load settings from profile // load settings from profile
int iValue; int iValue;
if ( GetProfile().GetLocalProfileInt("Setup", "Resolution", iValue) ) { if ( GetProfile().GetLocalProfileInt("Setup", "Resolution", iValue) )
{
std::vector<Math::IntPoint> modes; std::vector<Math::IntPoint> modes;
GetVideoResolutionList(modes, true, true); GetVideoResolutionList(modes, true, true);
if (static_cast<unsigned int>(iValue) < modes.size()) if (static_cast<unsigned int>(iValue) < modes.size())
m_deviceConfig.size = modes.at(iValue); m_deviceConfig.size = modes.at(iValue);
} }
if ( GetProfile().GetLocalProfileInt("Setup", "Fullscreen", iValue) ) { if ( GetProfile().GetLocalProfileInt("Setup", "Fullscreen", iValue) )
{
m_deviceConfig.fullScreen = (iValue == 1); m_deviceConfig.fullScreen = (iValue == 1);
} }
@ -1503,6 +1535,32 @@ char CApplication::GetLanguageChar()
return langChar; 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) void CApplication::SetLanguage(Language language)
{ {
m_language = language; m_language = language;

View File

@ -327,6 +327,7 @@ public:
Language GetLanguage(); Language GetLanguage();
char GetLanguageChar(); char GetLanguageChar();
void SetLanguage(Language language); void SetLanguage(Language language);
static bool ParseLanguage(const std::string& str, Language& language);
//@} //@}
//! Management of sleep in main loop (lowers CPU usage) //! Management of sleep in main loop (lowers CPU usage)

View File

@ -36,18 +36,30 @@ 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) if (type < mLogLevel)
return; return;
switch (type) { switch (type)
case LOG_TRACE: fprintf(IsOpened() ? mFile : stderr, "[TRACE]: "); break; {
case LOG_DEBUG: fprintf(IsOpened() ? mFile : stderr, "[DEBUG]: "); break; case LOG_TRACE:
case LOG_WARN: fprintf(IsOpened() ? mFile : stderr, "[WARN]: "); break; fprintf(IsOpened() ? mFile : stderr, "[TRACE]: ");
case LOG_INFO: fprintf(IsOpened() ? mFile : stderr, "[INFO]: "); break; break;
case LOG_ERROR: fprintf(IsOpened() ? mFile : stderr, "[ERROR]: "); break; case LOG_DEBUG:
default: break; 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); vfprintf(IsOpened() ? mFile : stderr, str, args);
@ -118,6 +130,7 @@ void CLogger::SetOutputFile(std::string filename)
void CLogger::Open() void CLogger::Open()
{ {
mFile = fopen(mFilename.c_str(), "w"); mFile = fopen(mFilename.c_str(), "w");
if (mFile == NULL) if (mFile == NULL)
fprintf(stderr, "Could not create file %s\n", mFilename.c_str()); 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; 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;
}

View File

@ -31,10 +31,10 @@
/** /**
* \public * \public
* \enum LogType common/logger.h * \enum LogLevel common/logger.h
* \brief Enum representing log level * \brief Enum representing log level
**/ **/
enum LogType enum LogLevel
{ {
LOG_TRACE = 1, /*!< lowest level, execution tracing */ LOG_TRACE = 1, /*!< lowest level, execution tracing */
LOG_DEBUG = 2, /*!< debugging messages */ LOG_DEBUG = 2, /*!< debugging messages */
@ -101,17 +101,26 @@ class CLogger : public CSingleton<CLogger>
/** Set log level. Logs with level below will not be shown /** Set log level. Logs with level below will not be shown
* \param level - minimum log level to write * \param level - minimum log level to write
*/ */
void SetLogLevel(LogType level); void SetLogLevel(LogLevel level);
/** 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: private:
std::string mFilename; std::string mFilename;
FILE *mFile; FILE *mFile;
LogType mLogLevel; LogLevel mLogLevel;
void Open(); void Open();
void Close(); void Close();
bool IsOpened(); bool IsOpened();
void Log(LogType type, const char* str, va_list args); void Log(LogLevel type, const char* str, va_list args);
}; };

View File

@ -51,6 +51,8 @@ void GLDeviceConfig::LoadDefault()
greenSize = 8; greenSize = 8;
alphaSize = 8; alphaSize = 8;
depthSize = 24; depthSize = 24;
vboMode = VBO_MODE_AUTO;
} }
@ -99,12 +101,27 @@ bool CGLDevice::Create()
if (!m_multitextureAvailable) if (!m_multitextureAvailable)
GetLogger()->Warn("GLEW reports multitexturing not supported - graphics quality will be degraded!\n"); 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"); m_vboAvailable = glewIsSupported("GL_ARB_vertex_buffer_object");
if (m_vboAvailable) if (m_vboAvailable)
GetLogger()->Info("Detected ARB_vertex_buffer_object extension - using VBOs\n"); GetLogger()->Info("Detected ARB_vertex_buffer_object extension - using VBOs\n");
else else
GetLogger()->Info("No ARB_vertex_buffer_object extension present - using display lists\n"); GetLogger()->Info("No ARB_vertex_buffer_object extension present - using display lists\n");
} }
}
// This is mostly done in all modern hardware by default // This is mostly done in all modern hardware by default
// DirectX doesn't even allow the option to turn off perspective correction anymore // DirectX doesn't even allow the option to turn off perspective correction anymore

View File

@ -33,6 +33,17 @@
// Graphics module namespace // Graphics module namespace
namespace Gfx { 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 \struct GLDeviceConfig
\brief Additional config with OpenGL-specific settings */ \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) //! Force hardware acceleration (video mode set will fail on lack of hw accel)
bool hardwareAccel; bool hardwareAccel;
//! VBO override/autodetect
VBOMode vboMode;
//! Constructor calls LoadDefaults() //! Constructor calls LoadDefaults()
GLDeviceConfig(); GLDeviceConfig();

View File

@ -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(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); 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); 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(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); 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); CheckLightSorting(ENG_OBJTYPE_TERRAIN, expectedLights);
} }