зеркало из https://github.com/mozilla/gecko-dev.git
Bug 950312 - Part 5: Implement SCREEN and MULTIPLY for CompositorOGL. r=mtseng
This commit is contained in:
Родитель
5aa1f5d7fe
Коммит
96efeab991
|
@ -803,7 +803,9 @@ CompositorOGL::CreateFBOWithTexture(const IntRect& aRect, bool aCopyFromSource,
|
|||
}
|
||||
|
||||
ShaderConfigOGL
|
||||
CompositorOGL::GetShaderConfigFor(Effect *aEffect, MaskType aMask) const
|
||||
CompositorOGL::GetShaderConfigFor(Effect *aEffect,
|
||||
MaskType aMask,
|
||||
gfx::CompositionOp aOp) const
|
||||
{
|
||||
ShaderConfigOGL config;
|
||||
|
||||
|
@ -841,6 +843,12 @@ CompositorOGL::GetShaderConfigFor(Effect *aEffect, MaskType aMask) const
|
|||
source->GetFormat() == gfx::SurfaceFormat::R5G6B5);
|
||||
config = ShaderConfigFromTargetAndFormat(source->GetTextureTarget(),
|
||||
source->GetFormat());
|
||||
if (aOp == gfx::CompositionOp::OP_MULTIPLY &&
|
||||
!texturedEffect->mPremultiplied) {
|
||||
// We can do these blend modes just using glBlendFunc but we need the data
|
||||
// to be premultiplied first.
|
||||
config.SetPremultiply(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -886,6 +894,40 @@ CompositorOGL::DrawLines(const std::vector<gfx::Point>& aLines, const gfx::Rect&
|
|||
}
|
||||
}
|
||||
|
||||
static bool SetBlendMode(GLContext* aGL, gfx::CompositionOp aBlendMode, bool aIsPremultiplied = true)
|
||||
{
|
||||
if (aBlendMode == gfx::CompositionOp::OP_OVER && aIsPremultiplied) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GLenum srcBlend;
|
||||
GLenum dstBlend;
|
||||
|
||||
switch (aBlendMode) {
|
||||
case gfx::CompositionOp::OP_OVER:
|
||||
MOZ_ASSERT(!aIsPremultiplied);
|
||||
srcBlend = LOCAL_GL_SRC_ALPHA;
|
||||
dstBlend = LOCAL_GL_ONE_MINUS_SRC_ALPHA;
|
||||
break;
|
||||
case gfx::CompositionOp::OP_SCREEN:
|
||||
srcBlend = aIsPremultiplied ? LOCAL_GL_ONE : LOCAL_GL_SRC_ALPHA;
|
||||
dstBlend = LOCAL_GL_ONE_MINUS_SRC_COLOR;
|
||||
break;
|
||||
case gfx::CompositionOp::OP_MULTIPLY:
|
||||
// If the source data was un-premultiplied we should have already
|
||||
// asked the fragment shader to fix that.
|
||||
srcBlend = LOCAL_GL_DST_COLOR;
|
||||
dstBlend = LOCAL_GL_ONE_MINUS_SRC_ALPHA;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(0, "Unsupported blend mode!");
|
||||
}
|
||||
|
||||
aGL->fBlendFuncSeparate(srcBlend, dstBlend,
|
||||
LOCAL_GL_ONE, LOCAL_GL_ONE);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CompositorOGL::DrawQuadInternal(const Rect& aRect,
|
||||
const Rect& aClipRect,
|
||||
|
@ -963,7 +1005,14 @@ CompositorOGL::DrawQuadInternal(const Rect& aRect,
|
|||
aOpacity = 1.f;
|
||||
}
|
||||
|
||||
ShaderConfigOGL config = GetShaderConfigFor(aEffectChain.mPrimaryEffect, maskType);
|
||||
gfx::CompositionOp blendMode = gfx::CompositionOp::OP_OVER;
|
||||
if (aEffectChain.mSecondaryEffects[EffectTypes::BLEND_MODE]) {
|
||||
EffectBlendMode *blendEffect =
|
||||
static_cast<EffectBlendMode*>(aEffectChain.mSecondaryEffects[EffectTypes::BLEND_MODE].get());
|
||||
blendMode = blendEffect->mBlendMode;
|
||||
}
|
||||
|
||||
ShaderConfigOGL config = GetShaderConfigFor(aEffectChain.mPrimaryEffect, maskType, blendMode);
|
||||
config.SetOpacity(aOpacity != 1.f);
|
||||
ShaderProgramOGL *program = GetShaderProgramFor(config);
|
||||
program->Activate();
|
||||
|
@ -982,6 +1031,8 @@ CompositorOGL::DrawQuadInternal(const Rect& aRect,
|
|||
program->SetTexCoordMultiplier(source->GetSize().width, source->GetSize().height);
|
||||
}
|
||||
|
||||
bool didSetBlendMode = false;
|
||||
|
||||
switch (aEffectChain.mPrimaryEffect->mType) {
|
||||
case EffectTypes::SOLID_COLOR: {
|
||||
program->SetRenderColor(color);
|
||||
|
@ -990,6 +1041,8 @@ CompositorOGL::DrawQuadInternal(const Rect& aRect,
|
|||
BindMaskForProgram(program, sourceMask, LOCAL_GL_TEXTURE0, maskQuadTransform);
|
||||
}
|
||||
|
||||
didSetBlendMode = SetBlendMode(gl(), blendMode);
|
||||
|
||||
BindAndDrawQuad(program, aDrawMode);
|
||||
}
|
||||
break;
|
||||
|
@ -999,10 +1052,7 @@ CompositorOGL::DrawQuadInternal(const Rect& aRect,
|
|||
static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
|
||||
TextureSource *source = texturedEffect->mTexture;
|
||||
|
||||
if (!texturedEffect->mPremultiplied) {
|
||||
mGLContext->fBlendFuncSeparate(LOCAL_GL_SRC_ALPHA, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
|
||||
LOCAL_GL_ONE, LOCAL_GL_ONE);
|
||||
}
|
||||
didSetBlendMode = SetBlendMode(gl(), blendMode, texturedEffect->mPremultiplied);
|
||||
|
||||
gfx::Filter filter = texturedEffect->mFilter;
|
||||
gfx3DMatrix textureTransform;
|
||||
|
@ -1030,11 +1080,6 @@ CompositorOGL::DrawQuadInternal(const Rect& aRect,
|
|||
|
||||
BindAndDrawQuadWithTextureRect(program, textureTransform,
|
||||
texturedEffect->mTextureCoords, source);
|
||||
|
||||
if (!texturedEffect->mPremultiplied) {
|
||||
mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
|
||||
LOCAL_GL_ONE, LOCAL_GL_ONE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EffectTypes::YCBCR: {
|
||||
|
@ -1060,6 +1105,7 @@ CompositorOGL::DrawQuadInternal(const Rect& aRect,
|
|||
if (maskType != MaskType::MaskNone) {
|
||||
BindMaskForProgram(program, sourceMask, LOCAL_GL_TEXTURE3, maskQuadTransform);
|
||||
}
|
||||
didSetBlendMode = SetBlendMode(gl(), blendMode);
|
||||
BindAndDrawQuadWithTextureRect(program,
|
||||
gfx3DMatrix(),
|
||||
effectYCbCr->mTextureCoords,
|
||||
|
@ -1096,11 +1142,13 @@ CompositorOGL::DrawQuadInternal(const Rect& aRect,
|
|||
// Drawing is always flipped, but when copying between surfaces we want to avoid
|
||||
// this. Pass true for the flip parameter to introduce a second flip
|
||||
// that cancels the other one out.
|
||||
didSetBlendMode = SetBlendMode(gl(), blendMode);
|
||||
BindAndDrawQuad(program);
|
||||
}
|
||||
break;
|
||||
case EffectTypes::COMPONENT_ALPHA: {
|
||||
MOZ_ASSERT(gfxPrefs::ComponentAlphaEnabled());
|
||||
MOZ_ASSERT(blendMode == gfx::CompositionOp::OP_OVER, "Can't support blend modes with component alpha!");
|
||||
EffectComponentAlpha* effectComponentAlpha =
|
||||
static_cast<EffectComponentAlpha*>(aEffectChain.mPrimaryEffect.get());
|
||||
TextureSourceOGL* sourceOnWhite = effectComponentAlpha->mOnWhite->AsSourceOGL();
|
||||
|
@ -1149,6 +1197,11 @@ CompositorOGL::DrawQuadInternal(const Rect& aRect,
|
|||
break;
|
||||
}
|
||||
|
||||
if (didSetBlendMode) {
|
||||
gl()->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
|
||||
LOCAL_GL_ONE, LOCAL_GL_ONE);
|
||||
}
|
||||
|
||||
// in case rendering has used some other GL context
|
||||
MakeCurrent();
|
||||
}
|
||||
|
|
|
@ -178,11 +178,15 @@ public:
|
|||
|
||||
virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() MOZ_OVERRIDE
|
||||
{
|
||||
return TextureFactoryIdentifier(LayersBackend::LAYERS_OPENGL,
|
||||
XRE_GetProcessType(),
|
||||
GetMaxTextureSize(),
|
||||
mFBOTextureTarget == LOCAL_GL_TEXTURE_2D,
|
||||
SupportsPartialTextureUpdate());
|
||||
TextureFactoryIdentifier result =
|
||||
TextureFactoryIdentifier(LayersBackend::LAYERS_OPENGL,
|
||||
XRE_GetProcessType(),
|
||||
GetMaxTextureSize(),
|
||||
mFBOTextureTarget == LOCAL_GL_TEXTURE_2D,
|
||||
SupportsPartialTextureUpdate());
|
||||
result.mSupportedBlendModes += gfx::CompositionOp::OP_SCREEN;
|
||||
result.mSupportedBlendModes += gfx::CompositionOp::OP_MULTIPLY;
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual TemporaryRef<CompositingRenderTarget>
|
||||
|
@ -360,7 +364,9 @@ private:
|
|||
gfx::Rect *aClipRectOut = nullptr,
|
||||
gfx::Rect *aRenderBoundsOut = nullptr) MOZ_OVERRIDE;
|
||||
|
||||
ShaderConfigOGL GetShaderConfigFor(Effect *aEffect, MaskType aMask = MaskType::MaskNone) const;
|
||||
ShaderConfigOGL GetShaderConfigFor(Effect *aEffect,
|
||||
MaskType aMask = MaskType::MaskNone,
|
||||
gfx::CompositionOp aOp = gfx::CompositionOp::OP_OVER) const;
|
||||
ShaderProgramOGL* GetShaderProgramFor(const ShaderConfigOGL &aConfig);
|
||||
|
||||
/**
|
||||
|
|
|
@ -130,6 +130,12 @@ ShaderConfigOGL::SetMask3D(bool aEnabled)
|
|||
SetFeature(ENABLE_MASK_3D, aEnabled);
|
||||
}
|
||||
|
||||
void
|
||||
ShaderConfigOGL::SetPremultiply(bool aEnabled)
|
||||
{
|
||||
SetFeature(ENABLE_PREMULTIPLY, aEnabled);
|
||||
}
|
||||
|
||||
/* static */ ProgramProfileOGL
|
||||
ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig)
|
||||
{
|
||||
|
@ -323,6 +329,9 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig)
|
|||
if (aConfig.mFeatures & ENABLE_OPACITY) {
|
||||
fs << " color *= uLayerOpacity;" << endl;
|
||||
}
|
||||
if (aConfig.mFeatures & ENABLE_PREMULTIPLY) {
|
||||
fs << " color.rgb *= color.a;" << endl;
|
||||
}
|
||||
}
|
||||
if (aConfig.mFeatures & ENABLE_MASK_3D) {
|
||||
fs << " vec2 maskCoords = vMaskCoord.xy / vMaskCoord.z;" << endl;
|
||||
|
|
|
@ -41,7 +41,8 @@ enum ShaderFeatures {
|
|||
ENABLE_BLUR=0x100,
|
||||
ENABLE_COLOR_MATRIX=0x200,
|
||||
ENABLE_MASK_2D=0x400,
|
||||
ENABLE_MASK_3D=0x800
|
||||
ENABLE_MASK_3D=0x800,
|
||||
ENABLE_PREMULTIPLY=0x1000
|
||||
};
|
||||
|
||||
class KnownUniform {
|
||||
|
@ -171,6 +172,7 @@ public:
|
|||
void SetBlur(bool aEnabled);
|
||||
void SetMask2D(bool aEnabled);
|
||||
void SetMask3D(bool aEnabled);
|
||||
void SetPremultiply(bool aEnabled);
|
||||
|
||||
bool operator< (const ShaderConfigOGL& other) const {
|
||||
return mFeatures < other.mFeatures;
|
||||
|
|
Загрузка…
Ссылка в новой задаче