mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2026-06-18 14:40:56 +00:00
Handle chroma co-siting in the Metal shaders
This commit is contained in:
@@ -10,6 +10,7 @@ struct CscParams
|
|||||||
{
|
{
|
||||||
float3 matrix[3];
|
float3 matrix[3];
|
||||||
float3 offsets;
|
float3 offsets;
|
||||||
|
float2 chromaOffset;
|
||||||
float bitnessScaleFactor;
|
float bitnessScaleFactor;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -25,8 +26,10 @@ fragment float4 ps_draw_biplanar(Vertex v [[ stage_in ]],
|
|||||||
texture2d<float> luminancePlane [[ texture(0) ]],
|
texture2d<float> luminancePlane [[ texture(0) ]],
|
||||||
texture2d<float> chrominancePlane [[ texture(1) ]])
|
texture2d<float> chrominancePlane [[ texture(1) ]])
|
||||||
{
|
{
|
||||||
|
float2 chromaOffset = float2(cscParams.chromaOffset.x / chrominancePlane.get_width(),
|
||||||
|
cscParams.chromaOffset.y / chrominancePlane.get_height());
|
||||||
float3 yuv = float3(luminancePlane.sample(s, v.texCoords).r,
|
float3 yuv = float3(luminancePlane.sample(s, v.texCoords).r,
|
||||||
chrominancePlane.sample(s, v.texCoords).rg);
|
chrominancePlane.sample(s, v.texCoords + chromaOffset).rg);
|
||||||
yuv *= cscParams.bitnessScaleFactor;
|
yuv *= cscParams.bitnessScaleFactor;
|
||||||
yuv -= cscParams.offsets;
|
yuv -= cscParams.offsets;
|
||||||
|
|
||||||
@@ -43,9 +46,13 @@ fragment float4 ps_draw_triplanar(Vertex v [[ stage_in ]],
|
|||||||
texture2d<float> chrominancePlaneU [[ texture(1) ]],
|
texture2d<float> chrominancePlaneU [[ texture(1) ]],
|
||||||
texture2d<float> chrominancePlaneV [[ texture(2) ]])
|
texture2d<float> chrominancePlaneV [[ texture(2) ]])
|
||||||
{
|
{
|
||||||
|
float2 chromaOffsetU = float2(cscParams.chromaOffset.x / chrominancePlaneU.get_width(),
|
||||||
|
cscParams.chromaOffset.y / chrominancePlaneU.get_height());
|
||||||
|
float2 chromaOffsetV = float2(cscParams.chromaOffset.x / chrominancePlaneV.get_width(),
|
||||||
|
cscParams.chromaOffset.y / chrominancePlaneV.get_height());
|
||||||
float3 yuv = float3(luminancePlane.sample(s, v.texCoords).r,
|
float3 yuv = float3(luminancePlane.sample(s, v.texCoords).r,
|
||||||
chrominancePlaneU.sample(s, v.texCoords).r,
|
chrominancePlaneU.sample(s, v.texCoords + chromaOffsetU).r,
|
||||||
chrominancePlaneV.sample(s, v.texCoords).r);
|
chrominancePlaneV.sample(s, v.texCoords + chromaOffsetV).r);
|
||||||
yuv *= cscParams.bitnessScaleFactor;
|
yuv *= cscParams.bitnessScaleFactor;
|
||||||
yuv -= cscParams.offsets;
|
yuv -= cscParams.offsets;
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ struct CscParams
|
|||||||
struct ParamBuffer
|
struct ParamBuffer
|
||||||
{
|
{
|
||||||
CscParams cscParams;
|
CscParams cscParams;
|
||||||
|
vector_float2 chromaOffset;
|
||||||
float bitnessScaleFactor;
|
float bitnessScaleFactor;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -313,6 +314,40 @@ public:
|
|||||||
paramBuffer.cscParams.matrix[i][2] *= uvScale;
|
paramBuffer.cscParams.matrix[i][2] *= uvScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (frame->chroma_location) {
|
||||||
|
default:
|
||||||
|
case AVCHROMA_LOC_LEFT:
|
||||||
|
paramBuffer.chromaOffset[0] = 0;
|
||||||
|
paramBuffer.chromaOffset[1] = 0.5;
|
||||||
|
break;
|
||||||
|
case AVCHROMA_LOC_CENTER:
|
||||||
|
paramBuffer.chromaOffset[0] = 0.5;
|
||||||
|
paramBuffer.chromaOffset[1] = 0.5;
|
||||||
|
break;
|
||||||
|
case AVCHROMA_LOC_TOPLEFT:
|
||||||
|
paramBuffer.chromaOffset[0] = 0;
|
||||||
|
paramBuffer.chromaOffset[1] = 0;
|
||||||
|
break;
|
||||||
|
case AVCHROMA_LOC_TOP:
|
||||||
|
paramBuffer.chromaOffset[0] = 0.5;
|
||||||
|
paramBuffer.chromaOffset[1] = 0;
|
||||||
|
break;
|
||||||
|
case AVCHROMA_LOC_BOTTOMLEFT:
|
||||||
|
paramBuffer.chromaOffset[0] = 0;
|
||||||
|
paramBuffer.chromaOffset[1] = 1.0;
|
||||||
|
break;
|
||||||
|
case AVCHROMA_LOC_BOTTOM:
|
||||||
|
paramBuffer.chromaOffset[0] = 0.5;
|
||||||
|
paramBuffer.chromaOffset[1] = 1.0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_VideoFormat & VIDEO_FORMAT_MASK_YUV444) {
|
||||||
|
// 4:4:4 has no subsampling
|
||||||
|
paramBuffer.chromaOffset[0] = 0;
|
||||||
|
paramBuffer.chromaOffset[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Set the EDR metadata for HDR10 to enable OS tonemapping
|
// Set the EDR metadata for HDR10 to enable OS tonemapping
|
||||||
if (frame->color_trc == AVCOL_TRC_SMPTE2084 && m_MasteringDisplayColorVolume != nullptr) {
|
if (frame->color_trc == AVCOL_TRC_SMPTE2084 && m_MasteringDisplayColorVolume != nullptr) {
|
||||||
m_MetalLayer.EDRMetadata = [CAEDRMetadata HDR10MetadataWithDisplayInfo:(__bridge NSData*)m_MasteringDisplayColorVolume
|
m_MetalLayer.EDRMetadata = [CAEDRMetadata HDR10MetadataWithDisplayInfo:(__bridge NSData*)m_MasteringDisplayColorVolume
|
||||||
@@ -676,6 +711,7 @@ public:
|
|||||||
|
|
||||||
m_Window = params->window;
|
m_Window = params->window;
|
||||||
m_FrameRateRange = CAFrameRateRangeMake(params->frameRate, params->frameRate, params->frameRate);
|
m_FrameRateRange = CAFrameRateRangeMake(params->frameRate, params->frameRate, params->frameRate);
|
||||||
|
m_VideoFormat = params->videoFormat;
|
||||||
|
|
||||||
id<MTLDevice> device = getMetalDevice();
|
id<MTLDevice> device = getMetalDevice();
|
||||||
if (!device) {
|
if (!device) {
|
||||||
@@ -972,6 +1008,7 @@ private:
|
|||||||
id<MTLCommandQueue> m_CommandQueue;
|
id<MTLCommandQueue> m_CommandQueue;
|
||||||
id<MTLTexture> m_SwMappingTextures[MAX_VIDEO_PLANES];
|
id<MTLTexture> m_SwMappingTextures[MAX_VIDEO_PLANES];
|
||||||
SDL_MetalView m_MetalView;
|
SDL_MetalView m_MetalView;
|
||||||
|
int m_VideoFormat;
|
||||||
int m_LastColorSpace;
|
int m_LastColorSpace;
|
||||||
bool m_LastFullRange;
|
bool m_LastFullRange;
|
||||||
int m_LastFrameWidth;
|
int m_LastFrameWidth;
|
||||||
|
|||||||
Reference in New Issue
Block a user