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:
@@ -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,
|
||||||
|
|||||||
@@ -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=", "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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="");
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ AddUniforms(ProgramProfileOGL& aProfile)
|
|||||||
"uRenderColor",
|
"uRenderColor",
|
||||||
"uTexCoordMultiplier",
|
"uTexCoordMultiplier",
|
||||||
"uTexturePass2",
|
"uTexturePass2",
|
||||||
|
"uColorMatrix",
|
||||||
|
"uColorMatrixVector",
|
||||||
nullptr
|
nullptr
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user