A second take on HDR support with an SDR white point and HDR headroom

This better reflects how HDR content is actually used, e.g. most content is in the SDR range, with specular highlights and bright details beyond the SDR range, in the HDR headroom.

This more closely matches how HDR is handled on Apple platforms, as EDR.

This also greatly simplifies application code which no longer has to think about color scaling. SDR content is rendered at the appropriate brightness automatically, and HDR content is scaled to the correct range for the display HDR headroom.
This commit is contained in:
Sam Lantinga 2024-02-19 08:45:02 -08:00
parent 3b7533f4a2
commit 4ba6aeee9d
24 changed files with 430 additions and 546 deletions

View file

@ -242,9 +242,9 @@ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window *window, co
* is displayed, if you want a software renderer without a window
* - `SDL_PROP_RENDERER_CREATE_OUTPUT_COLORSPACE_NUMBER`: an SDL_ColorSpace
* value describing the colorspace for output to the display, defaults to
* SDL_COLORSPACE_SRGB. The direct3d11 and direct3d12 renderers support
* SDL_COLORSPACE_SCRGB, which is a linear color space and supports HDR
* output. If you select SDL_COLORSPACE_SCRGB, drawing still uses the sRGB
* SDL_COLORSPACE_SRGB. The direct3d11, direct3d12, and metal renderers support
* SDL_COLORSPACE_SRGB_LINEAR, which is a linear color space and supports HDR
* output. If you select SDL_COLORSPACE_SRGB_LINEAR, drawing still uses the sRGB
* colorspace, but values can go beyond 1.0 and float (linear) format
* textures can be used for HDR content.
* - `SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN`: true if you want
@ -342,6 +342,9 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend
* - `SDL_PROP_RENDERER_OUTPUT_COLORSPACE_NUMBER`: an SDL_ColorSpace value
* describing the colorspace for output to the display, defaults to
* SDL_COLORSPACE_SRGB.
* - `SDL_PROP_RENDERER_HDR_ENABLED_BOOLEAN`: true if the output colorspace is SDL_COLORSPACE_SRGB_LINEAR and the renderer is showing on a display with HDR enabled.
* - `SDL_PROP_RENDERER_SDR_WHITE_POINT_FLOAT`: the value of SDR white in the SDL_COLORSPACE_SRGB_LINEAR colorspace. When HDR is enabled, this value is automatically multiplied into the color scale.
* - `SDL_PROP_RENDERER_HDR_HEADROOM_FLOAT`: the additional high dynamic range that can be displayed, in terms of the SDR white point. When HDR is not enabled, this will be 1.0.
* - `SDL_PROP_RENDERER_D3D9_DEVICE_POINTER`: the IDirect3DDevice9 associated
* with the renderer
* - `SDL_PROP_RENDERER_D3D11_DEVICE_POINTER`: the ID3D11Device associated
@ -366,6 +369,9 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetRendererProperties(SDL_Renderer
#define SDL_PROP_RENDERER_WINDOW_POINTER "SDL.renderer.window"
#define SDL_PROP_RENDERER_SURFACE_POINTER "SDL.renderer.surface"
#define SDL_PROP_RENDERER_OUTPUT_COLORSPACE_NUMBER "SDL.renderer.output_colorspace"
#define SDL_PROP_RENDERER_HDR_ENABLED_BOOLEAN "SDL.renderer.HDR_enabled"
#define SDL_PROP_RENDERER_SDR_WHITE_POINT_FLOAT "SDL.renderer.SDR_white_point"
#define SDL_PROP_RENDERER_HDR_HEADROOM_FLOAT "SDL.renderer.HDR_headroom"
#define SDL_PROP_RENDERER_D3D9_DEVICE_POINTER "SDL.renderer.d3d9.device"
#define SDL_PROP_RENDERER_D3D11_DEVICE_POINTER "SDL.renderer.d3d11.device"
#define SDL_PROP_RENDERER_D3D12_DEVICE_POINTER "SDL.renderer.d3d12.device"
@ -468,7 +474,7 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer *
* These are the supported properties:
*
* - `SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER`: an SDL_ColorSpace value
* describing the texture colorspace, defaults to SDL_COLORSPACE_SCRGB for
* describing the texture colorspace, defaults to SDL_COLORSPACE_SRGB_LINEAR for
* floating point textures, SDL_COLORSPACE_HDR10 for 10-bit textures,
* SDL_COLORSPACE_SRGB for other RGB textures and SDL_COLORSPACE_JPEG for
* YUV textures.
@ -480,6 +486,8 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer *
* pixels, required
* - `SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER`: the height of the texture in
* pixels, required
* - `SDL_PROP_TEXTURE_CREATE_SDR_WHITE_POINT_FLOAT`: for HDR10 and floating point textures, this defines the value of 100% diffuse white, with higher values being displayed in the High Dynamic Range headroom. This defaults to 100 for HDR10 textures and 1.0 for floating point textures.
* - `SDL_PROP_TEXTURE_CREATE_HDR_HEADROOM_FLOAT`: for HDR10 and floating point textures, this defines the maximum dynamic range used by the content, in terms of the SDR white point. This would be equivalent to maxCLL / SDL_PROP_TEXTURE_CREATE_SDR_WHITE_POINT_FLOAT for HDR10 content. If this is defined, any values outside the range supported by the display will be scaled into the available HDR headroom, otherwise they are clipped.
*
* With the direct3d11 renderer:
*
@ -560,6 +568,8 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Rendere
#define SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER "access"
#define SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER "width"
#define SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER "height"
#define SDL_PROP_TEXTURE_CREATE_SDR_WHITE_POINT_FLOAT "SDR_white_point"
#define SDL_PROP_TEXTURE_CREATE_HDR_HEADROOM_FLOAT "HDR_headroom"
#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_POINTER "d3d11.texture"
#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER "d3d11.texture_u"
#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER "d3d11.texture_v"
@ -577,7 +587,6 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Rendere
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER "opengles2.texture_u"
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER "opengles2.texture_v"
/**
* Get the properties associated with a texture.
*
@ -585,6 +594,8 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Rendere
*
* - `SDL_PROP_TEXTURE_COLORSPACE_NUMBER`: an SDL_ColorSpace value describing
* the colorspace used by the texture
* - `SDL_PROP_TEXTURE_SDR_WHITE_POINT_FLOAT`: for HDR10 and floating point textures, this defines the value of 100% diffuse white, with higher values being displayed in the High Dynamic Range headroom. This defaults to 100 for HDR10 textures and 1.0 for other textures.
* - `SDL_PROP_TEXTURE_HDR_HEADROOM_FLOAT`: for HDR10 and floating point textures, this defines the maximum dynamic range used by the content, in terms of the SDR white point. If this is defined, any values outside the range supported by the display will be scaled into the available HDR headroom, otherwise they are clipped. This defaults to 1.0 for SDR textures, 4.0 for HDR10 textures, and no default for floating point textures.
*
* With the direct3d11 renderer:
*
@ -646,6 +657,8 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Rendere
extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetTextureProperties(SDL_Texture *texture);
#define SDL_PROP_TEXTURE_COLORSPACE_NUMBER "SDL.texture.colorspace"
#define SDL_PROP_TEXTURE_SDR_WHITE_POINT_FLOAT "SDL.texture.SDR_white_point"
#define SDL_PROP_TEXTURE_HDR_HEADROOM_FLOAT "SDL.texture.HDR_headroom"
#define SDL_PROP_TEXTURE_D3D11_TEXTURE_POINTER "SDL.texture.d3d11.texture"
#define SDL_PROP_TEXTURE_D3D11_TEXTURE_U_POINTER "SDL.texture.d3d11.texture_u"
#define SDL_PROP_TEXTURE_D3D11_TEXTURE_V_POINTER "SDL.texture.d3d11.texture_v"