/src/mozilla-central/gfx/layers/basic/BasicPaintedLayer.cpp
Line | Count | Source (jump to first uncovered line) |
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 "BasicPaintedLayer.h" |
8 | | #include <stdint.h> // for uint32_t |
9 | | #include "GeckoProfiler.h" // for AUTO_PROFILER_LABEL |
10 | | #include "ReadbackLayer.h" // for ReadbackLayer, ReadbackSink |
11 | | #include "ReadbackProcessor.h" // for ReadbackProcessor::Update, etc |
12 | | #include "RenderTrace.h" // for RenderTraceInvalidateEnd, etc |
13 | | #include "BasicLayersImpl.h" // for AutoMaskData, etc |
14 | | #include "gfxContext.h" // for gfxContext, etc |
15 | | #include "gfxRect.h" // for gfxRect |
16 | | #include "gfxUtils.h" // for gfxUtils |
17 | | #include "mozilla/gfx/2D.h" // for DrawTarget |
18 | | #include "mozilla/gfx/BaseRect.h" // for BaseRect |
19 | | #include "mozilla/gfx/Matrix.h" // for Matrix |
20 | | #include "mozilla/gfx/Rect.h" // for Rect, IntRect |
21 | | #include "mozilla/gfx/Types.h" // for Float, etc |
22 | | #include "mozilla/layers/LayersTypes.h" |
23 | | #include "nsCOMPtr.h" // for already_AddRefed |
24 | | #include "nsISupportsImpl.h" // for gfxContext::Release, etc |
25 | | #include "nsPoint.h" // for nsIntPoint |
26 | | #include "nsRect.h" // for mozilla::gfx::IntRect |
27 | | #include "nsTArray.h" // for nsTArray, nsTArray_Impl |
28 | | #include "AutoMaskData.h" |
29 | | #include "gfx2DGlue.h" |
30 | | |
31 | | namespace mozilla { |
32 | | namespace layers { |
33 | | |
34 | | using namespace mozilla::gfx; |
35 | | |
36 | | static nsIntRegion |
37 | | IntersectWithClip(const nsIntRegion& aRegion, gfxContext* aContext) |
38 | 0 | { |
39 | 0 | gfxRect clip = aContext->GetClipExtents(); |
40 | 0 | nsIntRegion result; |
41 | 0 | result.And(aRegion, IntRect::RoundOut(clip.X(), clip.Y(), |
42 | 0 | clip.Width(), clip.Height())); |
43 | 0 | return result; |
44 | 0 | } |
45 | | |
46 | | void |
47 | | BasicPaintedLayer::PaintThebes(gfxContext* aContext, |
48 | | Layer* aMaskLayer, |
49 | | LayerManager::DrawPaintedLayerCallback aCallback, |
50 | | void* aCallbackData) |
51 | 0 | { |
52 | 0 | AUTO_PROFILER_LABEL("BasicPaintedLayer::PaintThebes", GRAPHICS); |
53 | 0 |
|
54 | 0 | NS_ASSERTION(BasicManager()->InDrawing(), |
55 | 0 | "Can only draw in drawing phase"); |
56 | 0 |
|
57 | 0 | float opacity = GetEffectiveOpacity(); |
58 | 0 | CompositionOp effectiveOperator = GetEffectiveOperator(this); |
59 | 0 |
|
60 | 0 | if (!BasicManager()->IsRetained()) { |
61 | 0 | ClearValidRegion(); |
62 | 0 | mContentClient->Clear(); |
63 | 0 |
|
64 | 0 | nsIntRegion toDraw = IntersectWithClip(GetLocalVisibleRegion().ToUnknownRegion(), aContext); |
65 | 0 |
|
66 | 0 | RenderTraceInvalidateStart(this, "FFFF00", toDraw.GetBounds()); |
67 | 0 |
|
68 | 0 | if (!toDraw.IsEmpty() && !IsHidden()) { |
69 | 0 | if (!aCallback) { |
70 | 0 | BasicManager()->SetTransactionIncomplete(); |
71 | 0 | return; |
72 | 0 | } |
73 | 0 | |
74 | 0 | aContext->Save(); |
75 | 0 |
|
76 | 0 | bool needsGroup = opacity != 1.0 || |
77 | 0 | effectiveOperator != CompositionOp::OP_OVER || |
78 | 0 | aMaskLayer; |
79 | 0 | RefPtr<gfxContext> context = nullptr; |
80 | 0 | BasicLayerManager::PushedGroup group; |
81 | 0 | bool availableGroup = false; |
82 | 0 |
|
83 | 0 | if (needsGroup) { |
84 | 0 | availableGroup = |
85 | 0 | BasicManager()->PushGroupForLayer(aContext, this, toDraw, group); |
86 | 0 | if (availableGroup) { |
87 | 0 | context = group.mGroupTarget; |
88 | 0 | } |
89 | 0 | } else { |
90 | 0 | context = aContext; |
91 | 0 | } |
92 | 0 | if (context) { |
93 | 0 | DrawTarget* target = context->GetDrawTarget(); |
94 | 0 | bool oldAA = target->GetPermitSubpixelAA(); |
95 | 0 | SetAntialiasingFlags(this, target); |
96 | 0 | aCallback(this, context, toDraw, toDraw, DrawRegionClip::NONE, |
97 | 0 | nsIntRegion(), aCallbackData); |
98 | 0 | target->SetPermitSubpixelAA(oldAA); |
99 | 0 | } |
100 | 0 | if (needsGroup && availableGroup) { |
101 | 0 | BasicManager()->PopGroupForLayer(group); |
102 | 0 | } |
103 | 0 |
|
104 | 0 | aContext->Restore(); |
105 | 0 | } |
106 | 0 |
|
107 | 0 | RenderTraceInvalidateEnd(this, "FFFF00"); |
108 | 0 | return; |
109 | 0 | } |
110 | 0 | |
111 | 0 | if (BasicManager()->IsTransactionIncomplete()) |
112 | 0 | return; |
113 | 0 | |
114 | 0 | gfxRect clipExtents; |
115 | 0 | clipExtents = aContext->GetClipExtents(); |
116 | 0 |
|
117 | 0 | // Pull out the mask surface and transform here, because the mask |
118 | 0 | // is internal to basic layers |
119 | 0 | AutoMoz2DMaskData mask; |
120 | 0 | SourceSurface* maskSurface = nullptr; |
121 | 0 | Matrix maskTransform; |
122 | 0 | if (GetMaskData(aMaskLayer, aContext->GetDeviceOffset(), &mask)) { |
123 | 0 | maskSurface = mask.GetSurface(); |
124 | 0 | maskTransform = mask.GetTransform(); |
125 | 0 | } |
126 | 0 |
|
127 | 0 | if (!IsHidden() && !clipExtents.IsEmpty()) { |
128 | 0 | mContentClient->DrawTo(this, aContext->GetDrawTarget(), opacity, |
129 | 0 | effectiveOperator, |
130 | 0 | maskSurface, &maskTransform); |
131 | 0 | } |
132 | 0 | } |
133 | | |
134 | | void |
135 | | BasicPaintedLayer::Validate(LayerManager::DrawPaintedLayerCallback aCallback, |
136 | | void* aCallbackData, |
137 | | ReadbackProcessor* aReadback) |
138 | 0 | { |
139 | 0 | if (!mContentClient) { |
140 | 0 | // This client will have a null Forwarder, which means it will not have |
141 | 0 | // a ContentHost on the other side. |
142 | 0 | mContentClient = new ContentClientBasic(mBackend); |
143 | 0 | } |
144 | 0 |
|
145 | 0 | if (!BasicManager()->IsRetained()) { |
146 | 0 | return; |
147 | 0 | } |
148 | 0 | |
149 | 0 | nsTArray<ReadbackProcessor::Update> readbackUpdates; |
150 | 0 | if (aReadback && UsedForReadback()) { |
151 | 0 | aReadback->GetPaintedLayerUpdates(this, &readbackUpdates); |
152 | 0 | } |
153 | 0 |
|
154 | 0 | uint32_t flags = 0; |
155 | 0 | #ifndef MOZ_WIDGET_ANDROID |
156 | 0 | if (BasicManager()->CompositorMightResample()) { |
157 | 0 | flags |= ContentClient::PAINT_WILL_RESAMPLE; |
158 | 0 | } |
159 | 0 | if (!(flags & ContentClient::PAINT_WILL_RESAMPLE)) { |
160 | 0 | if (MayResample()) { |
161 | 0 | flags |= ContentClient::PAINT_WILL_RESAMPLE; |
162 | 0 | } |
163 | 0 | } |
164 | 0 | #endif |
165 | 0 | if (mDrawAtomically) { |
166 | 0 | flags |= ContentClient::PAINT_NO_ROTATION; |
167 | 0 | } |
168 | 0 | PaintState state = |
169 | 0 | mContentClient->BeginPaint(this, flags); |
170 | 0 | SubtractFromValidRegion(state.mRegionToInvalidate); |
171 | 0 |
|
172 | 0 | DrawTarget* target = mContentClient->BorrowDrawTargetForPainting(state); |
173 | 0 | if (target && target->IsValid()) { |
174 | 0 | // The area that became invalid and is visible needs to be repainted |
175 | 0 | // (this could be the whole visible area if our buffer switched |
176 | 0 | // from RGB to RGBA, because we might need to repaint with |
177 | 0 | // subpixel AA) |
178 | 0 | state.mRegionToInvalidate.And(state.mRegionToInvalidate, |
179 | 0 | GetLocalVisibleRegion().ToUnknownRegion()); |
180 | 0 | SetAntialiasingFlags(this, target); |
181 | 0 |
|
182 | 0 | RenderTraceInvalidateStart(this, "FFFF00", state.mRegionToDraw.GetBounds()); |
183 | 0 |
|
184 | 0 | RefPtr<gfxContext> ctx = gfxContext::CreatePreservingTransformOrNull(target); |
185 | 0 | MOZ_ASSERT(ctx); // already checked the target above |
186 | 0 |
|
187 | 0 | PaintBuffer(ctx, |
188 | 0 | state.mRegionToDraw, state.mRegionToDraw, state.mRegionToInvalidate, |
189 | 0 | state.mClip, |
190 | 0 | aCallback, aCallbackData); |
191 | 0 | MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PaintThebes", this)); |
192 | 0 | Mutated(); |
193 | 0 | ctx = nullptr; |
194 | 0 | mContentClient->ReturnDrawTarget(target); |
195 | 0 | target = nullptr; |
196 | 0 |
|
197 | 0 | RenderTraceInvalidateEnd(this, "FFFF00"); |
198 | 0 | } else { |
199 | 0 | if (target) { |
200 | 0 | mContentClient->ReturnDrawTarget(target); |
201 | 0 | target = nullptr; |
202 | 0 | } |
203 | 0 |
|
204 | 0 | // It's possible that state.mRegionToInvalidate is nonempty here, |
205 | 0 | // if we are shrinking the valid region to nothing. So use mRegionToDraw |
206 | 0 | // instead. |
207 | 0 | NS_WARNING_ASSERTION( |
208 | 0 | state.mRegionToDraw.IsEmpty(), |
209 | 0 | "No context when we have something to draw, resource exhaustion?"); |
210 | 0 | } |
211 | 0 |
|
212 | 0 | for (uint32_t i = 0; i < readbackUpdates.Length(); ++i) { |
213 | 0 | ReadbackProcessor::Update& update = readbackUpdates[i]; |
214 | 0 | nsIntPoint offset = update.mLayer->GetBackgroundLayerOffset(); |
215 | 0 | RefPtr<DrawTarget> dt = |
216 | 0 | update.mLayer->GetSink()->BeginUpdate(update.mUpdateRect + offset, |
217 | 0 | update.mSequenceCounter); |
218 | 0 | if (dt) { |
219 | 0 | NS_ASSERTION(GetEffectiveOpacity() == 1.0, "Should only read back opaque layers"); |
220 | 0 | NS_ASSERTION(!GetMaskLayer(), "Should only read back layers without masks"); |
221 | 0 | dt->SetTransform(dt->GetTransform().PreTranslate(offset.x, offset.y)); |
222 | 0 | mContentClient->DrawTo(this, dt, 1.0, CompositionOp::OP_OVER, |
223 | 0 | nullptr, nullptr); |
224 | 0 | update.mLayer->GetSink()->EndUpdate(update.mUpdateRect + offset); |
225 | 0 | } |
226 | 0 | } |
227 | 0 | } |
228 | | |
229 | | already_AddRefed<PaintedLayer> |
230 | | BasicLayerManager::CreatePaintedLayer() |
231 | 0 | { |
232 | 0 | NS_ASSERTION(InConstruction(), "Only allowed in construction phase"); |
233 | 0 |
|
234 | 0 | BackendType backend = gfxPlatform::GetPlatform()->GetDefaultContentBackend(); |
235 | 0 |
|
236 | 0 | if (mDefaultTarget) { |
237 | 0 | backend = mDefaultTarget->GetDrawTarget()->GetBackendType(); |
238 | 0 | } else if (mType == BLM_WIDGET) { |
239 | 0 | backend = gfxPlatform::GetPlatform()->GetContentBackendFor(LayersBackend::LAYERS_BASIC); |
240 | 0 | } |
241 | 0 |
|
242 | 0 | RefPtr<PaintedLayer> layer = new BasicPaintedLayer(this, backend); |
243 | 0 | return layer.forget(); |
244 | 0 | } |
245 | | |
246 | | } // namespace layers |
247 | | } // namespace mozilla |