Monday, June 15, 2020

BadMatch Error: My First Linux Bug

First Some Background
My first task as a new member of the project involved setting up Gateware on Windows, Mac, and Linux. When running the Gateware unit tests on each operating system, all the tests should pass without error. However, Linux's graphics tests failed, and that is when I first encountered the BadMatch error. I am new to developing on Linux, and this bug was the perfect opportunity to sink my teeth in. The following is what I learned.


Introducing the Bug
The error message is helpful in that it provides the name of the function that generated it, glXMakeCurrent(). The GLX function produces a BadMatch error if:

  • The drawable is not created with the same screen and visual as the context.
  • The drawable is none, and the context is not null.

It doesn't take long to rule-out the second cause of the error. The first cause, however, requires some background information.

X11 and GLX
X11 is the window system responsible for creating and managing windows on the version of Linux I'm using, Linux Mint. GLX is an extension of X11 that enables OpenGL to work within an X11 window. Surprisingly, I found both X11 and GLX documentation quite useful during my efforts to learn more about the error.

The Path to the Error
These are the steps Gateware takes leading up to the error:

  1. Create a display connection to the X11 server.
  2. Create a window using that connection, the root window, the depth of the root window, and the visual from the parent window.
  3. Find a config that matches the framebuffer attributes we want.
  4. Get a visual that matches that config.
  5. Creating a context using the server connection and visual.
  6. glXMakeCurrent(server connection, window, context).
  7. BadMatch error.

I'll reference these steps as we go from here.

Visuals and Configs
When running "glxinfo" in the terminal, you can see a print out of the different GLX visuals and frame buffer configurations (configs) available. The visual and config must be compatible to avoid errors. On my machine, there are 180 visuals and 263 configs. Each visual has a corresponding config.



The Cause of the Error
In the path to the error, 'step 2' creates a window using the parent's visual. In 'step 4', a visual is found using a config. That visual is then used in 'step 6' to create the context. Because two different visuals are being used in setting up the parameters for glXMakeCurrent(), the function outputs a Badmatch error.

A Fix
By choosing a config in 'step 3' that is compatible with the parent visual, the BadMatch error can be avoided. In my case, half of the GLX visuals available were compatible, allowing all of the unit tests to pass without error.

A Better Fix
All of the visuals that were compatible only supported a 24-bit color buffer. What if we wanted to use a 32-bit color buffer? This would allow us to use 8 bits per RGBA color channel. The visual from the parent window in 'step 2' has a 24-bit color buffer. The solution is to find a visual that has a 32-bit depth and use it in 'step 2.' Then, in 'step 3', choose a compatible configuration that has a 32-bit color buffer.


Farewell BadMatch
This error was great to have as my first Linux bug. It caused me to learn more about X11 and GLX, how they function, and how Gateware uses them. I'm looking forward to my next bug and the other things I learn along the way.

No comments:

Post a Comment