mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-05-19 20:07:42 +08:00
Added support for HDR10 video on Apple platforms
This commit is contained in:
@@ -76,7 +76,9 @@ static const size_t CONSTANTS_OFFSET_DECODE_BT601_LIMITED = ALIGN_CONSTANTS(16,
|
||||
static const size_t CONSTANTS_OFFSET_DECODE_BT601_FULL = ALIGN_CONSTANTS(16, CONSTANTS_OFFSET_DECODE_BT601_LIMITED + sizeof(float) * 4 * 4);
|
||||
static const size_t CONSTANTS_OFFSET_DECODE_BT709_LIMITED = ALIGN_CONSTANTS(16, CONSTANTS_OFFSET_DECODE_BT601_FULL + sizeof(float) * 4 * 4);
|
||||
static const size_t CONSTANTS_OFFSET_DECODE_BT709_FULL = ALIGN_CONSTANTS(16, CONSTANTS_OFFSET_DECODE_BT709_LIMITED + sizeof(float) * 4 * 4);
|
||||
static const size_t CONSTANTS_LENGTH = CONSTANTS_OFFSET_DECODE_BT709_FULL + sizeof(float) * 4 * 4;
|
||||
static const size_t CONSTANTS_OFFSET_DECODE_BT2020_LIMITED = ALIGN_CONSTANTS(16, CONSTANTS_OFFSET_DECODE_BT709_FULL + sizeof(float) * 4 * 4);
|
||||
static const size_t CONSTANTS_OFFSET_DECODE_BT2020_FULL = ALIGN_CONSTANTS(16, CONSTANTS_OFFSET_DECODE_BT2020_LIMITED + sizeof(float) * 4 * 4);
|
||||
static const size_t CONSTANTS_LENGTH = CONSTANTS_OFFSET_DECODE_BT2020_FULL + sizeof(float) * 4 * 4;
|
||||
|
||||
typedef enum SDL_MetalVertexFunction
|
||||
{
|
||||
@@ -91,6 +93,7 @@ typedef enum SDL_MetalFragmentFunction
|
||||
SDL_METAL_FRAGMENT_YUV,
|
||||
SDL_METAL_FRAGMENT_NV12,
|
||||
SDL_METAL_FRAGMENT_NV21,
|
||||
SDL_METAL_FRAGMENT_HDR10,
|
||||
SDL_METAL_FRAGMENT_COUNT,
|
||||
} SDL_MetalFragmentFunction;
|
||||
|
||||
@@ -248,6 +251,8 @@ static NSString *GetFragmentFunctionName(SDL_MetalFragmentFunction function)
|
||||
return @"SDL_NV12_fragment";
|
||||
case SDL_METAL_FRAGMENT_NV21:
|
||||
return @"SDL_NV21_fragment";
|
||||
case SDL_METAL_FRAGMENT_HDR10:
|
||||
return @"SDL_HDR10_fragment";
|
||||
default:
|
||||
return nil;
|
||||
}
|
||||
@@ -387,6 +392,7 @@ void MakeShaderPipelines(METAL_RenderData *data, METAL_ShaderPipelines *pipeline
|
||||
MakePipelineCache(data, &pipelines->caches[SDL_METAL_FRAGMENT_YUV], "SDL YUV pipeline", rtformat, SDL_METAL_VERTEX_COPY, SDL_METAL_FRAGMENT_YUV);
|
||||
MakePipelineCache(data, &pipelines->caches[SDL_METAL_FRAGMENT_NV12], "SDL NV12 pipeline", rtformat, SDL_METAL_VERTEX_COPY, SDL_METAL_FRAGMENT_NV12);
|
||||
MakePipelineCache(data, &pipelines->caches[SDL_METAL_FRAGMENT_NV21], "SDL NV21 pipeline", rtformat, SDL_METAL_VERTEX_COPY, SDL_METAL_FRAGMENT_NV21);
|
||||
MakePipelineCache(data, &pipelines->caches[SDL_METAL_FRAGMENT_HDR10], "SDL HDR10 pipeline", rtformat, SDL_METAL_VERTEX_COPY, SDL_METAL_FRAGMENT_HDR10);
|
||||
}
|
||||
|
||||
static METAL_ShaderPipelines *ChooseShaderPipelines(METAL_RenderData *data, MTLPixelFormat rtformat)
|
||||
@@ -551,10 +557,8 @@ size_t GetBT601ConversionMatrix( SDL_Colorspace colorspace )
|
||||
case SDL_COLOR_RANGE_LIMITED:
|
||||
case SDL_COLOR_RANGE_UNKNOWN:
|
||||
return CONSTANTS_OFFSET_DECODE_BT601_LIMITED;
|
||||
break;
|
||||
case SDL_COLOR_RANGE_FULL:
|
||||
return CONSTANTS_OFFSET_DECODE_BT601_FULL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -567,10 +571,8 @@ size_t GetBT709ConversionMatrix(SDL_Colorspace colorspace)
|
||||
case SDL_COLOR_RANGE_LIMITED:
|
||||
case SDL_COLOR_RANGE_UNKNOWN:
|
||||
return CONSTANTS_OFFSET_DECODE_BT709_LIMITED;
|
||||
break;
|
||||
case SDL_COLOR_RANGE_FULL:
|
||||
return CONSTANTS_OFFSET_DECODE_BT709_FULL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -582,11 +584,9 @@ size_t GetBT2020ConversionMatrix(SDL_Colorspace colorspace)
|
||||
switch (SDL_COLORSPACERANGE(colorspace)) {
|
||||
case SDL_COLOR_RANGE_LIMITED:
|
||||
case SDL_COLOR_RANGE_UNKNOWN:
|
||||
return 0;
|
||||
break;
|
||||
return CONSTANTS_OFFSET_DECODE_BT2020_LIMITED;
|
||||
case SDL_COLOR_RANGE_FULL:
|
||||
return 0;
|
||||
break;
|
||||
return CONSTANTS_OFFSET_DECODE_BT2020_FULL;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -671,6 +671,9 @@ static int METAL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL
|
||||
case SDL_PIXELFORMAT_NV21:
|
||||
pixfmt = MTLPixelFormatR8Unorm;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_P010:
|
||||
pixfmt = MTLPixelFormatR16Unorm;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_RGBA64_FLOAT:
|
||||
pixfmt = MTLPixelFormatRGBA16Float;
|
||||
break;
|
||||
@@ -706,8 +709,8 @@ static int METAL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL
|
||||
|
||||
mtltextureUv = nil;
|
||||
#if SDL_HAVE_YUV
|
||||
yuv = (texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12);
|
||||
nv12 = (texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21);
|
||||
yuv = (texture->format == SDL_PIXELFORMAT_IYUV || texture->format == SDL_PIXELFORMAT_YV12);
|
||||
nv12 = (texture->format == SDL_PIXELFORMAT_NV12 || texture->format == SDL_PIXELFORMAT_NV21 || texture->format == SDL_PIXELFORMAT_P010);
|
||||
|
||||
if (yuv) {
|
||||
mtltexdesc.pixelFormat = MTLPixelFormatR8Unorm;
|
||||
@@ -715,6 +718,10 @@ static int METAL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL
|
||||
mtltexdesc.height = (texture->h + 1) / 2;
|
||||
mtltexdesc.textureType = MTLTextureType2DArray;
|
||||
mtltexdesc.arrayLength = 2;
|
||||
} else if (texture->format == SDL_PIXELFORMAT_P010) {
|
||||
mtltexdesc.pixelFormat = MTLPixelFormatRG16Unorm;
|
||||
mtltexdesc.width = (texture->w + 1) / 2;
|
||||
mtltexdesc.height = (texture->h + 1) / 2;
|
||||
} else if (nv12) {
|
||||
mtltexdesc.pixelFormat = MTLPixelFormatRG8Unorm;
|
||||
mtltexdesc.width = (texture->w + 1) / 2;
|
||||
@@ -750,6 +757,8 @@ static int METAL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL
|
||||
texturedata.fragmentFunction = SDL_METAL_FRAGMENT_NV12;
|
||||
} else if (texture->format == SDL_PIXELFORMAT_NV21) {
|
||||
texturedata.fragmentFunction = SDL_METAL_FRAGMENT_NV21;
|
||||
} else if (texture->format == SDL_PIXELFORMAT_P010) {
|
||||
texturedata.fragmentFunction = SDL_METAL_FRAGMENT_HDR10;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@@ -2011,6 +2020,8 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, SDL_PropertiesID c
|
||||
SDL_memcpy(constantdata + CONSTANTS_OFFSET_DECODE_BT601_FULL, SDL_GetYCbCRtoRGBConversionMatrix(SDL_COLORSPACE_BT601_FULL, 0, 0, 8), YCbCr_shader_matrix_size);
|
||||
SDL_memcpy(constantdata + CONSTANTS_OFFSET_DECODE_BT709_LIMITED, SDL_GetYCbCRtoRGBConversionMatrix(SDL_COLORSPACE_BT709_LIMITED, 0, 0, 8), YCbCr_shader_matrix_size);
|
||||
SDL_memcpy(constantdata + CONSTANTS_OFFSET_DECODE_BT709_FULL, SDL_GetYCbCRtoRGBConversionMatrix(SDL_COLORSPACE_BT709_FULL, 0, 0, 8), YCbCr_shader_matrix_size);
|
||||
SDL_memcpy(constantdata + CONSTANTS_OFFSET_DECODE_BT2020_LIMITED, SDL_GetYCbCRtoRGBConversionMatrix(SDL_COLORSPACE_BT2020_LIMITED, 0, 0, 10), YCbCr_shader_matrix_size);
|
||||
SDL_memcpy(constantdata + CONSTANTS_OFFSET_DECODE_BT2020_FULL, SDL_GetYCbCRtoRGBConversionMatrix(SDL_COLORSPACE_BT2020_FULL, 0, 0, 10), YCbCr_shader_matrix_size);
|
||||
|
||||
mtlbufquadindicesstaging = [data.mtldevice newBufferWithLength:indicessize options:MTLResourceStorageModeShared];
|
||||
|
||||
@@ -2139,7 +2150,7 @@ SDL_RenderDriver METAL_RenderDriver = {
|
||||
{
|
||||
"metal",
|
||||
(SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
|
||||
8,
|
||||
9,
|
||||
{ SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_PIXELFORMAT_ABGR8888,
|
||||
SDL_PIXELFORMAT_RGBA64_FLOAT,
|
||||
@@ -2147,7 +2158,8 @@ SDL_RenderDriver METAL_RenderDriver = {
|
||||
SDL_PIXELFORMAT_YV12,
|
||||
SDL_PIXELFORMAT_IYUV,
|
||||
SDL_PIXELFORMAT_NV12,
|
||||
SDL_PIXELFORMAT_NV21 },
|
||||
SDL_PIXELFORMAT_NV21,
|
||||
SDL_PIXELFORMAT_P010 },
|
||||
0,
|
||||
0,
|
||||
}
|
||||
|
||||
@@ -34,6 +34,19 @@ float sRGBfromLinear(float v)
|
||||
return v;
|
||||
}
|
||||
|
||||
float3 PQtoNits(float3 v)
|
||||
{
|
||||
const float c1 = 0.8359375;
|
||||
const float c2 = 18.8515625;
|
||||
const float c3 = 18.6875;
|
||||
const float oo_m1 = 1.0 / 0.1593017578125;
|
||||
const float oo_m2 = 1.0 / 78.84375;
|
||||
|
||||
float3 num = max(pow(abs(v), oo_m2) - c1, 0.0);
|
||||
float3 den = c2 - c3 * pow(abs(v), oo_m2);
|
||||
return 10000.0 * pow(abs(num / den), oo_m1);
|
||||
}
|
||||
|
||||
float4 GetOutputColor(float4 rgba, float color_scale)
|
||||
{
|
||||
float4 output;
|
||||
@@ -215,3 +228,35 @@ fragment float4 SDL_NV21_fragment(CopyVertexOutput vert [[stage_in]],
|
||||
return GetOutputColorFromSRGB(rgb, c.scRGB_output, c.color_scale) * vert.color;
|
||||
}
|
||||
|
||||
fragment float4 SDL_HDR10_fragment(CopyVertexOutput vert [[stage_in]],
|
||||
constant ShaderConstants &c [[buffer(0)]],
|
||||
constant YUVDecode &decode [[buffer(1)]],
|
||||
texture2d<float> texY [[texture(0)]],
|
||||
texture2d<float> texUV [[texture(1)]],
|
||||
sampler s [[sampler(0)]])
|
||||
{
|
||||
const float3x3 mat2020to709 = {
|
||||
{ 1.660496, -0.587656, -0.072840 },
|
||||
{ -0.124547, 1.132895, -0.008348 },
|
||||
{ -0.018154, -0.100597, 1.118751 }
|
||||
};
|
||||
|
||||
float3 yuv;
|
||||
yuv.x = texY.sample(s, vert.texcoord).r;
|
||||
yuv.yz = texUV.sample(s, vert.texcoord).rg;
|
||||
|
||||
float3 rgb;
|
||||
yuv += decode.offset;
|
||||
rgb.r = dot(yuv, decode.Rcoeff);
|
||||
rgb.g = dot(yuv, decode.Gcoeff);
|
||||
rgb.b = dot(yuv, decode.Bcoeff);
|
||||
|
||||
rgb = PQtoNits(rgb);
|
||||
|
||||
rgb = rgb * mat2020to709;
|
||||
|
||||
rgb = scRGBfromNits(rgb);
|
||||
|
||||
return GetOutputColorFromSCRGB(rgb, c.scRGB_output, c.color_scale) * vert.color;
|
||||
}
|
||||
|
||||
|
||||
+2554
-2154
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+2446
-2062
File diff suppressed because it is too large
Load Diff
+2554
-2154
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -815,10 +815,8 @@ static const float *SDL_GetBT601ConversionMatrix( SDL_Colorspace colorspace )
|
||||
case SDL_COLOR_RANGE_LIMITED:
|
||||
case SDL_COLOR_RANGE_UNKNOWN:
|
||||
return mat_BT601_Limited_8bit;
|
||||
break;
|
||||
case SDL_COLOR_RANGE_FULL:
|
||||
return mat_BT601_Full_8bit;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -831,10 +829,8 @@ static const float *SDL_GetBT709ConversionMatrix(SDL_Colorspace colorspace)
|
||||
case SDL_COLOR_RANGE_LIMITED:
|
||||
case SDL_COLOR_RANGE_UNKNOWN:
|
||||
return mat_BT709_Limited_8bit;
|
||||
break;
|
||||
case SDL_COLOR_RANGE_FULL:
|
||||
return mat_BT709_Full_8bit;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -847,10 +843,8 @@ static const float *SDL_GetBT2020ConversionMatrix(SDL_Colorspace colorspace)
|
||||
case SDL_COLOR_RANGE_LIMITED:
|
||||
case SDL_COLOR_RANGE_UNKNOWN:
|
||||
return mat_BT2020_Limited_10bit;
|
||||
break;
|
||||
case SDL_COLOR_RANGE_FULL:
|
||||
return mat_BT2020_Full_10bit;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -759,6 +759,11 @@ static SDL_bool GetTextureForVideoToolboxFrame(AVFrame *frame, SDL_Texture **tex
|
||||
case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange:
|
||||
format = SDL_PIXELFORMAT_NV12;
|
||||
break;
|
||||
case kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange:
|
||||
case kCVPixelFormatType_420YpCbCr10BiPlanarFullRange:
|
||||
format = SDL_PIXELFORMAT_P010;
|
||||
HDR_video = SDL_TRUE;
|
||||
break;
|
||||
default:
|
||||
SDL_SetError("Unsupported texture format %c%c%c%c",
|
||||
(char)((nPixelBufferType >> 24) & 0xFF),
|
||||
|
||||
Reference in New Issue
Block a user