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.main
parent
3b7533f4a2
commit
4ba6aeee9d
|
@ -576,16 +576,16 @@ typedef enum
|
||||||
SDL_COLOR_RANGE_FULL,
|
SDL_COLOR_RANGE_FULL,
|
||||||
SDL_COLOR_PRIMARIES_BT709,
|
SDL_COLOR_PRIMARIES_BT709,
|
||||||
SDL_TRANSFER_CHARACTERISTICS_SRGB,
|
SDL_TRANSFER_CHARACTERISTICS_SRGB,
|
||||||
SDL_MATRIX_COEFFICIENTS_UNSPECIFIED,
|
SDL_MATRIX_COEFFICIENTS_IDENTITY,
|
||||||
SDL_CHROMA_LOCATION_NONE),
|
SDL_CHROMA_LOCATION_NONE),
|
||||||
|
|
||||||
/* scRGB is a linear colorspace and the default colorspace for floating point surfaces */
|
/* This is a linear colorspace and the default colorspace for floating point surfaces. On Windows this is the scRGB colorspace, and on Apple platforms this is kCGColorSpaceExtendedLinearSRGB for EDR content */
|
||||||
SDL_COLORSPACE_SCRGB = /**< Equivalent to DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709 */
|
SDL_COLORSPACE_SRGB_LINEAR = /**< Equivalent to DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709 */
|
||||||
SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_RGB,
|
SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_RGB,
|
||||||
SDL_COLOR_RANGE_FULL,
|
SDL_COLOR_RANGE_FULL,
|
||||||
SDL_COLOR_PRIMARIES_BT709,
|
SDL_COLOR_PRIMARIES_BT709,
|
||||||
SDL_TRANSFER_CHARACTERISTICS_LINEAR,
|
SDL_TRANSFER_CHARACTERISTICS_LINEAR,
|
||||||
SDL_MATRIX_COEFFICIENTS_UNSPECIFIED,
|
SDL_MATRIX_COEFFICIENTS_IDENTITY,
|
||||||
SDL_CHROMA_LOCATION_NONE),
|
SDL_CHROMA_LOCATION_NONE),
|
||||||
|
|
||||||
/* HDR10 is a non-linear HDR colorspace and the default colorspace for 10-bit surfaces */
|
/* HDR10 is a non-linear HDR colorspace and the default colorspace for 10-bit surfaces */
|
||||||
|
@ -594,7 +594,7 @@ typedef enum
|
||||||
SDL_COLOR_RANGE_FULL,
|
SDL_COLOR_RANGE_FULL,
|
||||||
SDL_COLOR_PRIMARIES_BT2020,
|
SDL_COLOR_PRIMARIES_BT2020,
|
||||||
SDL_TRANSFER_CHARACTERISTICS_PQ,
|
SDL_TRANSFER_CHARACTERISTICS_PQ,
|
||||||
SDL_MATRIX_COEFFICIENTS_UNSPECIFIED,
|
SDL_MATRIX_COEFFICIENTS_IDENTITY,
|
||||||
SDL_CHROMA_LOCATION_NONE),
|
SDL_CHROMA_LOCATION_NONE),
|
||||||
|
|
||||||
SDL_COLORSPACE_JPEG = /**< Equivalent to DXGI_COLOR_SPACE_YCBCR_FULL_G22_NONE_P709_X601 */
|
SDL_COLORSPACE_JPEG = /**< Equivalent to DXGI_COLOR_SPACE_YCBCR_FULL_G22_NONE_P709_X601 */
|
||||||
|
|
|
@ -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
|
* is displayed, if you want a software renderer without a window
|
||||||
* - `SDL_PROP_RENDERER_CREATE_OUTPUT_COLORSPACE_NUMBER`: an SDL_ColorSpace
|
* - `SDL_PROP_RENDERER_CREATE_OUTPUT_COLORSPACE_NUMBER`: an SDL_ColorSpace
|
||||||
* value describing the colorspace for output to the display, defaults to
|
* value describing the colorspace for output to the display, defaults to
|
||||||
* SDL_COLORSPACE_SRGB. The direct3d11 and direct3d12 renderers support
|
* SDL_COLORSPACE_SRGB. The direct3d11, direct3d12, and metal renderers support
|
||||||
* SDL_COLORSPACE_SCRGB, which is a linear color space and supports HDR
|
* SDL_COLORSPACE_SRGB_LINEAR, which is a linear color space and supports HDR
|
||||||
* output. If you select SDL_COLORSPACE_SCRGB, drawing still uses the sRGB
|
* 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
|
* colorspace, but values can go beyond 1.0 and float (linear) format
|
||||||
* textures can be used for HDR content.
|
* textures can be used for HDR content.
|
||||||
* - `SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN`: true if you want
|
* - `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
|
* - `SDL_PROP_RENDERER_OUTPUT_COLORSPACE_NUMBER`: an SDL_ColorSpace value
|
||||||
* describing the colorspace for output to the display, defaults to
|
* describing the colorspace for output to the display, defaults to
|
||||||
* SDL_COLORSPACE_SRGB.
|
* 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
|
* - `SDL_PROP_RENDERER_D3D9_DEVICE_POINTER`: the IDirect3DDevice9 associated
|
||||||
* with the renderer
|
* with the renderer
|
||||||
* - `SDL_PROP_RENDERER_D3D11_DEVICE_POINTER`: the ID3D11Device associated
|
* - `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_WINDOW_POINTER "SDL.renderer.window"
|
||||||
#define SDL_PROP_RENDERER_SURFACE_POINTER "SDL.renderer.surface"
|
#define SDL_PROP_RENDERER_SURFACE_POINTER "SDL.renderer.surface"
|
||||||
#define SDL_PROP_RENDERER_OUTPUT_COLORSPACE_NUMBER "SDL.renderer.output_colorspace"
|
#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_D3D9_DEVICE_POINTER "SDL.renderer.d3d9.device"
|
||||||
#define SDL_PROP_RENDERER_D3D11_DEVICE_POINTER "SDL.renderer.d3d11.device"
|
#define SDL_PROP_RENDERER_D3D11_DEVICE_POINTER "SDL.renderer.d3d11.device"
|
||||||
#define SDL_PROP_RENDERER_D3D12_DEVICE_POINTER "SDL.renderer.d3d12.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:
|
* These are the supported properties:
|
||||||
*
|
*
|
||||||
* - `SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER`: an SDL_ColorSpace value
|
* - `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,
|
* floating point textures, SDL_COLORSPACE_HDR10 for 10-bit textures,
|
||||||
* SDL_COLORSPACE_SRGB for other RGB textures and SDL_COLORSPACE_JPEG for
|
* SDL_COLORSPACE_SRGB for other RGB textures and SDL_COLORSPACE_JPEG for
|
||||||
* YUV textures.
|
* YUV textures.
|
||||||
|
@ -480,6 +486,8 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer *
|
||||||
* pixels, required
|
* pixels, required
|
||||||
* - `SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER`: the height of the texture in
|
* - `SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER`: the height of the texture in
|
||||||
* pixels, required
|
* 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:
|
* 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_ACCESS_NUMBER "access"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER "width"
|
#define SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER "width"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER "height"
|
#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_POINTER "d3d11.texture"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER "d3d11.texture_u"
|
#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER "d3d11.texture_u"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER "d3d11.texture_v"
|
#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_U_NUMBER "opengles2.texture_u"
|
||||||
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER "opengles2.texture_v"
|
#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER "opengles2.texture_v"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the properties associated with a texture.
|
* 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
|
* - `SDL_PROP_TEXTURE_COLORSPACE_NUMBER`: an SDL_ColorSpace value describing
|
||||||
* the colorspace used by the texture
|
* 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:
|
* 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);
|
extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetTextureProperties(SDL_Texture *texture);
|
||||||
|
|
||||||
#define SDL_PROP_TEXTURE_COLORSPACE_NUMBER "SDL.texture.colorspace"
|
#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_POINTER "SDL.texture.d3d11.texture"
|
||||||
#define SDL_PROP_TEXTURE_D3D11_TEXTURE_U_POINTER "SDL.texture.d3d11.texture_u"
|
#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"
|
#define SDL_PROP_TEXTURE_D3D11_TEXTURE_V_POINTER "SDL.texture.d3d11.texture_v"
|
||||||
|
|
|
@ -206,14 +206,15 @@ extern DECLSPEC void SDLCALL SDL_DestroySurface(SDL_Surface *surface);
|
||||||
* The following properties are understood by SDL:
|
* The following properties are understood by SDL:
|
||||||
*
|
*
|
||||||
* - `SDL_PROP_SURFACE_COLORSPACE_NUMBER`: an SDL_ColorSpace value describing
|
* - `SDL_PROP_SURFACE_COLORSPACE_NUMBER`: an SDL_ColorSpace value describing
|
||||||
* the surface colorspace, defaults to SDL_COLORSPACE_SCRGB for floating
|
* the surface colorspace, defaults to SDL_COLORSPACE_SRGB_LINEAR for floating
|
||||||
* point formats, SDL_COLORSPACE_HDR10 for 10-bit formats,
|
* point formats, SDL_COLORSPACE_HDR10 for 10-bit formats,
|
||||||
* SDL_COLORSPACE_SRGB for other RGB surfaces and SDL_COLORSPACE_BT709_FULL
|
* SDL_COLORSPACE_SRGB for other RGB surfaces and SDL_COLORSPACE_BT709_FULL
|
||||||
* for YUV textures.
|
* for YUV surfaces.
|
||||||
* - `SDL_PROP_SURFACE_TONEMAP_OPERATOR_STRING`: the tone mapping operator
|
* - `SDL_PROP_SURFACE_MAXCLL_NUMBER`: MaxCLL (Maximum Content Light Level) indicates the maximum light level of any single pixel (in cd/m2 or nits) of the content. MaxCLL is usually measured off the final delivered content after mastering. If one uses the full light level of the HDR mastering display and adds a hard clip at its maximum value, MaxCLL would be equal to the peak luminance of the mastering monitor. This defaults to 400 for HDR10 surfaces.
|
||||||
* used when converting between different colorspaces. Currently this
|
* - `SDL_PROP_SURFACE_MAXFALL_NUMBER`: MaxFALL (Maximum Frame Average Light Level) indicates the maximum value of the frame average light level (in cd/m2 or nits) of the content. MaxFALL is calculated by averaging the decoded luminance values of all the pixels within a frame. MaxFALL is usually much lower than MaxCLL.
|
||||||
* supports the form "*=N", where N is a floating point scale factor applied
|
* - `SDL_PROP_SURFACE_SDR_WHITE_POINT_FLOAT`: for HDR10 and floating point surfaces, this defines the value of 100% diffuse white, with higher values being displayed in the High Dynamic Range headroom. This defaults to 100 for surfaces using the PQ colorspace and 1.0 for other surfaces.
|
||||||
* in linear space.
|
* - `SDL_PROP_SURFACE_HDR_HEADROOM_FLOAT`: for HDR10 and floating point surfaces, this defines the maximum dynamic range used by the content, in terms of the SDR white point. This defaults to SDL_PROP_SURFACE_MAXCLL_NUMBER / SDL_PROP_SURFACE_SDR_WHITE_POINT_FLOAT, or 4.0, for HDR10 surfaces.
|
||||||
|
* - `SDL_PROP_SURFACE_TONEMAP_OPERATOR_STRING`: the tone mapping operator used when converting between different SDR/HDR ranges. Currently this supports the form "*=N", where N is a floating point scale factor applied in linear space.
|
||||||
*
|
*
|
||||||
* \param surface the SDL_Surface structure to query
|
* \param surface the SDL_Surface structure to query
|
||||||
* \returns a valid property ID on success or 0 on failure; call
|
* \returns a valid property ID on success or 0 on failure; call
|
||||||
|
@ -227,6 +228,10 @@ extern DECLSPEC void SDLCALL SDL_DestroySurface(SDL_Surface *surface);
|
||||||
extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSurfaceProperties(SDL_Surface *surface);
|
extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSurfaceProperties(SDL_Surface *surface);
|
||||||
|
|
||||||
#define SDL_PROP_SURFACE_COLORSPACE_NUMBER "SDL.surface.colorspace"
|
#define SDL_PROP_SURFACE_COLORSPACE_NUMBER "SDL.surface.colorspace"
|
||||||
|
#define SDL_PROP_SURFACE_MAXCLL_NUMBER "SDL.surface.maxCLL"
|
||||||
|
#define SDL_PROP_SURFACE_MAXFALL_NUMBER "SDL.surface.maxFALL"
|
||||||
|
#define SDL_PROP_SURFACE_SDR_WHITE_POINT_FLOAT "SDL.surface.SDR_white_point"
|
||||||
|
#define SDL_PROP_SURFACE_HDR_HEADROOM_FLOAT "SDL.surface.HDR_headroom"
|
||||||
#define SDL_PROP_SURFACE_TONEMAP_OPERATOR_STRING "SDL.surface.tonemap"
|
#define SDL_PROP_SURFACE_TONEMAP_OPERATOR_STRING "SDL.surface.tonemap"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -247,7 +252,7 @@ extern DECLSPEC int SDLCALL SDL_SetSurfaceColorspace(SDL_Surface *surface, SDL_C
|
||||||
/**
|
/**
|
||||||
* Get the colorspace used by a surface.
|
* Get the colorspace used by a surface.
|
||||||
*
|
*
|
||||||
* The colorspace defaults to SDL_COLORSPACE_SCRGB for floating point formats,
|
* The colorspace defaults to SDL_COLORSPACE_SRGB_LINEAR for floating point formats,
|
||||||
* SDL_COLORSPACE_HDR10 for 10-bit formats, SDL_COLORSPACE_SRGB for other RGB
|
* SDL_COLORSPACE_HDR10 for 10-bit formats, SDL_COLORSPACE_SRGB for other RGB
|
||||||
* surfaces and SDL_COLORSPACE_BT709_FULL for YUV textures.
|
* surfaces and SDL_COLORSPACE_BT709_FULL for YUV textures.
|
||||||
*
|
*
|
||||||
|
@ -723,7 +728,7 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurfaceFormat(SDL_Surface *surfa
|
||||||
* \sa SDL_ConvertSurface
|
* \sa SDL_ConvertSurface
|
||||||
* \sa SDL_CreateSurface
|
* \sa SDL_CreateSurface
|
||||||
*/
|
*/
|
||||||
extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurfaceFormatAndColorspace(SDL_Surface *surface, Uint32 pixel_format, SDL_Colorspace colorspace);
|
extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurfaceFormatAndColorspace(SDL_Surface *surface, Uint32 pixel_format, SDL_Colorspace colorspace, SDL_PropertiesID props);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy a block of pixels of one format to another format.
|
* Copy a block of pixels of one format to another format.
|
||||||
|
@ -764,7 +769,7 @@ extern DECLSPEC int SDLCALL SDL_ConvertPixels(int width, int height, Uint32 src_
|
||||||
*
|
*
|
||||||
* \since This function is available since SDL 3.0.0.
|
* \since This function is available since SDL 3.0.0.
|
||||||
*/
|
*/
|
||||||
extern DECLSPEC int SDLCALL SDL_ConvertPixelsAndColorspace(int width, int height, Uint32 src_format, SDL_Colorspace src_colorspace, const void *src, int src_pitch, Uint32 dst_format, SDL_Colorspace dst_colorspace, void *dst, int dst_pitch);
|
extern DECLSPEC int SDLCALL SDL_ConvertPixelsAndColorspace(int width, int height, Uint32 src_format, SDL_Colorspace src_colorspace, SDL_PropertiesID src_properties, const void *src, int src_pitch, Uint32 dst_format, SDL_Colorspace dst_colorspace, SDL_PropertiesID dst_properties, void *dst, int dst_pitch);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Premultiply the alpha on a block of pixels.
|
* Premultiply the alpha on a block of pixels.
|
||||||
|
|
|
@ -355,14 +355,9 @@ extern DECLSPEC SDL_DisplayID SDLCALL SDL_GetPrimaryDisplay(void);
|
||||||
*
|
*
|
||||||
* The following read-only properties are provided by SDL:
|
* The following read-only properties are provided by SDL:
|
||||||
*
|
*
|
||||||
* - `SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN`: true if the display has High
|
* - `SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN`: true if the display has HDR headroom above the SDR white point.
|
||||||
* Dynamic Range enabled
|
* - `SDL_PROP_DISPLAY_SDR_WHITE_POINT_FLOAT`: the value of SDR white in the SDL_COLORSPACE_SRGB_LINEAR colorspace. On Windows this corresponds to the SDR white level in scRGB colorspace, and on Apple platforms this is always 1.0 for EDR content.
|
||||||
* - `SDL_PROP_DISPLAY_SDR_WHITE_LEVEL_FLOAT`: the luminance, in nits, that
|
* - `SDL_PROP_DISPLAY_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.
|
||||||
* SDR white is rendered on this display. If this value is not set or is
|
|
||||||
* zero, the value 200 is a reasonable default when HDR is enabled.
|
|
||||||
* - `SDL_PROP_DISPLAY_HDR_WHITE_LEVEL_FLOAT`: the maximum luminance, in nits,
|
|
||||||
* of HDR content on this display. If this value is not set or is zero, the
|
|
||||||
* value 400 is a reasonable default when HDR is enabled.
|
|
||||||
*
|
*
|
||||||
* \param displayID the instance ID of the display to query
|
* \param displayID the instance ID of the display to query
|
||||||
* \returns a valid property ID on success or 0 on failure; call
|
* \returns a valid property ID on success or 0 on failure; call
|
||||||
|
@ -376,8 +371,8 @@ extern DECLSPEC SDL_DisplayID SDLCALL SDL_GetPrimaryDisplay(void);
|
||||||
extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetDisplayProperties(SDL_DisplayID displayID);
|
extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetDisplayProperties(SDL_DisplayID displayID);
|
||||||
|
|
||||||
#define SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN "SDL.display.HDR_enabled"
|
#define SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN "SDL.display.HDR_enabled"
|
||||||
#define SDL_PROP_DISPLAY_SDR_WHITE_LEVEL_FLOAT "SDL.display.SDR_white_level"
|
#define SDL_PROP_DISPLAY_SDR_WHITE_POINT_FLOAT "SDL.display.SDR_white_point"
|
||||||
#define SDL_PROP_DISPLAY_HDR_WHITE_LEVEL_FLOAT "SDL.display.HDR_white_level"
|
#define SDL_PROP_DISPLAY_HDR_HEADROOM_FLOAT "SDL.display.HDR_headroom"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the name of a display in UTF-8 encoding.
|
* Get the name of a display in UTF-8 encoding.
|
||||||
|
|
|
@ -996,10 +996,10 @@ SDL_DYNAPI_PROC(int,SDL_SetTextureAlphaModFloat,(SDL_Texture *a, float b),(a,b),
|
||||||
SDL_DYNAPI_PROC(int,SDL_GetTextureAlphaModFloat,(SDL_Texture *a, float *b),(a,b),return)
|
SDL_DYNAPI_PROC(int,SDL_GetTextureAlphaModFloat,(SDL_Texture *a, float *b),(a,b),return)
|
||||||
SDL_DYNAPI_PROC(int,SDL_SetRenderDrawColorFloat,(SDL_Renderer *a, float b, float c, float d, float e),(a,b,c,d,e),return)
|
SDL_DYNAPI_PROC(int,SDL_SetRenderDrawColorFloat,(SDL_Renderer *a, float b, float c, float d, float e),(a,b,c,d,e),return)
|
||||||
SDL_DYNAPI_PROC(int,SDL_GetRenderDrawColorFloat,(SDL_Renderer *a, float *b, float *c, float *d, float *e),(a,b,c,d,e),return)
|
SDL_DYNAPI_PROC(int,SDL_GetRenderDrawColorFloat,(SDL_Renderer *a, float *b, float *c, float *d, float *e),(a,b,c,d,e),return)
|
||||||
SDL_DYNAPI_PROC(int,SDL_ConvertPixelsAndColorspace,(int a, int b, Uint32 c, SDL_Colorspace d, const void *e, int f, Uint32 g, SDL_Colorspace h, void *i, int j),(a,b,c,d,e,f,g,h,i,j),return)
|
SDL_DYNAPI_PROC(int,SDL_ConvertPixelsAndColorspace,(int a, int b, Uint32 c, SDL_Colorspace d, SDL_PropertiesID e, const void *f, int g, Uint32 h, SDL_Colorspace i, SDL_PropertiesID j, void *k, int l),(a,b,c,d,e,f,g,h,i,j,k,l),return)
|
||||||
SDL_DYNAPI_PROC(int,SDL_SetSurfaceColorspace,(SDL_Surface *a, SDL_Colorspace b),(a,b),return)
|
SDL_DYNAPI_PROC(int,SDL_SetSurfaceColorspace,(SDL_Surface *a, SDL_Colorspace b),(a,b),return)
|
||||||
SDL_DYNAPI_PROC(int,SDL_GetSurfaceColorspace,(SDL_Surface *a, SDL_Colorspace *b),(a,b),return)
|
SDL_DYNAPI_PROC(int,SDL_GetSurfaceColorspace,(SDL_Surface *a, SDL_Colorspace *b),(a,b),return)
|
||||||
SDL_DYNAPI_PROC(SDL_Surface*,SDL_ConvertSurfaceFormatAndColorspace,(SDL_Surface *a, Uint32 b, SDL_Colorspace c),(a,b,c),return)
|
SDL_DYNAPI_PROC(SDL_Surface*,SDL_ConvertSurfaceFormatAndColorspace,(SDL_Surface *a, Uint32 b, SDL_Colorspace c, SDL_PropertiesID d),(a,b,c,d),return)
|
||||||
SDL_DYNAPI_PROC(int,SDL_CopyProperties,(SDL_PropertiesID a, SDL_PropertiesID b),(a,b),return)
|
SDL_DYNAPI_PROC(int,SDL_CopyProperties,(SDL_PropertiesID a, SDL_PropertiesID b),(a,b),return)
|
||||||
SDL_DYNAPI_PROC(int,SDL_SetRenderColorScale,(SDL_Renderer *a, float b),(a,b),return)
|
SDL_DYNAPI_PROC(int,SDL_SetRenderColorScale,(SDL_Renderer *a, float b),(a,b),return)
|
||||||
SDL_DYNAPI_PROC(int,SDL_GetRenderColorScale,(SDL_Renderer *a, float *b),(a,b),return)
|
SDL_DYNAPI_PROC(int,SDL_GetRenderColorScale,(SDL_Renderer *a, float *b),(a,b),return)
|
||||||
|
|
|
@ -150,7 +150,7 @@ SDL_bool SDL_RenderingLinearSpace(SDL_Renderer *renderer)
|
||||||
} else {
|
} else {
|
||||||
colorspace = renderer->output_colorspace;
|
colorspace = renderer->output_colorspace;
|
||||||
}
|
}
|
||||||
if (colorspace == SDL_COLORSPACE_SCRGB) {
|
if (colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
|
@ -737,6 +737,47 @@ static void UpdateMainViewDimensions(SDL_Renderer *renderer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void UpdateHDRProperties(SDL_Renderer *renderer)
|
||||||
|
{
|
||||||
|
SDL_DisplayID displayID = SDL_GetDisplayForWindow(renderer->window);
|
||||||
|
SDL_PropertiesID display_props;
|
||||||
|
SDL_PropertiesID renderer_props;
|
||||||
|
|
||||||
|
if (!displayID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
display_props = SDL_GetDisplayProperties(displayID);
|
||||||
|
if (!display_props) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer_props = SDL_GetRendererProperties(renderer);
|
||||||
|
if (!renderer_props) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer->color_scale /= renderer->SDR_white_point;
|
||||||
|
|
||||||
|
if (renderer->output_colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
|
||||||
|
renderer->SDR_white_point = SDL_GetFloatProperty(display_props, SDL_PROP_DISPLAY_SDR_WHITE_POINT_FLOAT, 1.0f);
|
||||||
|
renderer->HDR_headroom = SDL_GetFloatProperty(display_props, SDL_PROP_DISPLAY_HDR_HEADROOM_FLOAT, 1.0f);
|
||||||
|
} else {
|
||||||
|
renderer->SDR_white_point = 1.0f;
|
||||||
|
renderer->HDR_headroom = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (renderer->HDR_headroom > 1.0f) {
|
||||||
|
SDL_SetBooleanProperty(renderer_props, SDL_PROP_RENDERER_HDR_ENABLED_BOOLEAN, SDL_TRUE);
|
||||||
|
} else {
|
||||||
|
SDL_SetBooleanProperty(renderer_props, SDL_PROP_RENDERER_HDR_ENABLED_BOOLEAN, SDL_FALSE);
|
||||||
|
}
|
||||||
|
SDL_SetFloatProperty(renderer_props, SDL_PROP_RENDERER_SDR_WHITE_POINT_FLOAT, renderer->SDR_white_point);
|
||||||
|
SDL_SetFloatProperty(renderer_props, SDL_PROP_RENDERER_HDR_HEADROOM_FLOAT, renderer->HDR_headroom);
|
||||||
|
|
||||||
|
renderer->color_scale *= renderer->SDR_white_point;
|
||||||
|
}
|
||||||
|
|
||||||
static int UpdateLogicalPresentation(SDL_Renderer *renderer);
|
static int UpdateLogicalPresentation(SDL_Renderer *renderer);
|
||||||
|
|
||||||
|
|
||||||
|
@ -792,8 +833,12 @@ static int SDLCALL SDL_RendererEventWatch(void *userdata, SDL_Event *event)
|
||||||
if (!(SDL_GetWindowFlags(window) & SDL_WINDOW_HIDDEN)) {
|
if (!(SDL_GetWindowFlags(window) & SDL_WINDOW_HIDDEN)) {
|
||||||
renderer->hidden = SDL_FALSE;
|
renderer->hidden = SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
} else if (event->type == SDL_EVENT_WINDOW_DISPLAY_CHANGED) {
|
||||||
|
UpdateHDRProperties(renderer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (event->type == SDL_EVENT_DISPLAY_HDR_STATE_CHANGED) {
|
||||||
|
UpdateHDRProperties(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -987,6 +1032,8 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
|
||||||
|
|
||||||
renderer->line_method = SDL_GetRenderLineMethod();
|
renderer->line_method = SDL_GetRenderLineMethod();
|
||||||
|
|
||||||
|
renderer->SDR_white_point = 1.0f;
|
||||||
|
renderer->HDR_headroom = 1.0f;
|
||||||
renderer->color_scale = 1.0f;
|
renderer->color_scale = 1.0f;
|
||||||
|
|
||||||
if (window) {
|
if (window) {
|
||||||
|
@ -1008,6 +1055,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
|
||||||
SDL_SetProperty(new_props, SDL_PROP_RENDERER_SURFACE_POINTER, surface);
|
SDL_SetProperty(new_props, SDL_PROP_RENDERER_SURFACE_POINTER, surface);
|
||||||
}
|
}
|
||||||
SDL_SetNumberProperty(new_props, SDL_PROP_RENDERER_OUTPUT_COLORSPACE_NUMBER, renderer->output_colorspace);
|
SDL_SetNumberProperty(new_props, SDL_PROP_RENDERER_OUTPUT_COLORSPACE_NUMBER, renderer->output_colorspace);
|
||||||
|
UpdateHDRProperties(renderer);
|
||||||
|
|
||||||
SDL_SetProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_RENDERER_POINTER, renderer);
|
SDL_SetProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_RENDERER_POINTER, renderer);
|
||||||
|
|
||||||
|
@ -1186,9 +1234,15 @@ static Uint32 GetClosestSupportedFormat(SDL_Renderer *renderer, Uint32 format)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (SDL_ISPIXELFORMAT_10BIT(format) || SDL_ISPIXELFORMAT_FLOAT(format)) {
|
} else if (SDL_ISPIXELFORMAT_10BIT(format) || SDL_ISPIXELFORMAT_FLOAT(format)) {
|
||||||
|
if (SDL_ISPIXELFORMAT_10BIT(format)) {
|
||||||
for (i = 0; i < renderer->info.num_texture_formats; ++i) {
|
for (i = 0; i < renderer->info.num_texture_formats; ++i) {
|
||||||
if (!SDL_ISPIXELFORMAT_FOURCC(renderer->info.texture_formats[i]) &&
|
if (SDL_ISPIXELFORMAT_10BIT(renderer->info.texture_formats[i])) {
|
||||||
SDL_ISPIXELFORMAT_FLOAT(renderer->info.texture_formats[i])) {
|
return renderer->info.texture_formats[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < renderer->info.num_texture_formats; ++i) {
|
||||||
|
if (SDL_ISPIXELFORMAT_FLOAT(renderer->info.texture_formats[i])) {
|
||||||
return renderer->info.texture_formats[i];
|
return renderer->info.texture_formats[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1214,6 +1268,8 @@ SDL_Texture *SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_Propert
|
||||||
int w = (int)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, 0);
|
int w = (int)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, 0);
|
||||||
int h = (int)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, 0);
|
int h = (int)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, 0);
|
||||||
SDL_Colorspace default_colorspace;
|
SDL_Colorspace default_colorspace;
|
||||||
|
float SDR_white_point_default = 1.0f;
|
||||||
|
float HDR_headroom_default = 1.0f;
|
||||||
SDL_bool texture_is_fourcc_and_target;
|
SDL_bool texture_is_fourcc_and_target;
|
||||||
|
|
||||||
CHECK_RENDERER_MAGIC(renderer, NULL);
|
CHECK_RENDERER_MAGIC(renderer, NULL);
|
||||||
|
@ -1271,6 +1327,15 @@ SDL_Texture *SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_Propert
|
||||||
}
|
}
|
||||||
renderer->textures = texture;
|
renderer->textures = texture;
|
||||||
|
|
||||||
|
if (SDL_COLORSPACETRANSFER(texture->colorspace) == SDL_TRANSFER_CHARACTERISTICS_PQ) {
|
||||||
|
SDR_white_point_default = 100.0f;
|
||||||
|
HDR_headroom_default = 4.0f;
|
||||||
|
} else if (SDL_COLORSPACETRANSFER(texture->colorspace) == SDL_TRANSFER_CHARACTERISTICS_LINEAR) {
|
||||||
|
HDR_headroom_default = 0.0f;
|
||||||
|
}
|
||||||
|
texture->SDR_white_point = SDL_GetFloatProperty(props, SDL_PROP_TEXTURE_CREATE_SDR_WHITE_POINT_FLOAT, SDR_white_point_default);
|
||||||
|
texture->HDR_headroom = SDL_GetFloatProperty(props, SDL_PROP_TEXTURE_CREATE_HDR_HEADROOM_FLOAT, HDR_headroom_default);
|
||||||
|
|
||||||
/* FOURCC format cannot be used directly by renderer back-ends for target texture */
|
/* FOURCC format cannot be used directly by renderer back-ends for target texture */
|
||||||
texture_is_fourcc_and_target = (access == SDL_TEXTUREACCESS_TARGET && SDL_ISPIXELFORMAT_FOURCC(format));
|
texture_is_fourcc_and_target = (access == SDL_TEXTUREACCESS_TARGET && SDL_ISPIXELFORMAT_FOURCC(format));
|
||||||
|
|
||||||
|
@ -1335,6 +1400,14 @@ SDL_Texture *SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_Propert
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Now set the properties for the new texture */
|
||||||
|
props = SDL_GetTextureProperties(texture);
|
||||||
|
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_COLORSPACE_NUMBER, texture->colorspace);
|
||||||
|
SDL_SetFloatProperty(props, SDL_PROP_TEXTURE_SDR_WHITE_POINT_FLOAT, texture->SDR_white_point);
|
||||||
|
if (texture->HDR_headroom > 0.0f) {
|
||||||
|
SDL_SetFloatProperty(props, SDL_PROP_TEXTURE_HDR_HEADROOM_FLOAT, texture->HDR_headroom);
|
||||||
|
}
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1359,8 +1432,9 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s
|
||||||
int i;
|
int i;
|
||||||
Uint32 format = SDL_PIXELFORMAT_UNKNOWN;
|
Uint32 format = SDL_PIXELFORMAT_UNKNOWN;
|
||||||
SDL_Texture *texture;
|
SDL_Texture *texture;
|
||||||
SDL_PropertiesID props;
|
SDL_PropertiesID surface_props, props;
|
||||||
SDL_Colorspace colorspace = SDL_COLORSPACE_UNKNOWN;
|
SDL_Colorspace surface_colorspace = SDL_COLORSPACE_UNKNOWN;
|
||||||
|
SDL_Colorspace texture_colorspace = SDL_COLORSPACE_UNKNOWN;
|
||||||
|
|
||||||
CHECK_RENDERER_MAGIC(renderer, NULL);
|
CHECK_RENDERER_MAGIC(renderer, NULL);
|
||||||
|
|
||||||
|
@ -1386,9 +1460,10 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SDL_GetSurfaceColorspace(surface, &colorspace) < 0) {
|
if (SDL_GetSurfaceColorspace(surface, &surface_colorspace) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
texture_colorspace = surface_colorspace;
|
||||||
|
|
||||||
/* Try to have the best pixel format for the texture */
|
/* Try to have the best pixel format for the texture */
|
||||||
/* No alpha, but a colorkey => promote to alpha */
|
/* No alpha, but a colorkey => promote to alpha */
|
||||||
|
@ -1418,6 +1493,16 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Look for 10-bit pixel formats if needed */
|
||||||
|
if (format == SDL_PIXELFORMAT_UNKNOWN && SDL_ISPIXELFORMAT_10BIT(fmt->format)) {
|
||||||
|
for (i = 0; i < (int)renderer->info.num_texture_formats; ++i) {
|
||||||
|
if (SDL_ISPIXELFORMAT_10BIT(renderer->info.texture_formats[i])) {
|
||||||
|
format = renderer->info.texture_formats[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Look for floating point pixel formats if needed */
|
/* Look for floating point pixel formats if needed */
|
||||||
if (format == SDL_PIXELFORMAT_UNKNOWN &&
|
if (format == SDL_PIXELFORMAT_UNKNOWN &&
|
||||||
(SDL_ISPIXELFORMAT_10BIT(fmt->format) || SDL_ISPIXELFORMAT_FLOAT(fmt->format))) {
|
(SDL_ISPIXELFORMAT_10BIT(fmt->format) || SDL_ISPIXELFORMAT_FLOAT(fmt->format))) {
|
||||||
|
@ -1455,17 +1540,29 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s
|
||||||
direct_update = SDL_FALSE;
|
direct_update = SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((SDL_COLORSPACETRANSFER(colorspace) == SDL_TRANSFER_CHARACTERISTICS_PQ && !SDL_ISPIXELFORMAT_10BIT(format)) ||
|
if ((SDL_COLORSPACETRANSFER(surface_colorspace) == SDL_TRANSFER_CHARACTERISTICS_PQ && !SDL_ISPIXELFORMAT_10BIT(format)) ||
|
||||||
colorspace == SDL_COLORSPACE_SCRGB) {
|
surface_colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
|
||||||
if (SDL_ISPIXELFORMAT_FLOAT(format)) {
|
if (SDL_ISPIXELFORMAT_FLOAT(format)) {
|
||||||
colorspace = SDL_COLORSPACE_SCRGB;
|
texture_colorspace = SDL_COLORSPACE_SRGB_LINEAR;
|
||||||
} else {
|
} else {
|
||||||
colorspace = SDL_COLORSPACE_SRGB;
|
texture_colorspace = SDL_COLORSPACE_SRGB;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (surface->flags & SDL_SURFACE_USES_PROPERTIES) {
|
||||||
|
surface_props = SDL_GetSurfaceProperties(surface);
|
||||||
|
} else {
|
||||||
|
surface_props = 0;
|
||||||
|
}
|
||||||
|
|
||||||
props = SDL_CreateProperties();
|
props = SDL_CreateProperties();
|
||||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER, colorspace);
|
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER, texture_colorspace);
|
||||||
|
if (surface_colorspace == texture_colorspace) {
|
||||||
|
SDL_SetFloatProperty(props, SDL_PROP_TEXTURE_CREATE_SDR_WHITE_POINT_FLOAT,
|
||||||
|
SDL_GetSurfaceSDRWhitePoint(surface, surface_colorspace));
|
||||||
|
}
|
||||||
|
SDL_SetFloatProperty(props, SDL_PROP_TEXTURE_CREATE_HDR_HEADROOM_FLOAT,
|
||||||
|
SDL_GetSurfaceHDRHeadroom(surface, surface_colorspace));
|
||||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER, format);
|
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER, format);
|
||||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_STATIC);
|
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_STATIC);
|
||||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, surface->w);
|
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, surface->w);
|
||||||
|
@ -1487,7 +1584,7 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s
|
||||||
SDL_Surface *temp = NULL;
|
SDL_Surface *temp = NULL;
|
||||||
|
|
||||||
/* Set up a destination surface for the texture update */
|
/* Set up a destination surface for the texture update */
|
||||||
temp = SDL_ConvertSurfaceFormatAndColorspace(surface, format, colorspace);
|
temp = SDL_ConvertSurfaceFormatAndColorspace(surface, format, texture_colorspace, surface_props);
|
||||||
if (temp) {
|
if (temp) {
|
||||||
SDL_UpdateTexture(texture, NULL, temp->pixels, temp->pitch);
|
SDL_UpdateTexture(texture, NULL, temp->pixels, temp->pitch);
|
||||||
SDL_DestroySurface(temp);
|
SDL_DestroySurface(temp);
|
||||||
|
@ -2888,7 +2985,7 @@ int SDL_SetRenderColorScale(SDL_Renderer *renderer, float scale)
|
||||||
{
|
{
|
||||||
CHECK_RENDERER_MAGIC(renderer, -1);
|
CHECK_RENDERER_MAGIC(renderer, -1);
|
||||||
|
|
||||||
renderer->color_scale = scale;
|
renderer->color_scale = scale * renderer->SDR_white_point;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2897,7 +2994,7 @@ int SDL_GetRenderColorScale(SDL_Renderer *renderer, float *scale)
|
||||||
CHECK_RENDERER_MAGIC(renderer, -1);
|
CHECK_RENDERER_MAGIC(renderer, -1);
|
||||||
|
|
||||||
if (scale) {
|
if (scale) {
|
||||||
*scale = renderer->color_scale;
|
*scale = renderer->color_scale / renderer->SDR_white_point;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -4229,6 +4326,7 @@ int SDL_RenderGeometryRaw(SDL_Renderer *renderer, SDL_Texture *texture, const fl
|
||||||
SDL_Surface *SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect)
|
SDL_Surface *SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect)
|
||||||
{
|
{
|
||||||
SDL_Rect real_rect;
|
SDL_Rect real_rect;
|
||||||
|
SDL_Surface *surface;
|
||||||
|
|
||||||
CHECK_RENDERER_MAGIC(renderer, NULL);
|
CHECK_RENDERER_MAGIC(renderer, NULL);
|
||||||
|
|
||||||
|
@ -4247,7 +4345,19 @@ SDL_Surface *SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return renderer->RenderReadPixels(renderer, &real_rect);
|
surface = renderer->RenderReadPixels(renderer, &real_rect);
|
||||||
|
if (surface) {
|
||||||
|
SDL_PropertiesID props = SDL_GetSurfaceProperties(surface);
|
||||||
|
|
||||||
|
if (renderer->target) {
|
||||||
|
SDL_SetFloatProperty(props, SDL_PROP_SURFACE_SDR_WHITE_POINT_FLOAT, renderer->target->SDR_white_point);
|
||||||
|
SDL_SetFloatProperty(props, SDL_PROP_SURFACE_HDR_HEADROOM_FLOAT, renderer->target->HDR_headroom);
|
||||||
|
} else {
|
||||||
|
SDL_SetFloatProperty(props, SDL_PROP_SURFACE_SDR_WHITE_POINT_FLOAT, renderer->SDR_white_point);
|
||||||
|
SDL_SetFloatProperty(props, SDL_PROP_SURFACE_HDR_HEADROOM_FLOAT, renderer->HDR_headroom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SDL_RenderApplyWindowShape(SDL_Renderer *renderer)
|
static void SDL_RenderApplyWindowShape(SDL_Renderer *renderer)
|
||||||
|
|
|
@ -64,6 +64,8 @@ struct SDL_Texture
|
||||||
{
|
{
|
||||||
const void *magic;
|
const void *magic;
|
||||||
SDL_Colorspace colorspace; /**< The colorspace of the texture */
|
SDL_Colorspace colorspace; /**< The colorspace of the texture */
|
||||||
|
float SDR_white_point; /**< The SDR white point for this content */
|
||||||
|
float HDR_headroom; /**< The HDR headroom needed by this content */
|
||||||
Uint32 format; /**< The pixel format of the texture */
|
Uint32 format; /**< The pixel format of the texture */
|
||||||
int access; /**< SDL_TextureAccess */
|
int access; /**< SDL_TextureAccess */
|
||||||
int w; /**< The width of the texture */
|
int w; /**< The width of the texture */
|
||||||
|
@ -254,6 +256,8 @@ struct SDL_Renderer
|
||||||
SDL_Mutex *target_mutex;
|
SDL_Mutex *target_mutex;
|
||||||
|
|
||||||
SDL_Colorspace output_colorspace;
|
SDL_Colorspace output_colorspace;
|
||||||
|
float SDR_white_point;
|
||||||
|
float HDR_headroom;
|
||||||
|
|
||||||
float color_scale;
|
float color_scale;
|
||||||
SDL_FColor color; /**< Color for drawing operations values */
|
SDL_FColor color; /**< Color for drawing operations values */
|
||||||
|
|
|
@ -246,12 +246,12 @@ static DXGI_FORMAT SDLPixelFormatToDXGITextureFormat(Uint32 format, Uint32 color
|
||||||
case SDL_PIXELFORMAT_RGBA64_FLOAT:
|
case SDL_PIXELFORMAT_RGBA64_FLOAT:
|
||||||
return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||||
case SDL_PIXELFORMAT_ARGB8888:
|
case SDL_PIXELFORMAT_ARGB8888:
|
||||||
if (colorspace == SDL_COLORSPACE_SCRGB) {
|
if (colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
|
||||||
return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
|
return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
|
||||||
}
|
}
|
||||||
return DXGI_FORMAT_B8G8R8A8_UNORM;
|
return DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||||
case SDL_PIXELFORMAT_XRGB8888:
|
case SDL_PIXELFORMAT_XRGB8888:
|
||||||
if (colorspace == SDL_COLORSPACE_SCRGB) {
|
if (colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
|
||||||
return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB;
|
return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB;
|
||||||
}
|
}
|
||||||
return DXGI_FORMAT_B8G8R8X8_UNORM;
|
return DXGI_FORMAT_B8G8R8X8_UNORM;
|
||||||
|
@ -276,12 +276,12 @@ static DXGI_FORMAT SDLPixelFormatToDXGIMainResourceViewFormat(Uint32 format, Uin
|
||||||
case SDL_PIXELFORMAT_RGBA64_FLOAT:
|
case SDL_PIXELFORMAT_RGBA64_FLOAT:
|
||||||
return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||||
case SDL_PIXELFORMAT_ARGB8888:
|
case SDL_PIXELFORMAT_ARGB8888:
|
||||||
if (colorspace == SDL_COLORSPACE_SCRGB) {
|
if (colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
|
||||||
return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
|
return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
|
||||||
}
|
}
|
||||||
return DXGI_FORMAT_B8G8R8A8_UNORM;
|
return DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||||
case SDL_PIXELFORMAT_XRGB8888:
|
case SDL_PIXELFORMAT_XRGB8888:
|
||||||
if (colorspace == SDL_COLORSPACE_SCRGB) {
|
if (colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
|
||||||
return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB;
|
return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB;
|
||||||
}
|
}
|
||||||
return DXGI_FORMAT_B8G8R8X8_UNORM;
|
return DXGI_FORMAT_B8G8R8X8_UNORM;
|
||||||
|
@ -880,7 +880,7 @@ static HRESULT D3D11_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
|
||||||
swapChainDesc.Width = w;
|
swapChainDesc.Width = w;
|
||||||
swapChainDesc.Height = h;
|
swapChainDesc.Height = h;
|
||||||
switch (renderer->output_colorspace) {
|
switch (renderer->output_colorspace) {
|
||||||
case SDL_COLORSPACE_SCRGB:
|
case SDL_COLORSPACE_SRGB_LINEAR:
|
||||||
swapChainDesc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT;
|
swapChainDesc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||||
break;
|
break;
|
||||||
case SDL_COLORSPACE_HDR10:
|
case SDL_COLORSPACE_HDR10:
|
||||||
|
@ -979,7 +979,7 @@ static HRESULT D3D11_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
|
||||||
UINT colorspace_support = 0;
|
UINT colorspace_support = 0;
|
||||||
DXGI_COLOR_SPACE_TYPE colorspace;
|
DXGI_COLOR_SPACE_TYPE colorspace;
|
||||||
switch (renderer->output_colorspace) {
|
switch (renderer->output_colorspace) {
|
||||||
case SDL_COLORSPACE_SCRGB:
|
case SDL_COLORSPACE_SRGB_LINEAR:
|
||||||
colorspace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
|
colorspace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
|
||||||
break;
|
break;
|
||||||
case SDL_COLORSPACE_HDR10:
|
case SDL_COLORSPACE_HDR10:
|
||||||
|
@ -2699,7 +2699,7 @@ SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_p
|
||||||
SDL_SetupRendererColorspace(renderer, create_props);
|
SDL_SetupRendererColorspace(renderer, create_props);
|
||||||
|
|
||||||
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB &&
|
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB &&
|
||||||
renderer->output_colorspace != SDL_COLORSPACE_SCRGB
|
renderer->output_colorspace != SDL_COLORSPACE_SRGB_LINEAR
|
||||||
/*&& renderer->output_colorspace != SDL_COLORSPACE_HDR10*/) {
|
/*&& renderer->output_colorspace != SDL_COLORSPACE_HDR10*/) {
|
||||||
SDL_SetError("Unsupported output colorspace");
|
SDL_SetError("Unsupported output colorspace");
|
||||||
SDL_free(renderer);
|
SDL_free(renderer);
|
||||||
|
|
|
@ -310,12 +310,12 @@ static DXGI_FORMAT SDLPixelFormatToDXGITextureFormat(Uint32 format, Uint32 color
|
||||||
case SDL_PIXELFORMAT_RGBA64_FLOAT:
|
case SDL_PIXELFORMAT_RGBA64_FLOAT:
|
||||||
return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||||
case SDL_PIXELFORMAT_ARGB8888:
|
case SDL_PIXELFORMAT_ARGB8888:
|
||||||
if (colorspace == SDL_COLORSPACE_SCRGB) {
|
if (colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
|
||||||
return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
|
return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
|
||||||
}
|
}
|
||||||
return DXGI_FORMAT_B8G8R8A8_UNORM;
|
return DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||||
case SDL_PIXELFORMAT_XRGB8888:
|
case SDL_PIXELFORMAT_XRGB8888:
|
||||||
if (colorspace == SDL_COLORSPACE_SCRGB) {
|
if (colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
|
||||||
return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB;
|
return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB;
|
||||||
}
|
}
|
||||||
return DXGI_FORMAT_B8G8R8X8_UNORM;
|
return DXGI_FORMAT_B8G8R8X8_UNORM;
|
||||||
|
@ -340,12 +340,12 @@ static DXGI_FORMAT SDLPixelFormatToDXGIMainResourceViewFormat(Uint32 format, Uin
|
||||||
case SDL_PIXELFORMAT_RGBA64_FLOAT:
|
case SDL_PIXELFORMAT_RGBA64_FLOAT:
|
||||||
return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||||
case SDL_PIXELFORMAT_ARGB8888:
|
case SDL_PIXELFORMAT_ARGB8888:
|
||||||
if (colorspace == SDL_COLORSPACE_SCRGB) {
|
if (colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
|
||||||
return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
|
return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
|
||||||
}
|
}
|
||||||
return DXGI_FORMAT_B8G8R8A8_UNORM;
|
return DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||||
case SDL_PIXELFORMAT_XRGB8888:
|
case SDL_PIXELFORMAT_XRGB8888:
|
||||||
if (colorspace == SDL_COLORSPACE_SCRGB) {
|
if (colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
|
||||||
return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB;
|
return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB;
|
||||||
}
|
}
|
||||||
return DXGI_FORMAT_B8G8R8X8_UNORM;
|
return DXGI_FORMAT_B8G8R8X8_UNORM;
|
||||||
|
@ -1218,7 +1218,7 @@ static HRESULT D3D12_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
|
||||||
swapChainDesc.Width = w;
|
swapChainDesc.Width = w;
|
||||||
swapChainDesc.Height = h;
|
swapChainDesc.Height = h;
|
||||||
switch (renderer->output_colorspace) {
|
switch (renderer->output_colorspace) {
|
||||||
case SDL_COLORSPACE_SCRGB:
|
case SDL_COLORSPACE_SRGB_LINEAR:
|
||||||
swapChainDesc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT;
|
swapChainDesc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||||
data->renderTargetFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
|
data->renderTargetFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||||
break;
|
break;
|
||||||
|
@ -1282,7 +1282,7 @@ static HRESULT D3D12_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
|
||||||
UINT colorspace_support = 0;
|
UINT colorspace_support = 0;
|
||||||
DXGI_COLOR_SPACE_TYPE colorspace;
|
DXGI_COLOR_SPACE_TYPE colorspace;
|
||||||
switch (renderer->output_colorspace) {
|
switch (renderer->output_colorspace) {
|
||||||
case SDL_COLORSPACE_SCRGB:
|
case SDL_COLORSPACE_SRGB_LINEAR:
|
||||||
colorspace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
|
colorspace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
|
||||||
break;
|
break;
|
||||||
case SDL_COLORSPACE_HDR10:
|
case SDL_COLORSPACE_HDR10:
|
||||||
|
@ -2985,11 +2985,7 @@ static SDL_Surface *D3D12_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rec
|
||||||
pitchedDesc.Width = (UINT)textureDesc.Width;
|
pitchedDesc.Width = (UINT)textureDesc.Width;
|
||||||
pitchedDesc.Height = textureDesc.Height;
|
pitchedDesc.Height = textureDesc.Height;
|
||||||
pitchedDesc.Depth = 1;
|
pitchedDesc.Depth = 1;
|
||||||
if (pitchedDesc.Format == DXGI_FORMAT_R8_UNORM) {
|
bpp = SDL_BYTESPERPIXEL(D3D12_DXGIFormatToSDLPixelFormat(pitchedDesc.Format));
|
||||||
bpp = 1;
|
|
||||||
} else {
|
|
||||||
bpp = 4;
|
|
||||||
}
|
|
||||||
pitchedDesc.RowPitch = D3D12_Align(pitchedDesc.Width * bpp, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
|
pitchedDesc.RowPitch = D3D12_Align(pitchedDesc.Width * bpp, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
|
||||||
|
|
||||||
SDL_zero(placedTextureDesc);
|
SDL_zero(placedTextureDesc);
|
||||||
|
@ -3155,7 +3151,7 @@ SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_p
|
||||||
SDL_SetupRendererColorspace(renderer, create_props);
|
SDL_SetupRendererColorspace(renderer, create_props);
|
||||||
|
|
||||||
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB &&
|
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB &&
|
||||||
renderer->output_colorspace != SDL_COLORSPACE_SCRGB
|
renderer->output_colorspace != SDL_COLORSPACE_SRGB_LINEAR
|
||||||
/*&& renderer->output_colorspace != SDL_COLORSPACE_HDR10*/) {
|
/*&& renderer->output_colorspace != SDL_COLORSPACE_HDR10*/) {
|
||||||
SDL_SetError("Unsupported output colorspace");
|
SDL_SetError("Unsupported output colorspace");
|
||||||
SDL_free(renderer);
|
SDL_free(renderer);
|
||||||
|
|
|
@ -652,14 +652,14 @@ static int METAL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL
|
||||||
|
|
||||||
switch (texture->format) {
|
switch (texture->format) {
|
||||||
case SDL_PIXELFORMAT_ABGR8888:
|
case SDL_PIXELFORMAT_ABGR8888:
|
||||||
if (renderer->output_colorspace == SDL_COLORSPACE_SCRGB) {
|
if (renderer->output_colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
|
||||||
pixfmt = MTLPixelFormatRGBA8Unorm_sRGB;
|
pixfmt = MTLPixelFormatRGBA8Unorm_sRGB;
|
||||||
} else {
|
} else {
|
||||||
pixfmt = MTLPixelFormatRGBA8Unorm;
|
pixfmt = MTLPixelFormatRGBA8Unorm;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SDL_PIXELFORMAT_ARGB8888:
|
case SDL_PIXELFORMAT_ARGB8888:
|
||||||
if (renderer->output_colorspace == SDL_COLORSPACE_SCRGB) {
|
if (renderer->output_colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
|
||||||
pixfmt = MTLPixelFormatBGRA8Unorm_sRGB;
|
pixfmt = MTLPixelFormatBGRA8Unorm_sRGB;
|
||||||
} else {
|
} else {
|
||||||
pixfmt = MTLPixelFormatBGRA8Unorm;
|
pixfmt = MTLPixelFormatBGRA8Unorm;
|
||||||
|
@ -1895,7 +1895,7 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, SDL_PropertiesID c
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
|
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
|
||||||
if (renderer->output_colorspace == SDL_COLORSPACE_SCRGB && scRGB_supported) {
|
if (renderer->output_colorspace == SDL_COLORSPACE_SRGB_LINEAR && scRGB_supported) {
|
||||||
/* This colorspace is supported */
|
/* This colorspace is supported */
|
||||||
} else {
|
} else {
|
||||||
SDL_SetError("Unsupported output colorspace");
|
SDL_SetError("Unsupported output colorspace");
|
||||||
|
@ -1963,7 +1963,7 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, SDL_PropertiesID c
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SDL_PLATFORM_TVOS
|
#ifndef SDL_PLATFORM_TVOS
|
||||||
if (renderer->output_colorspace == SDL_COLORSPACE_SCRGB) {
|
if (renderer->output_colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
|
||||||
if (@available(macos 10.11, iOS 16.0, *)) {
|
if (@available(macos 10.11, iOS 16.0, *)) {
|
||||||
layer.wantsExtendedDynamicRangeContent = YES;
|
layer.wantsExtendedDynamicRangeContent = YES;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -370,7 +370,7 @@ static Uint16 float_to_half(float a)
|
||||||
return ir;
|
return ir;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ReadFloatPixel(Uint8 *pixels, SlowBlitPixelAccess access, SDL_PixelFormat *fmt, SDL_Colorspace colorspace,
|
static void ReadFloatPixel(Uint8 *pixels, SlowBlitPixelAccess access, SDL_PixelFormat *fmt, SDL_Colorspace colorspace, float SDR_white_point,
|
||||||
float *outR, float *outG, float *outB, float *outA)
|
float *outR, float *outG, float *outB, float *outA)
|
||||||
{
|
{
|
||||||
Uint32 pixel;
|
Uint32 pixel;
|
||||||
|
@ -500,20 +500,19 @@ static void ReadFloatPixel(Uint8 *pixels, SlowBlitPixelAccess access, SDL_PixelF
|
||||||
/* Convert to nits so src and dst are guaranteed to be linear and in the same units */
|
/* Convert to nits so src and dst are guaranteed to be linear and in the same units */
|
||||||
switch (SDL_COLORSPACETRANSFER(colorspace)) {
|
switch (SDL_COLORSPACETRANSFER(colorspace)) {
|
||||||
case SDL_TRANSFER_CHARACTERISTICS_SRGB:
|
case SDL_TRANSFER_CHARACTERISTICS_SRGB:
|
||||||
fR = SDL_sRGBtoNits(fR);
|
fR = SDL_sRGBtoLinear(fR);
|
||||||
fG = SDL_sRGBtoNits(fG);
|
fG = SDL_sRGBtoLinear(fG);
|
||||||
fB = SDL_sRGBtoNits(fB);
|
fB = SDL_sRGBtoLinear(fB);
|
||||||
break;
|
break;
|
||||||
case SDL_TRANSFER_CHARACTERISTICS_PQ:
|
case SDL_TRANSFER_CHARACTERISTICS_PQ:
|
||||||
fR = SDL_PQtoNits(fR);
|
fR = SDL_PQtoNits(fR) / SDR_white_point;
|
||||||
fG = SDL_PQtoNits(fG);
|
fG = SDL_PQtoNits(fG) / SDR_white_point;
|
||||||
fB = SDL_PQtoNits(fB);
|
fB = SDL_PQtoNits(fB) / SDR_white_point;
|
||||||
break;
|
break;
|
||||||
case SDL_TRANSFER_CHARACTERISTICS_LINEAR:
|
case SDL_TRANSFER_CHARACTERISTICS_LINEAR:
|
||||||
/* Assuming scRGB for now */
|
fR /= SDR_white_point;
|
||||||
fR = SDL_scRGBtoNits(fR);
|
fG /= SDR_white_point;
|
||||||
fG = SDL_scRGBtoNits(fG);
|
fB /= SDR_white_point;
|
||||||
fB = SDL_scRGBtoNits(fB);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Unknown, leave it alone */
|
/* Unknown, leave it alone */
|
||||||
|
@ -526,7 +525,7 @@ static void ReadFloatPixel(Uint8 *pixels, SlowBlitPixelAccess access, SDL_PixelF
|
||||||
*outA = fA;
|
*outA = fA;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteFloatPixel(Uint8 *pixels, SlowBlitPixelAccess access, SDL_PixelFormat *fmt, SDL_Colorspace colorspace,
|
static void WriteFloatPixel(Uint8 *pixels, SlowBlitPixelAccess access, SDL_PixelFormat *fmt, SDL_Colorspace colorspace, float SDR_white_point,
|
||||||
float fR, float fG, float fB, float fA)
|
float fR, float fG, float fB, float fA)
|
||||||
{
|
{
|
||||||
Uint32 R, G, B, A;
|
Uint32 R, G, B, A;
|
||||||
|
@ -535,20 +534,19 @@ static void WriteFloatPixel(Uint8 *pixels, SlowBlitPixelAccess access, SDL_Pixel
|
||||||
/* We converted to nits so src and dst are guaranteed to be linear and in the same units */
|
/* We converted to nits so src and dst are guaranteed to be linear and in the same units */
|
||||||
switch (SDL_COLORSPACETRANSFER(colorspace)) {
|
switch (SDL_COLORSPACETRANSFER(colorspace)) {
|
||||||
case SDL_TRANSFER_CHARACTERISTICS_SRGB:
|
case SDL_TRANSFER_CHARACTERISTICS_SRGB:
|
||||||
fR = SDL_sRGBfromNits(fR);
|
fR = SDL_sRGBfromLinear(fR);
|
||||||
fG = SDL_sRGBfromNits(fG);
|
fG = SDL_sRGBfromLinear(fG);
|
||||||
fB = SDL_sRGBfromNits(fB);
|
fB = SDL_sRGBfromLinear(fB);
|
||||||
break;
|
break;
|
||||||
case SDL_TRANSFER_CHARACTERISTICS_PQ:
|
case SDL_TRANSFER_CHARACTERISTICS_PQ:
|
||||||
fR = SDL_PQfromNits(fR);
|
fR = SDL_PQfromNits(fR * SDR_white_point);
|
||||||
fG = SDL_PQfromNits(fG);
|
fG = SDL_PQfromNits(fG * SDR_white_point);
|
||||||
fB = SDL_PQfromNits(fB);
|
fB = SDL_PQfromNits(fB * SDR_white_point);
|
||||||
break;
|
break;
|
||||||
case SDL_TRANSFER_CHARACTERISTICS_LINEAR:
|
case SDL_TRANSFER_CHARACTERISTICS_LINEAR:
|
||||||
/* Assuming scRGB for now */
|
fR *= SDR_white_point;
|
||||||
fR = SDL_scRGBfromNits(fR);
|
fG *= SDR_white_point;
|
||||||
fG = SDL_scRGBfromNits(fG);
|
fB *= SDR_white_point;
|
||||||
fB = SDL_scRGBfromNits(fB);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Unknown, leave it alone */
|
/* Unknown, leave it alone */
|
||||||
|
@ -672,6 +670,7 @@ typedef enum
|
||||||
{
|
{
|
||||||
SDL_TONEMAP_NONE,
|
SDL_TONEMAP_NONE,
|
||||||
SDL_TONEMAP_LINEAR,
|
SDL_TONEMAP_LINEAR,
|
||||||
|
SDL_TONEMAP_PIECEWISE_HDR,
|
||||||
} SDL_TonemapOperator;
|
} SDL_TonemapOperator;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -682,6 +681,11 @@ typedef struct
|
||||||
struct {
|
struct {
|
||||||
float scale;
|
float scale;
|
||||||
} linear;
|
} linear;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
float scale;
|
||||||
|
} piecewise_HDR;
|
||||||
} data;
|
} data;
|
||||||
|
|
||||||
} SDL_TonemapContext;
|
} SDL_TonemapContext;
|
||||||
|
@ -694,6 +698,11 @@ static void ApplyTonemap(SDL_TonemapContext *ctx, float *r, float *g, float *b)
|
||||||
*g *= ctx->data.linear.scale;
|
*g *= ctx->data.linear.scale;
|
||||||
*b *= ctx->data.linear.scale;
|
*b *= ctx->data.linear.scale;
|
||||||
break;
|
break;
|
||||||
|
case SDL_TONEMAP_PIECEWISE_HDR:
|
||||||
|
*r = (*r <= 1.0f) ? *r : (1.0f + (*r - 1.0f) * ctx->data.piecewise_HDR.scale);
|
||||||
|
*g = (*g <= 1.0f) ? *g : (1.0f + (*g - 1.0f) * ctx->data.piecewise_HDR.scale);
|
||||||
|
*b = (*r <= 1.0f) ? *b : (1.0f + (*b - 1.0f) * ctx->data.piecewise_HDR.scale);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -701,7 +710,7 @@ static void ApplyTonemap(SDL_TonemapContext *ctx, float *r, float *g, float *b)
|
||||||
|
|
||||||
static SDL_bool IsHDRColorspace(SDL_Colorspace colorspace)
|
static SDL_bool IsHDRColorspace(SDL_Colorspace colorspace)
|
||||||
{
|
{
|
||||||
if (colorspace == SDL_COLORSPACE_SCRGB ||
|
if (colorspace == SDL_COLORSPACE_SRGB_LINEAR ||
|
||||||
SDL_COLORSPACETRANSFER(colorspace) == SDL_TRANSFER_CHARACTERISTICS_PQ) {
|
SDL_COLORSPACETRANSFER(colorspace) == SDL_TRANSFER_CHARACTERISTICS_PQ) {
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
@ -732,6 +741,8 @@ void SDL_Blit_Slow_Float(SDL_BlitInfo *info)
|
||||||
SDL_Colorspace src_colorspace;
|
SDL_Colorspace src_colorspace;
|
||||||
SDL_Colorspace dst_colorspace;
|
SDL_Colorspace dst_colorspace;
|
||||||
const float *color_primaries_matrix = NULL;
|
const float *color_primaries_matrix = NULL;
|
||||||
|
float SDR_white_point_src = 1.0f;
|
||||||
|
float SDR_white_point_dst = 1.0f;
|
||||||
SDL_TonemapContext tonemap;
|
SDL_TonemapContext tonemap;
|
||||||
|
|
||||||
if (SDL_GetSurfaceColorspace(info->src_surface, &src_colorspace) < 0 ||
|
if (SDL_GetSurfaceColorspace(info->src_surface, &src_colorspace) < 0 ||
|
||||||
|
@ -756,6 +767,9 @@ void SDL_Blit_Slow_Float(SDL_BlitInfo *info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDR_white_point_src = SDL_GetSurfaceSDRWhitePoint(info->src_surface, src_colorspace);
|
||||||
|
SDR_white_point_dst = SDL_GetSurfaceSDRWhitePoint(info->dst_surface, dst_colorspace);
|
||||||
|
|
||||||
src_access = GetPixelAccessMethod(src_fmt);
|
src_access = GetPixelAccessMethod(src_fmt);
|
||||||
dst_access = GetPixelAccessMethod(dst_fmt);
|
dst_access = GetPixelAccessMethod(dst_fmt);
|
||||||
|
|
||||||
|
@ -773,7 +787,7 @@ void SDL_Blit_Slow_Float(SDL_BlitInfo *info)
|
||||||
srcx = posx >> 16;
|
srcx = posx >> 16;
|
||||||
src = (info->src + (srcy * info->src_pitch) + (srcx * srcbpp));
|
src = (info->src + (srcy * info->src_pitch) + (srcx * srcbpp));
|
||||||
|
|
||||||
ReadFloatPixel(src, src_access, src_fmt, src_colorspace, &srcR, &srcG, &srcB, &srcA);
|
ReadFloatPixel(src, src_access, src_fmt, src_colorspace, SDR_white_point_src, &srcR, &srcG, &srcB, &srcA);
|
||||||
|
|
||||||
if (color_primaries_matrix) {
|
if (color_primaries_matrix) {
|
||||||
SDL_ConvertColorPrimaries(&srcR, &srcG, &srcB, color_primaries_matrix);
|
SDL_ConvertColorPrimaries(&srcR, &srcG, &srcB, color_primaries_matrix);
|
||||||
|
@ -787,7 +801,7 @@ void SDL_Blit_Slow_Float(SDL_BlitInfo *info)
|
||||||
/* colorkey isn't supported */
|
/* colorkey isn't supported */
|
||||||
}
|
}
|
||||||
if ((flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL))) {
|
if ((flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL))) {
|
||||||
ReadFloatPixel(dst, dst_access, dst_fmt, dst_colorspace, &dstR, &dstG, &dstB, &dstA);
|
ReadFloatPixel(dst, dst_access, dst_fmt, dst_colorspace, SDR_white_point_dst, &dstR, &dstG, &dstB, &dstA);
|
||||||
} else {
|
} else {
|
||||||
/* don't care */
|
/* don't care */
|
||||||
dstR = dstG = dstB = dstA = 0.0f;
|
dstR = dstG = dstB = dstA = 0.0f;
|
||||||
|
@ -839,7 +853,7 @@ void SDL_Blit_Slow_Float(SDL_BlitInfo *info)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteFloatPixel(dst, dst_access, dst_fmt, dst_colorspace, dstR, dstG, dstB, dstA);
|
WriteFloatPixel(dst, dst_access, dst_fmt, dst_colorspace, SDR_white_point_dst, dstR, dstG, dstB, dstA);
|
||||||
|
|
||||||
posx += incx;
|
posx += incx;
|
||||||
dst += dstbpp;
|
dst += dstbpp;
|
||||||
|
|
|
@ -706,7 +706,7 @@ SDL_Colorspace SDL_GetDefaultColorspaceForFormat(Uint32 format)
|
||||||
if (SDL_ISPIXELFORMAT_FOURCC(format)) {
|
if (SDL_ISPIXELFORMAT_FOURCC(format)) {
|
||||||
return SDL_COLORSPACE_YUV_DEFAULT;
|
return SDL_COLORSPACE_YUV_DEFAULT;
|
||||||
} else if (SDL_ISPIXELFORMAT_FLOAT(format)) {
|
} else if (SDL_ISPIXELFORMAT_FLOAT(format)) {
|
||||||
return SDL_COLORSPACE_SCRGB;
|
return SDL_COLORSPACE_SRGB_LINEAR;
|
||||||
} else if (SDL_ISPIXELFORMAT_10BIT(format)) {
|
} else if (SDL_ISPIXELFORMAT_10BIT(format)) {
|
||||||
return SDL_COLORSPACE_HDR10;
|
return SDL_COLORSPACE_HDR10;
|
||||||
} else {
|
} else {
|
||||||
|
@ -714,30 +714,18 @@ SDL_Colorspace SDL_GetDefaultColorspaceForFormat(Uint32 format)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float SDL_scRGBtoNits(float v)
|
float SDL_sRGBtoLinear(float v)
|
||||||
{
|
|
||||||
return v * 80.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
float SDL_scRGBfromNits(float v)
|
|
||||||
{
|
|
||||||
return v / 80.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
float SDL_sRGBtoNits(float v)
|
|
||||||
{
|
{
|
||||||
if (v <= 0.04045f) {
|
if (v <= 0.04045f) {
|
||||||
v = (v / 12.92f);
|
v = (v / 12.92f);
|
||||||
} else {
|
} else {
|
||||||
v = SDL_powf((v + 0.055f) / 1.055f, 2.4f);
|
v = SDL_powf((v + 0.055f) / 1.055f, 2.4f);
|
||||||
}
|
}
|
||||||
return SDL_scRGBtoNits(v);
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
float SDL_sRGBfromNits(float v)
|
float SDL_sRGBfromLinear(float v)
|
||||||
{
|
{
|
||||||
v = SDL_scRGBfromNits(v);
|
|
||||||
|
|
||||||
if (v <= 0.0031308f) {
|
if (v <= 0.0031308f) {
|
||||||
v = (v * 12.92f);
|
v = (v * 12.92f);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -34,10 +34,8 @@ extern int SDL_CalculateSize(Uint32 format, int width, int height, size_t *size,
|
||||||
extern SDL_Colorspace SDL_GetDefaultColorspaceForFormat(Uint32 pixel_format);
|
extern SDL_Colorspace SDL_GetDefaultColorspaceForFormat(Uint32 pixel_format);
|
||||||
|
|
||||||
/* Colorspace conversion functions */
|
/* Colorspace conversion functions */
|
||||||
extern float SDL_scRGBtoNits(float v);
|
extern float SDL_sRGBtoLinear(float v);
|
||||||
extern float SDL_scRGBfromNits(float v);
|
extern float SDL_sRGBfromLinear(float v);
|
||||||
extern float SDL_sRGBtoNits(float v);
|
|
||||||
extern float SDL_sRGBfromNits(float v);
|
|
||||||
extern float SDL_PQtoNits(float v);
|
extern float SDL_PQtoNits(float v);
|
||||||
extern float SDL_PQfromNits(float v);
|
extern float SDL_PQfromNits(float v);
|
||||||
extern const float *SDL_GetYCbCRtoRGBConversionMatrix(SDL_Colorspace colorspace, int w, int h, int bits_per_pixel);
|
extern const float *SDL_GetYCbCRtoRGBConversionMatrix(SDL_Colorspace colorspace, int w, int h, int bits_per_pixel);
|
||||||
|
@ -52,6 +50,10 @@ extern void SDL_FreeBlitMap(SDL_BlitMap *map);
|
||||||
|
|
||||||
extern void SDL_InvalidateAllBlitMap(SDL_Surface *surface);
|
extern void SDL_InvalidateAllBlitMap(SDL_Surface *surface);
|
||||||
|
|
||||||
|
/* Surface functions */
|
||||||
|
extern float SDL_GetSurfaceSDRWhitePoint(SDL_Surface *surface, SDL_Colorspace colorspace);
|
||||||
|
extern float SDL_GetSurfaceHDRHeadroom(SDL_Surface *surface, SDL_Colorspace colorspace);
|
||||||
|
|
||||||
/* Miscellaneous functions */
|
/* Miscellaneous functions */
|
||||||
extern void SDL_DitherColors(SDL_Color *colors, int bpp);
|
extern void SDL_DitherColors(SDL_Color *colors, int bpp);
|
||||||
extern Uint8 SDL_FindColor(SDL_Palette *pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
|
extern Uint8 SDL_FindColor(SDL_Palette *pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
|
||||||
|
|
|
@ -303,6 +303,52 @@ int SDL_GetSurfaceColorspace(SDL_Surface *surface, SDL_Colorspace *colorspace)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float SDL_GetSurfaceSDRWhitePoint(SDL_Surface *surface, SDL_Colorspace colorspace)
|
||||||
|
{
|
||||||
|
SDL_TransferCharacteristics transfer = SDL_COLORSPACETRANSFER(colorspace);
|
||||||
|
|
||||||
|
if (transfer == SDL_TRANSFER_CHARACTERISTICS_LINEAR ||
|
||||||
|
transfer == SDL_TRANSFER_CHARACTERISTICS_PQ) {
|
||||||
|
SDL_PropertiesID props;
|
||||||
|
float default_value = 1.0f;
|
||||||
|
|
||||||
|
if (surface->flags & SDL_SURFACE_USES_PROPERTIES) {
|
||||||
|
props = SDL_GetSurfaceProperties(surface);
|
||||||
|
} else {
|
||||||
|
props = 0;
|
||||||
|
}
|
||||||
|
if (transfer == SDL_TRANSFER_CHARACTERISTICS_PQ) {
|
||||||
|
const float DEFAULT_PQ_SDR_WHITE_POINT = 100.0f;
|
||||||
|
default_value = DEFAULT_PQ_SDR_WHITE_POINT;
|
||||||
|
}
|
||||||
|
return SDL_GetFloatProperty(props, SDL_PROP_SURFACE_SDR_WHITE_POINT_FLOAT, default_value);
|
||||||
|
}
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float SDL_GetSurfaceHDRHeadroom(SDL_Surface *surface, SDL_Colorspace colorspace)
|
||||||
|
{
|
||||||
|
SDL_TransferCharacteristics transfer = SDL_COLORSPACETRANSFER(colorspace);
|
||||||
|
|
||||||
|
if (transfer == SDL_TRANSFER_CHARACTERISTICS_LINEAR ||
|
||||||
|
transfer == SDL_TRANSFER_CHARACTERISTICS_PQ) {
|
||||||
|
SDL_PropertiesID props;
|
||||||
|
float default_value = 0.0f;
|
||||||
|
|
||||||
|
if (surface->flags & SDL_SURFACE_USES_PROPERTIES) {
|
||||||
|
props = SDL_GetSurfaceProperties(surface);
|
||||||
|
} else {
|
||||||
|
props = 0;
|
||||||
|
}
|
||||||
|
if (transfer == SDL_TRANSFER_CHARACTERISTICS_PQ &&
|
||||||
|
SDL_HasProperty(props, SDL_PROP_SURFACE_MAXCLL_NUMBER)) {
|
||||||
|
default_value = (float)SDL_GetNumberProperty(props, SDL_PROP_SURFACE_MAXCLL_NUMBER, 0) / SDL_GetSurfaceSDRWhitePoint(surface, colorspace);
|
||||||
|
}
|
||||||
|
return SDL_GetFloatProperty(props, SDL_PROP_SURFACE_HDR_HEADROOM_FLOAT, default_value);
|
||||||
|
}
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
int SDL_SetSurfacePalette(SDL_Surface *surface, SDL_Palette *palette)
|
int SDL_SetSurfacePalette(SDL_Surface *surface, SDL_Palette *palette)
|
||||||
{
|
{
|
||||||
if (!surface) {
|
if (!surface) {
|
||||||
|
@ -1193,10 +1239,11 @@ int SDL_FlipSurface(SDL_Surface *surface, SDL_FlipMode flip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_Surface *SDL_ConvertSurfaceWithPixelFormatAndColorspace(SDL_Surface *surface, const SDL_PixelFormat *format, Uint32 colorspace)
|
static SDL_Surface *SDL_ConvertSurfaceWithPixelFormatAndColorspace(SDL_Surface *surface, const SDL_PixelFormat *format, Uint32 colorspace, SDL_PropertiesID props)
|
||||||
{
|
{
|
||||||
SDL_Surface *convert;
|
SDL_Surface *convert;
|
||||||
SDL_Colorspace src_colorspace;
|
SDL_Colorspace src_colorspace;
|
||||||
|
SDL_PropertiesID src_properties;
|
||||||
Uint32 copy_flags;
|
Uint32 copy_flags;
|
||||||
SDL_Color copy_color;
|
SDL_Color copy_color;
|
||||||
SDL_Rect bounds;
|
SDL_Rect bounds;
|
||||||
|
@ -1234,6 +1281,12 @@ static SDL_Surface *SDL_ConvertSurfaceWithPixelFormatAndColorspace(SDL_Surface *
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (surface->flags & SDL_SURFACE_USES_PROPERTIES) {
|
||||||
|
src_properties = SDL_GetSurfaceProperties(surface);
|
||||||
|
} else {
|
||||||
|
src_properties = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create a new surface with the desired format */
|
/* Create a new surface with the desired format */
|
||||||
convert = SDL_CreateSurface(surface->w, surface->h, format->format);
|
convert = SDL_CreateSurface(surface->w, surface->h, format->format);
|
||||||
if (!convert) {
|
if (!convert) {
|
||||||
|
@ -1246,7 +1299,7 @@ static SDL_Surface *SDL_ConvertSurfaceWithPixelFormatAndColorspace(SDL_Surface *
|
||||||
SDL_SetSurfaceColorspace(convert, colorspace);
|
SDL_SetSurfaceColorspace(convert, colorspace);
|
||||||
|
|
||||||
if (SDL_ISPIXELFORMAT_FOURCC(format->format) || SDL_ISPIXELFORMAT_FOURCC(surface->format->format)) {
|
if (SDL_ISPIXELFORMAT_FOURCC(format->format) || SDL_ISPIXELFORMAT_FOURCC(surface->format->format)) {
|
||||||
if (SDL_ConvertPixelsAndColorspace(surface->w, surface->h, surface->format->format, src_colorspace, surface->pixels, surface->pitch, convert->format->format, colorspace, convert->pixels, convert->pitch) < 0) {
|
if (SDL_ConvertPixelsAndColorspace(surface->w, surface->h, surface->format->format, src_colorspace, src_properties, surface->pixels, surface->pitch, convert->format->format, colorspace, props, convert->pixels, convert->pitch) < 0) {
|
||||||
SDL_DestroySurface(convert);
|
SDL_DestroySurface(convert);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1411,7 +1464,7 @@ static SDL_Surface *SDL_ConvertSurfaceWithPixelFormatAndColorspace(SDL_Surface *
|
||||||
tmp->map->info.flags &= ~SDL_COPY_COLORKEY;
|
tmp->map->info.flags &= ~SDL_COPY_COLORKEY;
|
||||||
|
|
||||||
/* Conversion of the colorkey */
|
/* Conversion of the colorkey */
|
||||||
tmp2 = SDL_ConvertSurfaceWithPixelFormatAndColorspace(tmp, format, colorspace);
|
tmp2 = SDL_ConvertSurfaceWithPixelFormatAndColorspace(tmp, format, colorspace, props);
|
||||||
if (!tmp2) {
|
if (!tmp2) {
|
||||||
SDL_DestroySurface(tmp);
|
SDL_DestroySurface(tmp);
|
||||||
SDL_DestroySurface(convert);
|
SDL_DestroySurface(convert);
|
||||||
|
@ -1460,7 +1513,7 @@ SDL_Surface *SDL_DuplicateSurface(SDL_Surface *surface)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SDL_ConvertSurfaceWithPixelFormatAndColorspace(surface, surface->format, SDL_COLORSPACE_UNKNOWN);
|
return SDL_ConvertSurfaceWithPixelFormatAndColorspace(surface, surface->format, SDL_COLORSPACE_UNKNOWN, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Surface *SDL_ConvertSurface(SDL_Surface *surface, const SDL_PixelFormat *format)
|
SDL_Surface *SDL_ConvertSurface(SDL_Surface *surface, const SDL_PixelFormat *format)
|
||||||
|
@ -1479,12 +1532,13 @@ SDL_Surface *SDL_ConvertSurface(SDL_Surface *surface, const SDL_PixelFormat *for
|
||||||
|
|
||||||
colorspace = SDL_GetDefaultColorspaceForFormat(format->format);
|
colorspace = SDL_GetDefaultColorspaceForFormat(format->format);
|
||||||
|
|
||||||
return SDL_ConvertSurfaceWithPixelFormatAndColorspace(surface, format, colorspace);
|
return SDL_ConvertSurfaceWithPixelFormatAndColorspace(surface, format, colorspace, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Surface *SDL_ConvertSurfaceFormat(SDL_Surface *surface, Uint32 pixel_format)
|
SDL_Surface *SDL_ConvertSurfaceFormat(SDL_Surface *surface, Uint32 pixel_format)
|
||||||
{
|
{
|
||||||
SDL_Colorspace colorspace;
|
SDL_Colorspace colorspace;
|
||||||
|
SDL_PropertiesID props;
|
||||||
|
|
||||||
if (!surface) {
|
if (!surface) {
|
||||||
SDL_InvalidParamError("surface");
|
SDL_InvalidParamError("surface");
|
||||||
|
@ -1493,17 +1547,23 @@ SDL_Surface *SDL_ConvertSurfaceFormat(SDL_Surface *surface, Uint32 pixel_format)
|
||||||
|
|
||||||
colorspace = SDL_GetDefaultColorspaceForFormat(pixel_format);
|
colorspace = SDL_GetDefaultColorspaceForFormat(pixel_format);
|
||||||
|
|
||||||
return SDL_ConvertSurfaceFormatAndColorspace(surface, pixel_format, colorspace);
|
if (surface->flags & SDL_SURFACE_USES_PROPERTIES) {
|
||||||
|
props = SDL_GetSurfaceProperties(surface);
|
||||||
|
} else {
|
||||||
|
props = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Surface *SDL_ConvertSurfaceFormatAndColorspace(SDL_Surface *surface, Uint32 pixel_format, SDL_Colorspace colorspace)
|
return SDL_ConvertSurfaceFormatAndColorspace(surface, pixel_format, colorspace, props);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Surface *SDL_ConvertSurfaceFormatAndColorspace(SDL_Surface *surface, Uint32 pixel_format, SDL_Colorspace colorspace, SDL_PropertiesID props)
|
||||||
{
|
{
|
||||||
SDL_PixelFormat *format;
|
SDL_PixelFormat *format;
|
||||||
SDL_Surface *convert = NULL;
|
SDL_Surface *convert = NULL;
|
||||||
|
|
||||||
format = SDL_CreatePixelFormat(pixel_format);
|
format = SDL_CreatePixelFormat(pixel_format);
|
||||||
if (format) {
|
if (format) {
|
||||||
convert = SDL_ConvertSurfaceWithPixelFormatAndColorspace(surface, format, colorspace);
|
convert = SDL_ConvertSurfaceWithPixelFormatAndColorspace(surface, format, colorspace, props);
|
||||||
SDL_DestroyPixelFormat(format);
|
SDL_DestroyPixelFormat(format);
|
||||||
}
|
}
|
||||||
return convert;
|
return convert;
|
||||||
|
@ -1512,7 +1572,7 @@ SDL_Surface *SDL_ConvertSurfaceFormatAndColorspace(SDL_Surface *surface, Uint32
|
||||||
/*
|
/*
|
||||||
* Create a surface on the stack for quick blit operations
|
* Create a surface on the stack for quick blit operations
|
||||||
*/
|
*/
|
||||||
static SDL_bool SDL_CreateSurfaceOnStack(int width, int height, Uint32 pixel_format, SDL_Colorspace colorspace, void *pixels, int pitch, SDL_Surface *surface, SDL_PixelFormat *format, SDL_BlitMap *blitmap)
|
static SDL_bool SDL_CreateSurfaceOnStack(int width, int height, Uint32 pixel_format, SDL_Colorspace colorspace, SDL_PropertiesID props, void *pixels, int pitch, SDL_Surface *surface, SDL_PixelFormat *format, SDL_BlitMap *blitmap)
|
||||||
{
|
{
|
||||||
if (SDL_ISPIXELFORMAT_INDEXED(pixel_format)) {
|
if (SDL_ISPIXELFORMAT_INDEXED(pixel_format)) {
|
||||||
SDL_SetError("Indexed pixel formats not supported");
|
SDL_SetError("Indexed pixel formats not supported");
|
||||||
|
@ -1542,6 +1602,13 @@ static SDL_bool SDL_CreateSurfaceOnStack(int width, int height, Uint32 pixel_for
|
||||||
|
|
||||||
SDL_SetSurfaceColorspace(surface, colorspace);
|
SDL_SetSurfaceColorspace(surface, colorspace);
|
||||||
|
|
||||||
|
if (props) {
|
||||||
|
SDL_PropertiesID surface_props = SDL_GetSurfaceProperties(surface);
|
||||||
|
if (SDL_CopyProperties(props, surface_props) < 0) {
|
||||||
|
return SDL_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* The surface is ready to go */
|
/* The surface is ready to go */
|
||||||
surface->refcount = 1;
|
surface->refcount = 1;
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
|
@ -1577,8 +1644,8 @@ SDL_Surface *SDL_DuplicatePixels(int width, int height, Uint32 format, SDL_Color
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDL_ConvertPixelsAndColorspace(int width, int height,
|
int SDL_ConvertPixelsAndColorspace(int width, int height,
|
||||||
Uint32 src_format, SDL_Colorspace src_colorspace, const void *src, int src_pitch,
|
Uint32 src_format, SDL_Colorspace src_colorspace, SDL_PropertiesID src_properties, const void *src, int src_pitch,
|
||||||
Uint32 dst_format, SDL_Colorspace dst_colorspace, void *dst, int dst_pitch)
|
Uint32 dst_format, SDL_Colorspace dst_colorspace, SDL_PropertiesID dst_properties, void *dst, int dst_pitch)
|
||||||
{
|
{
|
||||||
SDL_Surface src_surface, dst_surface;
|
SDL_Surface src_surface, dst_surface;
|
||||||
SDL_PixelFormat src_fmt, dst_fmt;
|
SDL_PixelFormat src_fmt, dst_fmt;
|
||||||
|
@ -1609,11 +1676,11 @@ int SDL_ConvertPixelsAndColorspace(int width, int height,
|
||||||
|
|
||||||
#if SDL_HAVE_YUV
|
#if SDL_HAVE_YUV
|
||||||
if (SDL_ISPIXELFORMAT_FOURCC(src_format) && SDL_ISPIXELFORMAT_FOURCC(dst_format)) {
|
if (SDL_ISPIXELFORMAT_FOURCC(src_format) && SDL_ISPIXELFORMAT_FOURCC(dst_format)) {
|
||||||
return SDL_ConvertPixels_YUV_to_YUV(width, height, src_format, src_colorspace, src, src_pitch, dst_format, dst_colorspace, dst, dst_pitch);
|
return SDL_ConvertPixels_YUV_to_YUV(width, height, src_format, src_colorspace, src_properties, src, src_pitch, dst_format, dst_colorspace, dst_properties, dst, dst_pitch);
|
||||||
} else if (SDL_ISPIXELFORMAT_FOURCC(src_format)) {
|
} else if (SDL_ISPIXELFORMAT_FOURCC(src_format)) {
|
||||||
return SDL_ConvertPixels_YUV_to_RGB(width, height, src_format, src_colorspace, src, src_pitch, dst_format, dst_colorspace, dst, dst_pitch);
|
return SDL_ConvertPixels_YUV_to_RGB(width, height, src_format, src_colorspace, src_properties, src, src_pitch, dst_format, dst_colorspace, dst_properties, dst, dst_pitch);
|
||||||
} else if (SDL_ISPIXELFORMAT_FOURCC(dst_format)) {
|
} else if (SDL_ISPIXELFORMAT_FOURCC(dst_format)) {
|
||||||
return SDL_ConvertPixels_RGB_to_YUV(width, height, src_format, src_colorspace, src, src_pitch, dst_format, dst_colorspace, dst, dst_pitch);
|
return SDL_ConvertPixels_RGB_to_YUV(width, height, src_format, src_colorspace, src_properties, src, src_pitch, dst_format, dst_colorspace, dst_properties, dst, dst_pitch);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (SDL_ISPIXELFORMAT_FOURCC(src_format) || SDL_ISPIXELFORMAT_FOURCC(dst_format)) {
|
if (SDL_ISPIXELFORMAT_FOURCC(src_format) || SDL_ISPIXELFORMAT_FOURCC(dst_format)) {
|
||||||
|
@ -1634,11 +1701,11 @@ int SDL_ConvertPixelsAndColorspace(int width, int height,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SDL_CreateSurfaceOnStack(width, height, src_format, src_colorspace, nonconst_src, src_pitch, &src_surface, &src_fmt, &src_blitmap)) {
|
if (!SDL_CreateSurfaceOnStack(width, height, src_format, src_colorspace, src_properties, nonconst_src, src_pitch, &src_surface, &src_fmt, &src_blitmap)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SDL_CreateSurfaceOnStack(width, height, dst_format, dst_colorspace, dst, dst_pitch, &dst_surface, &dst_fmt, &dst_blitmap)) {
|
if (!SDL_CreateSurfaceOnStack(width, height, dst_format, dst_colorspace, dst_properties, dst, dst_pitch, &dst_surface, &dst_fmt, &dst_blitmap)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1660,8 +1727,8 @@ int SDL_ConvertPixels(int width, int height,
|
||||||
Uint32 dst_format, void *dst, int dst_pitch)
|
Uint32 dst_format, void *dst, int dst_pitch)
|
||||||
{
|
{
|
||||||
return SDL_ConvertPixelsAndColorspace(width, height,
|
return SDL_ConvertPixelsAndColorspace(width, height,
|
||||||
src_format, SDL_COLORSPACE_UNKNOWN, src, src_pitch,
|
src_format, SDL_COLORSPACE_UNKNOWN, 0, src, src_pitch,
|
||||||
dst_format, SDL_COLORSPACE_UNKNOWN, dst, dst_pitch);
|
dst_format, SDL_COLORSPACE_UNKNOWN, 0, dst, dst_pitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1777,7 +1844,7 @@ int SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g,
|
||||||
SDL_Colorspace colorspace;
|
SDL_Colorspace colorspace;
|
||||||
|
|
||||||
if (SDL_GetSurfaceColorspace(surface, &colorspace) == 0 &&
|
if (SDL_GetSurfaceColorspace(surface, &colorspace) == 0 &&
|
||||||
SDL_ConvertPixelsAndColorspace(1, 1, surface->format->format, colorspace, p, surface->pitch, SDL_PIXELFORMAT_RGBA32, SDL_COLORSPACE_SRGB, rgba, sizeof(rgba)) == 0) {
|
SDL_ConvertPixelsAndColorspace(1, 1, surface->format->format, colorspace, SDL_GetSurfaceProperties(surface), p, surface->pitch, SDL_PIXELFORMAT_RGBA32, SDL_COLORSPACE_SRGB, 0, rgba, sizeof(rgba)) == 0) {
|
||||||
*r = rgba[0];
|
*r = rgba[0];
|
||||||
*g = rgba[1];
|
*g = rgba[1];
|
||||||
*b = rgba[2];
|
*b = rgba[2];
|
||||||
|
|
|
@ -120,9 +120,8 @@ struct SDL_Window
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
SDL_bool enabled;
|
float SDR_white_point;
|
||||||
float SDR_whitelevel;
|
float HDR_headroom;
|
||||||
float HDR_whitelevel;
|
|
||||||
} SDL_HDRDisplayProperties;
|
} SDL_HDRDisplayProperties;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -701,14 +701,20 @@ SDL_DisplayID SDL_AddVideoDisplay(const SDL_VideoDisplay *display, SDL_bool send
|
||||||
|
|
||||||
props = SDL_GetDisplayProperties(id);
|
props = SDL_GetDisplayProperties(id);
|
||||||
|
|
||||||
if (display->HDR.enabled) {
|
if (display->HDR.HDR_headroom > 1.0f) {
|
||||||
SDL_SetBooleanProperty(props, SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN, SDL_TRUE);
|
SDL_SetBooleanProperty(props, SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN, SDL_TRUE);
|
||||||
|
} else {
|
||||||
|
SDL_SetBooleanProperty(props, SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN, SDL_FALSE);
|
||||||
}
|
}
|
||||||
if (display->HDR.SDR_whitelevel != 0.0f) {
|
if (display->HDR.SDR_white_point <= 1.0f) {
|
||||||
SDL_SetFloatProperty(props, SDL_PROP_DISPLAY_SDR_WHITE_LEVEL_FLOAT, display->HDR.SDR_whitelevel);
|
SDL_SetFloatProperty(props, SDL_PROP_DISPLAY_SDR_WHITE_POINT_FLOAT, 1.0f);
|
||||||
|
} else {
|
||||||
|
SDL_SetFloatProperty(props, SDL_PROP_DISPLAY_SDR_WHITE_POINT_FLOAT, display->HDR.SDR_white_point);
|
||||||
}
|
}
|
||||||
if (display->HDR.HDR_whitelevel != 0.0f) {
|
if (display->HDR.HDR_headroom <= 1.0f) {
|
||||||
SDL_SetFloatProperty(props, SDL_PROP_DISPLAY_HDR_WHITE_LEVEL_FLOAT, display->HDR.HDR_whitelevel);
|
SDL_SetFloatProperty(props, SDL_PROP_DISPLAY_HDR_HEADROOM_FLOAT, 1.0f);
|
||||||
|
} else {
|
||||||
|
SDL_SetFloatProperty(props, SDL_PROP_DISPLAY_HDR_HEADROOM_FLOAT, display->HDR.HDR_headroom);
|
||||||
}
|
}
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
|
@ -979,22 +985,32 @@ void SDL_SetDisplayHDRProperties(SDL_VideoDisplay *display, const SDL_HDRDisplay
|
||||||
SDL_PropertiesID props = SDL_GetDisplayProperties(display->id);
|
SDL_PropertiesID props = SDL_GetDisplayProperties(display->id);
|
||||||
SDL_bool changed = SDL_FALSE;
|
SDL_bool changed = SDL_FALSE;
|
||||||
|
|
||||||
if (HDR->enabled != display->HDR.enabled) {
|
if (HDR->SDR_white_point != display->HDR.SDR_white_point) {
|
||||||
SDL_SetBooleanProperty(props, SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN, HDR->enabled);
|
if (HDR->SDR_white_point <= 1.0f) {
|
||||||
|
SDL_SetFloatProperty(props, SDL_PROP_DISPLAY_SDR_WHITE_POINT_FLOAT, 1.0f);
|
||||||
|
} else {
|
||||||
|
SDL_SetFloatProperty(props, SDL_PROP_DISPLAY_SDR_WHITE_POINT_FLOAT, HDR->SDR_white_point);
|
||||||
|
}
|
||||||
changed = SDL_TRUE;
|
changed = SDL_TRUE;
|
||||||
}
|
}
|
||||||
if (HDR->SDR_whitelevel != display->HDR.SDR_whitelevel) {
|
if (HDR->HDR_headroom != display->HDR.HDR_headroom) {
|
||||||
SDL_SetFloatProperty(props, SDL_PROP_DISPLAY_SDR_WHITE_LEVEL_FLOAT, HDR->SDR_whitelevel);
|
if (HDR->HDR_headroom > 1.0f) {
|
||||||
changed = SDL_TRUE;
|
SDL_SetBooleanProperty(props, SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN, SDL_TRUE);
|
||||||
|
} else {
|
||||||
|
SDL_SetBooleanProperty(props, SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN, SDL_FALSE);
|
||||||
|
}
|
||||||
|
if (HDR->HDR_headroom <= 1.0f) {
|
||||||
|
SDL_SetFloatProperty(props, SDL_PROP_DISPLAY_HDR_HEADROOM_FLOAT, 1.0f);
|
||||||
|
} else {
|
||||||
|
SDL_SetFloatProperty(props, SDL_PROP_DISPLAY_HDR_HEADROOM_FLOAT, HDR->HDR_headroom);
|
||||||
}
|
}
|
||||||
if (HDR->HDR_whitelevel != display->HDR.HDR_whitelevel) {
|
|
||||||
SDL_SetFloatProperty(props, SDL_PROP_DISPLAY_HDR_WHITE_LEVEL_FLOAT, HDR->HDR_whitelevel);
|
|
||||||
changed = SDL_TRUE;
|
changed = SDL_TRUE;
|
||||||
}
|
}
|
||||||
SDL_copyp(&display->HDR, HDR);
|
SDL_copyp(&display->HDR, HDR);
|
||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_HDR_STATE_CHANGED, HDR->enabled);
|
SDL_bool enabled = SDL_GetBooleanProperty(props, SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN, SDL_FALSE);
|
||||||
|
SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_HDR_STATE_CHANGED, enabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -555,8 +555,8 @@ static SDL_bool yuv_rgb_std(
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDL_ConvertPixels_YUV_to_RGB(int width, int height,
|
int SDL_ConvertPixels_YUV_to_RGB(int width, int height,
|
||||||
Uint32 src_format, SDL_Colorspace src_colorspace, const void *src, int src_pitch,
|
Uint32 src_format, SDL_Colorspace src_colorspace, SDL_PropertiesID src_properties, const void *src, int src_pitch,
|
||||||
Uint32 dst_format, SDL_Colorspace dst_colorspace, void *dst, int dst_pitch)
|
Uint32 dst_format, SDL_Colorspace dst_colorspace, SDL_PropertiesID dst_properties, void *dst, int dst_pitch)
|
||||||
{
|
{
|
||||||
const Uint8 *y = NULL;
|
const Uint8 *y = NULL;
|
||||||
const Uint8 *u = NULL;
|
const Uint8 *u = NULL;
|
||||||
|
@ -597,14 +597,14 @@ int SDL_ConvertPixels_YUV_to_RGB(int width, int height,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convert src/src_format to tmp/ARGB8888 */
|
/* convert src/src_format to tmp/ARGB8888 */
|
||||||
ret = SDL_ConvertPixels_YUV_to_RGB(width, height, src_format, src_colorspace, src, src_pitch, SDL_PIXELFORMAT_ARGB8888, SDL_COLORSPACE_SRGB, tmp, tmp_pitch);
|
ret = SDL_ConvertPixels_YUV_to_RGB(width, height, src_format, src_colorspace, src_properties, src, src_pitch, SDL_PIXELFORMAT_ARGB8888, SDL_COLORSPACE_SRGB, 0, tmp, tmp_pitch);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
SDL_free(tmp);
|
SDL_free(tmp);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convert tmp/ARGB8888 to dst/RGB */
|
/* convert tmp/ARGB8888 to dst/RGB */
|
||||||
ret = SDL_ConvertPixelsAndColorspace(width, height, SDL_PIXELFORMAT_ARGB8888, SDL_COLORSPACE_SRGB, tmp, tmp_pitch, dst_format, dst_colorspace, dst, dst_pitch);
|
ret = SDL_ConvertPixelsAndColorspace(width, height, SDL_PIXELFORMAT_ARGB8888, SDL_COLORSPACE_SRGB, 0, tmp, tmp_pitch, dst_format, dst_colorspace, dst_properties, dst, dst_pitch);
|
||||||
SDL_free(tmp);
|
SDL_free(tmp);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -935,8 +935,8 @@ static int SDL_ConvertPixels_ARGB8888_to_YUV(int width, int height, const void *
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDL_ConvertPixels_RGB_to_YUV(int width, int height,
|
int SDL_ConvertPixels_RGB_to_YUV(int width, int height,
|
||||||
Uint32 src_format, SDL_Colorspace src_colorspace, const void *src, int src_pitch,
|
Uint32 src_format, SDL_Colorspace src_colorspace, SDL_PropertiesID src_properties, const void *src, int src_pitch,
|
||||||
Uint32 dst_format, SDL_Colorspace dst_colorspace, void *dst, int dst_pitch)
|
Uint32 dst_format, SDL_Colorspace dst_colorspace, SDL_PropertiesID dst_properties, void *dst, int dst_pitch)
|
||||||
{
|
{
|
||||||
YCbCrType yuv_type = YCBCR_601;
|
YCbCrType yuv_type = YCBCR_601;
|
||||||
|
|
||||||
|
@ -2323,8 +2323,8 @@ static int SDL_ConvertPixels_Packed4_to_Planar2x2(int width, int height,
|
||||||
#endif /* SDL_HAVE_YUV */
|
#endif /* SDL_HAVE_YUV */
|
||||||
|
|
||||||
int SDL_ConvertPixels_YUV_to_YUV(int width, int height,
|
int SDL_ConvertPixels_YUV_to_YUV(int width, int height,
|
||||||
Uint32 src_format, SDL_Colorspace src_colorspace, const void *src, int src_pitch,
|
Uint32 src_format, SDL_Colorspace src_colorspace, SDL_PropertiesID src_properties, const void *src, int src_pitch,
|
||||||
Uint32 dst_format, SDL_Colorspace dst_colorspace, void *dst, int dst_pitch)
|
Uint32 dst_format, SDL_Colorspace dst_colorspace, SDL_PropertiesID dst_properties, void *dst, int dst_pitch)
|
||||||
{
|
{
|
||||||
#if SDL_HAVE_YUV
|
#if SDL_HAVE_YUV
|
||||||
if (src_colorspace != dst_colorspace) {
|
if (src_colorspace != dst_colorspace) {
|
||||||
|
|
|
@ -26,9 +26,9 @@
|
||||||
|
|
||||||
/* YUV conversion functions */
|
/* YUV conversion functions */
|
||||||
|
|
||||||
extern int SDL_ConvertPixels_YUV_to_RGB(int width, int height, Uint32 src_format, SDL_Colorspace src_colorspace, const void *src, int src_pitch, Uint32 dst_format, SDL_Colorspace dst_colorspace, void *dst, int dst_pitch);
|
extern int SDL_ConvertPixels_YUV_to_RGB(int width, int height, Uint32 src_format, SDL_Colorspace src_colorspace, SDL_PropertiesID src_properties, const void *src, int src_pitch, Uint32 dst_format, SDL_Colorspace dst_colorspace, SDL_PropertiesID dst_properties, void *dst, int dst_pitch);
|
||||||
extern int SDL_ConvertPixels_RGB_to_YUV(int width, int height, Uint32 src_format, SDL_Colorspace src_colorspace, const void *src, int src_pitch, Uint32 dst_format, SDL_Colorspace dst_colorspace, void *dst, int dst_pitch);
|
extern int SDL_ConvertPixels_RGB_to_YUV(int width, int height, Uint32 src_format, SDL_Colorspace src_colorspace, SDL_PropertiesID src_properties, const void *src, int src_pitch, Uint32 dst_format, SDL_Colorspace dst_colorspace, SDL_PropertiesID dst_properties, void *dst, int dst_pitch);
|
||||||
extern int SDL_ConvertPixels_YUV_to_YUV(int width, int height, Uint32 src_format, SDL_Colorspace src_colorspace, const void *src, int src_pitch, Uint32 dst_format, SDL_Colorspace dst_colorspace, void *dst, int dst_pitch);
|
extern int SDL_ConvertPixels_YUV_to_YUV(int width, int height, Uint32 src_format, SDL_Colorspace src_colorspace, SDL_PropertiesID src_properties, const void *src, int src_pitch, Uint32 dst_format, SDL_Colorspace dst_colorspace, SDL_PropertiesID dst_properties, void *dst, int dst_pitch);
|
||||||
|
|
||||||
|
|
||||||
extern int SDL_CalculateYUVSize(Uint32 format, int w, int h, size_t *size, size_t *pitch);
|
extern int SDL_CalculateYUVSize(Uint32 format, int w, int h, size_t *size, size_t *pitch);
|
||||||
|
|
|
@ -292,17 +292,14 @@ static char *Cocoa_GetDisplayName(CGDirectDisplayID displayID)
|
||||||
|
|
||||||
static void Cocoa_GetHDRProperties(CGDirectDisplayID displayID, SDL_HDRDisplayProperties *HDR)
|
static void Cocoa_GetHDRProperties(CGDirectDisplayID displayID, SDL_HDRDisplayProperties *HDR)
|
||||||
{
|
{
|
||||||
HDR->enabled = SDL_FALSE;
|
HDR->SDR_white_point = 1.0f;
|
||||||
HDR->SDR_whitelevel = 0.0f;
|
HDR->HDR_headroom = 1.0f;
|
||||||
|
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101500 /* Added in the 10.15 SDK */
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101500 /* Added in the 10.15 SDK */
|
||||||
if (@available(macOS 10.15, *)) {
|
if (@available(macOS 10.15, *)) {
|
||||||
NSScreen *screen = GetNSScreenForDisplayID(displayID);
|
NSScreen *screen = GetNSScreenForDisplayID(displayID);
|
||||||
|
if (screen) {
|
||||||
if (screen && screen.maximumPotentialExtendedDynamicRangeColorComponentValue > 1.0f) {
|
HDR->HDR_headroom = screen.maximumExtendedDynamicRangeColorComponentValue;
|
||||||
HDR->enabled = SDL_TRUE;
|
|
||||||
HDR->SDR_whitelevel = 80.0f; /* SDR content is always at scRGB 1.0 */
|
|
||||||
HDR->HDR_whitelevel = HDR->SDR_whitelevel * screen.maximumExtendedDynamicRangeColorComponentValue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -242,13 +242,12 @@ int UIKit_AddDisplay(UIScreen *uiscreen, SDL_bool send_event)
|
||||||
}
|
}
|
||||||
display.desktop_mode = mode;
|
display.desktop_mode = mode;
|
||||||
|
|
||||||
|
display.HDR.SDR_white_point = 1.0f;
|
||||||
|
display.HDR.HDR_headroom = 1.0f;
|
||||||
|
|
||||||
#ifndef SDL_PLATFORM_TVOS
|
#ifndef SDL_PLATFORM_TVOS
|
||||||
if (@available(iOS 16.0, *)) {
|
if (@available(iOS 16.0, *)) {
|
||||||
if (uiscreen.potentialEDRHeadroom > 1.0f) {
|
display.HDR.HDR_headroom = uiscreen.currentEDRHeadroom;
|
||||||
display.HDR.enabled = SDL_TRUE;
|
|
||||||
display.HDR.SDR_whitelevel = 80.0f; /* SDR content is always at scRGB 1.0 */
|
|
||||||
display.HDR.HDR_whitelevel = display.HDR.SDR_whitelevel * uiscreen.currentEDRHeadroom;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* !SDL_PLATFORM_TVOS */
|
#endif /* !SDL_PLATFORM_TVOS */
|
||||||
|
|
||||||
|
|
|
@ -452,10 +452,10 @@ done:
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
static float WIN_GetSDRWhiteLevel(HMONITOR hMonitor)
|
static float WIN_GetSDRWhitePoint(HMONITOR hMonitor)
|
||||||
{
|
{
|
||||||
DISPLAYCONFIG_PATH_INFO path_info;
|
DISPLAYCONFIG_PATH_INFO path_info;
|
||||||
float SDR_whitelevel = 200.0f;
|
float SDR_white_point = 1.0f;
|
||||||
|
|
||||||
if (WIN_GetMonitorPathInfo(hMonitor, &path_info)) {
|
if (WIN_GetMonitorPathInfo(hMonitor, &path_info)) {
|
||||||
DISPLAYCONFIG_SDR_WHITE_LEVEL white_level;
|
DISPLAYCONFIG_SDR_WHITE_LEVEL white_level;
|
||||||
|
@ -465,11 +465,12 @@ static float WIN_GetSDRWhiteLevel(HMONITOR hMonitor)
|
||||||
white_level.header.size = sizeof(white_level);
|
white_level.header.size = sizeof(white_level);
|
||||||
white_level.header.adapterId = path_info.targetInfo.adapterId;
|
white_level.header.adapterId = path_info.targetInfo.adapterId;
|
||||||
white_level.header.id = path_info.targetInfo.id;
|
white_level.header.id = path_info.targetInfo.id;
|
||||||
if (DisplayConfigGetDeviceInfo(&white_level.header) == ERROR_SUCCESS) {
|
if (DisplayConfigGetDeviceInfo(&white_level.header) == ERROR_SUCCESS &&
|
||||||
SDR_whitelevel = (white_level.SDRWhiteLevel / 1000.0f) * 80.0f;
|
white_level.SDRWhiteLevel > 0) {
|
||||||
|
SDR_white_point = (white_level.SDRWhiteLevel / 1000.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return SDR_whitelevel;
|
return SDR_white_point;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WIN_GetHDRProperties(SDL_VideoDevice *_this, HMONITOR hMonitor, SDL_HDRDisplayProperties *HDR)
|
static void WIN_GetHDRProperties(SDL_VideoDevice *_this, HMONITOR hMonitor, SDL_HDRDisplayProperties *HDR)
|
||||||
|
@ -480,9 +481,8 @@ static void WIN_GetHDRProperties(SDL_VideoDevice *_this, HMONITOR hMonitor, SDL_
|
||||||
|
|
||||||
if (WIN_GetMonitorDESC1(hMonitor, &desc)) {
|
if (WIN_GetMonitorDESC1(hMonitor, &desc)) {
|
||||||
if (desc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) {
|
if (desc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) {
|
||||||
HDR->enabled = SDL_TRUE;
|
HDR->SDR_white_point = WIN_GetSDRWhitePoint(hMonitor);
|
||||||
HDR->SDR_whitelevel = WIN_GetSDRWhiteLevel(hMonitor);
|
HDR->HDR_headroom = (desc.MaxLuminance / 80.0f) / HDR->SDR_white_point;
|
||||||
HDR->HDR_whitelevel = desc.MaxLuminance;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,18 +18,6 @@
|
||||||
#include <emscripten/emscripten.h>
|
#include <emscripten/emscripten.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The value for the SDR white level on an SDR display, scRGB 1.0 */
|
|
||||||
#define SDR_DISPLAY_WHITE_LEVEL 80.0f
|
|
||||||
|
|
||||||
/* The default value for the SDR white level on an HDR display */
|
|
||||||
#define DEFAULT_SDR_WHITE_LEVEL 200.0f
|
|
||||||
|
|
||||||
/* The default value for the HDR white level on an HDR display */
|
|
||||||
#define DEFAULT_HDR_WHITE_LEVEL 400.0f
|
|
||||||
|
|
||||||
/* The maximum value for the HDR white level on an HDR display */
|
|
||||||
#define MAXIMUM_HDR_WHITE_LEVEL 1000.0f
|
|
||||||
|
|
||||||
#define WINDOW_WIDTH 640
|
#define WINDOW_WIDTH 640
|
||||||
#define WINDOW_HEIGHT 480
|
#define WINDOW_HEIGHT 480
|
||||||
|
|
||||||
|
@ -46,13 +34,7 @@ static int renderer_count = 0;
|
||||||
static int renderer_index = 0;
|
static int renderer_index = 0;
|
||||||
static int stage_index = 0;
|
static int stage_index = 0;
|
||||||
static int done;
|
static int done;
|
||||||
static SDL_bool HDR_enabled = SDL_FALSE;
|
static float HDR_headroom = 1.0f;
|
||||||
static float SDR_white_level = SDR_DISPLAY_WHITE_LEVEL;
|
|
||||||
static float SDR_color_scale = 1.0f;
|
|
||||||
static SDL_FRect SDR_calibration_rect;
|
|
||||||
static float HDR_white_level = SDR_DISPLAY_WHITE_LEVEL;
|
|
||||||
static float HDR_color_scale = 1.0f;
|
|
||||||
static SDL_FRect HDR_calibration_rect;
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -60,7 +42,6 @@ enum
|
||||||
StageDrawBackground,
|
StageDrawBackground,
|
||||||
StageBlendDrawing,
|
StageBlendDrawing,
|
||||||
StageBlendTexture,
|
StageBlendTexture,
|
||||||
StageHDRCalibration,
|
|
||||||
StageGradientDrawing,
|
StageGradientDrawing,
|
||||||
StageGradientTexture,
|
StageGradientTexture,
|
||||||
StageCount
|
StageCount
|
||||||
|
@ -73,84 +54,22 @@ static void FreeRenderer(void)
|
||||||
renderer = NULL;
|
renderer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static float GetDisplaySDRWhiteLevel(void)
|
|
||||||
{
|
|
||||||
SDL_PropertiesID props;
|
|
||||||
|
|
||||||
if (!HDR_enabled) {
|
|
||||||
/* HDR is not enabled, use the SDR white level */
|
|
||||||
return SDR_DISPLAY_WHITE_LEVEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
props = SDL_GetRendererProperties(renderer);
|
|
||||||
if (SDL_GetNumberProperty(props, SDL_PROP_RENDERER_OUTPUT_COLORSPACE_NUMBER, SDL_COLORSPACE_SRGB) != SDL_COLORSPACE_SCRGB) {
|
|
||||||
/* We're not displaying in HDR, use the SDR white level */
|
|
||||||
return SDR_DISPLAY_WHITE_LEVEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
props = SDL_GetDisplayProperties(SDL_GetDisplayForWindow(window));
|
|
||||||
return SDL_GetFloatProperty(props, SDL_PROP_DISPLAY_SDR_WHITE_LEVEL_FLOAT, DEFAULT_SDR_WHITE_LEVEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void SetSDRWhiteLevel(float value)
|
|
||||||
{
|
|
||||||
if (value == SDR_white_level) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_Log("SDR white level set to %g nits\n", value);
|
|
||||||
SDR_white_level = value;
|
|
||||||
SDR_color_scale = SDR_white_level / SDR_DISPLAY_WHITE_LEVEL;
|
|
||||||
SDL_SetRenderColorScale(renderer, SDR_color_scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
static float GetDisplayHDRWhiteLevel(void)
|
|
||||||
{
|
|
||||||
SDL_PropertiesID props;
|
|
||||||
|
|
||||||
if (!HDR_enabled) {
|
|
||||||
/* HDR is not enabled, use the SDR white level */
|
|
||||||
return SDR_DISPLAY_WHITE_LEVEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
props = SDL_GetRendererProperties(renderer);
|
|
||||||
if (SDL_GetNumberProperty(props, SDL_PROP_RENDERER_OUTPUT_COLORSPACE_NUMBER, SDL_COLORSPACE_SRGB) != SDL_COLORSPACE_SCRGB) {
|
|
||||||
/* We're not displaying in HDR, use the SDR white level */
|
|
||||||
return SDR_DISPLAY_WHITE_LEVEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
props = SDL_GetDisplayProperties(SDL_GetDisplayForWindow(window));
|
|
||||||
return SDL_GetFloatProperty(props, SDL_PROP_DISPLAY_HDR_WHITE_LEVEL_FLOAT, DEFAULT_HDR_WHITE_LEVEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void SetHDRWhiteLevel(float value)
|
|
||||||
{
|
|
||||||
if (value == HDR_white_level) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_Log("HDR white level set to %g nits\n", value);
|
|
||||||
HDR_white_level = value;
|
|
||||||
HDR_color_scale = HDR_white_level / SDR_DISPLAY_WHITE_LEVEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void UpdateHDRState(void)
|
static void UpdateHDRState(void)
|
||||||
{
|
{
|
||||||
SDL_PropertiesID props;
|
SDL_PropertiesID props;
|
||||||
|
SDL_bool HDR_enabled;
|
||||||
|
|
||||||
props = SDL_GetDisplayProperties(SDL_GetDisplayForWindow(window));
|
props = SDL_GetDisplayProperties(SDL_GetDisplayForWindow(window));
|
||||||
HDR_enabled = SDL_GetBooleanProperty(props, SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN, SDL_FALSE);
|
HDR_enabled = SDL_GetBooleanProperty(props, SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN, SDL_FALSE);
|
||||||
|
|
||||||
SetHDRWhiteLevel(GetDisplayHDRWhiteLevel());
|
|
||||||
SetSDRWhiteLevel(GetDisplaySDRWhiteLevel());
|
|
||||||
|
|
||||||
SDL_Log("HDR %s\n", HDR_enabled ? "enabled" : "disabled");
|
SDL_Log("HDR %s\n", HDR_enabled ? "enabled" : "disabled");
|
||||||
|
|
||||||
if (HDR_enabled) {
|
if (HDR_enabled) {
|
||||||
props = SDL_GetRendererProperties(renderer);
|
props = SDL_GetRendererProperties(renderer);
|
||||||
if (SDL_GetNumberProperty(props, SDL_PROP_RENDERER_OUTPUT_COLORSPACE_NUMBER, SDL_COLORSPACE_SRGB) != SDL_COLORSPACE_SCRGB) {
|
if (SDL_GetNumberProperty(props, SDL_PROP_RENDERER_OUTPUT_COLORSPACE_NUMBER, SDL_COLORSPACE_SRGB) != SDL_COLORSPACE_SRGB_LINEAR) {
|
||||||
SDL_Log("Run with --colorspace scRGB to display HDR colors\n");
|
SDL_Log("Run with --colorspace linear to display HDR colors\n");
|
||||||
}
|
}
|
||||||
|
HDR_headroom = SDL_GetFloatProperty(props, SDL_PROP_RENDERER_HDR_HEADROOM_FLOAT, 1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,6 +157,9 @@ static SDL_bool ReadPixel(int x, int y, SDL_Color *c)
|
||||||
|
|
||||||
surface = SDL_RenderReadPixels(renderer, &r);
|
surface = SDL_RenderReadPixels(renderer, &r);
|
||||||
if (surface) {
|
if (surface) {
|
||||||
|
/* We don't want to do any HDR -> SDR tone mapping */
|
||||||
|
SDL_SetFloatProperty(SDL_GetSurfaceProperties(surface), SDL_PROP_SURFACE_HDR_HEADROOM_FLOAT, 0.0f);
|
||||||
|
|
||||||
if (SDL_ReadSurfacePixel(surface, 0, 0, &c->r, &c->g, &c->b, &c->a) == 0) {
|
if (SDL_ReadSurfacePixel(surface, 0, 0, &c->r, &c->g, &c->b, &c->a) == 0) {
|
||||||
result = SDL_TRUE;
|
result = SDL_TRUE;
|
||||||
} else {
|
} else {
|
||||||
|
@ -266,20 +188,6 @@ static void DrawText(float x, float y, const char *fmt, ...)
|
||||||
SDL_free(text);
|
SDL_free(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawTextWhite(float x, float y, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
char *text;
|
|
||||||
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, fmt);
|
|
||||||
SDL_vasprintf(&text, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
|
||||||
SDLTest_DrawString(renderer, x, y, text);
|
|
||||||
SDL_free(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void RenderClearBackground(void)
|
static void RenderClearBackground(void)
|
||||||
{
|
{
|
||||||
/* Draw a 50% gray background.
|
/* Draw a 50% gray background.
|
||||||
|
@ -488,85 +396,38 @@ static void DrawGradient(float x, float y, float width, float height, float star
|
||||||
SDL_RenderGeometryRawFloat(renderer, NULL, xy, xy_stride, color, color_stride, NULL, 0, num_vertices, indices, num_indices, size_indices);
|
SDL_RenderGeometryRawFloat(renderer, NULL, xy, xy_stride, color, color_stride, NULL, 0, num_vertices, indices, num_indices, size_indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
static float scRGBtoNits(float v)
|
|
||||||
{
|
|
||||||
return v * 80.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static float scRGBfromNits(float v)
|
|
||||||
{
|
|
||||||
return v / 80.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static float sRGBtoLinear(float v)
|
|
||||||
{
|
|
||||||
if (v <= 0.04045f) {
|
|
||||||
v = (v / 12.92f);
|
|
||||||
} else {
|
|
||||||
v = SDL_powf(((v + 0.055f) / 1.055f), 2.4f);
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static float sRGBFromLinear(float v)
|
|
||||||
{
|
|
||||||
if (v <= 0.0031308f) {
|
|
||||||
v = (v * 12.92f);
|
|
||||||
} else {
|
|
||||||
v = (SDL_powf(v, 1.0f / 2.4f) * 1.055f - 0.055f);
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static float sRGBtoNits(float v)
|
|
||||||
{
|
|
||||||
return scRGBtoNits(sRGBtoLinear(v));
|
|
||||||
}
|
|
||||||
|
|
||||||
static float sRGBfromNits(float v)
|
|
||||||
{
|
|
||||||
return sRGBFromLinear(scRGBfromNits(v));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void RenderGradientDrawing(void)
|
static void RenderGradientDrawing(void)
|
||||||
{
|
{
|
||||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
||||||
SDL_RenderClear(renderer);
|
SDL_RenderClear(renderer);
|
||||||
|
|
||||||
float x = TEXT_START_X;
|
float x = TEXT_START_X;
|
||||||
float y = TEXT_START_Y;
|
float y = TEXT_START_Y;
|
||||||
DrawTextWhite(x, y, "%s %s", renderer_name, colorspace_name);
|
DrawText(x, y, "%s %s", renderer_name, colorspace_name);
|
||||||
y += TEXT_LINE_ADVANCE;
|
y += TEXT_LINE_ADVANCE;
|
||||||
DrawTextWhite(x, y, "Test: Draw SDR and HDR gradients");
|
DrawText(x, y, "Test: Draw SDR and HDR gradients");
|
||||||
y += TEXT_LINE_ADVANCE;
|
y += TEXT_LINE_ADVANCE;
|
||||||
|
|
||||||
y += TEXT_LINE_ADVANCE;
|
y += TEXT_LINE_ADVANCE;
|
||||||
|
|
||||||
DrawTextWhite(x, y, "SDR gradient (%g nits)", SDR_white_level);
|
DrawText(x, y, "SDR gradient");
|
||||||
y += TEXT_LINE_ADVANCE;
|
y += TEXT_LINE_ADVANCE;
|
||||||
SDL_SetRenderColorScale(renderer, 1.0f);
|
DrawGradient(x, y, WINDOW_WIDTH - 2 * x, 64.0f, 0.0f, 1.0f);
|
||||||
DrawGradient(x, y, WINDOW_WIDTH - 2 * x, 64.0f, 0.0f, sRGBfromNits(SDR_white_level));
|
|
||||||
SDL_SetRenderColorScale(renderer, SDR_color_scale);
|
|
||||||
y += 64.0f;
|
y += 64.0f;
|
||||||
|
|
||||||
y += TEXT_LINE_ADVANCE;
|
y += TEXT_LINE_ADVANCE;
|
||||||
y += TEXT_LINE_ADVANCE;
|
y += TEXT_LINE_ADVANCE;
|
||||||
|
|
||||||
DrawTextWhite(x, y, "HDR gradient (%g nits)", HDR_white_level);
|
if (HDR_headroom > 1.0f) {
|
||||||
|
DrawText(x, y, "HDR gradient");
|
||||||
|
} else {
|
||||||
|
DrawText(x, y, "No HDR headroom, HDR and SDR gradient are the same");
|
||||||
|
}
|
||||||
y += TEXT_LINE_ADVANCE;
|
y += TEXT_LINE_ADVANCE;
|
||||||
|
/* Drawing is in the sRGB colorspace, so we need to use the color scale, which is applied in linear space, to get into high dynamic range */
|
||||||
|
SDL_SetRenderColorScale(renderer, HDR_headroom);
|
||||||
|
DrawGradient(x, y, WINDOW_WIDTH - 2 * x, 64.0f, 0.0f, 1.0f);
|
||||||
SDL_SetRenderColorScale(renderer, 1.0f);
|
SDL_SetRenderColorScale(renderer, 1.0f);
|
||||||
DrawGradient(x, y, WINDOW_WIDTH - 2 * x, 64.0f, 0.0f, sRGBfromNits(HDR_white_level));
|
|
||||||
SDL_SetRenderColorScale(renderer, SDR_color_scale);
|
|
||||||
y += 64.0f;
|
|
||||||
|
|
||||||
y += TEXT_LINE_ADVANCE;
|
|
||||||
y += TEXT_LINE_ADVANCE;
|
|
||||||
|
|
||||||
DrawTextWhite(x, y, "HDR gradient (%g nits)", MAXIMUM_HDR_WHITE_LEVEL);
|
|
||||||
y += TEXT_LINE_ADVANCE;
|
|
||||||
SDL_SetRenderColorScale(renderer, 1.0f);
|
|
||||||
DrawGradient(x, y, WINDOW_WIDTH - 2 * x, 64.0f, 0.0f, sRGBfromNits(MAXIMUM_HDR_WHITE_LEVEL));
|
|
||||||
SDL_SetRenderColorScale(renderer, SDR_color_scale);
|
|
||||||
y += 64.0f;
|
y += 64.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -575,20 +436,12 @@ static SDL_Texture *CreateGradientTexture(int width, float start, float end)
|
||||||
SDL_Texture *texture;
|
SDL_Texture *texture;
|
||||||
float *pixels;
|
float *pixels;
|
||||||
|
|
||||||
/* Floating point textures are in the scRGB colorspace by default */
|
/* Floating point textures are in the linear colorspace by default */
|
||||||
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA128_FLOAT, SDL_TEXTUREACCESS_STATIC, width, 1);
|
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA128_FLOAT, SDL_TEXTUREACCESS_STATIC, width, 1);
|
||||||
if (!texture) {
|
if (!texture) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (colorspace == SDL_COLORSPACE_SCRGB) {
|
|
||||||
/* The input values are in the sRGB colorspace, but we're blending in linear space */
|
|
||||||
start = sRGBtoLinear(start);
|
|
||||||
end = sRGBtoLinear(end);
|
|
||||||
} else if (colorspace == SDL_COLORSPACE_SRGB) {
|
|
||||||
/* The input values are in the sRGB colorspace, and we're blending in sRGB space */
|
|
||||||
}
|
|
||||||
|
|
||||||
pixels = (float *)SDL_malloc(width * sizeof(float) * 4);
|
pixels = (float *)SDL_malloc(width * sizeof(float) * 4);
|
||||||
if (pixels) {
|
if (pixels) {
|
||||||
int i;
|
int i;
|
||||||
|
@ -617,129 +470,35 @@ static void DrawGradientTexture(float x, float y, float width, float height, flo
|
||||||
|
|
||||||
static void RenderGradientTexture(void)
|
static void RenderGradientTexture(void)
|
||||||
{
|
{
|
||||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
||||||
SDL_RenderClear(renderer);
|
SDL_RenderClear(renderer);
|
||||||
|
|
||||||
float x = TEXT_START_X;
|
float x = TEXT_START_X;
|
||||||
float y = TEXT_START_Y;
|
float y = TEXT_START_Y;
|
||||||
DrawTextWhite(x, y, "%s %s", renderer_name, colorspace_name);
|
DrawText(x, y, "%s %s", renderer_name, colorspace_name);
|
||||||
y += TEXT_LINE_ADVANCE;
|
y += TEXT_LINE_ADVANCE;
|
||||||
DrawTextWhite(x, y, "Test: Texture SDR and HDR gradients");
|
DrawText(x, y, "Test: Texture SDR and HDR gradients");
|
||||||
y += TEXT_LINE_ADVANCE;
|
y += TEXT_LINE_ADVANCE;
|
||||||
|
|
||||||
y += TEXT_LINE_ADVANCE;
|
y += TEXT_LINE_ADVANCE;
|
||||||
|
|
||||||
DrawTextWhite(x, y, "SDR gradient (%g nits)", SDR_white_level);
|
DrawText(x, y, "SDR gradient");
|
||||||
y += TEXT_LINE_ADVANCE;
|
y += TEXT_LINE_ADVANCE;
|
||||||
SDL_SetRenderColorScale(renderer, 1.0f);
|
DrawGradientTexture(x, y, WINDOW_WIDTH - 2 * x, 64.0f, 0.0f, 1.0f);
|
||||||
DrawGradientTexture(x, y, WINDOW_WIDTH - 2 * x, 64.0f, 0.0f, sRGBfromNits(SDR_white_level));
|
|
||||||
SDL_SetRenderColorScale(renderer, SDR_color_scale);
|
|
||||||
y += 64.0f;
|
y += 64.0f;
|
||||||
|
|
||||||
y += TEXT_LINE_ADVANCE;
|
y += TEXT_LINE_ADVANCE;
|
||||||
y += TEXT_LINE_ADVANCE;
|
y += TEXT_LINE_ADVANCE;
|
||||||
|
|
||||||
DrawTextWhite(x, y, "HDR gradient (%g nits)", HDR_white_level);
|
if (HDR_headroom > 1.0f) {
|
||||||
|
DrawText(x, y, "HDR gradient");
|
||||||
|
} else {
|
||||||
|
DrawText(x, y, "No HDR headroom, HDR and SDR gradient are the same");
|
||||||
|
}
|
||||||
y += TEXT_LINE_ADVANCE;
|
y += TEXT_LINE_ADVANCE;
|
||||||
SDL_SetRenderColorScale(renderer, 1.0f);
|
/* The gradient texture is in the linear colorspace, so we can use the HDR_headroom value directly */
|
||||||
DrawGradientTexture(x, y, WINDOW_WIDTH - 2 * x, 64.0f, 0.0f, sRGBfromNits(HDR_white_level));
|
DrawGradientTexture(x, y, WINDOW_WIDTH - 2 * x, 64.0f, 0.0f, HDR_headroom);
|
||||||
SDL_SetRenderColorScale(renderer, SDR_color_scale);
|
|
||||||
y += 64.0f;
|
y += 64.0f;
|
||||||
|
|
||||||
y += TEXT_LINE_ADVANCE;
|
|
||||||
y += TEXT_LINE_ADVANCE;
|
|
||||||
|
|
||||||
DrawTextWhite(x, y, "HDR gradient (%g nits)", MAXIMUM_HDR_WHITE_LEVEL);
|
|
||||||
y += TEXT_LINE_ADVANCE;
|
|
||||||
SDL_SetRenderColorScale(renderer, 1.0f);
|
|
||||||
DrawGradientTexture(x, y, WINDOW_WIDTH - 2 * x, 64.0f, 0.0f, sRGBfromNits(MAXIMUM_HDR_WHITE_LEVEL));
|
|
||||||
SDL_SetRenderColorScale(renderer, SDR_color_scale);
|
|
||||||
y += 64.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void RenderHDRCalibration(void)
|
|
||||||
{
|
|
||||||
SDL_FRect rect;
|
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
|
||||||
SDL_RenderClear(renderer);
|
|
||||||
|
|
||||||
float x = TEXT_START_X;
|
|
||||||
float y = TEXT_START_Y;
|
|
||||||
DrawTextWhite(x, y, "%s %s", renderer_name, colorspace_name);
|
|
||||||
y += TEXT_LINE_ADVANCE;
|
|
||||||
DrawTextWhite(x, y, "Test: HDR calibration");
|
|
||||||
y += TEXT_LINE_ADVANCE;
|
|
||||||
|
|
||||||
y += TEXT_LINE_ADVANCE;
|
|
||||||
|
|
||||||
if (!HDR_enabled) {
|
|
||||||
DrawTextWhite(x, y, "HDR not enabled");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawTextWhite(x, y, "Select HDR maximum brightness (%g nits)", HDR_white_level);
|
|
||||||
y += TEXT_LINE_ADVANCE;
|
|
||||||
DrawTextWhite(x, y, "The square in the middle should just barely be visible");
|
|
||||||
y += TEXT_LINE_ADVANCE;
|
|
||||||
HDR_calibration_rect.x = x;
|
|
||||||
HDR_calibration_rect.y = y;
|
|
||||||
HDR_calibration_rect.w = WINDOW_WIDTH - 2 * x;
|
|
||||||
HDR_calibration_rect.h = 64.0f;
|
|
||||||
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
|
||||||
SDL_SetRenderColorScale(renderer, MAXIMUM_HDR_WHITE_LEVEL / SDR_DISPLAY_WHITE_LEVEL);
|
|
||||||
SDL_RenderFillRect(renderer, &HDR_calibration_rect);
|
|
||||||
SDL_SetRenderColorScale(renderer, HDR_color_scale * 0.90f);
|
|
||||||
rect = HDR_calibration_rect;
|
|
||||||
rect.h -= 4.0f;
|
|
||||||
rect.w = 60.0f;
|
|
||||||
rect.x = (WINDOW_WIDTH - rect.w) / 2.0f;
|
|
||||||
rect.y += 2.0f;
|
|
||||||
SDL_RenderFillRect(renderer, &rect);
|
|
||||||
SDL_SetRenderColorScale(renderer, SDR_color_scale);
|
|
||||||
y += 64.0f;
|
|
||||||
|
|
||||||
y += TEXT_LINE_ADVANCE;
|
|
||||||
y += TEXT_LINE_ADVANCE;
|
|
||||||
|
|
||||||
DrawTextWhite(x, y, "Select SDR maximum brightness (%g nits)", SDR_white_level);
|
|
||||||
y += TEXT_LINE_ADVANCE;
|
|
||||||
SDR_calibration_rect.x = x;
|
|
||||||
SDR_calibration_rect.y = y;
|
|
||||||
SDR_calibration_rect.w = WINDOW_WIDTH - 2 * x;
|
|
||||||
SDR_calibration_rect.h = 64.0f;
|
|
||||||
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
|
||||||
SDL_RenderFillRect(renderer, &SDR_calibration_rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void OnHDRCalibrationMouseHeld(float x, float y)
|
|
||||||
{
|
|
||||||
SDL_FPoint mouse = { x, y };
|
|
||||||
|
|
||||||
if (SDL_PointInRectFloat(&mouse, &HDR_calibration_rect)) {
|
|
||||||
float v = (x - HDR_calibration_rect.x) / HDR_calibration_rect.w;
|
|
||||||
v *= (sRGBfromNits(MAXIMUM_HDR_WHITE_LEVEL) - 1.0f);
|
|
||||||
v += 1.0f;
|
|
||||||
v = sRGBtoNits(v);
|
|
||||||
SetHDRWhiteLevel(v);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SDL_PointInRectFloat(&mouse, &SDR_calibration_rect)) {
|
|
||||||
float v = (x - SDR_calibration_rect.x) / SDR_calibration_rect.w;
|
|
||||||
v *= (sRGBfromNits(MAXIMUM_HDR_WHITE_LEVEL) - 1.0f);
|
|
||||||
v += 1.0f;
|
|
||||||
v = sRGBtoNits(v);
|
|
||||||
SetSDRWhiteLevel(v);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void OnMouseHeld(float x, float y)
|
|
||||||
{
|
|
||||||
if (stage_index == StageHDRCalibration) {
|
|
||||||
OnHDRCalibrationMouseHeld(x, y);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void loop(void)
|
static void loop(void)
|
||||||
|
@ -768,12 +527,6 @@ static void loop(void)
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
|
|
||||||
OnMouseHeld(event.button.x, event.button.y);
|
|
||||||
} else if (event.type == SDL_EVENT_MOUSE_MOTION) {
|
|
||||||
if (event.motion.state) {
|
|
||||||
OnMouseHeld(event.button.x, event.button.y);
|
|
||||||
}
|
|
||||||
} else if (event.type == SDL_EVENT_DISPLAY_HDR_STATE_CHANGED) {
|
} else if (event.type == SDL_EVENT_DISPLAY_HDR_STATE_CHANGED) {
|
||||||
UpdateHDRState();
|
UpdateHDRState();
|
||||||
} else if (event.type == SDL_EVENT_QUIT) {
|
} else if (event.type == SDL_EVENT_QUIT) {
|
||||||
|
@ -798,9 +551,6 @@ static void loop(void)
|
||||||
case StageBlendTexture:
|
case StageBlendTexture:
|
||||||
RenderBlendTexture();
|
RenderBlendTexture();
|
||||||
break;
|
break;
|
||||||
case StageHDRCalibration:
|
|
||||||
RenderHDRCalibration();
|
|
||||||
break;
|
|
||||||
case StageGradientDrawing:
|
case StageGradientDrawing:
|
||||||
RenderGradientDrawing();
|
RenderGradientDrawing();
|
||||||
break;
|
break;
|
||||||
|
@ -844,8 +594,8 @@ int main(int argc, char *argv[])
|
||||||
colorspace_name = argv[i + 1];
|
colorspace_name = argv[i + 1];
|
||||||
if (SDL_strcasecmp(colorspace_name, "sRGB") == 0) {
|
if (SDL_strcasecmp(colorspace_name, "sRGB") == 0) {
|
||||||
colorspace = SDL_COLORSPACE_SRGB;
|
colorspace = SDL_COLORSPACE_SRGB;
|
||||||
} else if (SDL_strcasecmp(colorspace_name, "scRGB") == 0) {
|
} else if (SDL_strcasecmp(colorspace_name, "linear") == 0) {
|
||||||
colorspace = SDL_COLORSPACE_SCRGB;
|
colorspace = SDL_COLORSPACE_SRGB_LINEAR;
|
||||||
/* Not currently supported
|
/* Not currently supported
|
||||||
} else if (SDL_strcasecmp(colorspace_name, "HDR10") == 0) {
|
} else if (SDL_strcasecmp(colorspace_name, "HDR10") == 0) {
|
||||||
colorspace = SDL_COLORSPACE_HDR10;
|
colorspace = SDL_COLORSPACE_HDR10;
|
||||||
|
|
|
@ -57,15 +57,6 @@
|
||||||
|
|
||||||
#include "icon.h"
|
#include "icon.h"
|
||||||
|
|
||||||
/* The value for the SDR white level on an SDR display, scRGB 1.0 */
|
|
||||||
#define SDR_DISPLAY_WHITE_LEVEL 80.0f
|
|
||||||
|
|
||||||
/* The default value for the SDR white level on an HDR display */
|
|
||||||
#define DEFAULT_SDR_WHITE_LEVEL 200.0f
|
|
||||||
|
|
||||||
/* The default value for the HDR white level on an HDR display */
|
|
||||||
#define DEFAULT_HDR_WHITE_LEVEL 400.0f
|
|
||||||
|
|
||||||
|
|
||||||
static SDL_Texture *sprite;
|
static SDL_Texture *sprite;
|
||||||
static SDL_FRect *positions;
|
static SDL_FRect *positions;
|
||||||
|
@ -97,56 +88,6 @@ struct SwsContextContainer
|
||||||
static const char *SWS_CONTEXT_CONTAINER_PROPERTY = "SWS_CONTEXT_CONTAINER";
|
static const char *SWS_CONTEXT_CONTAINER_PROPERTY = "SWS_CONTEXT_CONTAINER";
|
||||||
static int done;
|
static int done;
|
||||||
|
|
||||||
/* This function isn't platform specific, but we haven't hooked up HDR video support on other platforms yet */
|
|
||||||
#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_APPLE)
|
|
||||||
static void GetDisplayHDRProperties(SDL_bool *HDR_display, float *SDR_white_level, float *HDR_white_level)
|
|
||||||
{
|
|
||||||
SDL_PropertiesID props;
|
|
||||||
|
|
||||||
*HDR_display = SDL_FALSE;
|
|
||||||
*SDR_white_level = SDR_DISPLAY_WHITE_LEVEL;
|
|
||||||
*HDR_white_level = SDR_DISPLAY_WHITE_LEVEL;
|
|
||||||
|
|
||||||
props = SDL_GetRendererProperties(renderer);
|
|
||||||
if (SDL_GetNumberProperty(props, SDL_PROP_RENDERER_OUTPUT_COLORSPACE_NUMBER, SDL_COLORSPACE_SRGB) != SDL_COLORSPACE_SCRGB) {
|
|
||||||
/* We're not displaying in HDR, use the SDR white level */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
props = SDL_GetDisplayProperties(SDL_GetDisplayForWindow(window));
|
|
||||||
if (!SDL_GetBooleanProperty(props, SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN, SDL_FALSE)) {
|
|
||||||
/* HDR is not enabled on the display */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
*HDR_display = SDL_TRUE;
|
|
||||||
*SDR_white_level = SDL_GetFloatProperty(props, SDL_PROP_DISPLAY_SDR_WHITE_LEVEL_FLOAT, DEFAULT_SDR_WHITE_LEVEL);
|
|
||||||
*HDR_white_level = SDL_GetFloatProperty(props, SDL_PROP_DISPLAY_HDR_WHITE_LEVEL_FLOAT, DEFAULT_HDR_WHITE_LEVEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void UpdateVideoColorScale(SDL_bool HDR_video)
|
|
||||||
{
|
|
||||||
SDL_bool HDR_display = SDL_FALSE;
|
|
||||||
float SDR_white_level, HDR_white_level, video_white_level;
|
|
||||||
|
|
||||||
GetDisplayHDRProperties(&HDR_display, &SDR_white_level, &HDR_white_level);
|
|
||||||
|
|
||||||
if (HDR_video) {
|
|
||||||
video_white_level = DEFAULT_HDR_WHITE_LEVEL;
|
|
||||||
} else {
|
|
||||||
video_white_level = SDR_DISPLAY_WHITE_LEVEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HDR_display && HDR_video) {
|
|
||||||
/* Scale the HDR range of the video to the HDR range of the display */
|
|
||||||
SDL_SetRenderColorScale(renderer, HDR_white_level / video_white_level);
|
|
||||||
} else {
|
|
||||||
/* Scale the range of the video to the SDR range of the display */
|
|
||||||
SDL_SetRenderColorScale(renderer, SDR_white_level / video_white_level);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* SDL_PLATFORM_WIN32 || SDL_PLATFORM_APPLE */
|
|
||||||
|
|
||||||
static SDL_bool CreateWindowAndRenderer(Uint32 window_flags, const char *driver)
|
static SDL_bool CreateWindowAndRenderer(Uint32 window_flags, const char *driver)
|
||||||
{
|
{
|
||||||
SDL_PropertiesID props;
|
SDL_PropertiesID props;
|
||||||
|
@ -178,7 +119,7 @@ static SDL_bool CreateWindowAndRenderer(Uint32 window_flags, const char *driver)
|
||||||
props = SDL_CreateProperties();
|
props = SDL_CreateProperties();
|
||||||
SDL_SetStringProperty(props, SDL_PROP_RENDERER_CREATE_NAME_STRING, driver);
|
SDL_SetStringProperty(props, SDL_PROP_RENDERER_CREATE_NAME_STRING, driver);
|
||||||
SDL_SetProperty(props, SDL_PROP_RENDERER_CREATE_WINDOW_POINTER, window);
|
SDL_SetProperty(props, SDL_PROP_RENDERER_CREATE_WINDOW_POINTER, window);
|
||||||
SDL_SetNumberProperty(props, SDL_PROP_RENDERER_CREATE_OUTPUT_COLORSPACE_NUMBER, SDL_COLORSPACE_SCRGB);
|
SDL_SetNumberProperty(props, SDL_PROP_RENDERER_CREATE_OUTPUT_COLORSPACE_NUMBER, SDL_COLORSPACE_SRGB_LINEAR);
|
||||||
renderer = SDL_CreateRendererWithProperties(props);
|
renderer = SDL_CreateRendererWithProperties(props);
|
||||||
if (!renderer) {
|
if (!renderer) {
|
||||||
/* Try again with the sRGB colorspace */
|
/* Try again with the sRGB colorspace */
|
||||||
|
@ -699,7 +640,6 @@ static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture)
|
||||||
}
|
}
|
||||||
if (!*texture || (UINT)texture_width != desc.Width || (UINT)texture_height != desc.Height) {
|
if (!*texture || (UINT)texture_width != desc.Width || (UINT)texture_height != desc.Height) {
|
||||||
Uint32 format;
|
Uint32 format;
|
||||||
SDL_bool HDR_video = SDL_FALSE;
|
|
||||||
|
|
||||||
switch (desc.Format) {
|
switch (desc.Format) {
|
||||||
case DXGI_FORMAT_NV12:
|
case DXGI_FORMAT_NV12:
|
||||||
|
@ -707,11 +647,6 @@ static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture)
|
||||||
break;
|
break;
|
||||||
case DXGI_FORMAT_P010:
|
case DXGI_FORMAT_P010:
|
||||||
format = SDL_PIXELFORMAT_P010;
|
format = SDL_PIXELFORMAT_P010;
|
||||||
HDR_video = SDL_TRUE;
|
|
||||||
break;
|
|
||||||
case DXGI_FORMAT_P016:
|
|
||||||
format = SDL_PIXELFORMAT_P016;
|
|
||||||
HDR_video = SDL_TRUE;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
SDL_SetError("Unsupported texture format %d", desc.Format);
|
SDL_SetError("Unsupported texture format %d", desc.Format);
|
||||||
|
@ -733,8 +668,6 @@ static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture)
|
||||||
if (!*texture) {
|
if (!*texture) {
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateVideoColorScale(HDR_video);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ID3D11Resource *dx11_resource = SDL_GetProperty(SDL_GetTextureProperties(*texture), SDL_PROP_TEXTURE_D3D11_TEXTURE_POINTER, NULL);
|
ID3D11Resource *dx11_resource = SDL_GetProperty(SDL_GetTextureProperties(*texture), SDL_PROP_TEXTURE_D3D11_TEXTURE_POINTER, NULL);
|
||||||
|
@ -759,7 +692,6 @@ static SDL_bool GetTextureForVideoToolboxFrame(AVFrame *frame, SDL_Texture **tex
|
||||||
size_t nPixelBufferHeight = CVPixelBufferGetHeightOfPlane(pPixelBuffer, 0);
|
size_t nPixelBufferHeight = CVPixelBufferGetHeightOfPlane(pPixelBuffer, 0);
|
||||||
SDL_PropertiesID props;
|
SDL_PropertiesID props;
|
||||||
Uint32 format;
|
Uint32 format;
|
||||||
SDL_bool HDR_video = SDL_FALSE;
|
|
||||||
|
|
||||||
switch (nPixelBufferType) {
|
switch (nPixelBufferType) {
|
||||||
case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange:
|
case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange:
|
||||||
|
@ -769,7 +701,6 @@ static SDL_bool GetTextureForVideoToolboxFrame(AVFrame *frame, SDL_Texture **tex
|
||||||
case kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange:
|
case kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange:
|
||||||
case kCVPixelFormatType_420YpCbCr10BiPlanarFullRange:
|
case kCVPixelFormatType_420YpCbCr10BiPlanarFullRange:
|
||||||
format = SDL_PIXELFORMAT_P010;
|
format = SDL_PIXELFORMAT_P010;
|
||||||
HDR_video = SDL_TRUE;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
SDL_SetError("Unsupported texture format %c%c%c%c",
|
SDL_SetError("Unsupported texture format %c%c%c%c",
|
||||||
|
@ -799,8 +730,6 @@ static SDL_bool GetTextureForVideoToolboxFrame(AVFrame *frame, SDL_Texture **tex
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateVideoColorScale(HDR_video);
|
|
||||||
|
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
#else
|
#else
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
|
|
|
@ -78,7 +78,7 @@ static SDL_bool verify_yuv_data(Uint32 format, SDL_Colorspace colorspace, const
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SDL_ConvertPixelsAndColorspace(surface->w, surface->h, format, colorspace, yuv, yuv_pitch, surface->format->format, SDL_COLORSPACE_SRGB, rgb, surface->pitch) == 0) {
|
if (SDL_ConvertPixelsAndColorspace(surface->w, surface->h, format, colorspace, 0, yuv, yuv_pitch, surface->format->format, SDL_COLORSPACE_SRGB, 0, rgb, surface->pitch) == 0) {
|
||||||
int x, y;
|
int x, y;
|
||||||
result = SDL_TRUE;
|
result = SDL_TRUE;
|
||||||
for (y = 0; y < surface->h; ++y) {
|
for (y = 0; y < surface->h; ++y) {
|
||||||
|
@ -156,7 +156,7 @@ static int run_automated_tests(int pattern_size, int extra_pitch)
|
||||||
/* Verify conversion to YUV formats */
|
/* Verify conversion to YUV formats */
|
||||||
for (i = 0; i < SDL_arraysize(formats); ++i) {
|
for (i = 0; i < SDL_arraysize(formats); ++i) {
|
||||||
yuv1_pitch = CalculateYUVPitch(formats[i], pattern->w) + extra_pitch;
|
yuv1_pitch = CalculateYUVPitch(formats[i], pattern->w) + extra_pitch;
|
||||||
if (SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, pattern->format->format, SDL_COLORSPACE_SRGB, pattern->pixels, pattern->pitch, formats[i], colorspace, yuv1, yuv1_pitch) < 0) {
|
if (SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, pattern->format->format, SDL_COLORSPACE_SRGB, 0, pattern->pixels, pattern->pitch, formats[i], colorspace, 0, yuv1, yuv1_pitch) < 0) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(pattern->format->format), SDL_GetPixelFormatName(formats[i]), SDL_GetError());
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(pattern->format->format), SDL_GetPixelFormatName(formats[i]), SDL_GetError());
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -171,11 +171,11 @@ static int run_automated_tests(int pattern_size, int extra_pitch)
|
||||||
for (j = 0; j < SDL_arraysize(formats); ++j) {
|
for (j = 0; j < SDL_arraysize(formats); ++j) {
|
||||||
yuv1_pitch = CalculateYUVPitch(formats[i], pattern->w) + extra_pitch;
|
yuv1_pitch = CalculateYUVPitch(formats[i], pattern->w) + extra_pitch;
|
||||||
yuv2_pitch = CalculateYUVPitch(formats[j], pattern->w) + extra_pitch;
|
yuv2_pitch = CalculateYUVPitch(formats[j], pattern->w) + extra_pitch;
|
||||||
if (SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, pattern->format->format, SDL_COLORSPACE_SRGB, pattern->pixels, pattern->pitch, formats[i], colorspace, yuv1, yuv1_pitch) < 0) {
|
if (SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, pattern->format->format, SDL_COLORSPACE_SRGB, 0, pattern->pixels, pattern->pitch, formats[i], colorspace, 0, yuv1, yuv1_pitch) < 0) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(pattern->format->format), SDL_GetPixelFormatName(formats[i]), SDL_GetError());
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(pattern->format->format), SDL_GetPixelFormatName(formats[i]), SDL_GetError());
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, formats[i], colorspace, yuv1, yuv1_pitch, formats[j], colorspace, yuv2, yuv2_pitch) < 0) {
|
if (SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, formats[i], colorspace, 0, yuv1, yuv1_pitch, formats[j], colorspace, 0, yuv2, yuv2_pitch) < 0) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(formats[i]), SDL_GetPixelFormatName(formats[j]), SDL_GetError());
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(formats[i]), SDL_GetPixelFormatName(formats[j]), SDL_GetError());
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -196,11 +196,11 @@ static int run_automated_tests(int pattern_size, int extra_pitch)
|
||||||
|
|
||||||
yuv1_pitch = CalculateYUVPitch(formats[i], pattern->w) + extra_pitch;
|
yuv1_pitch = CalculateYUVPitch(formats[i], pattern->w) + extra_pitch;
|
||||||
yuv2_pitch = CalculateYUVPitch(formats[j], pattern->w) + extra_pitch;
|
yuv2_pitch = CalculateYUVPitch(formats[j], pattern->w) + extra_pitch;
|
||||||
if (SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, pattern->format->format, SDL_COLORSPACE_SRGB, pattern->pixels, pattern->pitch, formats[i], colorspace, yuv1, yuv1_pitch) < 0) {
|
if (SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, pattern->format->format, SDL_COLORSPACE_SRGB, 0, pattern->pixels, pattern->pitch, formats[i], colorspace, 0, yuv1, yuv1_pitch) < 0) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(pattern->format->format), SDL_GetPixelFormatName(formats[i]), SDL_GetError());
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(pattern->format->format), SDL_GetPixelFormatName(formats[i]), SDL_GetError());
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, formats[i], colorspace, yuv1, yuv1_pitch, formats[j], colorspace, yuv1, yuv2_pitch) < 0) {
|
if (SDL_ConvertPixelsAndColorspace(pattern->w, pattern->h, formats[i], colorspace, 0, yuv1, yuv1_pitch, formats[j], colorspace, 0, yuv1, yuv2_pitch) < 0) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(formats[i]), SDL_GetPixelFormatName(formats[j]), SDL_GetError());
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't convert %s to %s: %s\n", SDL_GetPixelFormatName(formats[i]), SDL_GetPixelFormatName(formats[j]), SDL_GetError());
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue