Developer Documentation
Loading...
Searching...
No Matches
OpenGLDetection.hh
1
2namespace
3{
4
5// Print human-readable GL profile strings
6std::string profileToString(QSurfaceFormat::OpenGLContextProfile _profile)
7{
8 if(_profile == QSurfaceFormat::CompatibilityProfile)
9 return "CompatibilityProfile";
10
11 if(_profile == QSurfaceFormat::CoreProfile)
12 return "CoreProfile";
13
14 if(_profile == QSurfaceFormat::NoProfile)
15 return "NoProfile";
16
17 return "[Unknown]";
18}
19
20// Check whether a specific context request can be fulfilled
21// Can also return the format of the actually created context
22bool verifySpecificContextFormat(QSurfaceFormat format, QSurfaceFormat* resultingFormat = nullptr)
23{
24 // All created surfaces try to obey the given format
25 QSurfaceFormat::setDefaultFormat(format);
26
27 // We need a temporary qApp to create a surface and test the current context
28 int tempArgC = 0;
29 QApplication tempApp(tempArgC, nullptr);
30 QOffscreenSurface *surface = new QOffscreenSurface();
31 surface->create();
32
33 auto shareContext = QOpenGLContext::globalShareContext();
34 if(!shareContext)
35 {
36 std::cerr << "Error: Apparently no GL context was created!" << std::endl;
37 return false;
38 }
39
40 // Make the globally shared OpenGLContext current
41 shareContext->makeCurrent(surface);
42
43 // The opengl surface properties that have actually been applied
44 // (does not necessarily match the requested properties)
45 auto resultFormat = QOpenGLContext::globalShareContext()->format();
46
47 // Return the format of the actually created context (may be identical to the requested one)
48 if(resultingFormat != nullptr)
49 *resultingFormat = resultFormat;
50
51 auto curVersion = resultFormat.version();
52
53 // Human-readable name of requested profile
54 auto reqProfileString = profileToString(format.profile());
55
56 // Human-readable name of current profile
57 auto curProfileString = profileToString(resultFormat.profile());
58
59
60 // Example: OpenGL Version 4.6 -> 46
61 auto reqVersionInt = format.version().first * 10 + format.version().second;
62 auto curVersionInt = curVersion.first * 10 + curVersion.second;
63
64
65
66 // We set the following guidelines:
67 // 1. Whenever the actually received GL version is < than the requested one, the context is not the one requested
68 // 2. If the received profile is not the requested one, the context is not the one requested
69
70 if(curVersionInt < 32 && resultFormat.profile() == QSurfaceFormat::CoreProfile)
71 {
72 std::cerr << "Warning: Got an OpenGL core context with OpengGL version < 3.2 (" << curVersion.first << "." << curVersion.second << ")! This should not be possible." << std::endl;
73 return false;
74 }
75
76 // Check whether the conditions above are met.
77 // If not, print some error to the console
78 if(curVersionInt < reqVersionInt ||
79 format.profile()!= resultFormat.profile() )
80 {
81 std::cout << "[OpenGL context] Requested: "
82 << format.version().first << "." << format.version().second << " (" << reqProfileString << ")"
83 << ", Actually created: "
84 << curVersion.first << "." << curVersion.second << " (" << curProfileString << ")"
85 << std::endl;
86 return false;
87 }
88
89 std::cout << "[OpenGL context] Successfully created OpenGL context with version " << curVersion.first << "."
90 << curVersion.second << " (" << curProfileString << ")." << std::endl;
91
92 if ( format.testOption(QSurfaceFormat::DebugContext) )
93 std::cout << "[OpenGL context] Created Debug Context" << std::endl;
94
95 return true;
96}
97
98// Create a QSurfaceFormat from the most important properties like version and profile
99QSurfaceFormat createFormat(QSurfaceFormat::OpenGLContextProfile _profile, int _glMajor, int _glMinor, int _multisamplingSamples, bool _stereo, bool _debugContext)
100{
101 QSurfaceFormat format;
102 format.setVersion(_glMajor, _glMinor);
103 format.setProfile(_profile);
104 format.setSamples(_multisamplingSamples);
105 format.setStereo(_stereo);
106 if(_profile != QSurfaceFormat::CoreProfile)
107 format.setOption(QSurfaceFormat::DeprecatedFunctions);
108 if (_debugContext)
109 format.setOption(QSurfaceFormat::DebugContext);
110
111 return format;
112}
113
114// This method tries to find the best possible OpenGL context format in the following order:
115// 1. The profile/format requested via the settings
116// 2. A 4.4 compatibility context (should contain all relevant GL functions)
117// 3. A 3.2 core context (best choice e.g. on MacOS)
118// 4. Return whatever context was applied instead of the requested ones
119QSurfaceFormat getContextFormat()
120{
121 auto reqProfile = OpenFlipper::Options::coreProfile() ? QSurfaceFormat::CoreProfile : QSurfaceFormat::CompatibilityProfile;
122 QPair<int,int> reqVersion = OpenFlipper::Options::glVersion();
123 auto reqSamples = OpenFlipper::Options::samples();
124 auto reqStereo = OpenFlipper::Options::glStereo();
125 bool debugContext = OpenFlipper::Options::debug();
126
127
128
129 /*
130 // Debug: test all (possible and impossible) OpenGL versions and profiles and exit
131 for(int majo = 1; majo < 5; ++majo)
132 for(int mino = 0; mino < 10; ++mino)
133 {
134 std::cout << "========== " << majo << "." << mino << " ==========="<<std::endl;
135 verifySpecificContextFormat(createFormat(QSurfaceFormat::CoreProfile, majo, mino, reqSamples, reqStereo, debugContext));
136 verifySpecificContextFormat(createFormat(QSurfaceFormat::CompatibilityProfile, majo, mino, reqSamples, reqStereo, debugContext));
137 verifySpecificContextFormat(createFormat(QSurfaceFormat::NoProfile, majo, mino, reqSamples, reqStereo, debugContext));
138 std::cout << "================================" << std::endl;
139 std::cout << std::endl;
140 }
141 exit(0);
142 */
143
144
145
146 QSurfaceFormat resultFormat;
147
148
149 std::cout << "[OpenGL context] Trying to create a " << reqVersion.first << "." << reqVersion.second << " " << profileToString(reqProfile) << " context (default from settings)..." << std::endl;
150 bool success = verifySpecificContextFormat(createFormat(reqProfile, reqVersion.first, reqVersion.second, reqSamples, reqStereo, debugContext), &resultFormat);
151
152 // If that did not work...
153 if(!success)
154 {
155 std::cout << "[OpenGL context] Trying to create a 4.4 compat context..." << std::endl;
156 success = verifySpecificContextFormat(createFormat(QSurfaceFormat::CompatibilityProfile, 4, 4, reqSamples, reqStereo, debugContext), &resultFormat);
157
158 if(!success)
159 {
160 std::cout << "[OpenGL context] Trying to create a 3.2 core context..." << std::endl;
161 success = verifySpecificContextFormat(createFormat(QSurfaceFormat::CoreProfile, 3, 2, reqSamples, reqStereo, debugContext), &resultFormat);
162 if(!success)
163 {
164 std::cerr << "[OpenGL context] Warning: Could not create any of the requested GL contexts." << std::endl;
165 std::cerr << "[OpenGL context] The following context (proposed by the graphics driver) will be created:" << std::endl;
166 std::cerr << "[OpenGL context] Profile: " << profileToString(resultFormat.profile()) << ", Version: "
167 << resultFormat.version().first << "." << resultFormat.version().second << std::endl;
168 std::cerr << "[OpenGL context] Please consider setting a supported OpenGL version and profile in the Options dialog." << std::endl;
169 }
170 }
171 }
172
173 return resultFormat;
174}
175
176}