Issue #2101 - Part 7: Add color range support on GPUs

This commit is contained in:
u3shit 2023-02-25 00:29:56 +01:00 committed by roytam1
commit 687733f9d1
18 changed files with 106 additions and 74 deletions

View file

@ -171,18 +171,14 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
uniform sampler2D uCrTexture; \n\
uniform vec2 uYTexScale; \n\
uniform vec2 uCbCrTexScale; \n\
uniform mat3 uYuvColorMatrix; \n\
uniform mat4 uYuvColorMatrix; \n\
void main() \n\
{ \n\
float y = texture2D(uYTexture, vTexCoord * uYTexScale).r; \n\
float cb = texture2D(uCbTexture, vTexCoord * uCbCrTexScale).r; \n\
float cr = texture2D(uCrTexture, vTexCoord * uCbCrTexScale).r; \n\
y = y - 0.06275; \n\
cb = cb - 0.50196; \n\
cr = cr - 0.50196; \n\
vec3 yuv = vec3(y, cb, cr); \n\
gl_FragColor.rgb = uYuvColorMatrix * yuv; \n\
gl_FragColor.a = 1.0; \n\
vec4 yuv = vec4(y, cb, cr, 1.0); \n\
gl_FragColor = uYuvColorMatrix * yuv; \n\
} \n\
";
@ -667,8 +663,8 @@ GLBlitHelper::BlitPlanarYCbCrImage(layers::PlanarYCbCrImage* yuvImage)
mGL->fUniform2f(mCbCrTexScaleLoc, (float)yuvData->mCbCrSize.width/yuvData->mCbCrStride, 1.0f);
}
const float* yuvToRgb = gfxUtils::Get3x3YuvColorMatrix(yuvData->mYUVColorSpace);
mGL->fUniformMatrix3fv(mYuvColorMatrixLoc, 1, 0, yuvToRgb);
const float* yuvToRgb = gfxUtils::YuvToRgbMatrix4x4ColumnMajor(yuvData->mYUVColorSpace, yuvData->mColorRange);
mGL->fUniformMatrix4fv(mYuvColorMatrixLoc, 1, 0, yuvToRgb);
mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
for (int i = 0; i < 3; i++) {

View file

@ -158,14 +158,17 @@ struct EffectRGB : public TexturedEffect
struct EffectYCbCr : public TexturedEffect
{
EffectYCbCr(TextureSource *aSource, YUVColorSpace aYUVColorSpace, gfx::SamplingFilter aSamplingFilter)
EffectYCbCr(TextureSource *aSource, YUVColorSpace aYUVColorSpace, ColorRange aColorRange,
gfx::SamplingFilter aSamplingFilter)
: TexturedEffect(EffectTypes::YCBCR, aSource, false, aSamplingFilter)
, mYUVColorSpace(aYUVColorSpace)
, mColorRange(aColorRange)
{}
virtual const char* Name() { return "EffectYCbCr"; }
YUVColorSpace mYUVColorSpace;
ColorRange mColorRange;
};
struct EffectNV12 : public TexturedEffect
@ -271,7 +274,9 @@ CreateTexturedEffect(TextureHost* aHost,
RefPtr<TexturedEffect> result;
if (aHost->GetReadFormat() == gfx::SurfaceFormat::YUV) {
MOZ_ASSERT(aHost->GetYUVColorSpace() != YUVColorSpace::UNKNOWN);
result = new EffectYCbCr(aSource, aHost->GetYUVColorSpace(), aSamplingFilter);
MOZ_ASSERT(aHost->GetColorRange() != ColorRange::UNKNOWN);
result = new EffectYCbCr(aSource, aHost->GetYUVColorSpace(), aHost->GetColorRange(),
aSamplingFilter);
} else {
result = CreateTexturedEffect(aHost->GetReadFormat(),
aSource,

View file

@ -68,6 +68,15 @@ GPUVideoTextureHost::GetYUVColorSpace() const
return YUVColorSpace::UNKNOWN;
}
ColorRange
GPUVideoTextureHost::GetColorRange() const
{
if (mWrappedTextureHost) {
return mWrappedTextureHost->GetColorRange();
}
return ColorRange::UNKNOWN;
}
gfx::IntSize
GPUVideoTextureHost::GetSize() const
{

View file

@ -36,6 +36,7 @@ public:
}
virtual YUVColorSpace GetYUVColorSpace() const override;
virtual ColorRange GetColorRange() const override;
virtual gfx::IntSize GetSize() const override;

View file

@ -828,6 +828,16 @@ BufferTextureHost::GetYUVColorSpace() const
return YUVColorSpace::UNKNOWN;
}
ColorRange
BufferTextureHost::GetColorRange() const
{
if (mFormat == gfx::SurfaceFormat::YUV) {
const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
return desc.colorRange();
}
return ColorRange::UNKNOWN;
}
bool
BufferTextureHost::MaybeUpload(nsIntRegion *aRegion)
{

View file

@ -420,6 +420,7 @@ public:
virtual gfx::SurfaceFormat GetReadFormat() const { return GetFormat(); }
virtual YUVColorSpace GetYUVColorSpace() const { return YUVColorSpace::UNKNOWN; }
virtual ColorRange GetColorRange() const { return ColorRange::UNKNOWN; }
/**
* Called during the transaction. The TextureSource may or may not be composited.
@ -672,6 +673,7 @@ public:
virtual gfx::SurfaceFormat GetFormat() const override;
virtual YUVColorSpace GetYUVColorSpace() const override;
virtual ColorRange GetColorRange() const override;
virtual gfx::IntSize GetSize() const override { return mSize; }

View file

@ -886,7 +886,8 @@ CompositorD3D11::DrawQuad(const gfx::Rect& aRect,
return;
}
const float* yuvToRgb = gfxUtils::Get4x3YuvColorMatrix(ycbcrEffect->mYUVColorSpace);
const float* yuvToRgb = gfxUtils::YuvToRgbMatrix4x4XRowMajor(
ycbcrEffect->mYUVColorSpace, ycbcrEffect->mColorRange);
memcpy(&mPSConstants.yuvColorMatrix, yuvToRgb, sizeof(mPSConstants.yuvColorMatrix));
TextureSourceD3D11* sourceY = source->GetSubSource(Y)->AsSourceD3D11();

View file

@ -35,7 +35,7 @@ struct PixelShaderConstants
float layerColor[4];
float layerOpacity[4];
int blendConfig[4];
float yuvColorMatrix[3][4];
float yuvColorMatrix[4][4];
};
struct DeviceAttachmentsD3D11;

View file

@ -25,7 +25,7 @@ float fLayerOpacity : register(ps, c1);
// w = is premultiplied
uint4 iBlendConfig : register(ps, c2);
row_major float3x3 mYuvColorMatrix : register(ps, c3);
row_major float4x4 mYuvColorMatrix : register(ps, c3);
sampler sSampler : register(ps, s0);
@ -205,17 +205,14 @@ For [0,1] instead of [0,255], and to 5 places:
*/
float4 CalculateYCbCrColor(const float2 aTexCoords)
{
float3 yuv;
float4 color;
float4 yuv;
yuv.x = tY.Sample(sSampler, aTexCoords).r - 0.06275;
yuv.y = tCb.Sample(sSampler, aTexCoords).r - 0.50196;
yuv.z = tCr.Sample(sSampler, aTexCoords).r - 0.50196;
yuv.x = tY.Sample(sSampler, aTexCoords).r;
yuv.y = tCb.Sample(sSampler, aTexCoords).r;
yuv.z = tCr.Sample(sSampler, aTexCoords).r;
yuv.w = 1.0;
color.rgb = mul(mYuvColorMatrix, yuv);
color.a = 1.0f;
return color;
return mul(mYuvColorMatrix, yuv);
}
float4 YCbCrShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target

View file

@ -361,6 +361,7 @@ public:
// Bug 1305906 fixes YUVColorSpace handling
virtual YUVColorSpace GetYUVColorSpace() const override { return YUVColorSpace::BT601; }
virtual ColorRange GetColorRange() const override { return ColorRange::LIMITED; }
virtual bool Lock() override;

View file

@ -413,7 +413,8 @@ CompositorD3D9::DrawQuad(const gfx::Rect &aRect,
}
const float* yuvToRgb = gfxUtils::Get4x3YuvColorMatrix(ycbcrEffect->mYUVColorSpace);
const float* yuvToRgb = gfxUtils::YuvToRgbMatrix4x4XRowMajor(
ycbcrEffect->mYUVColorSpace, ycbcrEffect->mColorRange);
d3d9Device->SetPixelShaderConstantF(CBmYuvColorMatrix, yuvToRgb, 3);
TextureSourceD3D9* sourceY = source->GetSubSource(Y)->AsSourceD3D9();

View file

@ -18,7 +18,7 @@ sampler s2DMask;
float fLayerOpacity;
float4 fLayerColor;
row_major float3x3 mYuvColorMatrix : register(ps, c1);
row_major float4x4 mYuvColorMatrix : register(ps, c1);
struct VS_INPUT {
float4 vPosition : POSITION;
@ -162,17 +162,14 @@ For [0,1] instead of [0,255], and to 5 places:
*/
float4 YCbCrShader(const VS_OUTPUT aVertex) : COLOR
{
float3 yuv;
float4 color;
float4 yuv;
yuv.x = tex2D(s2DY, aVertex.vTexCoords).a - 0.06275;
yuv.y = tex2D(s2DCb, aVertex.vTexCoords).a - 0.50196;
yuv.z = tex2D(s2DCr, aVertex.vTexCoords).a - 0.50196;
yuv.x = tY.Sample(sSampler, aTexCoords).r;
yuv.y = tCb.Sample(sSampler, aTexCoords).r;
yuv.z = tCr.Sample(sSampler, aTexCoords).r;
yuv.w = 1.0;
color.rgb = mul(mYuvColorMatrix, yuv);
color.a = 1.0f;
return color * fLayerOpacity;
return mul(mYuvColorMatrix, yuv);
}
float4 SolidColorShader(const VS_OUTPUT aVertex) : COLOR

View file

@ -368,6 +368,7 @@ public:
// Bug 1305906 fixes YUVColorSpace handling
virtual YUVColorSpace GetYUVColorSpace() const override { return YUVColorSpace::BT601; }
virtual ColorRange GetColorRange() const override { return ColorRange::LIMITED; }
virtual bool Lock() override;
virtual void Unlock() override;

View file

@ -1303,7 +1303,7 @@ CompositorOGL::DrawGeometry(const Geometry& aGeometry,
program->SetYCbCrTextureUnits(Y, Cb, Cr);
program->SetTextureTransform(Matrix4x4());
program->SetYUVColorSpace(effectYCbCr->mYUVColorSpace);
program->SetYUVColorSpace(effectYCbCr->mYUVColorSpace, effectYCbCr->mColorRange);
if (maskType != MaskType::MaskNone) {
BindMaskForProgram(program, sourceMask, LOCAL_GL_TEXTURE3, maskQuadTransform);

View file

@ -377,7 +377,7 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig)
fs << "uniform sampler2D uYTexture;" << endl;
fs << "uniform sampler2D uCbTexture;" << endl;
fs << "uniform sampler2D uCrTexture;" << endl;
fs << "uniform mat3 uYuvColorMatrix;" << endl;
fs << "uniform mat4 uYuvColorMatrix;" << endl;
} else if (aConfig.mFeatures & ENABLE_TEXTURE_NV12) {
fs << "uniform " << sampler2D << " uYTexture;" << endl;
fs << "uniform " << sampler2D << " uCbTexture;" << endl;
@ -436,12 +436,8 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig)
}
}
fs << " y = y - 0.06275;" << endl;
fs << " cb = cb - 0.50196;" << endl;
fs << " cr = cr - 0.50196;" << endl;
fs << " vec3 yuv = vec3(y, cb, cr);" << endl;
fs << " color.rgb = uYuvColorMatrix * yuv;" << endl;
fs << " color.a = 1.0;" << endl;
fs << " vec4 yuv = vec4(y, cb, cr, 1.0);" << endl;
fs << " color = uYuvColorMatrix * yuv;" << endl;
} else if (aConfig.mFeatures & ENABLE_TEXTURE_COMPONENT_ALPHA) {
if (aConfig.mFeatures & ENABLE_TEXTURE_RECT) {
fs << " COLOR_PRECISION vec3 onBlack = " << texture2D << "(uBlackTexture, coord * uTexCoordMultiplier).rgb;" << endl;
@ -964,10 +960,10 @@ ShaderProgramOGL::SetBlurRadius(float aRX, float aRY)
}
void
ShaderProgramOGL::SetYUVColorSpace(YUVColorSpace aYUVColorSpace)
ShaderProgramOGL::SetYUVColorSpace(YUVColorSpace aYUVColorSpace, ColorRange aColorRange)
{
const float* yuvToRgb = gfxUtils::Get3x3YuvColorMatrix(aYUVColorSpace);
SetMatrix3fvUniform(KnownUniform::YuvColorMatrix, yuvToRgb);
const float* yuvToRgb = gfxUtils::YuvToRgbMatrix4x4ColumnMajor(aYUVColorSpace, aColorRange);
SetMatrixUniform(KnownUniform::YuvColorMatrix, yuvToRgb);
}
} // namespace layers

View file

@ -479,7 +479,7 @@ public:
SetUniform(KnownUniform::CbCrTexCoordMultiplier, 2, f);
}
void SetYUVColorSpace(YUVColorSpace aYUVColorSpace);
void SetYUVColorSpace(YUVColorSpace aYUVColorSpace, ColorRange aColorRange);
// Set whether we want the component alpha shader to return the color
// vector (pass 1, false) or the alpha vector (pass2, true). With support

View file

@ -1084,59 +1084,71 @@ gfxUtils::EncodeSourceSurface(SourceSurface* aSurface,
// https://jdashg.github.io/misc/colors/from-coeffs.html
const float kBT601NarrowYCbCrToRGB_RowMajor[16] = {
1.16438f, 0.00000f, 1.59603f, -0.87420f, 1.16438f, -0.39176f,
-0.81297f, 0.53167f, 1.16438f, 2.01723f, 0.00000f, -1.08563f,
0.00000f, 0.00000f, 0.00000f, 1.00000f};
1.16438f, 0.00000f, 1.59603f, -0.87420f,
1.16438f, -0.39176f, -0.81297f, 0.53167f,
1.16438f, 2.01723f, 0.00000f, -1.08563f,
0.00000f, 0.00000f, 0.00000f, 1.00000f};
const float kBT601FullYCbCrToRGB_RowMajor[16] = {
1.00000f, 0.00000f, 1.40752f, -0.70652f,
1.00000f, -0.34549f, -0.71695f, 0.53330f,
1.00000f, 1.77898f, -0.00000f, -0.89298f,
0.00000f, 0.00000f, 0.00000f, 1.00000f};
const float kBT709NarrowYCbCrToRGB_RowMajor[16] = {
1.16438f, 0.00000f, 1.79274f, -0.97295f, 1.16438f, -0.21325f,
-0.53291f, 0.30148f, 1.16438f, 2.11240f, 0.00000f, -1.13340f,
0.00000f, 0.00000f, 0.00000f, 1.00000f};
1.16438f, 0.00000f, 1.79274f, -0.97295f,
1.16438f, -0.21325f, -0.53291f, 0.30148f,
1.16438f, 2.11240f, 0.00000f, -1.13340f,
0.00000f, 0.00000f, 0.00000f, 1.00000f};
const float kBT709FullYCbCrToRGB_RowMajor[16] = {
1.00000f, 0.00000f, 1.58100f, -0.79360f,
1.00000f, -0.18806f, -0.46997f, 0.33030f,
1.00000f, 1.86291f, 0.00000f, -0.93511f,
0.00000f, 0.00000f, 0.00000f, 1.00000f};
const float kIdentityNarrowYCbCrToRGB_RowMajor[16] = {
0.00000f, 0.00000f, 1.00000f, 0.00000f, 1.00000f, 0.00000f,
0.00000f, 0.00000f, 0.00000f, 1.00000f, 0.00000f, 0.00000f,
0.00000f, 0.00000f, 0.00000f, 1.00000f};
/* static */ const float*
gfxUtils::Get4x3YuvColorMatrix(YUVColorSpace aYUVColorSpace)
gfxUtils::YuvToRgbMatrix4x4XRowMajor(YUVColorSpace aYUVColorSpace, ColorRange aColorRange)
{
#define X(x) \
{ x[0], x[1], x[2], 0.0f, x[4], x[5], x[6], 0.0f, x[8], x[9], x[10], 0.0f }
static const float rec601[12] = X(kBT601NarrowYCbCrToRGB_RowMajor);
static const float rec709[12] = X(kBT709NarrowYCbCrToRGB_RowMajor);
static const float identity[12] = X(kIdentityNarrowYCbCrToRGB_RowMajor);
#undef X
switch (aYUVColorSpace) {
case YUVColorSpace::BT601:
return rec601;
return aColorRange == ColorRange::LIMITED ? kBT601NarrowYCbCrToRGB_RowMajor
: kBT601FullYCbCrToRGB_RowMajor;
case YUVColorSpace::BT709:
return rec709;
return aColorRange == ColorRange::LIMITED ? kBT709NarrowYCbCrToRGB_RowMajor
: kBT709FullYCbCrToRGB_RowMajor;
case YUVColorSpace::IDENTITY:
return identity;
return kIdentityNarrowYCbCrToRGB_RowMajor;
default:
MOZ_CRASH("Bad YUVColorSpace");
}
}
/* static */ const float*
gfxUtils::Get3x3YuvColorMatrix(YUVColorSpace aYUVColorSpace)
gfxUtils::YuvToRgbMatrix4x4ColumnMajor(YUVColorSpace aYUVColorSpace, ColorRange aColorRange)
{
#define X(x) \
{ x[0], x[4], x[8], x[1], x[5], x[9], x[2], x[6], x[10] }
{ x[0], x[4], x[8], 0.0f, \
x[1], x[5], x[9], 0.0f, \
x[2], x[6], x[10], 0.0f, \
x[3], x[7], x[11], 1.0f }
static const float rec601[9] = X(kBT601NarrowYCbCrToRGB_RowMajor);
static const float rec709[9] = X(kBT709NarrowYCbCrToRGB_RowMajor);
static const float identity[9] = X(kIdentityNarrowYCbCrToRGB_RowMajor);
static const float rec601Narrow[16] = X(kBT601NarrowYCbCrToRGB_RowMajor);
static const float rec601Full[16] = X(kBT601FullYCbCrToRGB_RowMajor);
static const float rec709Narrow[16] = X(kBT709NarrowYCbCrToRGB_RowMajor);
static const float rec709Full[16] = X(kBT709FullYCbCrToRGB_RowMajor);
static const float identity[16] = X(kIdentityNarrowYCbCrToRGB_RowMajor);
#undef X
switch (aYUVColorSpace) {
case YUVColorSpace::BT601:
return rec601;
return aColorRange == ColorRange::LIMITED ? rec601Narrow : rec601Full;
case YUVColorSpace::BT709:
return rec709;
return aColorRange == ColorRange::LIMITED ? rec709Narrow : rec709Full;
case YUVColorSpace::IDENTITY:
return identity;
default:

View file

@ -43,6 +43,7 @@ public:
typedef mozilla::gfx::SurfaceFormat SurfaceFormat;
typedef mozilla::image::ImageRegion ImageRegion;
typedef mozilla::YUVColorSpace YUVColorSpace;
typedef mozilla::ColorRange ColorRange;
/*
* Premultiply or Unpremultiply aSourceSurface, writing the result
@ -139,9 +140,11 @@ public:
/**
* Get array of yuv to rgb conversion matrix.
*/
static const float* Get4x3YuvColorMatrix(YUVColorSpace aYUVColorSpace);
static const float* YuvToRgbMatrix4x4XRowMajor(YUVColorSpace aYUVColorSpace,
ColorRange aColorRange);
static const float* Get3x3YuvColorMatrix(YUVColorSpace aYUVColorSpace);
static const float* YuvToRgbMatrix4x4ColumnMajor(YUVColorSpace aYUVColorSpace,
ColorRange aColorRange);
/**
* Creates a copy of aSurface, but having the SurfaceFormat aFormat.