Firefox & Linux in 2025

5 min read Original article ↗
HDR YouTube video clip I used for testing


Last year brought a wealth of new features and fixes to Firefox on Linux. Besides numerous improvements and bug fixes, I want to highlight some major achievements: HDR video playback support, reworked rendering for fractionally scaled displays, and asynchronous rendering implementation. All this progress was enabled by advances in the Wayland compositor ecosystem, with new features implemented by Mutter and KWin.

HDR

The most significant news on the Wayland scene is HDR support, tracked by Bug 1642854. It’s disabled by default but can be enabled in recent Wayland compositors using the gfx.wayland.hdr preference at about:config (or by gfx.wayland.hdr.force-enabled if you don’t have an HDR display).

HDR mode uses a completely different rendering path, similar to the rendering used on Windows and macOS. It’s called native rendering or composited rendering, and it places specific application layers directly into the Wayland compositor as subsurfaces.

The first implementation was done by Robert Mader (presented at FOSDEM), and I unified the implementation for HDR and non-HDR rendering paths as new WaylandSurface object.

The Firefox application window is actually composited from multiple subsurfaces layered together. This design allows HDR content like video frames to be sent directly to the screen while the rest of the application (controls and HTML page) remains in SDR mode. It also enables power-efficient rendering when video frames are decoded on the graphics card and sent directly to the screen (zero-copy playback). In fullscreen mode, this rendering is similar to mpv or mplayer playback and uses minimal power resources.

I also received valuable feedback from AMD engineers who suggested various improvements to HDR playback. We removed unnecessary texture creation over decoded video frames (they’re now displayed directly as wl_buffers without any GL operations) and implemented wl_buffer recycling as mpv does.

For HDR itself (since composited rendering is available for any video playback), Firefox on Wayland uses the color-management-v1 protocol to display HDR content on screen, along with BT.2020 video color space and PQ color transfer function. It uses 10-bit color vectors, so you need VP9 version 2 to decode it in hardware. Firefox also implements software decoding and direct upload to dmabuf frames as a fallback.

The basic HDR rendering implementation is complete, and we’re now in the testing and bug-fixing phase. Layered rendering is quite tricky as it involves rapid wl_surface mapping/unmapping and quick wl_buffer switches, which are difficult to handle properly. HDR rendering of scaled surfaces is still missing—we need fractional-scale-v2 for this (see below), which allows positioning scaled subsurfaces directly in device pixels. We also need to test composited/layered rendering for regular web page rendering to ensure it doesn’t drain your battery. You’re very welcome to test it and report any bugs you find.

Fractional scale

The next major work was done for fractional scale rendering, which shipped in Firefox 147.0. We updated the rendering pipeline and widget sizing to support fractionally scaled displays (scales like 125%, etc.). This required reworking the widget size code to strictly upscale window/surface sizes and coordinates and never downscale them, as downscaling introduces rounding errors.

Another step was identifying the correct rounding algorithm for Wayland subsurfaces and implementing it. Wayland doesn’t define rounding for it, only for toplevel windows, so we’re in a gray area here. I was directed to Stable rounding by Michel Daenzer. It’s used by Mutter and Sway so Firefox implements it for those two compositors while using a different implementation for KWin. This may be updated to use the fractional-scale-v2 protocol when it becomes available.

Fractional scaling is enabled by default, and you should see crisp and clear output regardless of your desktop environment or screen scale.

Asynchronous rendering

Historically, Firefox disabled and re-enabled the rendering pipeline for scale changes, window create/destroy events, and hide/show sequences. This stems from Wayland’s architecture, where a Wayland surface is deleted when a window becomes invisible or is submitted to the compositor with mismatched size/scale (e.g., 111 pixels wide at 200% scale).

Such rendering disruptions cause issues with multi-threaded rendering—they need to be synchronized among threads, and we must ensure surfaces with the wrong scale aren’t sent to the screen, as this leads to application crashes due to protocol errors.

Firefox 149.0 (recent nightly) has a reworked Wayland painting pipeline (Bug 1739232) for both EGL and software rendering. Scale management was moved from wl_buffer fixed scale to wp_viewport, which doesn’t cause protocol errors when size/scale doesn’t match (producing only blurred output instead of crashes).

We also use a clever technique: the rendering wl_surface / wl_buffer / EGLWindow is created right after window creation and before it’s shown, allowing us to paint to it offscreen. When a window becomes visible, we only attach the wl_surface as a subsurface (making it visible) and remove the attachment when it’s hidden. This allows us to keep painting and updating the backbuffer regardless of the actual window status, and the synchronized calls can be removed.

This brings speed improvements when windows are opened and closed, and Linux rendering is now synchronized with the Windows and macOS implementations.

… and more

Other improvements include a screen lock update for audio playback, which allows the screen to dim but prevents sleep when audio is playing. We also added asynchronous Wayland object management to ensure we cleanly remove Wayland objects without pending callbacks, along with various stability fixes.

And there are even more challenges waiting for us Firefox Linux hackers:

  • Wayland session restore (session-restore-v1) to restore Firefox windows to the correct workspace and position.
  • Implement drag and drop for the Firefox main window, and possibly add a custom Wayland drag and drop handler to avoid Gtk3 limitations and race conditions.
  • Utilize the fractional-scale-v2 protocol when it becomes available.
  • Investigate using xdg-positioner directly instead of Gtk3 widget positioning to better handle popups.
  • Vulkan video support via the ffmpeg decoder to enable hardware decoding on NVIDIA hardware.

And of course, we should plan properly before we even start. Ready, Scrum, Go!