filament icon indicating copy to clipboard operation
filament copied to clipboard

GLX + GLFW: BadMatch with combination of shared context & native window handle

Open jfaust opened this issue 2 years ago • 4 comments

Describe the bug When passing a GL context to share into Filament and a native window handle to createSwapChain(), I get a BadMatch error thrown by the X server in the call to glXMakeContextCurrent() in PlatformGLX::makeCurrent().

Interestingly, disabling the GLXFBConfig search introduced in https://github.com/google/filament/pull/1456 fixed my problem.

After writing some code to dump the difference between the two GLXFBConfigs (with & without the search), I discovered I needed:

glfwWindowHint(GLFW_ALPHA_BITS, 0);

With the default (where it's set to 8), somehow the GL context that was created was incompatible with the (glfw-created) window that was passed in.

To Reproduce I'll try to find some time to create a repro repo, but in summary: Using GLFW

  1. Create a 1x1 invisible window to act as the share context
  2. Create another window to use as the actual swapchain
  3. Create filament engine/swapchain/renderer, and render one frame
...
  glfwWindowHint(GLFW_SAMPLES, 1);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);

 glfwWindowHint(GLFW_VISIBLE, GL_FALSE);

  glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
  GLFWwindow *share_win = glfwCreateWindow(1, 1, "dummy", nullptr, nullptr);

  glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);

  GLFWwindow *win = glfwCreateWindow(100, 100, "Main Window", nullptr, nullptr);

  void* share_context = (void *)glfwGetGLXContext(share_win);
  void* native_window = (void *)glfwGetX11Window(win);

  filament::Engine *engine = filament::Engine::create(
      filament::backend::Backend::OPENGL,
      nullptr,
      share_context
  );
  filament::SwapChain *swap_chain = engine->createSwapChain(native_window);

  // .. create a renderer, camera, view, etc.
  // do the main loop

Expected behavior Ideally I'd be able to create a share context that has alpha bits in its framebuffer (though fortunately I don't need that right now). Since disabling the GLXFBConfig search results in exactly that situation, and it works, I'm very confused.

The glXMakeContextCurrent() docs also don't make it really clear to me what's going wrong.

BadMatch is generated if:
draw and read are not compatible. 
draw and read cannot fit into frame buffer memory simultaneously.
draw or read is a GLXPixmap and ctx is a direct-rendering context.
draw or read is a GLXPixmap and ctx was previously bound to a GLXWindow or GLXPbuffer.
draw or read is a GLXWindow or GLXPbuffer and ctx was previously bound to a GLXPixmap. 

The first one can't be true since draw and read are the same. The 2nd maybe, but the framebuffer I was creating is pretty small. The other three don't seem to apply, but I'm not sure.

Honestly, I'm mainly filing this ticket so if anyone else runs into this and searches for "shared context BadMatch" they'll find it.

Desktop (please complete the following information):

  • OS: Linux
  • GPU: NVIDIA GeForce GTX 980 Ti
  • Backend: OpenGL

jfaust avatar Jun 01 '22 05:06 jfaust

Right this is unfortunately a GL annoyance: shared contexts must have a compatible configuration, which often means matching the configurations. We should probably at least document our config to make it easier to match.

romainguy avatar Jun 01 '22 05:06 romainguy

The weird part (unless I’m misunderstanding something), is that disabling the search implemented in https://github.com/google/filament/pull/1456 yields a config that doesn’t match, but works. Whereas keeping the search ensures the configs match but doesn’t work. I must be missing something.

jfaust avatar Jun 01 '22 05:06 jfaust

We'd have to look at the exact differences but GL has a narrow definition of a match. Not all attributes need to match.

romainguy avatar Jun 01 '22 05:06 romainguy

Right - my confusion comes from the fact that in the case where it's generating a BadMatch, the configs are identical. The search succeeds and retrieves the exact config that the share context is using.

Setting the context current on the dummy surface succeeds (PlatformGLX.cpp:227), but then the first time it tries to set current on the window it fails (PlatformGLX.cpp:275).

Anyway... I've created a repo demonstrating it working, as well as generating the BadMatch: https://github.com/jfaust/filament-glfw-share-context

jfaust avatar Jun 01 '22 18:06 jfaust