Skip to content

Commit

Permalink
Bug 1210357 - Handle VP9 colorspace BT.709 r=mattwoodrow,bas.schouten
Browse files Browse the repository at this point in the history
  • Loading branch information
Sotaro Ikeda committed Oct 18, 2016
1 parent 1989821 commit 5a134d6
Show file tree
Hide file tree
Showing 23 changed files with 9,929 additions and 9,809 deletions.
39 changes: 28 additions & 11 deletions gfx/gl/GLBlitHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "gfxUtils.h"
#include "GLBlitHelper.h"
#include "GLContext.h"
#include "GLScreenBuffer.h"
Expand Down Expand Up @@ -59,6 +60,7 @@ GLBlitHelper::GLBlitHelper(GLContext* gl)
, mSrcTexEGL(0)
, mYTexScaleLoc(-1)
, mCbCrTexScaleLoc(-1)
, mYuvColorMatrixLoc(-1)
, mTexWidth(0)
, mTexHeight(0)
, mCurYScale(1.0f)
Expand Down Expand Up @@ -171,14 +173,24 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
";
#endif
/* From Rec601:
[R] [1.1643835616438356, 0.0, 1.5960267857142858] [ Y - 16]
[G] = [1.1643835616438358, -0.3917622900949137, -0.8129676472377708] x [Cb - 128]
[B] [1.1643835616438356, 2.017232142857143, 8.862867620416422e-17] [Cr - 128]
[R] [1.1643835616438356, 0.0, 1.5960267857142858] [ Y - 16]
[G] = [1.1643835616438358, -0.3917622900949137, -0.8129676472377708] x [Cb - 128]
[B] [1.1643835616438356, 2.017232142857143, 8.862867620416422e-17] [Cr - 128]
For [0,1] instead of [0,255], and to 5 places:
[R] [1.16438, 0.00000, 1.59603] [ Y - 0.06275]
[R] [1.16438, 0.00000, 1.59603] [ Y - 0.06275]
[G] = [1.16438, -0.39176, -0.81297] x [Cb - 0.50196]
[B] [1.16438, 2.01723, 0.00000] [Cr - 0.50196]
[B] [1.16438, 2.01723, 0.00000] [Cr - 0.50196]
From Rec709:
[R] [1.1643835616438356, 4.2781193979771426e-17, 1.7927410714285714] [ Y - 16]
[G] = [1.1643835616438358, -0.21324861427372963, -0.532909328559444] x [Cb - 128]
[B] [1.1643835616438356, 2.1124017857142854, 0.0] [Cr - 128]
For [0,1] instead of [0,255], and to 5 places:
[R] [1.16438, 0.00000, 1.79274] [ Y - 0.06275]
[G] = [1.16438, -0.21325, -0.53291] x [Cb - 0.50196]
[B] [1.16438, 2.11240, 0.00000] [Cr - 0.50196]
*/
const char kTexYUVPlanarBlit_FragShaderSource[] = "\
#version 100 \n\
Expand All @@ -191,17 +203,17 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
uniform sampler2D uCrTexture; \n\
uniform vec2 uYTexScale; \n\
uniform vec2 uCbCrTexScale; \n\
uniform mat3 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) * 1.16438; \n\
y = y - 0.06275; \n\
cb = cb - 0.50196; \n\
cr = cr - 0.50196; \n\
gl_FragColor.r = y + cr * 1.59603; \n\
gl_FragColor.g = y - 0.81297 * cr - 0.39176 * cb; \n\
gl_FragColor.b = y + cb * 2.01723; \n\
vec3 yuv = vec3(y, cb, cr); \n\
gl_FragColor.rgb = uYuvColorMatrix * yuv; \n\
gl_FragColor.a = 1.0; \n\
} \n\
";
Expand Down Expand Up @@ -409,13 +421,15 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
GLint texCb = mGL->fGetUniformLocation(program, "uCbTexture");
GLint texCr = mGL->fGetUniformLocation(program, "uCrTexture");
mYTexScaleLoc = mGL->fGetUniformLocation(program, "uYTexScale");
mCbCrTexScaleLoc= mGL->fGetUniformLocation(program, "uCbCrTexScale");
mCbCrTexScaleLoc = mGL->fGetUniformLocation(program, "uCbCrTexScale");
mYuvColorMatrixLoc = mGL->fGetUniformLocation(program, "uYuvColorMatrix");

DebugOnly<bool> hasUniformLocations = texY != -1 &&
texCb != -1 &&
texCr != -1 &&
mYTexScaleLoc != -1 &&
mCbCrTexScaleLoc != -1;
mCbCrTexScaleLoc != -1 &&
mYuvColorMatrixLoc != -1;
MOZ_ASSERT(hasUniformLocations, "uniforms not found");

mGL->fUniform1i(texY, Channel_Y);
Expand Down Expand Up @@ -790,6 +804,9 @@ GLBlitHelper::BlitPlanarYCbCrImage(layers::PlanarYCbCrImage* yuvImage)
mGL->fUniform2f(mCbCrTexScaleLoc, (float)yuvData->mCbCrSize.width/yuvData->mCbCrStride, 1.0f);
}

float* yuvToRgb = gfxUtils::Get3x3YuvColorMatrix(yuvData->mYUVColorSpace);
mGL->fUniformMatrix3fv(mYuvColorMatrixLoc, 1, 0, yuvToRgb);

mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
for (int i = 0; i < 3; i++) {
mGL->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
Expand Down
1 change: 1 addition & 0 deletions gfx/gl/GLBlitHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class GLBlitHelper final
GLuint mSrcTexEGL;
GLint mYTexScaleLoc;
GLint mCbCrTexScaleLoc;
GLint mYuvColorMatrixLoc;
int mTexWidth;
int mTexHeight;

Expand Down
35 changes: 31 additions & 4 deletions gfx/layers/Effects.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,14 @@ struct EffectRGB : public TexturedEffect

struct EffectYCbCr : public TexturedEffect
{
EffectYCbCr(TextureSource *aSource, gfx::SamplingFilter aSamplingFilter)
EffectYCbCr(TextureSource *aSource, YUVColorSpace aYUVColorSpace, gfx::SamplingFilter aSamplingFilter)
: TexturedEffect(EffectTypes::YCBCR, aSource, false, aSamplingFilter)
, mYUVColorSpace(aYUVColorSpace)
{}

virtual const char* Name() { return "EffectYCbCr"; }

YUVColorSpace mYUVColorSpace;
};

struct EffectNV12 : public TexturedEffect
Expand Down Expand Up @@ -239,12 +242,12 @@ CreateTexturedEffect(gfx::SurfaceFormat aFormat,
case gfx::SurfaceFormat::R8G8B8A8:
result = new EffectRGB(aSource, isAlphaPremultiplied, aSamplingFilter);
break;
case gfx::SurfaceFormat::YUV:
result = new EffectYCbCr(aSource, aSamplingFilter);
break;
case gfx::SurfaceFormat::NV12:
result = new EffectNV12(aSource, aSamplingFilter);
break;
case gfx::SurfaceFormat::YUV:
MOZ_ASSERT_UNREACHABLE("gfx::SurfaceFormat::YUV is invalid");
break;
default:
NS_WARNING("unhandled program type");
break;
Expand All @@ -255,6 +258,30 @@ CreateTexturedEffect(gfx::SurfaceFormat aFormat,
return result.forget();
}

inline already_AddRefed<TexturedEffect>
CreateTexturedEffect(TextureHost* aHost,
TextureSource* aSource,
const gfx::SamplingFilter aSamplingFilter,
bool isAlphaPremultiplied,
const LayerRenderState &state = LayerRenderState())
{
MOZ_ASSERT(aHost);
MOZ_ASSERT(aSource);

RefPtr<TexturedEffect> result;
if (aHost->GetReadFormat() == gfx::SurfaceFormat::YUV) {
MOZ_ASSERT(aHost->GetYUVColorSpace() != YUVColorSpace::UNKNOWN);
result = new EffectYCbCr(aSource, aHost->GetYUVColorSpace(), aSamplingFilter);
} else {
result = CreateTexturedEffect(aHost->GetReadFormat(),
aSource,
aSamplingFilter,
isAlphaPremultiplied,
state);
}
return result.forget();
}

/**
* Create a textured effect based on aSource format and the presence of
* aSourceOnWhite.
Expand Down
4 changes: 2 additions & 2 deletions gfx/layers/composite/ImageHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ ImageHost::Composite(LayerComposite* aLayer,
bool isAlphaPremultiplied =
!(mCurrentTextureHost->GetFlags() & TextureFlags::NON_PREMULTIPLIED);
RefPtr<TexturedEffect> effect =
CreateTexturedEffect(mCurrentTextureHost->GetReadFormat(),
CreateTexturedEffect(mCurrentTextureHost,
mCurrentTextureSource.get(), aSamplingFilter, isAlphaPremultiplied,
GetRenderState());
if (!effect) {
Expand Down Expand Up @@ -611,7 +611,7 @@ ImageHost::GenEffect(const gfx::SamplingFilter aSamplingFilter)
isAlphaPremultiplied = false;
}

return CreateTexturedEffect(mCurrentTextureHost->GetReadFormat(),
return CreateTexturedEffect(mCurrentTextureHost,
mCurrentTextureSource,
aSamplingFilter,
isAlphaPremultiplied,
Expand Down
10 changes: 10 additions & 0 deletions gfx/layers/composite/TextureHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,16 @@ BufferTextureHost::GetFormat() const
return mFormat;
}

YUVColorSpace
BufferTextureHost::GetYUVColorSpace() const
{
if (mFormat == gfx::SurfaceFormat::YUV) {
const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
return desc.yUVColorSpace();
}
return YUVColorSpace::UNKNOWN;
}

bool
BufferTextureHost::MaybeUpload(nsIntRegion *aRegion)
{
Expand Down
4 changes: 4 additions & 0 deletions gfx/layers/composite/TextureHost.h
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,8 @@ class TextureHost
*/
virtual gfx::SurfaceFormat GetReadFormat() const { return GetFormat(); }

virtual YUVColorSpace GetYUVColorSpace() const { return YUVColorSpace::UNKNOWN; }

/**
* Called during the transaction. The TextureSource may or may not be composited.
*
Expand Down Expand Up @@ -701,6 +703,8 @@ class BufferTextureHost : public TextureHost
*/
virtual gfx::SurfaceFormat GetFormat() const override;

virtual YUVColorSpace GetYUVColorSpace() const override;

virtual gfx::IntSize GetSize() const override { return mSize; }

virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override;
Expand Down
4 changes: 4 additions & 0 deletions gfx/layers/d3d11/CompositorD3D11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "gfxPrefs.h"
#include "gfxConfig.h"
#include "gfxCrashReporterUtils.h"
#include "gfxUtils.h"
#include "mozilla/gfx/StackArray.h"
#include "mozilla/Services.h"
#include "mozilla/widget/WinCompositorWidget.h"
Expand Down Expand Up @@ -888,6 +889,9 @@ CompositorD3D11::DrawQuad(const gfx::Rect& aRect,
return;
}

float* yuvToRgb = gfxUtils::Get4x3YuvColorMatrix(ycbcrEffect->mYUVColorSpace);
memcpy(&mPSConstants.yuvColorMatrix, yuvToRgb, sizeof(mPSConstants.yuvColorMatrix));

TextureSourceD3D11* sourceY = source->GetSubSource(Y)->AsSourceD3D11();
TextureSourceD3D11* sourceCb = source->GetSubSource(Cb)->AsSourceD3D11();
TextureSourceD3D11* sourceCr = source->GetSubSource(Cr)->AsSourceD3D11();
Expand Down
1 change: 1 addition & 0 deletions gfx/layers/d3d11/CompositorD3D11.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ struct PixelShaderConstants
float layerColor[4];
float layerOpacity[4];
int blendConfig[4];
float yuvColorMatrix[3][4];
};

struct DeviceAttachmentsD3D11;
Expand Down
24 changes: 17 additions & 7 deletions gfx/layers/d3d11/CompositorD3D11.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ float fLayerOpacity : register(ps, c1);
// w = is premultiplied
uint4 iBlendConfig : register(ps, c2);

row_major float3x3 mYuvColorMatrix : register(ps, c3);

sampler sSampler : register(ps, s0);

// The mix-blend mega shader uses all variables, so we have to make sure they
Expand Down Expand Up @@ -190,19 +192,27 @@ For [0,1] instead of [0,255], and to 5 places:
[R] [1.16438, 0.00000, 1.59603] [ Y - 0.06275]
[G] = [1.16438, -0.39176, -0.81297] x [Cb - 0.50196]
[B] [1.16438, 2.01723, 0.00000] [Cr - 0.50196]
From Rec709:
[R] [1.1643835616438356, 4.2781193979771426e-17, 1.7927410714285714] [ Y - 16]
[G] = [1.1643835616438358, -0.21324861427372963, -0.532909328559444] x [Cb - 128]
[B] [1.1643835616438356, 2.1124017857142854, 0.0] [Cr - 128]
For [0,1] instead of [0,255], and to 5 places:
[R] [1.16438, 0.00000, 1.79274] [ Y - 0.06275]
[G] = [1.16438, -0.21325, -0.53291] x [Cb - 0.50196]
[B] [1.16438, 2.11240, 0.00000] [Cr - 0.50196]
*/
float4 CalculateYCbCrColor(const float2 aTexCoords)
{
float4 yuv;
float3 yuv;
float4 color;

yuv.r = tCr.Sample(sSampler, aTexCoords).r - 0.50196;
yuv.g = tY.Sample(sSampler, aTexCoords).r - 0.06275;
yuv.b = tCb.Sample(sSampler, aTexCoords).r - 0.50196;
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;

color.r = yuv.g * 1.16438 + yuv.r * 1.59603;
color.g = yuv.g * 1.16438 - 0.81297 * yuv.r - 0.39176 * yuv.b;
color.b = yuv.g * 1.16438 + yuv.b * 2.01723;
color.rgb = mul(mYuvColorMatrix, yuv);
color.a = 1.0f;

return color;
Expand Down
Loading

0 comments on commit 5a134d6

Please sign in to comment.