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
parent 514ad83db5
commit 46a8420ee3
13 changed files with 150 additions and 7 deletions

View File

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

View File

@@ -61,3 +61,11 @@ EffectBlendMode::PrintInfo(std::stringstream& aStream, const char* aPrefix)
aStream << nsPrintfCString("EffectBlendMode (0x%p) [blendmode=%i]", this, (int)mBlendMode).get(); 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=", "]");
}

View File

@@ -121,8 +121,29 @@ struct EffectRenderTarget : public TexturedEffect
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix); virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix);
RefPtr<CompositingRenderTarget> mRenderTarget; 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 struct EffectRGB : public TexturedEffect
{ {
EffectRGB(TextureSource *aTexture, EffectRGB(TextureSource *aTexture,

View File

@@ -169,6 +169,22 @@ AppendToString(std::stringstream& aStream, const Matrix4x4& m,
aStream << sfx; 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 void
AppendToString(std::stringstream& aStream, const Filter filter, AppendToString(std::stringstream& aStream, const Filter filter,
const char* pfx, const char* sfx) const char* pfx, const char* sfx)

View File

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

View File

@@ -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 void
LayerManagerComposite::Render() LayerManagerComposite::Render()
{ {
@@ -442,6 +494,10 @@ LayerManagerComposite::Render()
LayerScope::SendLayerDump(Move(packet)); LayerScope::SendLayerDump(Move(packet));
} }
if (gfxPrefs::Invert() || gfxPrefs::Grayscale()) {
composer2D = nullptr;
}
if (!mTarget && composer2D && composer2D->TryRender(mRoot, mWorldMatrix, mGeometryChanged)) { if (!mTarget && composer2D && composer2D->TryRender(mRoot, mWorldMatrix, mGeometryChanged)) {
if (mFPS) { if (mFPS) {
double fps = mFPS->mCompositionFps.AddFrameAndGetFps(TimeStamp::Now()); double fps = mFPS->mCompositionFps.AddFrameAndGetFps(TimeStamp::Now());
@@ -501,6 +557,13 @@ LayerManagerComposite::Render()
actualBounds.width, actualBounds.width,
actualBounds.height)); actualBounds.height));
RefPtr<CompositingRenderTarget> previousTarget;
if (gfxPrefs::Invert() || gfxPrefs::Grayscale()) {
previousTarget = PushGroup();
} else {
mTwoPassTmpTarget = nullptr;
}
// Render our layers. // Render our layers.
RootLayer()->Prepare(clipRect); RootLayer()->Prepare(clipRect);
RootLayer()->RenderLayer(clipRect); RootLayer()->RenderLayer(clipRect);
@@ -513,6 +576,10 @@ LayerManagerComposite::Render()
} }
} }
if (mTwoPassTmpTarget) {
PopGroup(previousTarget, clipRect);
}
// Allow widget to render a custom foreground. // Allow widget to render a custom foreground.
mCompositor->GetWidget()->DrawWindowOverlay(this, nsIntRect(actualBounds.x, mCompositor->GetWidget()->DrawWindowOverlay(this, nsIntRect(actualBounds.x,
actualBounds.y, actualBounds.y,

View File

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

View File

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

View File

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

View File

@@ -333,7 +333,8 @@ private:
ShaderConfigOGL GetShaderConfigFor(Effect *aEffect, ShaderConfigOGL GetShaderConfigFor(Effect *aEffect,
MaskType aMask = MaskType::MaskNone, 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); ShaderProgramOGL* GetShaderProgramFor(const ShaderConfigOGL &aConfig);
/** /**

View File

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

View File

@@ -68,6 +68,8 @@ public:
RenderColor, RenderColor,
TexCoordMultiplier, TexCoordMultiplier,
TexturePass2, TexturePass2,
ColorMatrix,
ColorMatrixVector,
KnownUniformCount KnownUniformCount
}; };
@@ -369,6 +371,12 @@ public:
SetUniform(KnownUniform::RenderColor, aColor); 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) { void SetTexCoordMultiplier(float aWidth, float aHeight) {
float f[] = {aWidth, aHeight}; float f[] = {aWidth, aHeight};
SetUniform(KnownUniform::TexCoordMultiplier, 2, f); 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; ASSERT_THIS_PROGRAM;
NS_ASSERTION(aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount, "Invalid known uniform"); NS_ASSERTION(aKnownUniform >= 0 && aKnownUniform < KnownUniform::KnownUniformCount, "Invalid known uniform");

View File

@@ -250,6 +250,8 @@ private:
DECL_GFX_PREF(Once, "layers.progressive-paint", UseProgressiveTilePainting, bool, false); 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.scroll-graph", LayersScrollGraph, bool, false);
DECL_GFX_PREF(Once, "layers.uniformity-info", UniformityInfo, 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.damping-ratio", ScrollBehaviorDampingRatio, float, 1.0f);
DECL_GFX_PREF(Live, "layout.css.scroll-behavior.enabled", ScrollBehaviorEnabled, bool, false); DECL_GFX_PREF(Live, "layout.css.scroll-behavior.enabled", ScrollBehaviorEnabled, bool, false);