Added HDR surface properties and tone mapping from HDR to SDR
This currently only supports PQ, but can be expanded in the futuremain
parent
a71f99c71f
commit
7cd914593f
|
@ -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
|
||||
*/
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
|
|
@ -360,6 +360,13 @@ 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); \
|
||||
|
@ -367,6 +374,13 @@ extern SDL_BlitFunc SDL_CalculateBlitA(SDL_Surface *surface);
|
|||
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) { \
|
||||
|
|
|
@ -235,3 +235,248 @@ void SDL_Blit_Slow(SDL_BlitInfo *info)
|
|||
info->dst += info->dst_pitch;
|
||||
}
|
||||
}
|
||||
|
||||
static float PQtoNits(float pq)
|
||||
{
|
||||
const float c1 = 0.8359375f;
|
||||
const float c2 = 18.8515625f;
|
||||
const float c3 = 18.6875f;
|
||||
|
||||
const float oo_m1 = 1.0f / 0.1593017578125f;
|
||||
const float oo_m2 = 1.0f / 78.84375f;
|
||||
|
||||
float num = SDL_max(SDL_powf(pq, oo_m2) - c1, 0.0f);
|
||||
float den = c2 - c3 * pow(pq, oo_m2);
|
||||
|
||||
return 10000.0f * SDL_powf(num / den, oo_m1);
|
||||
}
|
||||
|
||||
static void Convert2020to709(float v[3])
|
||||
{
|
||||
static const float matrix[3][3] = {
|
||||
{ 1.660496f, -0.587656f, -0.072840f },
|
||||
{ -0.124547f, 1.132895f, -0.008348f },
|
||||
{ -0.018154f, -0.100597f, 1.118751f }
|
||||
};
|
||||
|
||||
float out[3];
|
||||
out[0] = matrix[0][0] * v[0] + matrix[0][1] * v[1] + matrix[0][2] * v[2];
|
||||
out[1] = matrix[1][0] * v[0] + matrix[1][1] * v[1] + matrix[1][2] * v[2];
|
||||
out[2] = matrix[2][0] * v[0] + matrix[2][1] * v[1] + matrix[2][2] * v[2];
|
||||
v[0] = out[0];
|
||||
v[1] = out[1];
|
||||
v[2] = out[2];
|
||||
}
|
||||
|
||||
/* This isn't really a tone mapping algorithm but it generally works well for HDR -> SDR display */
|
||||
static void PQtoSDR(float floatR, float floatG, float floatB, Uint32 *outR, Uint32 *outG, Uint32 *outB)
|
||||
{
|
||||
float v[3];
|
||||
int i;
|
||||
|
||||
v[0] = PQtoNits(floatR);
|
||||
v[1] = PQtoNits(floatG);
|
||||
v[2] = PQtoNits(floatB);
|
||||
|
||||
Convert2020to709(v);
|
||||
|
||||
for (i = 0; i < SDL_arraysize(v); ++i) {
|
||||
v[i] /= 400.0f;
|
||||
v[i] = SDL_clamp(v[i], 0.0f, 1.0f);
|
||||
v[i] = SDL_powf(v[i], 1.0f / 2.2f);
|
||||
}
|
||||
|
||||
*outR = (Uint32)(v[0] * 255);
|
||||
*outG = (Uint32)(v[1] * 255);
|
||||
*outB = (Uint32)(v[2] * 255);
|
||||
}
|
||||
|
||||
void SDL_Blit_Slow_PQtoSDR(SDL_BlitInfo *info)
|
||||
{
|
||||
const int flags = info->flags;
|
||||
const Uint32 modulateR = info->r;
|
||||
const Uint32 modulateG = info->g;
|
||||
const Uint32 modulateB = info->b;
|
||||
const Uint32 modulateA = info->a;
|
||||
Uint32 srcpixel;
|
||||
float srcFloatR, srcFloatG, srcFloatB, srcFloatA;
|
||||
Uint32 srcR, srcG, srcB, srcA;
|
||||
Uint32 dstpixel;
|
||||
Uint32 dstR, dstG, dstB, dstA;
|
||||
Uint64 srcy, srcx;
|
||||
Uint64 posy, posx;
|
||||
Uint64 incy, incx;
|
||||
SDL_PixelFormat *src_fmt = info->src_fmt;
|
||||
SDL_PixelFormat *dst_fmt = info->dst_fmt;
|
||||
int srcbpp = src_fmt->BytesPerPixel;
|
||||
int dstbpp = dst_fmt->BytesPerPixel;
|
||||
int dstfmt_val;
|
||||
Uint32 rgbmask = ~src_fmt->Amask;
|
||||
Uint32 ckey = info->colorkey & rgbmask;
|
||||
|
||||
dstfmt_val = detect_format(dst_fmt);
|
||||
|
||||
incy = ((Uint64)info->src_h << 16) / info->dst_h;
|
||||
incx = ((Uint64)info->src_w << 16) / info->dst_w;
|
||||
posy = incy / 2; /* start at the middle of pixel */
|
||||
|
||||
while (info->dst_h--) {
|
||||
Uint8 *src = 0;
|
||||
Uint8 *dst = info->dst;
|
||||
int n = info->dst_w;
|
||||
posx = incx / 2; /* start at the middle of pixel */
|
||||
srcy = posy >> 16;
|
||||
while (n--) {
|
||||
srcx = posx >> 16;
|
||||
src = (info->src + (srcy * info->src_pitch) + (srcx * srcbpp));
|
||||
|
||||
/* 10-bit pixel format */
|
||||
srcpixel = *((Uint32 *)(src));
|
||||
switch (src_fmt->format) {
|
||||
case SDL_PIXELFORMAT_XRGB2101010:
|
||||
RGBAFLOAT_FROM_ARGB2101010(srcpixel, srcFloatR, srcFloatG, srcFloatB, srcFloatA);
|
||||
srcFloatA = 1.0f;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_XBGR2101010:
|
||||
RGBAFLOAT_FROM_ABGR2101010(srcpixel, srcFloatR, srcFloatG, srcFloatB, srcFloatA);
|
||||
srcFloatA = 1.0f;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_ARGB2101010:
|
||||
RGBAFLOAT_FROM_ARGB2101010(srcpixel, srcFloatR, srcFloatG, srcFloatB, srcFloatA);
|
||||
break;
|
||||
case SDL_PIXELFORMAT_ABGR2101010:
|
||||
RGBAFLOAT_FROM_ABGR2101010(srcpixel, srcFloatR, srcFloatG, srcFloatB, srcFloatA);
|
||||
break;
|
||||
default:
|
||||
/* Unsupported pixel format */
|
||||
srcFloatR = srcFloatG = srcFloatB = srcFloatA = 0.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
PQtoSDR(srcFloatR, srcFloatG, srcFloatB, &srcR, &srcG, &srcB);
|
||||
srcA = (Uint32)(srcFloatA * 255);
|
||||
|
||||
if (flags & SDL_COPY_COLORKEY) {
|
||||
/* srcpixel isn't set for 24 bpp */
|
||||
if (srcbpp == 3) {
|
||||
srcpixel = (srcR << src_fmt->Rshift) |
|
||||
(srcG << src_fmt->Gshift) | (srcB << src_fmt->Bshift);
|
||||
}
|
||||
if ((srcpixel & rgbmask) == ckey) {
|
||||
posx += incx;
|
||||
dst += dstbpp;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ((flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL))) {
|
||||
if (FORMAT_HAS_ALPHA(dstfmt_val)) {
|
||||
DISEMBLE_RGBA(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB, dstA);
|
||||
} else if (FORMAT_HAS_NO_ALPHA(dstfmt_val)) {
|
||||
DISEMBLE_RGB(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB);
|
||||
dstA = 0xFF;
|
||||
} else {
|
||||
/* SDL_PIXELFORMAT_ARGB2101010 */
|
||||
dstpixel = *((Uint32 *)(dst));
|
||||
RGBA_FROM_ARGB2101010(dstpixel, dstR, dstG, dstB, dstA);
|
||||
}
|
||||
} else {
|
||||
/* don't care */
|
||||
dstR = dstG = dstB = dstA = 0;
|
||||
}
|
||||
|
||||
if (flags & SDL_COPY_MODULATE_COLOR) {
|
||||
srcR = (srcR * modulateR) / 255;
|
||||
srcG = (srcG * modulateG) / 255;
|
||||
srcB = (srcB * modulateB) / 255;
|
||||
}
|
||||
if (flags & SDL_COPY_MODULATE_ALPHA) {
|
||||
srcA = (srcA * modulateA) / 255;
|
||||
}
|
||||
if (flags & (SDL_COPY_BLEND | SDL_COPY_ADD)) {
|
||||
/* This goes away if we ever use premultiplied alpha */
|
||||
if (srcA < 255) {
|
||||
srcR = (srcR * srcA) / 255;
|
||||
srcG = (srcG * srcA) / 255;
|
||||
srcB = (srcB * srcA) / 255;
|
||||
}
|
||||
}
|
||||
switch (flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL)) {
|
||||
case 0:
|
||||
dstR = srcR;
|
||||
dstG = srcG;
|
||||
dstB = srcB;
|
||||
dstA = srcA;
|
||||
break;
|
||||
case SDL_COPY_BLEND:
|
||||
dstR = srcR + ((255 - srcA) * dstR) / 255;
|
||||
dstG = srcG + ((255 - srcA) * dstG) / 255;
|
||||
dstB = srcB + ((255 - srcA) * dstB) / 255;
|
||||
dstA = srcA + ((255 - srcA) * dstA) / 255;
|
||||
break;
|
||||
case SDL_COPY_ADD:
|
||||
dstR = srcR + dstR;
|
||||
if (dstR > 255) {
|
||||
dstR = 255;
|
||||
}
|
||||
dstG = srcG + dstG;
|
||||
if (dstG > 255) {
|
||||
dstG = 255;
|
||||
}
|
||||
dstB = srcB + dstB;
|
||||
if (dstB > 255) {
|
||||
dstB = 255;
|
||||
}
|
||||
break;
|
||||
case SDL_COPY_MOD:
|
||||
dstR = (srcR * dstR) / 255;
|
||||
dstG = (srcG * dstG) / 255;
|
||||
dstB = (srcB * dstB) / 255;
|
||||
break;
|
||||
case SDL_COPY_MUL:
|
||||
dstR = ((srcR * dstR) + (dstR * (255 - srcA))) / 255;
|
||||
if (dstR > 255) {
|
||||
dstR = 255;
|
||||
}
|
||||
dstG = ((srcG * dstG) + (dstG * (255 - srcA))) / 255;
|
||||
if (dstG > 255) {
|
||||
dstG = 255;
|
||||
}
|
||||
dstB = ((srcB * dstB) + (dstB * (255 - srcA))) / 255;
|
||||
if (dstB > 255) {
|
||||
dstB = 255;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (FORMAT_HAS_ALPHA(dstfmt_val)) {
|
||||
ASSEMBLE_RGBA(dst, dstbpp, dst_fmt, dstR, dstG, dstB, dstA);
|
||||
} else if (FORMAT_HAS_NO_ALPHA(dstfmt_val)) {
|
||||
ASSEMBLE_RGB(dst, dstbpp, dst_fmt, dstR, dstG, dstB);
|
||||
} else {
|
||||
/* 10-bit pixel format */
|
||||
Uint32 pixel;
|
||||
switch (dst_fmt->format) {
|
||||
case SDL_PIXELFORMAT_XRGB2101010:
|
||||
dstA = 0xFF;
|
||||
SDL_FALLTHROUGH;
|
||||
case SDL_PIXELFORMAT_ARGB2101010:
|
||||
ARGB2101010_FROM_RGBA(pixel, dstR, dstG, dstB, dstA);
|
||||
break;
|
||||
case SDL_PIXELFORMAT_XBGR2101010:
|
||||
dstA = 0xFF;
|
||||
SDL_FALLTHROUGH;
|
||||
case SDL_PIXELFORMAT_ABGR2101010:
|
||||
ABGR2101010_FROM_RGBA(pixel, dstR, dstG, dstB, dstA);
|
||||
break;
|
||||
default:
|
||||
pixel = 0;
|
||||
break;
|
||||
}
|
||||
*(Uint32 *)dst = pixel;
|
||||
}
|
||||
posx += incx;
|
||||
dst += dstbpp;
|
||||
}
|
||||
posy += incy;
|
||||
info->dst += info->dst_pitch;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,5 +25,6 @@
|
|||
#include "SDL_internal.h"
|
||||
|
||||
extern void SDL_Blit_Slow(SDL_BlitInfo *info);
|
||||
extern void SDL_Blit_Slow_PQtoSDR(SDL_BlitInfo *info);
|
||||
|
||||
#endif /* SDL_blit_slow_h_ */
|
||||
|
|
Loading…
Reference in New Issue