Skip to content

Instantly share code, notes, and snippets.

@Mluckydwyer
Last active April 18, 2026 14:50
Show Gist options
  • Select an option

  • Save Mluckydwyer/8df7782b1a6a040e5d01305222149f3c to your computer and use it in GitHub Desktop.

Select an option

Save Mluckydwyer/8df7782b1a6a040e5d01305222149f3c to your computer and use it in GitHub Desktop.
Install OpenGL on Ubuntu in WSL

How to Install OpenGL in Ubuntu in WSL2

These steps have been tested on Windows 10 with WSL2 running Ubuntu.

1. Dependencies

First install the dependencies:

apt install mesa-utils libglu1-mesa-dev freeglut3-dev mesa-common-dev

There are more than we need, but also include GLut and Glu libraries to link aginst during compilation for application development (these can be removed if that functionality is not required).

2. Window Server

Installing

Then, you will need to setup a window server. Windows 11 should have this built in and work out of the box (skip to step 3). In Windows 10 you will need to install one VcXsrv is a popular option (also known as XLaunch).

Configuration

Once installed, then you will need to make a configuration. You want the following settings:

  • First Screen: Multi-Window, Display=0

  • Second Screen: Start No Client

  • Third Screen: Clipboard=True, Primary Selection=True, Native OpenGL=False, Disable Access Control=True

I recomend you save your configuration file somewhere so that each time you start you window server you can open it instead of rebuilding it. Then start your window server.

WSL Display

Once you have setup and started your Window server, you need to tell Ubuntu/WSL where your display is, we can do this by running the following command:

export DISPLAY=$(awk '/nameserver / {print $2; exit}' /etc/resolv.conf 2>/dev/null):0
export LIBGL_ALWAYS_INDIRECT=0

You will need to do this for every new shell you open. Alternatively, you can add this to your .bashrc file to have your shell do it for you an start up.

3. Running a Test

After the following configuration you should be able to run the test application below and see some multi-colored gears spinning:

glxgears
@itakatz
Copy link
Copy Markdown

itakatz commented Dec 21, 2022

Great explanation, works and saved me time. Thanks

@pauloud
Copy link
Copy Markdown

pauloud commented Apr 19, 2023

With wsl2 windows10 and ubuntu I followed the tutorial, but when I try to run an opengl application I have no window (and the program doesn't exit).
Did you assume somme prerequisite ?
Does anybody have a solution please ?
EDIT : Ok it was a problem with the firewall, this solved my issue microsoft/WSL#6430 (comment)

@Mluckydwyer
Copy link
Copy Markdown
Author

With wsl2 windows10 and ubuntu I followed the tutorial, but when I try to run an opengl application I have no window (and the program doesn't exit).
Did you assume somme prerequisite ?
Does anybody have a solution please ?
EDIT : Ok it was a problem with the firewall, this solved my issue microsoft/WSL#6430 (comment)

Happy to hear you found a solution and included it here.

@shreyas0924
Copy link
Copy Markdown

Thank you for the solution

@arin-r
Copy link
Copy Markdown

arin-r commented Jul 13, 2023

On windows 11 with WSL2, on running "glxgears", a black window opens. I can expand / minimize & close the window but the content is all black. I don't see any multi-colored gears spinning.

Does anyone have a similar issue? Can someone suggest a fix?

@bjarthur
Copy link
Copy Markdown

on windows 10 with WSL2 i don't see anything with glxgears. no window, not even black.

@Mluckydwyer
Copy link
Copy Markdown
Author

On windows 11 with WSL2, on running "glxgears", a black window opens. I can expand / minimize & close the window but the content is all black. I don't see any multi-colored gears spinning.

Does anyone have a similar issue? Can someone suggest a fix?

It is possible you have some sort of driver issue. If you see a window your windowing system is setup. Maybe just double check your window manager settings. I found I got black screens when I changed settings from what is above. Specifically, Native OpenGL.

@Mluckydwyer
Copy link
Copy Markdown
Author

on windows 10 with WSL2 i don't see anything with glxgears. no window, not even black.

Do you see any errors about being unable to find a display/the DISPLAY environment variable? Not seeing a window would suggest to me it cannot find your window manager.

@bjarthur
Copy link
Copy Markdown

bjarthur commented Jul 28, 2023

window manager? you mean vcXsrv?? if i wait long enough, glxinfo eventually says it's unable to find open the display. i was thinking a driver issue too, but not sure how to fix or check that.

@Mluckydwyer
Copy link
Copy Markdown
Author

window manager? you mean vcXsrv?? if i wait long enough, glxinfo eventually says it's unable to find the display. i was thinking a driver issue too, but not sure how to fix or check that.

@bjarthur Yes, vcXsrv is your window manager in this case. If you are seeing the "Unable to find a display" error, that means your window manager is either not setup correctly, not running, or your DISPLAY environment variable is not pointing correctly to your window manager. If you run echo $DISPLAY, what is printed?

@bjarthur
Copy link
Copy Markdown

DISPLAY was set to an IPaddress, but the wrong one. i changed it to be the same as the one in network settings and it now works. thanks!

@Mluckydwyer
Copy link
Copy Markdown
Author

DISPLAY was set to an IPaddress, but the wrong one. i changed it to be the same as the one in network settings and it now works. thanks!

Great to hear! Did you use export DISPLAY=$(awk '/nameserver / {print $2; exit}' /etc/resolv.conf 2>/dev/null):0 in your terminal/RC file, or was it set some other way? Just want to check if you hit a case where this doesn't work.

@bjarthur
Copy link
Copy Markdown

bjarthur commented Jul 28, 2023

this command above didn't work for me: export DISPLAY=$(awk '/nameserver / {print $2; exit}' /etc/resolv.conf 2>/dev/null):0. i had to lookup my correct ipaddr in network settings and set the envvar in .bashrc manually.

@Jamms224
Copy link
Copy Markdown

On windows 11 with WSL2, on running "glxgears", a black window opens. I can expand / minimize & close the window but the content is all black. I don't see any multi-colored gears spinning.

Does anyone have a similar issue? Can someone suggest a fix?

I'm encountering the exact same issue on Windows 11 with WSL2. Upon running glxgears, the native Windows Server for Windows 11 launches, but it only displays a black screen. Whilst the terminal outputs values like "frames in 5.0 seconds," there's no actual visual output. I decided to test VcXsrv to see if it would yield different results, but unfortunately, the same problem persists - this time with an even worse frame rate for the black screen.

Comments suggest that this could potentially stem from a driver problem, given that a window does appear, or that it might be related to window manager settings. However, I'm unsure how to address these concerns within the built-in Windows 11 Windows Server.

Does anyone have any suggestions or recommendations for troubleshooting this?

@BassamAbdellatif
Copy link
Copy Markdown

BassamAbdellatif commented Dec 3, 2023

I got this window
image

I got also this flickering window when I ran an application from within Ubuntu/wsl

@turboslapper
Copy link
Copy Markdown

Some might encounter an error on WSL2 Windows11 that:
MESA: error: ZINK: failed to choose pdev
glx: failed to create drisw screen
Here is a fix that worked for me:
https://askubuntu.com/a/1529249

@abeebyekeen
Copy link
Copy Markdown

If you don't see the glxgears window after running the glxgears command for a test, try running export DISPLAY=$localhost:0 and try glxgears again.

Copy link
Copy Markdown

ghost commented Feb 16, 2025

I had issues with running certain graphical apps under WSL2 (e.g. PyMOL) and while I could run xeyes and glxgears, the gears were actually not running. I run Win11 with WSL2, Debian 12.

glxinfo -B
name of display: localhost:10.0
display: localhost:10  screen: 0
direct rendering: No (LIBGL_ALWAYS_INDIRECT set)
OpenGL vendor string: Mesa Project
OpenGL renderer string: Software Rasterizer
OpenGL version string: 1.4 (2.1 Mesa 10.5.4)

I did

apt install mesa-utils libglu1-mesa-dev freeglut3-dev mesa-common-dev

This did not make a difference. What did the trick was

export LIBGL_ALWAYS_INDIRECT=0

glxinfo -B
name of display: localhost:10.0
display: localhost:10  screen: 0
direct rendering: Yes
Extended renderer info (GLX_MESA_query_renderer):
    Vendor: Microsoft Corporation (0xffffffff)
    Device: D3D12 (Intel(R) Iris(R) Xe Graphics) (0xffffffff)
    Version: 22.3.6
    Accelerated: yes
    Video memory: 16354MB
    Unified memory: yes
    Preferred profile: core (0x1)
    Max core profile version: 4.1
    Max compat profile version: 4.1
    Max GLES1 profile version: 1.1
    Max GLES[23] profile version: 3.0
OpenGL vendor string: Microsoft Corporation
OpenGL renderer string: D3D12 (Intel(R) Iris(R) Xe Graphics)
OpenGL core profile version string: 4.1 (Core Profile) Mesa 22.3.6
OpenGL core profile shading language version string: 4.10
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile

OpenGL version string: 4.1 (Compatibility Profile) Mesa 22.3.6
OpenGL shading language version string: 4.10
OpenGL context flags: (none)
OpenGL profile mask: compatibility profile

OpenGL ES profile version string: OpenGL ES 3.0 Mesa 22.3.6
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.00

Now the gears of glxgears are actually spinning, and I can run PyMOL from within WSL2.

I did the following to always allow direct rendering:

echo "export LIBGL_ALWAYS_INDIRECT=0" >> ~/.bashrc

As far as I can tell there is no need to run an X server under Windows for this to work.

Best wishes/Evert

@ShrikanthX
Copy link
Copy Markdown

I had issues with running certain graphical apps under WSL2 (e.g. PyMOL) and while I could run xeyes and glxgears, the gears were actually not running. I run Win11 with WSL2, Debian 12.

glxinfo -B
name of display: localhost:10.0
display: localhost:10  screen: 0
direct rendering: No (LIBGL_ALWAYS_INDIRECT set)
OpenGL vendor string: Mesa Project
OpenGL renderer string: Software Rasterizer
OpenGL version string: 1.4 (2.1 Mesa 10.5.4)

I did

apt install mesa-utils libglu1-mesa-dev freeglut3-dev mesa-common-dev

This did not make a difference. What did the trick was

export LIBGL_ALWAYS_INDIRECT=0

glxinfo -B
name of display: localhost:10.0
display: localhost:10  screen: 0
direct rendering: Yes
Extended renderer info (GLX_MESA_query_renderer):
    Vendor: Microsoft Corporation (0xffffffff)
    Device: D3D12 (Intel(R) Iris(R) Xe Graphics) (0xffffffff)
    Version: 22.3.6
    Accelerated: yes
    Video memory: 16354MB
    Unified memory: yes
    Preferred profile: core (0x1)
    Max core profile version: 4.1
    Max compat profile version: 4.1
    Max GLES1 profile version: 1.1
    Max GLES[23] profile version: 3.0
OpenGL vendor string: Microsoft Corporation
OpenGL renderer string: D3D12 (Intel(R) Iris(R) Xe Graphics)
OpenGL core profile version string: 4.1 (Core Profile) Mesa 22.3.6
OpenGL core profile shading language version string: 4.10
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile

OpenGL version string: 4.1 (Compatibility Profile) Mesa 22.3.6
OpenGL shading language version string: 4.10
OpenGL context flags: (none)
OpenGL profile mask: compatibility profile

OpenGL ES profile version string: OpenGL ES 3.0 Mesa 22.3.6
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.00

Now the gears of glxgears are actually spinning, and I can run PyMOL from within WSL2.

I did the following to always allow direct rendering:

echo "export LIBGL_ALWAYS_INDIRECT=0" >> ~/.bashrc

As far as I can tell there is no need to run an X server under Windows for this to work.

Best wishes/Evert

Thank you so much. This worked !!!

@bolclaire
Copy link
Copy Markdown

bolclaire commented Apr 10, 2025

On windows 11 with WSL2, on running "glxgears", a black window opens. I can expand / minimize & close the window but the content is all black. I don't see any multi-colored gears spinning.
Does anyone have a similar issue? Can someone suggest a fix?

I'm encountering the exact same issue on Windows 11 with WSL2. Upon running glxgears, the native Windows Server for Windows 11 launches, but it only displays a black screen. Whilst the terminal outputs values like "frames in 5.0 seconds," there's no actual visual output. I decided to test VcXsrv to see if it would yield different results, but unfortunately, the same problem persists - this time with an even worse frame rate for the black screen.

Comments suggest that this could potentially stem from a driver problem, given that a window does appear, or that it might be related to window manager settings. However, I'm unsure how to address these concerns within the built-in Windows 11 Windows Server.

Does anyone have any suggestions or recommendations for troubleshooting this?

I had the same problem and solved it by running
export LIBGL_ALWAYS_SOFTWARE=true
(instead of export LIBGL_ALWAYS_INDIRECT=0)

Hope this works for you.

@Kniganiga
Copy link
Copy Markdown

Kniganiga commented Jul 15, 2025

Thank you so much, worked like a charm for me! ❤️
(wsl2, ubuntu 24.04, win 10 22h2)

@AlwinEsch
Copy link
Copy Markdown

AlwinEsch commented Apr 18, 2026

Hi, thanks for this gist!

About "WSL Display", on my computer (maybe on others different and OK) has this not worked.
As solution I found where works on WSL v1 and v2 is to use the IP given on Windows ipconfig.exe (where also listed on ifconfig by v1 only), there his output about

Ethernet-Adapter vEthernet (WSL (Hyper-V firewall)):

   Verbindungsspezifisches DNS-Suffix:
   Verbindungslokale IPv6-Adresse  . : fe80::40fb:183e:e346:188b%70
   IPv4-Adresse  . . . . . . . . . . : 172.27.16.1
   Subnetzmaske  . . . . . . . . . . : 255.255.240.0
   Standardgateway . . . . . . . . . :

EDIT: VcXsrv moved to GitHub: https://github.com/marchaesen/vcxsrv


Here what I found during fault search:

During test I seen following parts:

  1. With /etc/resolv.conf not match in my case:
    Here his output:
~$ cat /etc/resolv.conf
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver 192.168.178.1
nameserver fd00::62b5:8dff:fe07:e6ed
nameserver 2003:fd:7706:d900:62b5:8dff:fe07:e6ed
search fritz.box

With ifconfig I checked and brought:

eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.56.1  netmask 255.255.255.0  broadcast 192.168.56.255
        inet6 fe80::e103:ee06:d74e:b921  prefixlen 64  scopeid 0xfd<compat,link,site,host>
        ether 0a:00:27:00:00:14  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.27.16.1  netmask 255.255.240.0  broadcast 172.27.31.255
        inet6 fe80::40fb:183e:e346:188b  prefixlen 64  scopeid 0xfd<compat,link,site,host>
        ether 00:15:5d:38:df:77  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Has tried the second IP with export DISPLAY="172.27.16.1:0" and has worked with it.

  1. It seems to make with IP problems by version 2 (wsl.exe --set-version ubuntu 2)
    There brings resolv.conf this:
$ cat /etc/resolv.conf
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver 10.255.255.254
search fritz.box

The ifconfig brings there:

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1492
        inet 172.27.27.235  netmask 255.255.240.0  broadcast 172.27.31.255
        inet6 fe80::215:5dff:fe3f:3c14  prefixlen 64  scopeid 0x20<link>
        ether 00:15:5d:3f:3c:14  txqueuelen 1000  (Ethernet)
        RX packets 1088  bytes 141015 (141.0 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1171  bytes 249798 (249.7 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 15  bytes 1631 (1.6 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 15  bytes 1631 (1.6 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

But the IP's 10.255.255.254 and 172.27.27.235 are not usable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment