Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions include/SDL3/SDL_surface.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,53 @@ typedef struct SDL_Surface
typedef int (SDLCALL *SDL_blit) (struct SDL_Surface *src, const SDL_Rect *srcrect,
struct SDL_Surface *dst, const SDL_Rect *dstrect);


/**
* The color primaries, as described by https://www.itu.int/rec/T-REC-H.273-201612-S/en
*/
typedef enum
{
SDL_COLOR_PRIMARIES_UNKNOWN = 0,
SDL_COLOR_PRIMARIES_BT709 = 1,
SDL_COLOR_PRIMARIES_IEC61966_2_4 = 1,
SDL_COLOR_PRIMARIES_UNSPECIFIED = 2,
SDL_COLOR_PRIMARIES_BT470M = 4,
SDL_COLOR_PRIMARIES_BT470BG = 5,
SDL_COLOR_PRIMARIES_BT601 = 6,
SDL_COLOR_PRIMARIES_SMPTE240 = 7,
SDL_COLOR_PRIMARIES_GENERIC_FILM = 8,
SDL_COLOR_PRIMARIES_BT2020 = 9,
SDL_COLOR_PRIMARIES_XYZ = 10,
SDL_COLOR_PRIMARIES_SMPTE431 = 11,
SDL_COLOR_PRIMARIES_SMPTE432 = 12, /* DCI P3 */
SDL_COLOR_PRIMARIES_EBU3213 = 22
} SDL_ColorPrimaries;

/**
* The transfer characteristics, as described by https://www.itu.int/rec/T-REC-H.273-201612-S/en
*/
typedef enum
{
SDL_TRANSFER_CHARACTERISTICS_UNKNOWN = 0,
SDL_TRANSFER_CHARACTERISTICS_BT709 = 1,
SDL_TRANSFER_CHARACTERISTICS_UNSPECIFIED = 2,
SDL_TRANSFER_CHARACTERISTICS_BT470M = 4, /* 2.2 gamma */
SDL_TRANSFER_CHARACTERISTICS_BT470BG = 5, /* 2.8 gamma */
SDL_TRANSFER_CHARACTERISTICS_BT601 = 6,
SDL_TRANSFER_CHARACTERISTICS_SMPTE240 = 7,
SDL_TRANSFER_CHARACTERISTICS_LINEAR = 8,
SDL_TRANSFER_CHARACTERISTICS_LOG100 = 9,
SDL_TRANSFER_CHARACTERISTICS_LOG100_SQRT10 = 10,
SDL_TRANSFER_CHARACTERISTICS_IEC61966 = 11,
SDL_TRANSFER_CHARACTERISTICS_BT1361 = 12,
SDL_TRANSFER_CHARACTERISTICS_SRGB = 13,
SDL_TRANSFER_CHARACTERISTICS_BT2020_10BIT = 14,
SDL_TRANSFER_CHARACTERISTICS_BT2020_12BIT = 15,
SDL_TRANSFER_CHARACTERISTICS_SMPTE2084 = 16, /* PQ */
SDL_TRANSFER_CHARACTERISTICS_SMPTE428 = 17,
SDL_TRANSFER_CHARACTERISTICS_HLG = 18
} SDL_TransferCharacteristics;

/**
* The formula used for converting between YUV and RGB
*/
Expand Down Expand Up @@ -213,6 +260,14 @@ extern DECLSPEC void SDLCALL SDL_DestroySurface(SDL_Surface *surface);
/**
* Get the properties associated with a surface.
*
* The following properties are understood by SDL:
*
* - `SDL_PROPERTY_SURFACE_HDR_BOOLEAN`: true if this surface has HDR properties
* - `SDL_PROPERTY_SURFACE_COLOR_PRIMARIES_NUMBER`: an SDL_ColorPrimaries value describing the surface colorspace
* - `SDL_PROPERTY_SURFACE_TRANSFER_CHARACTERISTICS_NUMBER`: an SDL_TransferCharacteristics value describing the surface colorspace
* - `SDL_PROPERTY_SURFACE_MAXCLL_NUMBER`: MaxCLL (Maximum Content Light Level) indicates the maximum light level of any single pixel (in cd/m2 or nits) of the entire playback sequence. 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.
* - `SDL_PROPERTY_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 entire playback sequence. MaxFALL is calculated by averaging the decoded luminance values of all the pixels within a frame. MaxFALL is usually much lower than MaxCLL.
*
* \param surface the SDL_Surface structure to query
* \returns a valid property ID on success or 0 on failure; call
* SDL_GetError() for more information.
Expand All @@ -224,6 +279,12 @@ extern DECLSPEC void SDLCALL SDL_DestroySurface(SDL_Surface *surface);
*/
extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSurfaceProperties(SDL_Surface *surface);

#define SDL_PROPERTY_SURFACE_HDR_BOOLEAN "SDL.surface.HDR"
#define SDL_PROPERTY_SURFACE_COLOR_PRIMARIES_NUMBER "SDL.surface.color_primaries"
#define SDL_PROPERTY_SURFACE_TRANSFER_CHARACTERISTICS_NUMBER "SDL.surface.transfer_characteristics"
#define SDL_PROPERTY_SURFACE_MAXCLL_NUMBER "SDL.surface.maxCLL"
#define SDL_PROPERTY_SURFACE_MAXFALL_NUMBER "SDL.surface.maxFALL"

/**
* Set the palette used by a surface.
*
Expand Down
88 changes: 70 additions & 18 deletions src/video/SDL_blit.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,23 @@ static SDL_BlitFunc SDL_ChooseBlitFunc(Uint32 src_format, Uint32 dst_format, int
}
#endif /* SDL_HAVE_BLIT_AUTO */

static SDL_bool IsSurfaceHDR(SDL_Surface *surface)
{
if (surface->flags & SDL_SURFACE_USES_PROPERTIES) {
SDL_PropertiesID props = SDL_GetSurfaceProperties(surface);
return SDL_GetBooleanProperty(props, SDL_PROPERTY_SURFACE_HDR_BOOLEAN, SDL_FALSE);
}
return SDL_FALSE;
}

/* Figure out which of many blit routines to set up on a surface */
int SDL_CalculateBlit(SDL_Surface *surface)
{
SDL_BlitFunc blit = NULL;
SDL_BlitMap *map = surface->map;
SDL_Surface *dst = map->dst;
SDL_bool src_HDR = IsSurfaceHDR(surface);
SDL_bool dst_HDR = IsSurfaceHDR(dst);

/* We don't currently support blitting to < 8 bpp surfaces */
if (dst->format->BitsPerPixel < 8) {
Expand Down Expand Up @@ -219,33 +230,74 @@ int SDL_CalculateBlit(SDL_Surface *surface)
#endif

/* Choose a standard blit function */
if (map->identity && !(map->info.flags & ~SDL_COPY_RLE_DESIRED)) {
blit = SDL_BlitCopy;
} else if (surface->format->Rloss > 8 || dst->format->Rloss > 8) {
blit = SDL_Blit_Slow;
if (src_HDR || dst_HDR) {
if (src_HDR && dst_HDR) {
/* See if they're in the same colorspace and light level */
SDL_PropertiesID src_props = SDL_GetSurfaceProperties(surface);
SDL_PropertiesID dst_props = SDL_GetSurfaceProperties(dst);
if ((SDL_GetNumberProperty(src_props, SDL_PROPERTY_SURFACE_COLOR_PRIMARIES_NUMBER, SDL_COLOR_PRIMARIES_UNKNOWN) !=
SDL_GetNumberProperty(dst_props, SDL_PROPERTY_SURFACE_COLOR_PRIMARIES_NUMBER, SDL_COLOR_PRIMARIES_UNKNOWN)) ||
(SDL_GetNumberProperty(src_props, SDL_PROPERTY_SURFACE_TRANSFER_CHARACTERISTICS_NUMBER, SDL_TRANSFER_CHARACTERISTICS_UNKNOWN) !=
SDL_GetNumberProperty(dst_props, SDL_PROPERTY_SURFACE_TRANSFER_CHARACTERISTICS_NUMBER, SDL_TRANSFER_CHARACTERISTICS_UNKNOWN)) ||
(SDL_GetNumberProperty(src_props, SDL_PROPERTY_SURFACE_MAXCLL_NUMBER, 0) !=
SDL_GetNumberProperty(dst_props, SDL_PROPERTY_SURFACE_MAXCLL_NUMBER, 0)) ||
(SDL_GetNumberProperty(src_props, SDL_PROPERTY_SURFACE_MAXFALL_NUMBER, 0) !=
SDL_GetNumberProperty(dst_props, SDL_PROPERTY_SURFACE_MAXFALL_NUMBER, 0))) {
SDL_InvalidateMap(map);
return SDL_SetError("Tone mapping between HDR surfaces not supported");
}

/* Fall through to the normal blit calculation (is this correct?) */

} else if (dst_HDR) {
SDL_InvalidateMap(map);
return SDL_SetError("Tone mapping from an SDR to an HDR surface not supported");
} else {
/* Tone mapping from an HDR surface to SDR surface */
SDL_PropertiesID props = SDL_GetSurfaceProperties(surface);
if (SDL_GetNumberProperty(props, SDL_PROPERTY_SURFACE_COLOR_PRIMARIES_NUMBER, SDL_COLOR_PRIMARIES_BT2020) == SDL_COLOR_PRIMARIES_BT2020 &&
SDL_GetNumberProperty(props, SDL_PROPERTY_SURFACE_TRANSFER_CHARACTERISTICS_NUMBER, SDL_TRANSFER_CHARACTERISTICS_SMPTE2084) == SDL_TRANSFER_CHARACTERISTICS_SMPTE2084) {
if (SDL_ISPIXELFORMAT_10BIT(surface->format->format)) {
blit = SDL_Blit_Slow_PQtoSDR;
} else {
SDL_InvalidateMap(map);
return SDL_SetError("Surface has unknown HDR pixel format");
}
} else {
SDL_InvalidateMap(map);
return SDL_SetError("Surface has unknown HDR colorspace");
}
}
}
if (!blit) {
if (map->identity && !(map->info.flags & ~SDL_COPY_RLE_DESIRED)) {
blit = SDL_BlitCopy;
} else if (surface->format->Rloss > 8 || dst->format->Rloss > 8) {
blit = SDL_Blit_Slow;
}
#if SDL_HAVE_BLIT_0
else if (surface->format->BitsPerPixel < 8 &&
SDL_ISPIXELFORMAT_INDEXED(surface->format->format)) {
blit = SDL_CalculateBlit0(surface);
}
else if (surface->format->BitsPerPixel < 8 &&
SDL_ISPIXELFORMAT_INDEXED(surface->format->format)) {
blit = SDL_CalculateBlit0(surface);
}
#endif
#if SDL_HAVE_BLIT_1
else if (surface->format->BytesPerPixel == 1 &&
SDL_ISPIXELFORMAT_INDEXED(surface->format->format)) {
blit = SDL_CalculateBlit1(surface);
}
else if (surface->format->BytesPerPixel == 1 &&
SDL_ISPIXELFORMAT_INDEXED(surface->format->format)) {
blit = SDL_CalculateBlit1(surface);
}
#endif
#if SDL_HAVE_BLIT_A
else if (map->info.flags & SDL_COPY_BLEND) {
blit = SDL_CalculateBlitA(surface);
}
else if (map->info.flags & SDL_COPY_BLEND) {
blit = SDL_CalculateBlitA(surface);
}
#endif
#if SDL_HAVE_BLIT_N
else {
blit = SDL_CalculateBlitN(surface);
}
else {
blit = SDL_CalculateBlitN(surface);
}
#endif
}
#if SDL_HAVE_BLIT_AUTO
if (!blit) {
Uint32 src_format = surface->format->format;
Expand Down
14 changes: 14 additions & 0 deletions src/video/SDL_blit.h
Original file line number Diff line number Diff line change
Expand Up @@ -360,13 +360,27 @@ extern SDL_BlitFunc SDL_CalculateBlitA(SDL_Surface *surface);
b = ((Pixel >> 2) & 0xFF); \
a = SDL_expand_byte[6][(Pixel >> 30)]; \
}
#define RGBAFLOAT_FROM_ARGB2101010(Pixel, r, g, b, a) \
{ \
r = (float)((Pixel >> 20) & 0x3FF) / 1023.0f; \
g = (float)((Pixel >> 10) & 0x3FF) / 1023.0f; \
b = (float)((Pixel >> 0) & 0x3FF) / 1023.0f; \
a = (float)SDL_expand_byte[6][(Pixel >> 30)] / 255.0f; \
}
#define RGBA_FROM_ABGR2101010(Pixel, r, g, b, a) \
{ \
r = ((Pixel >> 2) & 0xFF); \
g = ((Pixel >> 12) & 0xFF); \
b = ((Pixel >> 22) & 0xFF); \
a = SDL_expand_byte[6][(Pixel >> 30)]; \
}
#define RGBAFLOAT_FROM_ABGR2101010(Pixel, r, g, b, a) \
{ \
r = (float)((Pixel >> 0) & 0x3FF) / 1023.0f; \
g = (float)((Pixel >> 10) & 0x3FF) / 1023.0f; \
b = (float)((Pixel >> 20) & 0x3FF) / 1023.0f; \
a = (float)SDL_expand_byte[6][(Pixel >> 30)] / 255.0f; \
}
#define DISEMBLE_RGBA(buf, bpp, fmt, Pixel, r, g, b, a) \
do { \
switch (bpp) { \
Expand Down
Loading