Bug 1016539. Add support for accelerated a11y filters. r=mwoodrow

This adds the ability to render to a temporary surface and use that
to apply a filter effect to all of the content.
This commit is contained in:
Jeff Muizelaar 2014-08-07 17:44:08 -04:00
Родитель deb2e761b1
Коммит df48ffb1b7
13 изменённых файлов: 150 добавлений и 7 удалений

Просмотреть файл

@ -143,6 +143,7 @@ MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(DiagnosticFlags)
MOZ_BEGIN_ENUM_CLASS(EffectTypes, uint8_t)
MASK,
BLEND_MODE,
COLOR_MATRIX,
MAX_SECONDARY, // sentinel for the count of secondary effect types
RGB,
YCBCR,

Просмотреть файл

@ -61,3 +61,11 @@ EffectBlendMode::PrintInfo(std::stringstream& aStream, const char* aPrefix)
aStream << nsPrintfCString("EffectBlendMode (0x%p) [blendmode=%i]", this, (int)mBlendMode).get();
}
void
EffectColorMatrix::PrintInfo(std::stringstream& aStream, const char* aPrefix)
{
aStream << aPrefix;
aStream << nsPrintfCString("EffectColorMatrix (0x%p)", this).get();
AppendToString(aStream, mColorMatrix, " [matrix=", "]");
}

Просмотреть файл

@ -121,8 +121,29 @@ struct EffectRenderTarget : public TexturedEffect
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix);
RefPtr<CompositingRenderTarget> mRenderTarget;
protected:
EffectRenderTarget(EffectTypes aType, CompositingRenderTarget *aRenderTarget)
: TexturedEffect(aType, aRenderTarget, true, gfx::Filter::LINEAR)
, mRenderTarget(aRenderTarget)
{}
};
// Render to a render target rather than the screen.
struct EffectColorMatrix : public Effect
{
EffectColorMatrix(gfx::Matrix5x4 aMatrix)
: Effect(EffectTypes::COLOR_MATRIX)
, mColorMatrix(aMatrix)
{}
virtual const char* Name() { return "EffectColorMatrix"; }
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix);
const gfx::Matrix5x4 mColorMatrix;
};
struct EffectRGB : public TexturedEffect
{
EffectRGB(TextureSource *aTexture,

Просмотреть файл

@ -169,6 +169,22 @@ AppendToString(std::stringstream& aStream, const Matrix4x4& m,
aStream << sfx;
}
void
AppendToString(std::stringstream& aStream, const Matrix5x4& m,
const char* pfx, const char* sfx)
{
aStream << pfx;
aStream << nsPrintfCString(
"[ %g %g %g %g; %g %g %g %g; %g %g %g %g; %g %g %g %g; %g %g %g %g]",
m._11, m._12, m._13, m._14,
m._21, m._22, m._23, m._24,
m._31, m._32, m._33, m._34,
m._41, m._42, m._43, m._44,
m._51, m._52, m._53, m._54).get();
aStream << sfx;
}
void
AppendToString(std::stringstream& aStream, const Filter filter,
const char* pfx, const char* sfx)

Просмотреть файл

@ -139,6 +139,10 @@ void
AppendToString(std::stringstream& aStream, const mozilla::gfx::Matrix4x4& m,
const char* pfx="", const char* sfx="");
void
AppendToString(std::stringstream& aStream, const mozilla::gfx::Matrix5x4& m,
const char* pfx="", const char* sfx="");
void
AppendToString(std::stringstream& aStream, const mozilla::gfx::Filter filter,
const char* pfx="", const char* sfx="");

Просмотреть файл

@ -410,6 +410,58 @@ LayerManagerComposite::RenderDebugOverlay(const Rect& aBounds)
}
}
RefPtr<CompositingRenderTarget>
LayerManagerComposite::PushGroup()
{
RefPtr<CompositingRenderTarget> previousTarget = mCompositor->GetCurrentRenderTarget();
// make our render target the same size as the destination target
// so that we don't have to change size if the drawing area changes.
IntRect rect(previousTarget->GetOrigin(), previousTarget->GetSize());
// XXX: I'm not sure if this is true or not...
MOZ_ASSERT(rect.x == 0 && rect.y == 0);
if (!mTwoPassTmpTarget ||
mTwoPassTmpTarget->GetSize() != previousTarget->GetSize() ||
mTwoPassTmpTarget->GetOrigin() != previousTarget->GetOrigin()) {
mTwoPassTmpTarget = mCompositor->CreateRenderTarget(rect, INIT_MODE_NONE);
}
mCompositor->SetRenderTarget(mTwoPassTmpTarget);
return previousTarget;
}
void LayerManagerComposite::PopGroup(RefPtr<CompositingRenderTarget> aPreviousTarget, nsIntRect aClipRect)
{
mCompositor->SetRenderTarget(aPreviousTarget);
EffectChain effectChain(RootLayer());
Matrix5x4 matrix;
if (gfxPrefs::Grayscale()) {
matrix._11 = matrix._12 = matrix._13 = 0.2126f;
matrix._21 = matrix._22 = matrix._23 = 0.7152f;
matrix._31 = matrix._32 = matrix._33 = 0.0722f;
}
if (gfxPrefs::Invert()) {
matrix._11 = -matrix._11;
matrix._12 = -matrix._12;
matrix._13 = -matrix._13;
matrix._21 = -matrix._21;
matrix._22 = -matrix._22;
matrix._23 = -matrix._23;
matrix._31 = -matrix._31;
matrix._32 = -matrix._32;
matrix._33 = -matrix._33;
matrix._51 = 1;
matrix._52 = 1;
matrix._53 = 1;
}
effectChain.mPrimaryEffect = new EffectRenderTarget(mTwoPassTmpTarget);
effectChain.mSecondaryEffects[EffectTypes::COLOR_MATRIX] = new EffectColorMatrix(matrix);
gfx::Rect clipRectF(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height);
mCompositor->DrawQuad(Rect(Point(0, 0), Size(mTwoPassTmpTarget->GetSize())), clipRectF, effectChain, 1.,
Matrix4x4());
}
void
LayerManagerComposite::Render()
{
@ -442,6 +494,10 @@ LayerManagerComposite::Render()
LayerScope::SendLayerDump(Move(packet));
}
if (gfxPrefs::Invert() || gfxPrefs::Grayscale()) {
composer2D = nullptr;
}
if (!mTarget && composer2D && composer2D->TryRender(mRoot, mWorldMatrix, mGeometryChanged)) {
if (mFPS) {
double fps = mFPS->mCompositionFps.AddFrameAndGetFps(TimeStamp::Now());
@ -501,6 +557,13 @@ LayerManagerComposite::Render()
actualBounds.width,
actualBounds.height));
RefPtr<CompositingRenderTarget> previousTarget;
if (gfxPrefs::Invert() || gfxPrefs::Grayscale()) {
previousTarget = PushGroup();
} else {
mTwoPassTmpTarget = nullptr;
}
// Render our layers.
RootLayer()->Prepare(clipRect);
RootLayer()->RenderLayer(clipRect);
@ -513,6 +576,10 @@ LayerManagerComposite::Render()
}
}
if (mTwoPassTmpTarget) {
PopGroup(previousTarget, clipRect);
}
// Allow widget to render a custom foreground.
mCompositor->GetWidget()->DrawWindowOverlay(this, nsIntRect(actualBounds.x,
actualBounds.y,

Просмотреть файл

@ -63,6 +63,7 @@ class SurfaceDescriptor;
class ThebesLayerComposite;
class TiledLayerComposer;
class TextRenderer;
class CompositingRenderTarget;
struct FPSState;
class LayerManagerComposite : public LayerManager
@ -268,6 +269,9 @@ private:
void WorldTransformRect(nsIntRect& aRect);
RefPtr<CompositingRenderTarget> PushGroup();
void PopGroup(RefPtr<CompositingRenderTarget> aPreviousTarget, nsIntRect aClipRect);
RefPtr<Compositor> mCompositor;
nsAutoPtr<LayerProperties> mClonedLayerTreeProperties;
@ -285,6 +289,7 @@ private:
bool mIsCompositorReady;
bool mDebugOverlayWantsNextFrame;
RefPtr<CompositingRenderTarget> mTwoPassTmpTarget;
RefPtr<TextRenderer> mTextRenderer;
bool mGeometryChanged;
};

Просмотреть файл

@ -137,9 +137,7 @@ public:
}
gfx::IntSize GetSize() const MOZ_OVERRIDE
{
// XXX - Bug 900770
MOZ_ASSERT(false, "CompositingRenderTargetOGL should not be used as a TextureSource");
return gfx::IntSize(0, 0);
return mInitParams.mSize;
}
gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE

Просмотреть файл

@ -897,7 +897,8 @@ CompositorOGL::CreateFBOWithTexture(const IntRect& aRect, bool aCopyFromSource,
ShaderConfigOGL
CompositorOGL::GetShaderConfigFor(Effect *aEffect,
MaskType aMask,
gfx::CompositionOp aOp) const
gfx::CompositionOp aOp,
bool aColorMatrix) const
{
ShaderConfigOGL config;
@ -944,6 +945,7 @@ CompositorOGL::GetShaderConfigFor(Effect *aEffect,
break;
}
}
config.SetColorMatrix(aColorMatrix);
config.SetMask2D(aMask == MaskType::Mask2d);
config.SetMask3D(aMask == MaskType::Mask3d);
return config;
@ -1091,12 +1093,20 @@ CompositorOGL::DrawQuad(const Rect& aRect,
blendMode = blendEffect->mBlendMode;
}
ShaderConfigOGL config = GetShaderConfigFor(aEffectChain.mPrimaryEffect, maskType, blendMode);
bool colorMatrix = aEffectChain.mSecondaryEffects[EffectTypes::COLOR_MATRIX];
ShaderConfigOGL config = GetShaderConfigFor(aEffectChain.mPrimaryEffect, maskType, blendMode, colorMatrix);
config.SetOpacity(aOpacity != 1.f);
ShaderProgramOGL *program = GetShaderProgramFor(config);
program->Activate();
program->SetProjectionMatrix(mProjMatrix);
program->SetLayerTransform(aTransform);
if (colorMatrix) {
EffectColorMatrix* effectColorMatrix =
static_cast<EffectColorMatrix*>(aEffectChain.mSecondaryEffects[EffectTypes::COLOR_MATRIX].get());
program->SetColorMatrix(effectColorMatrix->mColorMatrix);
}
IntPoint offset = mCurrentRenderTarget->GetOrigin();
program->SetRenderOffset(offset.x, offset.y);
if (aOpacity != 1.f)

Просмотреть файл

@ -333,7 +333,8 @@ private:
ShaderConfigOGL GetShaderConfigFor(Effect *aEffect,
MaskType aMask = MaskType::MaskNone,
gfx::CompositionOp aOp = gfx::CompositionOp::OP_OVER) const;
gfx::CompositionOp aOp = gfx::CompositionOp::OP_OVER,
bool aColorMatrix = false) const;
ShaderProgramOGL* GetShaderProgramFor(const ShaderConfigOGL &aConfig);
/**

Просмотреть файл

@ -47,6 +47,8 @@ AddUniforms(ProgramProfileOGL& aProfile)
"uRenderColor",
"uTexCoordMultiplier",
"uTexturePass2",
"uColorMatrix",
"uColorMatrixVector",
nullptr
};

Просмотреть файл

@ -68,6 +68,8 @@ public:
RenderColor,
TexCoordMultiplier,
TexturePass2,
ColorMatrix,
ColorMatrixVector,
KnownUniformCount
};
@ -369,6 +371,12 @@ public:
SetUniform(KnownUniform::RenderColor, aColor);
}
void SetColorMatrix(const gfx::Matrix5x4& aColorMatrix)
{
SetMatrixUniform(KnownUniform::ColorMatrix, &aColorMatrix._11);
SetUniform(KnownUniform::ColorMatrixVector, 4, &aColorMatrix._51);
}
void SetTexCoordMultiplier(float aWidth, float aHeight) {
float f[] = {aWidth, aHeight};
SetUniform(KnownUniform::TexCoordMultiplier, 2, f);
@ -432,7 +440,7 @@ protected:
}
}
void SetUniform(KnownUniform::KnownUniformName aKnownUniform, int aLength, float *aFloatValues)
void SetUniform(KnownUniform::KnownUniformName aKnownUniform, int aLength, const float *aFloatValues)
{
ASSERT_THIS_PROGRAM;
NS_ASSERTION(aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount, "Invalid known uniform");

Просмотреть файл

@ -250,6 +250,8 @@ private:
DECL_GFX_PREF(Once, "layers.progressive-paint", UseProgressiveTilePainting, bool, false);
DECL_GFX_PREF(Once, "layers.scroll-graph", LayersScrollGraph, bool, false);
DECL_GFX_PREF(Once, "layers.uniformity-info", UniformityInfo, bool, false);
DECL_GFX_PREF(Live, "layers.invert", Invert, bool, false);
DECL_GFX_PREF(Live, "layers.grayscale", Grayscale, bool, false);
DECL_GFX_PREF(Live, "layout.css.scroll-behavior.damping-ratio", ScrollBehaviorDampingRatio, float, 1.0f);
DECL_GFX_PREF(Live, "layout.css.scroll-behavior.enabled", ScrollBehaviorEnabled, bool, false);