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