Skip to content

Commit 666b730

Browse files
authored
Desktop OpenGL 4.6: fall back to the newest available version (Windows / Linux) (#8580)
* Desktop OpenGL 4.6: fall back to the newest available version Requesting a GL version the driver can't create (e.g. 4.6 on a driver that tops out at 4.5, Mesa llvmpipe, or macOS's 4.1) made glfwCreateWindow fail and the app exit with "couldn't create GLFW window". ofAppGLFWWindow now retries 4.6 -> 4.5 -> ... -> 3.2 (only versions below the request) and logs a warning with the version it used. The window settings are updated, so ofGLProgrammableRenderer is set up with the context's real version and shaders get the matching #version (e.g. 450 instead of 460). GLFW errors from the retries are silenced; the first failure is still logged. Requests the driver can satisfy are unchanged. * Only report the GLFW context error if no fallback version works
1 parent 6fe7474 commit 666b730

1 file changed

Lines changed: 42 additions & 2 deletions

File tree

‎libs/openFrameworks/app/ofAppGLFWWindow.cpp‎

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,46 @@ void ofAppGLFWWindow::setup(const ofGLESWindowSettings & settings) {
236236
sharedContext = (GLFWwindow *)settings.shareContextWith->getWindowContext();
237237
}
238238

239+
auto createWindow = [&](int w, int h, GLFWmonitor * monitor) {
240+
#ifndef TARGET_OPENGLES
241+
if (settings.glVersionMajor >= 3) {
242+
// try the requested version silently, its error is only reported if no fallback version works either
243+
GLFWerrorfun errorCallback = glfwSetErrorCallback(nullptr);
244+
GLFWwindow * window = glfwCreateWindow(w, h, settings.title.c_str(), monitor, sharedContext);
245+
int errorCode = 0;
246+
std::string errorDescription;
247+
#if (GLFW_VERSION_MAJOR >= 3 && GLFW_VERSION_MINOR > 2) || (GLFW_VERSION_MAJOR > 3)
248+
if (!window) {
249+
const char * description = nullptr;
250+
errorCode = glfwGetError(&description);
251+
if (description) errorDescription = description;
252+
}
253+
#endif
254+
static const int versions[][2] = { {4, 6}, {4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}, {3, 3}, {3, 2} };
255+
for (auto & v : versions) {
256+
if (window) break;
257+
if (v[0] * 10 + v[1] >= settings.glVersionMajor * 10 + settings.glVersionMinor) continue;
258+
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, v[0]);
259+
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, v[1]);
260+
window = glfwCreateWindow(w, h, settings.title.c_str(), monitor, sharedContext);
261+
if (window) {
262+
ofLogWarning("ofAppGLFWWindow") << "OpenGL " << settings.glVersionMajor << "." << settings.glVersionMinor
263+
<< " is not available, using OpenGL " << v[0] << "." << v[1];
264+
settings.glVersionMajor = v[0];
265+
settings.glVersionMinor = v[1];
266+
break;
267+
}
268+
}
269+
glfwSetErrorCallback(errorCallback);
270+
if (!window && errorCallback && errorCode) {
271+
errorCallback(errorCode, errorDescription.c_str());
272+
}
273+
return window;
274+
}
275+
#endif
276+
return glfwCreateWindow(w, h, settings.title.c_str(), monitor, sharedContext);
277+
};
278+
239279
if (settings.windowMode == OF_GAME_MODE) {
240280
int count;
241281
GLFWmonitor ** monitors = glfwGetMonitors(&count);
@@ -252,13 +292,13 @@ void ofAppGLFWWindow::setup(const ofGLESWindowSettings & settings) {
252292
currentH = mode->height;
253293
}
254294
if (count > settings.monitor) {
255-
windowP = glfwCreateWindow(currentW, currentH, settings.title.c_str(), monitors[settings.monitor], sharedContext);
295+
windowP = createWindow(currentW, currentH, monitors[settings.monitor]);
256296
} else {
257297
ofLogError("ofAppGLFWWindow") << "couldn't find any monitors";
258298
return;
259299
}
260300
} else {
261-
windowP = glfwCreateWindow(settings.getWidth(), settings.getHeight(), settings.title.c_str(), nullptr, sharedContext);
301+
windowP = createWindow(settings.getWidth(), settings.getHeight(), nullptr);
262302
if (!windowP) {
263303
ofLogError("ofAppGLFWWindow") << "couldn't create GLFW window";
264304
return;

0 commit comments

Comments
 (0)