Full-screen problem with multiple displays (Microsoft Windows + OpenGL), with solution, sort of

I met an odd problem with creating multiple full screen windows (on multiple displays).
This works for me OK with single Nvidia card and multiple displays, it has also worked with two older Nvidia cards with old drivers (and old Windows?). But now it failed with two current generation Nvidia cards (3070) and latest Windows + Driver version. Tested with GLFW 3.3.2 and shortly with 3.3.3.

The error code I am receiving is:
GLFW(65543)(WGL: Failed to create OpenGL context)

The failure happens when creating the second full screen window. The two screens in question are connected to the same card. Some tests which placed the windows on screens from different graphics cards actually seemed to work. I did experiment with adding delay between creating windows, but that didn’t seem to help.

I am currently not able to really debug this issue, because I have only seen it on customer site, where I have been testing using remote access.

After searching other full-screen related threads on this site, I seem to have found some kind of solution for this problem. The program works if I first create normal windows on the target displays and then later change them to full screen mode.

Testing GLFW 3.3.3 would be useful, as there are some monitor related fixes for Win32.

If this still fails it would be handy to add some logging output at various stages in GLFW to track down the problem, and I can help with that.

Seems to fail the same way, when I retested with 3.3.3.

It manages to create the first window, but the second window creation fails

My fullscreen window code is as follows: (hope I get it through correctly)

GLFWwindow *glfw_fullscreen_win(const char *title,int posx,int posy,
      int sx,int sy,GLFWwindow *share)
{
  GLFWmonitor *monitor=get_monitor(posx,posy,sx,sy);
  if (!monitor){
    fprintf(stderr,"glfw_fullscreen_win failure\n");
  }else{
    const GLFWvidmode *mode=glfwGetVideoMode(monitor);
    glfwWindowHint(GLFW_RED_BITS,mode->redBits);
    glfwWindowHint(GLFW_GREEN_BITS,mode->greenBits);
    glfwWindowHint(GLFW_BLUE_BITS,mode->blueBits);
    glfwWindowHint(GLFW_REFRESH_RATE,mode->refreshRate);
    sx=mode->width;
    sy=mode->height;
  }
  GLFWwindow *win=glfwCreateWindow(sx,sy,
			   title,monitor,share);
  int rsx,rsy;
  glfwGetWindowSize(win,&rsx,&rsy);
  fprintf(stderr,"Window size is %d %d\n",rsx,rsy);
  return win;

}

The get_monitor and glfwGetVideoMode calls return correct results (and similar results for first and the second window). The glfwCreateWindow call triggers the error callback which produces the
GLFW(65543)(WGL: Failed to create OpenGL context)

message. It also returns a null pointer which crashes my program in the glfwGetWindowSize step.

Note that glfwCreateWindow will return NULL on error, so it’s often good to have a backup path:
https://www.glfw.org/docs/3.3/group__window.html#ga5c336fddf2cbb5b92f65f10fb6043344

Do you know what happens if you do not pass share? Normally this would produce another error ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB rather than GLFW_VERSION_UNAVAILABLE which is what you’re seeing, but it’s worth a try.

Note that ‘share’ should not be current on another thread when calling glfwCreateWindow.

There are two places which generate this error, one where the context is created by wglCreateContextAttribsARB (the route modern OpenGL drivers & hardware shouild take) and one using wglCreateContext. If you are building from source it might be worth while to change either message (wgl_context.c line 733 or 751) to a different message to see which is failing.

If these don’t work, I can look into adding debug output to a branch for you - I take it fprintf to stderr would work in your build?

(I hope I got my email alerts set up correctly this time, so I can reply sooner)

The fact that my program crashes if the window is not created is not an issue for me, I need that second window, so crashing is a nice “visible” choice.

Share seems to be essential for the problem, if I don’t pass the window to be shared, the second window is created. I cannot be sure if everything is OK, as sharing is needed by my program, but it certainly gets to go much further.

The window creation problem is detected at the 733 line branch.

I added some code to checkout the attributes passed to the wglCreateContextAttribsARB, and it seems like an empty attribute list still exhibits the problem. My original code used the GLFW_CONTEXT_RELEASE_BEHAVIOUR hint, but it doesn’t really seem to matter.

I will try some additional tests later. Thank you for your help, but don’t worry too much for this issue for me, as I can currently work around it by creating the window first in non full screen mode.

This makes me think there is a driver related problem, as both windows use the same graphics card/driver and so should be able to share lists even if on different windows.

This is the modern wglCreateContextAttribsARB route as expected.

One solution would be to create the window fullscreen, if that fails fall back to creating it windowed and then go fullscreen. This way you get better behaviour if it works.

Retested some things, mostly for fun.

Similar graphics card, and same driver version, but only one card in computer. OK

On the computer with two cards, if the windows are going to displays which are connected to same card: FAIL

On the computer with two cards, if the windows are going to displays which are connected to different cards: OK

The one card and two card computers have different display types, so the card count is not the only difference, but otherwise they are similar.

I also forced the glfw to use the second context creation path. In that case it is the wglShareLists function which fails. The raw error code is: c00720d0 which I really don’t understand

I might try the alternative window creation sequence you suggested, but so far the “normal window” - → change to → “full screen” has been OK also.

I think I gave wrong information in my last message. It actually seems that the failing configuration is when the windows are going to monitors attached to different graphics cards.

This is of course the more logical case. I will confirm when I get the cables swapped.

1 Like

This makes a lot more sense if it is the case, as context sharing between contexts created on two different GPUs is unlikely to work.

You can use:

glGetString( GL_VENDOR );
glGetString( GL_RENDERER );
glGetString( GL_VERSION );
glGetString( GL_SHADING_LANGUAGE_VERSION );

to get more information on the context created with the window to see if they are different.

Note that Windows plays some magic with OpenGL, so I suspect your working solution is because the windows are created with the context of one GPU, and when you go fullscreen the window on the second monitor doesn’t go ‘dedicated fullscreen’ but instead is simply a borderless fullscreen window - in OpenGL there is no real distinction but drivers and Windows DWM handle these in the background.

1 Like