gfx/layers/client/SimpleTiledContentClient.cpp

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:d8925e802307
1 /* -*- Mode: C++; tab-width: 20; 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 "mozilla/layers/SimpleTiledContentClient.h"
7
8 #include <math.h> // for ceil, ceilf, floor
9 #include "ClientTiledThebesLayer.h" // for ClientTiledThebesLayer
10 #include "GeckoProfiler.h" // for PROFILER_LABEL
11 #include "Units.h" // for ScreenIntRect, CSSPoint, etc
12 #include "UnitTransforms.h" // for TransformTo
13 #include "ClientLayerManager.h" // for ClientLayerManager
14 #include "CompositorChild.h" // for CompositorChild
15 #include "gfxContext.h" // for gfxContext, etc
16 #include "gfxPlatform.h" // for gfxPlatform
17 #include "gfxPrefs.h" // for gfxPrefs::LayersTileWidth/Height
18 #include "gfxRect.h" // for gfxRect
19 #include "mozilla/Attributes.h" // for MOZ_THIS_IN_INITIALIZER_LIST
20 #include "mozilla/MathAlgorithms.h" // for Abs
21 #include "mozilla/gfx/Point.h" // for IntSize
22 #include "mozilla/gfx/Rect.h" // for Rect
23 #include "mozilla/layers/CompositableForwarder.h"
24 #include "mozilla/layers/ShadowLayers.h" // for ShadowLayerForwarder
25 #include "SimpleTextureClientPool.h"
26 #include "nsDebug.h" // for NS_ASSERTION
27 #include "nsISupportsImpl.h" // for gfxContext::AddRef, etc
28 #include "nsSize.h" // for nsIntSize
29 #include "gfxReusableSharedImageSurfaceWrapper.h"
30 #include "nsMathUtils.h" // for NS_roundf
31 #include "gfx2DGlue.h"
32
33 #define ALOG(...) __android_log_print(ANDROID_LOG_INFO, "SimpleTiles", __VA_ARGS__)
34
35 using namespace mozilla::gfx;
36
37 namespace mozilla {
38 namespace layers {
39
40 void
41 SimpleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
42 const nsIntRegion& aPaintRegion,
43 LayerManager::DrawThebesLayerCallback aCallback,
44 void* aCallbackData)
45 {
46 mCallback = aCallback;
47 mCallbackData = aCallbackData;
48
49 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
50 long start = PR_IntervalNow();
51 #endif
52
53 // If this region is empty XMost() - 1 will give us a negative value.
54 NS_ASSERTION(!aPaintRegion.GetBounds().IsEmpty(), "Empty paint region\n");
55
56 PROFILER_LABEL("SimpleTiledLayerBuffer", "PaintThebesUpdate");
57
58 Update(aNewValidRegion, aPaintRegion);
59
60 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
61 if (PR_IntervalNow() - start > 10) {
62 const nsIntRect bounds = aPaintRegion.GetBounds();
63 printf_stderr("Time to tile [%i, %i, %i, %i] -> %i\n", bounds.x, bounds.y, bounds.width, bounds.height, PR_IntervalNow() - start);
64 }
65 #endif
66
67 mLastPaintOpaque = mThebesLayer->CanUseOpaqueSurface();
68 mCallback = nullptr;
69 mCallbackData = nullptr;
70 }
71
72 SimpleTiledLayerTile
73 SimpleTiledLayerBuffer::ValidateTile(SimpleTiledLayerTile aTile,
74 const nsIntPoint& aTileOrigin,
75 const nsIntRegion& aDirtyRegion)
76 {
77 PROFILER_LABEL("SimpleTiledLayerBuffer", "ValidateTile");
78 static gfx::IntSize kTileSize(gfxPrefs::LayersTileWidth(), gfxPrefs::LayersTileHeight());
79
80 gfx::SurfaceFormat tileFormat = gfxPlatform::GetPlatform()->Optimal2DFormatForContent(GetContentType());
81
82 // if this is true, we're using a separate buffer to do our drawing first
83 bool doBufferedDrawing = true;
84 bool fullPaint = false;
85
86 RefPtr<TextureClient> textureClient = mManager->GetSimpleTileTexturePool(tileFormat)->GetTextureClientWithAutoRecycle();
87
88 if (!textureClient) {
89 NS_WARNING("TextureClient allocation failed");
90 return SimpleTiledLayerTile();
91 }
92
93 if (!textureClient->Lock(OPEN_READ_WRITE)) {
94 NS_WARNING("TextureClient lock failed");
95 return SimpleTiledLayerTile();
96 }
97
98 if (!textureClient->CanExposeDrawTarget()) {
99 doBufferedDrawing = false;
100 }
101
102 RefPtr<DrawTarget> drawTarget;
103
104 unsigned char *bufferData = nullptr;
105
106 // these are set/updated differently based on doBufferedDrawing
107 nsIntRect drawBounds;
108 nsIntRegion drawRegion;
109 nsIntRegion invalidateRegion;
110
111 RefPtr<DrawTarget> srcDT;
112 uint8_t* srcData = nullptr;
113 int32_t srcStride = 0;
114 gfx::IntSize srcSize;
115 gfx::SurfaceFormat srcFormat = gfx::SurfaceFormat::UNKNOWN;
116
117 if (doBufferedDrawing) {
118 // try to directly access the pixels of the TextureClient
119 srcDT = textureClient->GetAsDrawTarget();
120 if (srcDT->LockBits(&srcData, &srcSize, &srcStride, &srcFormat)) {
121 if (!aTile.mCachedBuffer) {
122 aTile.mCachedBuffer = SharedBuffer::Create(srcStride * srcSize.height);
123 fullPaint = true;
124 }
125 bufferData = (unsigned char*) aTile.mCachedBuffer->Data();
126
127 drawTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForData(bufferData,
128 kTileSize,
129 srcStride,
130 tileFormat);
131
132 if (fullPaint) {
133 drawBounds = nsIntRect(aTileOrigin.x, aTileOrigin.y, GetScaledTileSize().width, GetScaledTileSize().height);
134 drawRegion = nsIntRegion(drawBounds);
135 } else {
136 drawBounds = aDirtyRegion.GetBounds();
137 drawRegion = nsIntRegion(drawBounds);
138 if (GetContentType() == gfxContentType::COLOR_ALPHA)
139 drawTarget->ClearRect(Rect(drawBounds.x - aTileOrigin.x, drawBounds.y - aTileOrigin.y,
140 drawBounds.width, drawBounds.height));
141 }
142 } else {
143 // failed to obtain the client as an ImageSurface
144 doBufferedDrawing = false;
145 }
146 }
147
148 // this might get set above if we couldn't extract out a buffer
149 if (!doBufferedDrawing) {
150 drawTarget = textureClient->GetAsDrawTarget();
151
152 fullPaint = true;
153 drawBounds = nsIntRect(aTileOrigin.x, aTileOrigin.y, GetScaledTileSize().width, GetScaledTileSize().height);
154 drawRegion = nsIntRegion(drawBounds);
155
156 if (GetContentType() == gfxContentType::COLOR_ALPHA)
157 drawTarget->ClearRect(Rect(0, 0, drawBounds.width, drawBounds.height));
158 }
159
160 // do the drawing
161 RefPtr<gfxContext> ctxt = new gfxContext(drawTarget);
162
163 ctxt->Scale(mResolution, mResolution);
164 ctxt->Translate(gfxPoint(-aTileOrigin.x, -aTileOrigin.y));
165
166 mCallback(mThebesLayer, ctxt,
167 drawRegion,
168 fullPaint ? DrawRegionClip::CLIP_NONE : DrawRegionClip::DRAW_SNAPPED, // XXX DRAW or DRAW_SNAPPED?
169 invalidateRegion,
170 mCallbackData);
171
172 ctxt = nullptr;
173
174 if (doBufferedDrawing) {
175 memcpy(srcData, bufferData, srcSize.height * srcStride);
176 bufferData = nullptr;
177 srcDT->ReleaseBits(srcData);
178 srcDT = nullptr;
179 }
180
181 drawTarget = nullptr;
182 textureClient->Unlock();
183
184 if (!mCompositableClient->AddTextureClient(textureClient)) {
185 NS_WARNING("Failed to add tile TextureClient [simple]");
186 return SimpleTiledLayerTile();
187 }
188
189 // aTile.mCachedBuffer was set earlier
190 aTile.mTileBuffer = textureClient;
191 aTile.mManager = mManager;
192 aTile.mLastUpdate = TimeStamp::Now();
193
194 return aTile;
195 }
196
197 SurfaceDescriptorTiles
198 SimpleTiledLayerBuffer::GetSurfaceDescriptorTiles()
199 {
200 InfallibleTArray<TileDescriptor> tiles;
201
202 for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
203 tiles.AppendElement(mRetainedTiles[i].GetTileDescriptor());
204 }
205
206 return SurfaceDescriptorTiles(mValidRegion, mPaintedRegion,
207 tiles, mRetainedWidth, mRetainedHeight,
208 mResolution, mFrameResolution.scale);
209 }
210
211 bool
212 SimpleTiledLayerBuffer::HasFormatChanged() const
213 {
214 return mThebesLayer->CanUseOpaqueSurface() != mLastPaintOpaque;
215 }
216
217 gfxContentType
218 SimpleTiledLayerBuffer::GetContentType() const
219 {
220 if (mThebesLayer->CanUseOpaqueSurface())
221 return gfxContentType::COLOR;
222
223 return gfxContentType::COLOR_ALPHA;
224 }
225
226 SimpleTiledContentClient::SimpleTiledContentClient(SimpleClientTiledThebesLayer* aThebesLayer,
227 ClientLayerManager* aManager)
228 : CompositableClient(aManager->AsShadowForwarder())
229 , mTiledBuffer(aThebesLayer, MOZ_THIS_IN_INITIALIZER_LIST(), aManager)
230 {
231 MOZ_COUNT_CTOR(SimpleTiledContentClient);
232 }
233
234 SimpleTiledContentClient::~SimpleTiledContentClient()
235 {
236 MOZ_COUNT_DTOR(SimpleTiledContentClient);
237 mTiledBuffer.Release();
238 }
239
240 void
241 SimpleTiledContentClient::UseTiledLayerBuffer()
242 {
243 mForwarder->UseTiledLayerBuffer(this, mTiledBuffer.GetSurfaceDescriptorTiles());
244 mTiledBuffer.ClearPaintedRegion();
245 }
246
247 SimpleClientTiledThebesLayer::SimpleClientTiledThebesLayer(ClientLayerManager* aManager)
248 : ThebesLayer(aManager,
249 static_cast<ClientLayer*>(MOZ_THIS_IN_INITIALIZER_LIST()))
250 , mContentClient()
251 {
252 MOZ_COUNT_CTOR(SimpleClientTiledThebesLayer);
253 }
254
255 SimpleClientTiledThebesLayer::~SimpleClientTiledThebesLayer()
256 {
257 MOZ_COUNT_DTOR(SimpleClientTiledThebesLayer);
258 }
259
260 void
261 SimpleClientTiledThebesLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
262 {
263 aAttrs = ThebesLayerAttributes(GetValidRegion());
264 }
265
266 void
267 SimpleClientTiledThebesLayer::RenderLayer()
268 {
269 LayerManager::DrawThebesLayerCallback callback =
270 ClientManager()->GetThebesLayerCallback();
271 void *data = ClientManager()->GetThebesLayerCallbackData();
272 if (!callback) {
273 ClientManager()->SetTransactionIncomplete();
274 return;
275 }
276
277 // First time? Create a content client.
278 if (!mContentClient) {
279 mContentClient = new SimpleTiledContentClient(this, ClientManager());
280
281 mContentClient->Connect();
282 ClientManager()->AsShadowForwarder()->Attach(mContentClient, this);
283 MOZ_ASSERT(mContentClient->GetForwarder());
284 }
285
286 // If the format changed, nothing is valid
287 if (mContentClient->mTiledBuffer.HasFormatChanged()) {
288 mValidRegion = nsIntRegion();
289 }
290
291 nsIntRegion invalidRegion = mVisibleRegion;
292 invalidRegion.Sub(invalidRegion, mValidRegion);
293 if (invalidRegion.IsEmpty()) {
294 return;
295 }
296
297 // Only paint the mask layer on the first transaction.
298 if (GetMaskLayer() && !ClientManager()->IsRepeatTransaction()) {
299 ToClientLayer(GetMaskLayer())->RenderLayer();
300 }
301
302 // SimpleTiledContentClient doesn't support progressive updates or the low
303 // precision buffer yet.
304 MOZ_ASSERT(!gfxPrefs::UseProgressiveTilePainting() &&
305 !gfxPrefs::UseLowPrecisionBuffer());
306
307 mValidRegion = mVisibleRegion;
308
309 NS_ASSERTION(!ClientManager()->IsRepeatTransaction(), "Didn't paint our mask layer");
310
311 mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion,
312 callback, data);
313
314 ClientManager()->Hold(this);
315
316 mContentClient->UseTiledLayerBuffer();
317 }
318
319
320 }
321 }

mercurial