1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef MOZILLA_LAYERS_EFFECTS_H
8 #define MOZILLA_LAYERS_EFFECTS_H
9 
10 #include "mozilla/Assertions.h"  // for MOZ_ASSERT, etc
11 #include "mozilla/RefPtr.h"      // for RefPtr, already_AddRefed, etc
12 #include "mozilla/gfx/Matrix.h"  // for Matrix4x4
13 #include "mozilla/gfx/Point.h"   // for IntSize
14 #include "mozilla/gfx/Rect.h"    // for Rect
15 #include "mozilla/gfx/Types.h"   // for SamplingFilter, etc
16 #include "mozilla/layers/CompositorTypes.h"  // for EffectTypes, etc
17 #include "mozilla/layers/LayersTypes.h"
18 #include "mozilla/layers/TextureHost.h"  // for CompositingRenderTarget, etc
19 #include "mozilla/mozalloc.h"            // for operator delete, etc
20 #include "nscore.h"                      // for nsACString
21 #include "mozilla/EnumeratedArray.h"
22 
23 namespace mozilla {
24 namespace layers {
25 
26 /**
27  * Effects and effect chains are used by the compositor API (see Compositor.h).
28  * An effect chain represents a rendering method, for example some shader and
29  * the data required for that shader to run. An effect is some component of the
30  * chain and its data.
31  *
32  * An effect chain consists of a primary effect - how the 'texture' memory
33  * should be interpreted (RGBA, BGRX, YCBCR, etc.) - and any number of secondary
34  * effects
35  * - any way in which rendering can be changed, e.g., applying a mask layer.
36  *
37  * During the rendering process, an effect chain is created by the layer being
38  * rendered and the primary effect is added by the compositable host. Secondary
39  * effects may be added by the layer or compositable. The effect chain is passed
40  * to the compositor by the compositable host as a parameter to DrawQuad.
41  */
42 
43 struct TexturedEffect;
44 
45 struct Effect {
NS_INLINE_DECL_REFCOUNTINGEffect46   NS_INLINE_DECL_REFCOUNTING(Effect)
47 
48   explicit Effect(EffectTypes aType) : mType(aType) {}
49 
50   EffectTypes mType;
51 
AsTexturedEffectEffect52   virtual TexturedEffect* AsTexturedEffect() { return nullptr; }
53   virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) = 0;
54 
55  protected:
56   virtual ~Effect() = default;
57 };
58 
59 // Render from a texture
60 struct TexturedEffect : public Effect {
TexturedEffectTexturedEffect61   TexturedEffect(EffectTypes aType, TextureSource* aTexture,
62                  bool aPremultiplied, gfx::SamplingFilter aSamplingFilter)
63       : Effect(aType),
64         mTextureCoords(0, 0, 1.0f, 1.0f),
65         mTexture(aTexture),
66         mPremultiplied(aPremultiplied),
67         mSamplingFilter(aSamplingFilter) {}
68 
AsTexturedEffectTexturedEffect69   TexturedEffect* AsTexturedEffect() override { return this; }
70   virtual const char* Name() = 0;
71   void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
72 
73   gfx::Rect mTextureCoords;
74   TextureSource* mTexture;
75   bool mPremultiplied;
76   gfx::SamplingFilter mSamplingFilter;
77 };
78 
79 // Support an alpha mask.
80 struct EffectMask : public Effect {
EffectMaskEffectMask81   EffectMask(TextureSource* aMaskTexture, gfx::IntSize aSize,
82              const gfx::Matrix4x4& aMaskTransform)
83       : Effect(EffectTypes::MASK),
84         mMaskTexture(aMaskTexture),
85         mSize(aSize),
86         mMaskTransform(aMaskTransform) {}
87 
88   void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
89 
90   TextureSource* mMaskTexture;
91   gfx::IntSize mSize;
92   gfx::Matrix4x4 mMaskTransform;
93 };
94 
95 struct EffectBlendMode : public Effect {
EffectBlendModeEffectBlendMode96   explicit EffectBlendMode(gfx::CompositionOp aBlendMode)
97       : Effect(EffectTypes::BLEND_MODE), mBlendMode(aBlendMode) {}
98 
NameEffectBlendMode99   virtual const char* Name() { return "EffectBlendMode"; }
100   void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
101 
102   gfx::CompositionOp mBlendMode;
103 };
104 
105 // Render to a render target rather than the screen.
106 struct EffectRenderTarget : public TexturedEffect {
EffectRenderTargetEffectRenderTarget107   explicit EffectRenderTarget(CompositingRenderTarget* aRenderTarget)
108       : TexturedEffect(EffectTypes::RENDER_TARGET, aRenderTarget, true,
109                        gfx::SamplingFilter::LINEAR),
110         mRenderTarget(aRenderTarget) {}
111 
NameEffectRenderTarget112   const char* Name() override { return "EffectRenderTarget"; }
113   void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
114 
115   RefPtr<CompositingRenderTarget> mRenderTarget;
116 
117  protected:
EffectRenderTargetEffectRenderTarget118   EffectRenderTarget(EffectTypes aType, CompositingRenderTarget* aRenderTarget)
119       : TexturedEffect(aType, aRenderTarget, true, gfx::SamplingFilter::LINEAR),
120         mRenderTarget(aRenderTarget) {}
121 };
122 
123 // Render to a render target rather than the screen.
124 struct EffectColorMatrix : public Effect {
EffectColorMatrixEffectColorMatrix125   explicit EffectColorMatrix(gfx::Matrix5x4 aMatrix)
126       : Effect(EffectTypes::COLOR_MATRIX), mColorMatrix(aMatrix) {}
127 
128   void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
129   const gfx::Matrix5x4 mColorMatrix;
130 };
131 
132 struct EffectRGB : public TexturedEffect {
133   EffectRGB(TextureSource* aTexture, bool aPremultiplied,
134             gfx::SamplingFilter aSamplingFilter, bool aFlipped = false)
TexturedEffectEffectRGB135       : TexturedEffect(EffectTypes::RGB, aTexture, aPremultiplied,
136                        aSamplingFilter) {}
137 
NameEffectRGB138   const char* Name() override { return "EffectRGB"; }
139 };
140 
141 struct EffectYCbCr : public TexturedEffect {
EffectYCbCrEffectYCbCr142   EffectYCbCr(TextureSource* aSource, gfx::YUVColorSpace aYUVColorSpace,
143               gfx::ColorRange aColorRange, gfx::ColorDepth aColorDepth,
144               gfx::SamplingFilter aSamplingFilter)
145       : TexturedEffect(EffectTypes::YCBCR, aSource, false, aSamplingFilter),
146         mYUVColorSpace(aYUVColorSpace),
147         mColorRange(aColorRange),
148         mColorDepth(aColorDepth) {}
149 
NameEffectYCbCr150   const char* Name() override { return "EffectYCbCr"; }
151 
152   gfx::YUVColorSpace mYUVColorSpace;
153   gfx::ColorRange mColorRange;
154   gfx::ColorDepth mColorDepth;
155 };
156 
157 struct EffectNV12 : public EffectYCbCr {
EffectNV12EffectNV12158   EffectNV12(TextureSource* aSource, gfx::YUVColorSpace aYUVColorSpace,
159              gfx::ColorRange aColorRange, gfx::ColorDepth aColorDepth,
160              gfx::SamplingFilter aSamplingFilter)
161       : EffectYCbCr(aSource, aYUVColorSpace, aColorRange, aColorDepth,
162                     aSamplingFilter) {
163     mType = EffectTypes::NV12;
164   }
165 
NameEffectNV12166   const char* Name() override { return "EffectNV12"; }
167 };
168 
169 struct EffectComponentAlpha : public TexturedEffect {
EffectComponentAlphaEffectComponentAlpha170   EffectComponentAlpha(TextureSource* aOnBlack, TextureSource* aOnWhite,
171                        gfx::SamplingFilter aSamplingFilter)
172       : TexturedEffect(EffectTypes::COMPONENT_ALPHA, nullptr, false,
173                        aSamplingFilter),
174         mOnBlack(aOnBlack),
175         mOnWhite(aOnWhite) {}
176 
NameEffectComponentAlpha177   const char* Name() override { return "EffectComponentAlpha"; }
178 
179   TextureSource* mOnBlack;
180   TextureSource* mOnWhite;
181 };
182 
183 struct EffectSolidColor : public Effect {
EffectSolidColorEffectSolidColor184   explicit EffectSolidColor(const gfx::DeviceColor& aColor)
185       : Effect(EffectTypes::SOLID_COLOR), mColor(aColor) {}
186 
187   void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
188 
189   gfx::DeviceColor mColor;
190 };
191 
192 struct EffectChain {
EffectChainEffectChain193   EffectChain() : mLayerRef(nullptr) {}
EffectChainEffectChain194   explicit EffectChain(void* aLayerRef) : mLayerRef(aLayerRef) {}
195 
196   RefPtr<Effect> mPrimaryEffect;
197   EnumeratedArray<EffectTypes, EffectTypes::MAX_SECONDARY, RefPtr<Effect>>
198       mSecondaryEffects;
199   void* mLayerRef;  //!< For LayerScope logging
200 };
201 
202 /**
203  * Create a Textured effect corresponding to aFormat and using
204  * aSource as the (first) texture source.
205  *
206  * Note that aFormat can be different form aSource->GetFormat if, we are
207  * creating an effect that takes several texture sources (like with YCBCR
208  * where aFormat would be FORMAT_YCBCR and each texture source would be
209  * a one-channel A8 texture)
210  */
CreateTexturedEffect(gfx::SurfaceFormat aFormat,TextureSource * aSource,const gfx::SamplingFilter aSamplingFilter,bool isAlphaPremultiplied)211 inline already_AddRefed<TexturedEffect> CreateTexturedEffect(
212     gfx::SurfaceFormat aFormat, TextureSource* aSource,
213     const gfx::SamplingFilter aSamplingFilter, bool isAlphaPremultiplied) {
214   MOZ_ASSERT(aSource);
215   RefPtr<TexturedEffect> result;
216   switch (aFormat) {
217     case gfx::SurfaceFormat::B8G8R8A8:
218     case gfx::SurfaceFormat::B8G8R8X8:
219     case gfx::SurfaceFormat::R8G8B8X8:
220     case gfx::SurfaceFormat::R5G6B5_UINT16:
221     case gfx::SurfaceFormat::R8G8B8A8:
222       result = new EffectRGB(aSource, isAlphaPremultiplied, aSamplingFilter);
223       break;
224     case gfx::SurfaceFormat::YUV:
225     case gfx::SurfaceFormat::NV12:
226     case gfx::SurfaceFormat::P010:
227     case gfx::SurfaceFormat::P016:
228       MOZ_ASSERT_UNREACHABLE(
229           "gfx::SurfaceFormat::YUV/NV12/P010/P016 is invalid");
230       break;
231     default:
232       NS_WARNING("unhandled program type");
233       break;
234   }
235 
236   return result.forget();
237 }
238 
CreateTexturedEffect(TextureHost * aHost,TextureSource * aSource,const gfx::SamplingFilter aSamplingFilter,bool isAlphaPremultiplied)239 inline already_AddRefed<TexturedEffect> CreateTexturedEffect(
240     TextureHost* aHost, TextureSource* aSource,
241     const gfx::SamplingFilter aSamplingFilter, bool isAlphaPremultiplied) {
242   MOZ_ASSERT(aHost);
243   MOZ_ASSERT(aSource);
244 
245   RefPtr<TexturedEffect> result;
246 
247   switch (aHost->GetReadFormat()) {
248     case gfx::SurfaceFormat::YUV:
249       MOZ_ASSERT(aHost->GetYUVColorSpace() != gfx::YUVColorSpace::UNKNOWN);
250       result = new EffectYCbCr(aSource, aHost->GetYUVColorSpace(),
251                                aHost->GetColorRange(), aHost->GetColorDepth(),
252                                aSamplingFilter);
253       break;
254     case gfx::SurfaceFormat::NV12:
255     case gfx::SurfaceFormat::P010:
256     case gfx::SurfaceFormat::P016:
257       result = new EffectNV12(aSource, aHost->GetYUVColorSpace(),
258                               aHost->GetColorRange(), aHost->GetColorDepth(),
259                               aSamplingFilter);
260       break;
261     default:
262       result = CreateTexturedEffect(aHost->GetReadFormat(), aSource,
263                                     aSamplingFilter, isAlphaPremultiplied);
264       break;
265   }
266   return result.forget();
267 }
268 
269 /**
270  * Create a textured effect based on aSource format and the presence of
271  * aSourceOnWhite.
272  *
273  * aSourceOnWhite can be null.
274  */
CreateTexturedEffect(TextureSource * aSource,TextureSource * aSourceOnWhite,const gfx::SamplingFilter aSamplingFilter,bool isAlphaPremultiplied)275 inline already_AddRefed<TexturedEffect> CreateTexturedEffect(
276     TextureSource* aSource, TextureSource* aSourceOnWhite,
277     const gfx::SamplingFilter aSamplingFilter, bool isAlphaPremultiplied) {
278   MOZ_ASSERT(aSource);
279   if (aSourceOnWhite) {
280     MOZ_ASSERT(aSource->GetFormat() == gfx::SurfaceFormat::R8G8B8X8 ||
281                aSource->GetFormat() == gfx::SurfaceFormat::B8G8R8X8);
282     MOZ_ASSERT(aSource->GetFormat() == aSourceOnWhite->GetFormat());
283     return MakeAndAddRef<EffectComponentAlpha>(aSource, aSourceOnWhite,
284                                                aSamplingFilter);
285   }
286 
287   return CreateTexturedEffect(aSource->GetFormat(), aSource, aSamplingFilter,
288                               isAlphaPremultiplied);
289 }
290 
291 /**
292  * Create a textured effect based on aSource format.
293  *
294  * This version excudes the possibility of component alpha.
295  */
CreateTexturedEffect(TextureSource * aTexture,const gfx::SamplingFilter aSamplingFilter)296 inline already_AddRefed<TexturedEffect> CreateTexturedEffect(
297     TextureSource* aTexture, const gfx::SamplingFilter aSamplingFilter) {
298   return CreateTexturedEffect(aTexture, nullptr, aSamplingFilter, true);
299 }
300 
301 }  // namespace layers
302 }  // namespace mozilla
303 
304 #endif
305