Commit 61c57e67 authored by Kersten Schuster's avatar Kersten Schuster

Try the following contexts: settings, 4.4 compat, 3.2 core and give...

Try the following contexts: settings, 4.4 compat, 3.2 core and give comprehensible error messages if anything fails.
parent 9e9f7e42
......@@ -458,6 +458,162 @@ CommandLineParseResult parseCommandLine(QCommandLineParser &parser, QString *err
return CommandLineOk;
}
namespace
{
// Print human-readable GL profile strings
std::string profileToString(QSurfaceFormat::OpenGLContextProfile _profile)
{
if(_profile == QSurfaceFormat::CompatibilityProfile)
return "CompatibilityProfile";
if(_profile == QSurfaceFormat::CoreProfile)
return "CoreProfile";
if(_profile == QSurfaceFormat::NoProfile)
return "NoProfile";
return "[Unknown]";
}
// Check whether a specific context request can be fulfilled
// Can also return the format of the actually created context
bool verifySpecificContextFormat(QSurfaceFormat format, QSurfaceFormat* resultingFormat = nullptr)
{
// All created surfaces try to obey the given format
QSurfaceFormat::setDefaultFormat(format);
// We need a temporary qApp to create a surface and test the current context
int tempArgC = 0;
QApplication tempApp(tempArgC, nullptr);
QOffscreenSurface *surface = new QOffscreenSurface();
surface->create();
auto shareContext = QOpenGLContext::globalShareContext();
if(!shareContext)
{
std::cerr << "Error: Apparently no GL context was created!" << std::endl;
return false;
}
// Make the globally shared OpenGLContext current
shareContext->makeCurrent(surface);
// The opengl surface properties that have actually been applied
// (does not necessarily match the requested properties)
auto resultFormat = QOpenGLContext::globalShareContext()->format();
// Return the format of the actually created context (may be identical to the requested one)
if(resultingFormat != nullptr)
*resultingFormat = resultFormat;
auto curVersion = resultFormat.version();
// Human-readable name of requested profile
auto reqProfileString = profileToString(format.profile());
// Human-readable name of current profile
auto curProfileString = profileToString(resultFormat.profile());
// Check whether the actually applied OpenGL context profile matches the requested one
// and the current GL version is at least the requested one (but may be higher)
// If not, print some error to the console
if(curVersion.first < format.version().first ||
((curVersion.first == format.version().first) && (curVersion.second < format.version().second)) ||
format.profile() != resultFormat.profile())
{
std::cout << "[OpenGL context] Requested: "
<< format.version().first << "." << format.version().second << " (" << reqProfileString << ")"
<< ", Actually created: "
<< curVersion.first << "." << curVersion.second << " (" << curProfileString << ")"
<< std::endl;
return false;
}
std::cout << "[OpenGL context] Successfully created OpenGL context with version " << curVersion.first << "."
<< curVersion.second << " (" << curProfileString << ")." << std::endl;
return true;
}
// Create a QSurfaceFormat from the most important properties like version and profile
QSurfaceFormat createFormat(QSurfaceFormat::OpenGLContextProfile _profile, int _glMajor, int _glMinor, int _multisamplingSamples, bool _stereo, bool _debugContext)
{
QSurfaceFormat format;
format.setVersion(_glMajor, _glMinor);
format.setProfile(_profile);
format.setSamples(_multisamplingSamples);
format.setStereo(_stereo);
if(_profile != QSurfaceFormat::CoreProfile)
format.setOption(QSurfaceFormat::DeprecatedFunctions);
if (_debugContext)
format.setOption(format.options() | QSurfaceFormat::DebugContext);
return format;
}
// This method tries to find the best possible OpenGL context format in the following order:
// 1. The profile/format requested via the settings
// 2. A 4.4 compatibility context (should contain all relevant GL functions)
// 3. A 3.2 core context (best choice e.g. on MacOS)
// 4. Return whatever context was applied instead of the requested ones
QSurfaceFormat getContextFormat()
{
auto reqProfile = OpenFlipper::Options::coreProfile() ? QSurfaceFormat::CoreProfile : QSurfaceFormat::CompatibilityProfile;
QPair<int,int> reqVersion = OpenFlipper::Options::glVersion();
auto reqSamples = OpenFlipper::Options::samples();
auto reqStereo = OpenFlipper::Options::glStereo();
bool debugContext = OpenFlipper::Options::debug();
/*
// Debug: test all (possible and impossible) OpenGL versions and profiles
for(int majo = 1; majo < 5; ++majo)
for(int mino = 0; mino < 10; ++mino)
{
std::cout << "========== " << majo << "." << mino << " ==========="<<std::endl;
verifySpecificContextFormat(createFormat(QSurfaceFormat::CoreProfile, majo, mino, reqSamples, reqStereo, debugContext));
verifySpecificContextFormat(createFormat(QSurfaceFormat::CompatibilityProfile, majo, mino, reqSamples, reqStereo, debugContext));
verifySpecificContextFormat(createFormat(QSurfaceFormat::NoProfile, majo, mino, reqSamples, reqStereo, debugContext));
std::cout << "================================" << std::endl;
std::cout << std::endl;
}
return format;
*/
QSurfaceFormat resultFormat;
std::cout << "[OpenGL context] Trying to create a " << reqVersion.first << "." << reqVersion.second << " " << profileToString(reqProfile) << " context (default from settings)..." << std::endl;
bool success = verifySpecificContextFormat(createFormat(reqProfile, reqVersion.first, reqVersion.second, reqSamples, reqStereo, debugContext), &resultFormat);
// If that did not work...
if(!success)
{
std::cout << "[OpenGL context] Trying to create a 4.4 compat context..." << std::endl;
success = verifySpecificContextFormat(createFormat(QSurfaceFormat::CompatibilityProfile, 4, 4, reqSamples, reqStereo, debugContext), &resultFormat);
if(!success)
{
std::cout << "[OpenGL context] Trying to create a 3.2 core context..." << std::endl;
success = verifySpecificContextFormat(createFormat(QSurfaceFormat::CoreProfile, 3, 2, reqSamples, reqStereo, debugContext), &resultFormat);
if(!success)
{
std::cerr << "[OpenGL context] Warning: Could not create any of the requested GL contexts." << std::endl;
std::cerr << "[OpenGL context] The following context (proposed by the graphics driver) will be created:" << std::endl;
std::cerr << "[OpenGL context] Profile: " << profileToString(resultFormat.profile()) << ", Version: "
<< resultFormat.version().first << "." << resultFormat.version().second << std::endl;
std::cerr << "[OpenGL context] Please consider setting a supported OpenGL version and profile in the Options dialog." << std::endl;
}
}
}
return resultFormat;
}
}
int main(int argc, char **argv)
{
......@@ -533,70 +689,30 @@ int main(int argc, char **argv)
QApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
QApplication::setColorSpec( QApplication::CustomColor );
// Try creating a valid OpenGL context
/******************************/
QSurfaceFormat format;
QPair<int,int> version = OpenFlipper::Options::glVersion();
format.setVersion(version.first, version.second);
// Get a valid context format
QSurfaceFormat resultFormat = getContextFormat();
if (OpenFlipper::Options::coreProfile())
{
format.setProfile(QSurfaceFormat::CoreProfile);
}
else {
format.setProfile(QSurfaceFormat::CompatibilityProfile);
format.setOption(QSurfaceFormat::DeprecatedFunctions);
}
if (OpenFlipper::Options::debug())
format.setOption(format.options() | QSurfaceFormat::DebugContext);
format.setSamples(OpenFlipper::Options::samples());
format.setStereo(OpenFlipper::Options::glStereo());
QSurfaceFormat::setDefaultFormat(format);
// Set temporary(!) OpenGL settings
OpenFlipper::Options::samples(resultFormat.samples(), true);
OpenFlipper::Options::glStereo(resultFormat.stereo(), true);
OpenFlipper::Options::glVersion(resultFormat.version(), true);
OpenFlipper::Options::coreProfile(resultFormat.profile() == QSurfaceFormat::CoreProfile, true);
// Create the actual context
QSurfaceFormat::setDefaultFormat(resultFormat);
QApplication app(argc, argv);
QScreen *screen = app.primaryScreen();
QOffscreenSurface *surface = new QOffscreenSurface();
surface->create();
//make the globally shared OpenGLContext current
// Make the globally shared OpenGLContext current
QOpenGLContext::globalShareContext()->makeCurrent(surface);
/******************************/
// The opengl surface properties that have actually been applied
// (does not necessarily match the requested properties)
QSurfaceFormat actuallyAppliedFormat = QOpenGLContext::globalShareContext()->format();
auto curVersion = actuallyAppliedFormat.version();
// Check whether the actually applied OpenGL context matches the requested one.
// If not, print some error to the console
if(curVersion.first != version.first ||
curVersion.second != version.second ||
format.profile() != actuallyAppliedFormat.profile())
{
auto reqProfileString = "None";
if(format.profile() == QSurfaceFormat::CoreProfile)
reqProfileString = "Core";
else if(format.profile() == QSurfaceFormat::CompatibilityProfile)
reqProfileString = "Compat";
auto curProfileString = "None";
if(actuallyAppliedFormat.profile() == QSurfaceFormat::CoreProfile)
curProfileString = "Core";
else if(actuallyAppliedFormat.profile() == QSurfaceFormat::CompatibilityProfile)
curProfileString = "Compat";
std::cerr << "Warning! OpenGL version " << version.first << "."
<< version.second << " (" << reqProfileString << ")"
<< " was requested, but version " << curVersion.first << "."
<< curVersion.second << " (" << curProfileString << ")"
<< " was applied." << std::endl;
std::cerr << "Please consider setting supported OpenGL version and context in the Options dialog." << std::endl;
}
// Check whether there is OpenGL support. If not, return.
if ( !QGLFormat::hasOpenGL() ) {
std::cerr << "This system has no OpenGL support.\n";
return -1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment