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 <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
GetLogger()->Error("Expected argument for option: %s\n", argv[optind-1]);
m_exitCode = 1;
return PARSE_ARGS_FAIL;
continue;
}
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;
}
index = -1;
if (arg == "-debug")
switch (c)
{
SetDebugMode(true);
}
else if (arg == "-loglevel")
{
waitLogLevel = true;
}
else if (arg == "-datadir")
{
waitDataDir = true;
}
else if (arg == "-language")
{
waitLanguage = true;
}
else if (arg == "-help")
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(" -datadir path set custom data directory path\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;
}
else
case OPT_DEBUG:
{
m_exitCode = 1;
return PARSE_ARGS_FAIL;
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;

View File

@ -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)

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)
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);
@ -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;
}

View File

@ -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 */
@ -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);
/** 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);
};

View File

@ -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

View File

@ -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();

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(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);
}