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 #include "BasicLayersImpl.h"
8 #include <new> // for operator new
9 #include "Layers.h" // for Layer, etc
10 #include "basic/BasicImplData.h" // for BasicImplData
11 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
12 #include "mozilla/DebugOnly.h" // for DebugOnly
13 #include "mozilla/layers/CompositorTypes.h"
14 #include "mozilla/layers/ISurfaceAllocator.h"
15 #include "AutoMaskData.h"
16
17 namespace mozilla {
18 namespace layers {
19
20 using namespace mozilla::gfx;
21
GetMaskData(Layer * aMaskLayer,const Point & aDeviceOffset,AutoMoz2DMaskData * aMaskData)22 bool GetMaskData(Layer* aMaskLayer, const Point& aDeviceOffset,
23 AutoMoz2DMaskData* aMaskData) {
24 if (aMaskLayer) {
25 RefPtr<SourceSurface> surface =
26 static_cast<BasicImplData*>(aMaskLayer->ImplData())
27 ->GetAsSourceSurface();
28 if (surface) {
29 Matrix transform;
30 Matrix4x4 effectiveTransform = aMaskLayer->GetEffectiveTransform();
31 DebugOnly<bool> maskIs2D = effectiveTransform.CanDraw2D(&transform);
32 NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
33 transform.PostTranslate(-aDeviceOffset.x, -aDeviceOffset.y);
34 aMaskData->Construct(transform, surface);
35 return true;
36 }
37 }
38 return false;
39 }
40
GetMaskForLayer(Layer * aLayer,Matrix * aMaskTransform)41 already_AddRefed<SourceSurface> GetMaskForLayer(Layer* aLayer,
42 Matrix* aMaskTransform) {
43 if (!aLayer->GetMaskLayer()) {
44 return nullptr;
45 }
46
47 MOZ_ASSERT(aMaskTransform);
48
49 AutoMoz2DMaskData mask;
50 if (GetMaskData(aLayer->GetMaskLayer(), Point(), &mask)) {
51 *aMaskTransform = mask.GetTransform();
52 RefPtr<SourceSurface> surf = mask.GetSurface();
53 return surf.forget();
54 }
55
56 return nullptr;
57 }
58
PaintWithMask(gfxContext * aContext,float aOpacity,Layer * aMaskLayer)59 void PaintWithMask(gfxContext* aContext, float aOpacity, Layer* aMaskLayer) {
60 AutoMoz2DMaskData mask;
61 if (GetMaskData(aMaskLayer, Point(), &mask)) {
62 aContext->SetMatrix(mask.GetTransform());
63 aContext->Mask(mask.GetSurface(), aOpacity);
64 return;
65 }
66
67 // if there is no mask, just paint normally
68 aContext->Paint(aOpacity);
69 }
70
FillRectWithMask(DrawTarget * aDT,const Rect & aRect,const Color & aColor,const DrawOptions & aOptions,SourceSurface * aMaskSource,const Matrix * aMaskTransform)71 void FillRectWithMask(DrawTarget* aDT, const Rect& aRect, const Color& aColor,
72 const DrawOptions& aOptions, SourceSurface* aMaskSource,
73 const Matrix* aMaskTransform) {
74 if (aMaskSource && aMaskTransform) {
75 aDT->PushClipRect(aRect);
76 Matrix oldTransform = aDT->GetTransform();
77
78 aDT->SetTransform(*aMaskTransform);
79 aDT->MaskSurface(ColorPattern(aColor), aMaskSource, Point(), aOptions);
80 aDT->SetTransform(oldTransform);
81 aDT->PopClip();
82 return;
83 }
84
85 aDT->FillRect(aRect, ColorPattern(aColor), aOptions);
86 }
FillRectWithMask(DrawTarget * aDT,const gfx::Point & aDeviceOffset,const Rect & aRect,const Color & aColor,const DrawOptions & aOptions,Layer * aMaskLayer)87 void FillRectWithMask(DrawTarget* aDT, const gfx::Point& aDeviceOffset,
88 const Rect& aRect, const Color& aColor,
89 const DrawOptions& aOptions, Layer* aMaskLayer) {
90 AutoMoz2DMaskData mask;
91 if (GetMaskData(aMaskLayer, aDeviceOffset, &mask)) {
92 const Matrix& maskTransform = mask.GetTransform();
93 FillRectWithMask(aDT, aRect, aColor, aOptions, mask.GetSurface(),
94 &maskTransform);
95 return;
96 }
97
98 FillRectWithMask(aDT, aRect, aColor, aOptions);
99 }
100
FillRectWithMask(DrawTarget * aDT,const Rect & aRect,SourceSurface * aSurface,SamplingFilter aSamplingFilter,const DrawOptions & aOptions,ExtendMode aExtendMode,SourceSurface * aMaskSource,const Matrix * aMaskTransform,const Matrix * aSurfaceTransform)101 void FillRectWithMask(DrawTarget* aDT, const Rect& aRect,
102 SourceSurface* aSurface, SamplingFilter aSamplingFilter,
103 const DrawOptions& aOptions, ExtendMode aExtendMode,
104 SourceSurface* aMaskSource, const Matrix* aMaskTransform,
105 const Matrix* aSurfaceTransform) {
106 if (aMaskSource && aMaskTransform) {
107 aDT->PushClipRect(aRect);
108 Matrix oldTransform = aDT->GetTransform();
109
110 Matrix inverseMask = *aMaskTransform;
111 inverseMask.Invert();
112
113 Matrix transform = oldTransform * inverseMask;
114 if (aSurfaceTransform) {
115 transform = (*aSurfaceTransform) * transform;
116 }
117
118 SurfacePattern source(aSurface, aExtendMode, transform, aSamplingFilter);
119
120 aDT->SetTransform(*aMaskTransform);
121 aDT->MaskSurface(source, aMaskSource, Point(0, 0), aOptions);
122
123 aDT->SetTransform(oldTransform);
124 aDT->PopClip();
125 return;
126 }
127
128 aDT->FillRect(
129 aRect,
130 SurfacePattern(aSurface, aExtendMode,
131 aSurfaceTransform ? (*aSurfaceTransform) : Matrix(),
132 aSamplingFilter),
133 aOptions);
134 }
135
FillRectWithMask(DrawTarget * aDT,const gfx::Point & aDeviceOffset,const Rect & aRect,SourceSurface * aSurface,SamplingFilter aSamplingFilter,const DrawOptions & aOptions,Layer * aMaskLayer)136 void FillRectWithMask(DrawTarget* aDT, const gfx::Point& aDeviceOffset,
137 const Rect& aRect, SourceSurface* aSurface,
138 SamplingFilter aSamplingFilter,
139 const DrawOptions& aOptions, Layer* aMaskLayer) {
140 AutoMoz2DMaskData mask;
141 if (GetMaskData(aMaskLayer, aDeviceOffset, &mask)) {
142 const Matrix& maskTransform = mask.GetTransform();
143 FillRectWithMask(aDT, aRect, aSurface, aSamplingFilter, aOptions,
144 ExtendMode::CLAMP, mask.GetSurface(), &maskTransform);
145 return;
146 }
147
148 FillRectWithMask(aDT, aRect, aSurface, aSamplingFilter, aOptions,
149 ExtendMode::CLAMP);
150 }
151
FillPathWithMask(DrawTarget * aDT,const Path * aPath,const Rect & aClipRect,const Color & aColor,const DrawOptions & aOptions,SourceSurface * aMaskSource,const Matrix * aMaskTransform)152 void FillPathWithMask(DrawTarget* aDT, const Path* aPath, const Rect& aClipRect,
153 const Color& aColor, const DrawOptions& aOptions,
154 SourceSurface* aMaskSource,
155 const Matrix* aMaskTransform) {
156 if (aMaskSource && aMaskTransform) {
157 aDT->PushClipRect(aClipRect);
158 Matrix oldTransform = aDT->GetTransform();
159
160 aDT->SetTransform(*aMaskTransform);
161 aDT->MaskSurface(ColorPattern(aColor), aMaskSource, Point(), aOptions);
162 aDT->SetTransform(oldTransform);
163 aDT->PopClip();
164 return;
165 }
166
167 aDT->Fill(aPath, ColorPattern(aColor), aOptions);
168 }
169
FillPathWithMask(DrawTarget * aDT,const Path * aPath,const Rect & aClipRect,SourceSurface * aSurface,SamplingFilter aSamplingFilter,const DrawOptions & aOptions,ExtendMode aExtendMode,SourceSurface * aMaskSource,const Matrix * aMaskTransform,const Matrix * aSurfaceTransform)170 void FillPathWithMask(DrawTarget* aDT, const Path* aPath, const Rect& aClipRect,
171 SourceSurface* aSurface, SamplingFilter aSamplingFilter,
172 const DrawOptions& aOptions, ExtendMode aExtendMode,
173 SourceSurface* aMaskSource, const Matrix* aMaskTransform,
174 const Matrix* aSurfaceTransform) {
175 if (aMaskSource && aMaskTransform) {
176 aDT->PushClipRect(aClipRect);
177 Matrix oldTransform = aDT->GetTransform();
178
179 Matrix inverseMask = *aMaskTransform;
180 inverseMask.Invert();
181
182 Matrix transform = oldTransform * inverseMask;
183 if (aSurfaceTransform) {
184 transform = (*aSurfaceTransform) * transform;
185 }
186
187 SurfacePattern source(aSurface, aExtendMode, transform, aSamplingFilter);
188
189 aDT->SetTransform(*aMaskTransform);
190 aDT->MaskSurface(source, aMaskSource, Point(0, 0), aOptions);
191 aDT->SetTransform(oldTransform);
192 aDT->PopClip();
193 return;
194 }
195
196 aDT->Fill(aPath,
197 SurfacePattern(aSurface, aExtendMode,
198 aSurfaceTransform ? (*aSurfaceTransform) : Matrix(),
199 aSamplingFilter),
200 aOptions);
201 }
202
ToData(Layer * aLayer)203 BasicImplData* ToData(Layer* aLayer) {
204 return static_cast<BasicImplData*>(aLayer->ImplData());
205 }
206
GetEffectiveOperator(Layer * aLayer)207 gfx::CompositionOp GetEffectiveOperator(Layer* aLayer) {
208 CompositionOp op = aLayer->GetEffectiveMixBlendMode();
209
210 if (op != CompositionOp::OP_OVER) {
211 return op;
212 }
213
214 return ToData(aLayer)->GetOperator();
215 }
216
ToShadowable(Layer * aLayer)217 ShadowableLayer* ToShadowable(Layer* aLayer) {
218 return aLayer->AsShadowableLayer();
219 }
220
ShouldShadow(Layer * aLayer)221 bool ShouldShadow(Layer* aLayer) {
222 if (!ToShadowable(aLayer)) {
223 MOZ_ASSERT(aLayer->GetType() == Layer::TYPE_READBACK,
224 "Only expect not to shadow ReadbackLayers");
225 return false;
226 }
227 return true;
228 }
229
230 } // namespace layers
231 } // namespace mozilla
232