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