Commit 82a04570 authored by Jan's avatar Jan

Moved OpenGL Detection into separate file

parent f9708661
......@@ -39,7 +39,8 @@ set (headers
../Core/OpenFunctionThread.hh
../Core/PluginInfo.hh
../Core/SpinBoxEventFilter.hh
../Logging/PluginLogging.hh
../Logging/PluginLogging.hh
../OpenGL/OpenGLDetection.hh
../Scripting/ScriptingWrapper.hh
../Scripting/scriptPrototypes/prototypeDataType.hh
../Scripting/scriptPrototypes/prototypeIdList.hh
......@@ -79,6 +80,7 @@ set (headers
../widgets/rendererWidget/rendererWidget.hh
../widgets/pythonWidget/PythonSyntaxHighlighter.hh
../widgets/pythonWidget/pythonWidget.hh
../Windows/windows-startup.hh
../PythonInterpreter/PythonInterpreter.hh
../PythonInterpreter/PythonTypeConversions.hh
)
......
......@@ -396,179 +396,8 @@ 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());
// Example: OpenGL Version 4.6 -> 46
auto reqVersionInt = format.version().first * 10 + format.version().second;
auto curVersionInt = curVersion.first * 10 + curVersion.second;
// We set the following guidelines:
// 1. Whenever the actually received GL version is < than the requested one, the context is not the one requested
// 2. If the received profile is not the requested one, the context is not the one requested
if(curVersionInt < 32 && resultFormat.profile() == QSurfaceFormat::CoreProfile)
{
std::cerr << "Warning: Got an OpenGL core context with OpengGL version < 3.2 (" << curVersion.first << "." << curVersion.second << ")! This should not be possible." << std::endl;
return false;
}
// Check whether the conditions above are met.
// If not, print some error to the console
if(curVersionInt < reqVersionInt ||
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(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 and exit
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;
}
exit(0);
*/
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;
}
}
// Detector for OpenGL
#include "OpenGL/OpenGLDetection.hh"
int main(int argc, char **argv)
{
......
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());
// Example: OpenGL Version 4.6 -> 46
auto reqVersionInt = format.version().first * 10 + format.version().second;
auto curVersionInt = curVersion.first * 10 + curVersion.second;
// We set the following guidelines:
// 1. Whenever the actually received GL version is < than the requested one, the context is not the one requested
// 2. If the received profile is not the requested one, the context is not the one requested
if(curVersionInt < 32 && resultFormat.profile() == QSurfaceFormat::CoreProfile)
{
std::cerr << "Warning: Got an OpenGL core context with OpengGL version < 3.2 (" << curVersion.first << "." << curVersion.second << ")! This should not be possible." << std::endl;
return false;
}
// Check whether the conditions above are met.
// If not, print some error to the console
if(curVersionInt < reqVersionInt ||
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(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 and exit
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;
}
exit(0);
*/
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;
}
}
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