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 "ClientPaintedLayer.h"
8 #include "ClientTiledPaintedLayer.h" // for ClientTiledPaintedLayer
9 #include <stdint.h> // for uint32_t
10 #include "client/ClientLayerManager.h" // for ClientLayerManager, etc
11 #include "gfxContext.h" // for gfxContext
12 #include "gfx2DGlue.h"
13 #include "gfxEnv.h" // for gfxEnv
14 #include "gfxRect.h" // for gfxRect
15
16 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
17 #include "mozilla/gfx/2D.h" // for DrawTarget
18 #include "mozilla/gfx/DrawEventRecorder.h"
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 "mozilla/Preferences.h"
24 #include "mozilla/ProfilerLabels.h"
25 #include "nsCOMPtr.h" // for already_AddRefed
26 #include "nsISupportsImpl.h" // for Layer::AddRef, etc
27 #include "nsRect.h" // for mozilla::gfx::IntRect
28 #include "PaintThread.h"
29 #include "ReadbackProcessor.h"
30 #include "RotatedBuffer.h"
31
32 namespace mozilla {
33 namespace layers {
34
35 using namespace mozilla::gfx;
36
EnsureContentClient()37 bool ClientPaintedLayer::EnsureContentClient() {
38 if (!mContentClient) {
39 mContentClient = ContentClient::CreateContentClient(
40 ClientManager()->AsShadowForwarder());
41
42 if (!mContentClient) {
43 return false;
44 }
45
46 mContentClient->Connect();
47 ClientManager()->AsShadowForwarder()->Attach(mContentClient, this);
48 MOZ_ASSERT(mContentClient->GetForwarder());
49 }
50
51 return true;
52 }
53
UpdateContentClient(PaintState & aState)54 void ClientPaintedLayer::UpdateContentClient(PaintState& aState) {
55 Mutated();
56
57 AddToValidRegion(aState.mRegionToDraw);
58
59 ContentClientRemoteBuffer* contentClientRemote =
60 static_cast<ContentClientRemoteBuffer*>(mContentClient.get());
61 MOZ_ASSERT(contentClientRemote->GetIPCHandle());
62
63 // Hold(this) ensures this layer is kept alive through the current transaction
64 // The ContentClient assumes this layer is kept alive (e.g., in CreateBuffer),
65 // so deleting this Hold for whatever reason will break things.
66 ClientManager()->Hold(this);
67 contentClientRemote->Updated(aState.mRegionToDraw,
68 mVisibleRegion.ToUnknownRegion());
69 }
70
UpdatePaintRegion(PaintState & aState)71 bool ClientPaintedLayer::UpdatePaintRegion(PaintState& aState) {
72 SubtractFromValidRegion(aState.mRegionToInvalidate);
73
74 if (!aState.mRegionToDraw.IsEmpty() &&
75 !ClientManager()->GetPaintedLayerCallback()) {
76 ClientManager()->SetTransactionIncomplete();
77 return false;
78 }
79
80 // The area that became invalid and is visible needs to be repainted
81 // (this could be the whole visible area if our buffer switched
82 // from RGB to RGBA, because we might need to repaint with
83 // subpixel AA)
84 aState.mRegionToInvalidate.And(aState.mRegionToInvalidate,
85 GetLocalVisibleRegion().ToUnknownRegion());
86 return true;
87 }
88
FinishPaintState(PaintState & aState)89 void ClientPaintedLayer::FinishPaintState(PaintState& aState) {
90 if (aState.mAsyncTask && !aState.mAsyncTask->mCapture->IsEmpty()) {
91 ClientManager()->SetQueuedAsyncPaints();
92 PaintThread::Get()->QueuePaintTask(std::move(aState.mAsyncTask));
93 }
94 }
95
GetPaintFlags(ReadbackProcessor * aReadback)96 uint32_t ClientPaintedLayer::GetPaintFlags(ReadbackProcessor* aReadback) {
97 uint32_t flags = ContentClient::PAINT_CAN_DRAW_ROTATED;
98 #ifndef MOZ_IGNORE_PAINT_WILL_RESAMPLE
99 if (ClientManager()->CompositorMightResample()) {
100 flags |= ContentClient::PAINT_WILL_RESAMPLE;
101 }
102 if (!(flags & ContentClient::PAINT_WILL_RESAMPLE)) {
103 if (MayResample()) {
104 flags |= ContentClient::PAINT_WILL_RESAMPLE;
105 }
106 }
107 #endif
108 if ((!aReadback || !UsedForReadback()) && PaintThread::Get()) {
109 flags |= ContentClient::PAINT_ASYNC;
110 }
111 return flags;
112 }
113
RenderLayerWithReadback(ReadbackProcessor * aReadback)114 void ClientPaintedLayer::RenderLayerWithReadback(ReadbackProcessor* aReadback) {
115 AUTO_PROFILER_LABEL("ClientPaintedLayer::RenderLayerWithReadback", GRAPHICS);
116 NS_ASSERTION(ClientManager()->InDrawing(), "Can only draw in drawing phase");
117
118 RenderMaskLayers(this);
119
120 if (!EnsureContentClient()) {
121 return;
122 }
123
124 nsTArray<ReadbackProcessor::Update> readbackUpdates;
125 nsIntRegion readbackRegion;
126 if (aReadback && UsedForReadback()) {
127 aReadback->GetPaintedLayerUpdates(this, &readbackUpdates);
128 }
129
130 uint32_t flags = GetPaintFlags(aReadback);
131
132 PaintState state = mContentClient->BeginPaint(this, flags);
133 if (!UpdatePaintRegion(state)) {
134 mContentClient->EndPaint(state, nullptr);
135 FinishPaintState(state);
136 return;
137 }
138
139 bool didUpdate = false;
140 RotatedBuffer::DrawIterator iter;
141 while (DrawTarget* target =
142 mContentClient->BorrowDrawTargetForPainting(state, &iter)) {
143 SetAntialiasingFlags(this, target);
144
145 RefPtr<gfxContext> ctx =
146 gfxContext::CreatePreservingTransformOrNull(target);
147 MOZ_ASSERT(ctx); // already checked the target above
148
149 if (!gfxEnv::SkipRasterization()) {
150 if (!target->IsCaptureDT()) {
151 target->ClearRect(Rect());
152 if (target->IsValid()) {
153 ClientManager()->GetPaintedLayerCallback()(
154 this, ctx, iter.mDrawRegion, iter.mDrawRegion, state.mClip,
155 state.mRegionToInvalidate,
156 ClientManager()->GetPaintedLayerCallbackData());
157 }
158 } else {
159 ClientManager()->GetPaintedLayerCallback()(
160 this, ctx, iter.mDrawRegion, iter.mDrawRegion, state.mClip,
161 state.mRegionToInvalidate,
162 ClientManager()->GetPaintedLayerCallbackData());
163 }
164 }
165
166 ctx = nullptr;
167 mContentClient->ReturnDrawTarget(target);
168 didUpdate = true;
169 }
170
171 mContentClient->EndPaint(state, &readbackUpdates);
172 FinishPaintState(state);
173
174 if (didUpdate) {
175 UpdateContentClient(state);
176 }
177 }
178
CreatePaintedLayer()179 already_AddRefed<PaintedLayer> ClientLayerManager::CreatePaintedLayer() {
180 return CreatePaintedLayerWithHint(NONE);
181 }
182
CreatePaintedLayerWithHint(PaintedLayerCreationHint aHint)183 already_AddRefed<PaintedLayer> ClientLayerManager::CreatePaintedLayerWithHint(
184 PaintedLayerCreationHint aHint) {
185 NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
186 if (gfxPlatform::GetPlatform()->UsesTiling()) {
187 RefPtr<ClientTiledPaintedLayer> layer =
188 new ClientTiledPaintedLayer(this, aHint);
189 CREATE_SHADOW(Painted);
190 return layer.forget();
191 } else {
192 RefPtr<ClientPaintedLayer> layer = new ClientPaintedLayer(this, aHint);
193 CREATE_SHADOW(Painted);
194 return layer.forget();
195 }
196 }
197
PrintInfo(std::stringstream & aStream,const char * aPrefix)198 void ClientPaintedLayer::PrintInfo(std::stringstream& aStream,
199 const char* aPrefix) {
200 PaintedLayer::PrintInfo(aStream, aPrefix);
201 if (mContentClient) {
202 aStream << "\n";
203 nsAutoCString pfx(aPrefix);
204 pfx += " ";
205 mContentClient->PrintInfo(aStream, pfx.get());
206 }
207 }
208
209 } // namespace layers
210 } // namespace mozilla
211