diff -r 000000000000 -r 6474c204b198 gfx/layers/Effects.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/layers/Effects.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,243 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- +* This Source Code Form is subject to the terms of the Mozilla Public +* 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/. */ + +#ifndef MOZILLA_LAYERS_EFFECTS_H +#define MOZILLA_LAYERS_EFFECTS_H + +#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc +#include "mozilla/RefPtr.h" // for RefPtr, TemporaryRef, etc +#include "mozilla/gfx/Matrix.h" // for Matrix4x4 +#include "mozilla/gfx/Point.h" // for IntSize +#include "mozilla/gfx/Rect.h" // for Rect +#include "mozilla/gfx/Types.h" // for Filter, etc +#include "mozilla/layers/CompositorTypes.h" // for EffectTypes, etc +#include "mozilla/layers/LayersTypes.h" +#include "mozilla/layers/TextureHost.h" // for CompositingRenderTarget, etc +#include "mozilla/mozalloc.h" // for operator delete, etc +#include "nscore.h" // for nsACString + +namespace mozilla { +namespace layers { + +/** + * Effects and effect chains are used by the compositor API (see Compositor.h). + * An effect chain represents a rendering method, for example some shader and + * the data required for that shader to run. An effect is some component of the + * chain and its data. + * + * An effect chain consists of a primary effect - how the 'texture' memory should + * be interpreted (RGBA, BGRX, YCBCR, etc.) - and any number of secondary effects + * - any way in which rendering can be changed, e.g., applying a mask layer. + * + * During the rendering process, an effect chain is created by the layer being + * rendered and the primary effect is added by the compositable host. Secondary + * effects may be added by the layer or compositable. The effect chain is passed + * to the compositor by the compositable host as a parameter to DrawQuad. + */ + +struct Effect +{ + NS_INLINE_DECL_REFCOUNTING(Effect) + + Effect(EffectTypes aType) : mType(aType) {} + + EffectTypes mType; + + virtual void PrintInfo(nsACString& aTo, const char* aPrefix) = 0; + +protected: + virtual ~Effect() {} +}; + +// Render from a texture +struct TexturedEffect : public Effect +{ + TexturedEffect(EffectTypes aType, + TextureSource *aTexture, + bool aPremultiplied, + gfx::Filter aFilter) + : Effect(aType) + , mTextureCoords(0, 0, 1.0f, 1.0f) + , mTexture(aTexture) + , mPremultiplied(aPremultiplied) + , mFilter(aFilter) + {} + + virtual const char* Name() = 0; + virtual void PrintInfo(nsACString& aTo, const char* aPrefix); + + gfx::Rect mTextureCoords; + TextureSource* mTexture; + bool mPremultiplied; + gfx::Filter mFilter;; +}; + +// Support an alpha mask. +struct EffectMask : public Effect +{ + EffectMask(TextureSource *aMaskTexture, + gfx::IntSize aSize, + const gfx::Matrix4x4 &aMaskTransform) + : Effect(EFFECT_MASK) + , mMaskTexture(aMaskTexture) + , mIs3D(false) + , mSize(aSize) + , mMaskTransform(aMaskTransform) + {} + + virtual void PrintInfo(nsACString& aTo, const char* aPrefix); + + TextureSource* mMaskTexture; + bool mIs3D; + gfx::IntSize mSize; + gfx::Matrix4x4 mMaskTransform; +}; + +// Render to a render target rather than the screen. +struct EffectRenderTarget : public TexturedEffect +{ + EffectRenderTarget(CompositingRenderTarget *aRenderTarget) + : TexturedEffect(EFFECT_RENDER_TARGET, aRenderTarget, true, gfx::Filter::LINEAR) + , mRenderTarget(aRenderTarget) + {} + + virtual const char* Name() { return "EffectRenderTarget"; } + virtual void PrintInfo(nsACString& aTo, const char* aPrefix); + + RefPtr mRenderTarget; +}; + +struct EffectRGB : public TexturedEffect +{ + EffectRGB(TextureSource *aTexture, + bool aPremultiplied, + gfx::Filter aFilter, + bool aFlipped = false) + : TexturedEffect(EFFECT_RGB, aTexture, aPremultiplied, aFilter) + {} + + virtual const char* Name() { return "EffectRGB"; } +}; + +struct EffectYCbCr : public TexturedEffect +{ + EffectYCbCr(TextureSource *aSource, gfx::Filter aFilter) + : TexturedEffect(EFFECT_YCBCR, aSource, false, aFilter) + {} + + virtual const char* Name() { return "EffectYCbCr"; } +}; + +struct EffectComponentAlpha : public TexturedEffect +{ + EffectComponentAlpha(TextureSource *aOnBlack, + TextureSource *aOnWhite, + gfx::Filter aFilter) + : TexturedEffect(EFFECT_COMPONENT_ALPHA, nullptr, false, aFilter) + , mOnBlack(aOnBlack) + , mOnWhite(aOnWhite) + {} + + virtual const char* Name() { return "EffectComponentAlpha"; } + + TextureSource* mOnBlack; + TextureSource* mOnWhite; +}; + +struct EffectSolidColor : public Effect +{ + EffectSolidColor(const gfx::Color &aColor) + : Effect(EFFECT_SOLID_COLOR) + , mColor(aColor) + {} + + virtual void PrintInfo(nsACString& aTo, const char* aPrefix); + + gfx::Color mColor; +}; + +struct EffectChain +{ + EffectChain() : mLayerRef(nullptr) {} + explicit EffectChain(void* aLayerRef) : mLayerRef(aLayerRef) {} + + RefPtr mPrimaryEffect; + RefPtr mSecondaryEffects[EFFECT_MAX_SECONDARY]; + void* mLayerRef; //!< For LayerScope logging +}; + +/** + * Create a Textured effect corresponding to aFormat and using + * aSource as the (first) texture source. + * + * Note that aFormat can be different form aSource->GetFormat if, we are + * creating an effect that takes several texture sources (like with YCBCR + * where aFormat would be FOMRAT_YCBCR and each texture source would be + * a one-channel A8 texture) + */ +inline TemporaryRef +CreateTexturedEffect(gfx::SurfaceFormat aFormat, + TextureSource* aSource, + const gfx::Filter& aFilter) +{ + MOZ_ASSERT(aSource); + RefPtr result; + switch (aFormat) { + case gfx::SurfaceFormat::B8G8R8A8: + case gfx::SurfaceFormat::B8G8R8X8: + case gfx::SurfaceFormat::R8G8B8X8: + case gfx::SurfaceFormat::R5G6B5: + case gfx::SurfaceFormat::R8G8B8A8: + result = new EffectRGB(aSource, true, aFilter); + break; + case gfx::SurfaceFormat::YUV: + result = new EffectYCbCr(aSource, aFilter); + break; + default: + NS_WARNING("unhandled program type"); + break; + } + + return result; +} + +/** + * Create a textured effect based on aSource format and the presence of + * aSourceOnWhite. + * + * aSourceOnWhite can be null. + */ +inline TemporaryRef +CreateTexturedEffect(TextureSource* aSource, + TextureSource* aSourceOnWhite, + const gfx::Filter& aFilter) +{ + MOZ_ASSERT(aSource); + if (aSourceOnWhite) { + MOZ_ASSERT(aSource->GetFormat() == gfx::SurfaceFormat::R8G8B8X8 || + aSourceOnWhite->GetFormat() == gfx::SurfaceFormat::B8G8R8X8); + return new EffectComponentAlpha(aSource, aSourceOnWhite, aFilter); + } + + return CreateTexturedEffect(aSource->GetFormat(), aSource, aFilter); +} + +/** + * Create a textured effect based on aSource format. + * + * This version excudes the possibility of component alpha. + */ +inline TemporaryRef +CreateTexturedEffect(TextureSource *aTexture, + const gfx::Filter& aFilter) +{ + return CreateTexturedEffect(aTexture, nullptr, aFilter); +} + + +} // namespace layers +} // namespace mozilla + +#endif