# How Hyprland Implements Color Management and HDR Support: Technical Architecture

> Discover how Hyprland achieves advanced color management and HDR support. Learn about its Wayland protocol pipeline, EDID parsing, and dynamic HDR mode switching for vibrant visuals.

- Repository: [Hypr Development/Hyprland](https://github.com/hyprwm/Hyprland)
- Tags: architecture
- Published: 2026-07-23

---

**Hyprland implements color management and HDR support through a Wayland protocol-based pipeline that detects HDR content via surface image descriptions, validates monitor capabilities through EDID parsing, and dynamically switches HDR modes at runtime by submitting metadata to the kernel DRM subsystem.**

Hyprland, the dynamic tiling Wayland compositor from the `hyprwm` organization, provides sophisticated color management that automatically adapts to HDR content and display capabilities. The implementation spans protocol handlers, output management, and the rendering pipeline to deliver accurate color reproduction and HDR10/HLG output. This article examines the source code architecture behind Hyprland's color management system.

## The Three-Stage Color Management Pipeline

Hyprland’s color management operates through a three-stage workflow that bridges Wayland protocol objects to kernel DRM outputs.

### Stage 1: Surface Image Description

Every surface in Hyprland can expose a **color-management image description** (`SImageDescription`) that defines its color space characteristics. This structure stores primaries, transfer function, luminance range, and optional HDR metadata. The `CColorManagementSurface` class creates and manages these descriptions, accessible via `CColorManagementSurface::imageDescription()`.

HDR detection occurs when the transfer function is `CM_TRANSFER_FUNCTION_ST2084_PQ` (PQ) or `CM_TRANSFER_FUNCTION_HLG`, or when the surface uses Windows scRGB (`isWindowsScRGB()`). This logic resides in [`src/protocols/ColorManagement.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/protocols/ColorManagement.cpp).

### Stage 2: Monitor Capability Detection

Each monitor reports HDR support through EDID parsing. The `CMonitor` class provides `supportsHDR()`, which returns `true` only if the monitor advertises wide-color (BT2020) and contains HDR metadata (`hdrMetadata.has_value()`). The current HDR state is read from the DRM `hdr_output_metadata` sent to the kernel via `inHDR()`. These capabilities are implemented in [`src/output/Monitor.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/output/Monitor.cpp).

### Stage 3: Runtime HDR Activation

When a fullscreen window appears, `IHyprRenderer::handleFullscreenSettings()` decides whether to enable HDR. It checks the monitor’s capability, the surface’s description (`surfaceIsHDR`), and the user-configurable `render:cm_auto_hdr`. If HDR is required, `createHDRMetadata()` builds an `hdr_output_metadata` structure containing EOTF, primaries, and mastering luminances, which is pushed to the monitor via `pMonitor->m_output->state->setHDRMetadata()`. When HDR is not needed, the compositor falls back to zeroed metadata (`NO_HDR_METADATA`). This logic lives in [`src/render/Renderer.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/render/Renderer.cpp).

## Core Color Management Architecture

### Color Space Definitions and Constants

The foundation of Hyprland's color system is defined in [`src/helpers/cm/ColorManagement.hpp`](https://github.com/hyprwm/Hyprland/blob/main/src/helpers/cm/ColorManagement.hpp). Key constants include:

- **SDR luminance range**: `SDR_MIN_LUMINANCE` to `SDR_MAX_LUMINANCE`
- **HDR luminance range**: `HDR_MIN_LUMINANCE` to `HDR_MAX_LUMINANCE`
- **Supported primaries**: `CM_PRIMARIES_*` enums
- **Transfer functions**: `CM_TRANSFER_FUNCTION_*` enums

Helper functions convert between internal enums and Wayland protocol values.

### HDR Detection Logic

A surface reports HDR content through `CColorManagementSurface::isHDR()`. This method returns `true` when the image description specifies PQ (ST 2084), HLG transfer functions, or when `isWindowsScRGB()` indicates linear extended-range content.

### Automatic HDR Configuration

The `render:cm_auto_hdr` configuration option enables automatic switching. When enabled and an HDR surface enters fullscreen, Hyprland sets the monitor’s color-management type to `CM_HDR` (or `CM_HDR_EDID` when the monitor provides its own HDR metadata).

### No-Shader Color Conversion Optimization

For cases where only primaries differ, Hyprland can skip shader-based conversion using `render:non_shader_cm`. The decision occurs in `CMonitor::canNoShaderCM()`, which checks transfer-function compatibility and whether the surface and monitor share identical image descriptions.

## Source Code Reference

### Detecting HDR Surfaces

To check if a surface provides HDR content in [`src/protocols/ColorManagement.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/protocols/ColorManagement.cpp):

```cpp
if (surface->m_colorManagement->isHDR()) {
    // surface provides HDR content (PQ/HLG or Windows scRGB)
}

```

### Validating Monitor HDR Support

In [`src/output/Monitor.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/output/Monitor.cpp), verify monitor capabilities:

```cpp
bool monitorCanHDR = monitor->supportsHDR();   // true only if EDID advertises HDR
bool monitorWantsHDR = monitor->wantsHDR();   // HDR is supported and currently enabled

```

### Triggering Automatic HDR Mode

The renderer checks configuration and surface state in [`src/render/Renderer.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/render/Renderer.cpp):

```cpp
static auto PAUTOHDR = CConfigValue<Config::INTEGER>("render:cm_auto_hdr");
if (*PAUTOHDR && surface->m_colorManagement->isHDR())
    wantHDR = true;   // trigger monitor HDR mode

```

### Constructing HDR Metadata

Create and apply metadata structures in [`src/render/Renderer.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/render/Renderer.cpp):

```cpp
hdr_output_metadata md = createHDRMetadata(
    surface->m_colorManagement->imageDescription(),
    monitor
);
monitor->m_output->state->setHDRMetadata(md);

```

The `createHDRMetadata()` function fills the `hdr_output_metadata` struct with:

- `eotf` values: `0` for SDR, `2` for PQ, `3` for HLG
- Primaries and white point converted to 16-bit values
- Mastering luminance range, max CLL, and max FALL

## Summary

- **Surface Detection**: `CColorManagementSurface` identifies HDR content via `SImageDescription` and transfer function analysis (PQ/HLG/scRGB) in [`src/protocols/ColorManagement.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/protocols/ColorManagement.cpp).
- **Monitor Validation**: `CMonitor::supportsHDR()` parses EDID data to confirm HDR capability using `hdrMetadata` in [`src/output/Monitor.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/output/Monitor.cpp).
- **Runtime Switching**: `handleFullscreenSettings()` coordinates HDR activation using `createHDRMetadata()` to build kernel DRM structures in [`src/render/Renderer.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/render/Renderer.cpp).
- **Configuration**: `render:cm_auto_hdr` enables automatic fullscreen HDR switching, while `render:non_shader_cm` optimizes performance when shader conversion is unnecessary.
- **Metadata Transmission**: The `hdr_output_metadata` struct communicates EOTF, primaries, and luminance data to the kernel via `setHDRMetadata()`.

## Frequently Asked Questions

### What triggers HDR mode in Hyprland?

HDR mode activates when a fullscreen window presents content with PQ, HLG, or scRGB transfer functions, provided `render:cm_auto_hdr` is enabled and the monitor reports HDR support via EDID. The `handleFullscreenSettings()` function evaluates these conditions during the rendering loop.

### How does Hyprland detect if a monitor supports HDR?

Hyprland parses the monitor's EDID metadata in [`src/output/Monitor.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/output/Monitor.cpp). The `supportsHDR()` method checks for the presence of HDR metadata and BT2020 primaries, returning `true` only when the hardware explicitly advertises HDR capability.

### What is the difference between `cm_auto_hdr` and `non_shader_cm`?

The `render:cm_auto_hdr` setting automatically switches monitors into HDR mode for fullscreen HDR content, while `render:non_shader_cm` allows the compositor to skip shader-based color conversion when surfaces and monitors share compatible primaries and transfer functions, reducing GPU load.

### Does Hyprland support Windows scRGB content?

Yes. Hyprland recognizes Windows scRGB (linear extended-range) content through `CColorManagementSurface::isWindowsScRGB()`, which returns `true` for such surfaces and treats them as HDR content requiring appropriate color management and output metadata.