gfx/layers/client/TiledContentClient.h

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:f530b9c61f3b
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 #ifndef MOZILLA_GFX_TILEDCONTENTCLIENT_H
7 #define MOZILLA_GFX_TILEDCONTENTCLIENT_H
8
9 #include <stddef.h> // for size_t
10 #include <stdint.h> // for uint16_t
11 #include <algorithm> // for swap
12 #include "Layers.h" // for LayerManager, etc
13 #include "TiledLayerBuffer.h" // for TiledLayerBuffer
14 #include "Units.h" // for CSSPoint
15 #include "gfx3DMatrix.h" // for gfx3DMatrix
16 #include "gfxTypes.h"
17 #include "mozilla/Attributes.h" // for MOZ_OVERRIDE
18 #include "mozilla/RefPtr.h" // for RefPtr
19 #include "mozilla/ipc/Shmem.h" // for Shmem
20 #include "mozilla/ipc/SharedMemory.h" // for SharedMemory
21 #include "mozilla/layers/CompositableClient.h" // for CompositableClient
22 #include "mozilla/layers/CompositorTypes.h" // for TextureInfo, etc
23 #include "mozilla/layers/LayersMessages.h" // for TileDescriptor
24 #include "mozilla/layers/TextureClient.h"
25 #include "mozilla/layers/TextureClientPool.h"
26 #include "ClientLayerManager.h"
27 #include "mozilla/mozalloc.h" // for operator delete
28 #include "nsAutoPtr.h" // for nsRefPtr
29 #include "nsISupportsImpl.h" // for MOZ_COUNT_DTOR
30 #include "nsPoint.h" // for nsIntPoint
31 #include "nsRect.h" // for nsIntRect
32 #include "nsRegion.h" // for nsIntRegion
33 #include "nsTArray.h" // for nsTArray, nsTArray_Impl, etc
34 #include "mozilla/layers/ISurfaceAllocator.h"
35 #include "gfxReusableSurfaceWrapper.h"
36 #include "pratom.h" // For PR_ATOMIC_INCREMENT/DECREMENT
37 #include "gfxPrefs.h"
38
39 namespace mozilla {
40 namespace layers {
41
42 class BasicTileDescriptor;
43 class ClientTiledThebesLayer;
44 class ClientLayerManager;
45
46
47 // A class to help implement copy-on-write semantics for shared tiles.
48 class gfxSharedReadLock {
49 protected:
50 virtual ~gfxSharedReadLock() {}
51
52 public:
53 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxSharedReadLock)
54
55 virtual int32_t ReadLock() = 0;
56 virtual int32_t ReadUnlock() = 0;
57 virtual int32_t GetReadCount() = 0;
58 virtual bool IsValid() const = 0;
59
60 enum gfxSharedReadLockType {
61 TYPE_MEMORY,
62 TYPE_SHMEM
63 };
64 virtual gfxSharedReadLockType GetType() = 0;
65
66 protected:
67 NS_DECL_OWNINGTHREAD
68 };
69
70 class gfxMemorySharedReadLock : public gfxSharedReadLock {
71 public:
72 gfxMemorySharedReadLock();
73
74 ~gfxMemorySharedReadLock();
75
76 virtual int32_t ReadLock() MOZ_OVERRIDE;
77
78 virtual int32_t ReadUnlock() MOZ_OVERRIDE;
79
80 virtual int32_t GetReadCount() MOZ_OVERRIDE;
81
82 virtual gfxSharedReadLockType GetType() MOZ_OVERRIDE { return TYPE_MEMORY; }
83
84 virtual bool IsValid() const MOZ_OVERRIDE { return true; };
85
86 private:
87 int32_t mReadCount;
88 };
89
90 class gfxShmSharedReadLock : public gfxSharedReadLock {
91 private:
92 struct ShmReadLockInfo {
93 int32_t readCount;
94 };
95
96 public:
97 gfxShmSharedReadLock(ISurfaceAllocator* aAllocator);
98
99 ~gfxShmSharedReadLock();
100
101 virtual int32_t ReadLock() MOZ_OVERRIDE;
102
103 virtual int32_t ReadUnlock() MOZ_OVERRIDE;
104
105 virtual int32_t GetReadCount() MOZ_OVERRIDE;
106
107 virtual bool IsValid() const MOZ_OVERRIDE { return mAllocSuccess; };
108
109 virtual gfxSharedReadLockType GetType() MOZ_OVERRIDE { return TYPE_SHMEM; }
110
111 mozilla::layers::ShmemSection& GetShmemSection() { return mShmemSection; }
112
113 static already_AddRefed<gfxShmSharedReadLock>
114 Open(mozilla::layers::ISurfaceAllocator* aAllocator, const mozilla::layers::ShmemSection& aShmemSection)
115 {
116 nsRefPtr<gfxShmSharedReadLock> readLock = new gfxShmSharedReadLock(aAllocator, aShmemSection);
117 return readLock.forget();
118 }
119
120 private:
121 gfxShmSharedReadLock(ISurfaceAllocator* aAllocator, const mozilla::layers::ShmemSection& aShmemSection)
122 : mAllocator(aAllocator)
123 , mShmemSection(aShmemSection)
124 , mAllocSuccess(true)
125 {
126 MOZ_COUNT_CTOR(gfxShmSharedReadLock);
127 }
128
129 ShmReadLockInfo* GetShmReadLockInfoPtr()
130 {
131 return reinterpret_cast<ShmReadLockInfo*>
132 (mShmemSection.shmem().get<char>() + mShmemSection.offset());
133 }
134
135 RefPtr<ISurfaceAllocator> mAllocator;
136 mozilla::layers::ShmemSection mShmemSection;
137 bool mAllocSuccess;
138 };
139
140 /**
141 * Represent a single tile in tiled buffer. The buffer keeps tiles,
142 * each tile keeps a reference to a texture client and a read-lock. This
143 * read-lock is used to help implement a copy-on-write mechanism. The tile
144 * should be locked before being sent to the compositor. The compositor should
145 * unlock the read-lock as soon as it has finished with the buffer in the
146 * TextureHost to prevent more textures being created than is necessary.
147 * Ideal place to store per tile debug information.
148 */
149 struct TileClient
150 {
151 // Placeholder
152 TileClient();
153
154 TileClient(const TileClient& o);
155
156 TileClient& operator=(const TileClient& o);
157
158 bool operator== (const TileClient& o) const
159 {
160 return mFrontBuffer == o.mFrontBuffer;
161 }
162
163 bool operator!= (const TileClient& o) const
164 {
165 return mFrontBuffer != o.mFrontBuffer;
166 }
167
168 void SetLayerManager(ClientLayerManager *aManager)
169 {
170 mManager = aManager;
171 }
172
173 bool IsPlaceholderTile()
174 {
175 return mBackBuffer == nullptr && mFrontBuffer == nullptr;
176 }
177
178 void ReadUnlock()
179 {
180 MOZ_ASSERT(mFrontLock, "ReadLock with no gfxSharedReadLock");
181 if (mFrontLock) {
182 mFrontLock->ReadUnlock();
183 }
184 }
185
186 void ReadLock()
187 {
188 MOZ_ASSERT(mFrontLock, "ReadLock with no gfxSharedReadLock");
189 if (mFrontLock) {
190 mFrontLock->ReadLock();
191 }
192 }
193
194 void Release()
195 {
196 DiscardFrontBuffer();
197 DiscardBackBuffer();
198 }
199
200 TileDescriptor GetTileDescriptor();
201
202 /**
203 * Swaps the front and back buffers.
204 */
205 void Flip();
206
207 /**
208 * Returns an unlocked TextureClient that can be used for writing new
209 * data to the tile. This may flip the front-buffer to the back-buffer if
210 * the front-buffer is still locked by the host, or does not have an
211 * internal buffer (and so will always be locked).
212 */
213 TextureClient* GetBackBuffer(const nsIntRegion& aDirtyRegion,
214 TextureClientPool *aPool,
215 bool *aCreatedTextureClient,
216 bool aCanRerasterizeValidRegion);
217
218 void DiscardFrontBuffer();
219
220 void DiscardBackBuffer();
221
222 RefPtr<TextureClient> mBackBuffer;
223 RefPtr<TextureClient> mFrontBuffer;
224 RefPtr<gfxSharedReadLock> mBackLock;
225 RefPtr<gfxSharedReadLock> mFrontLock;
226 RefPtr<ClientLayerManager> mManager;
227 #ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
228 TimeStamp mLastUpdate;
229 #endif
230 nsIntRegion mInvalidFront;
231 nsIntRegion mInvalidBack;
232
233 private:
234 void ValidateBackBufferFromFront(const nsIntRegion &aDirtyRegion,
235 bool aCanRerasterizeValidRegion);
236 };
237
238 /**
239 * This struct stores all the data necessary to perform a paint so that it
240 * doesn't need to be recalculated on every repeated transaction.
241 */
242 struct BasicTiledLayerPaintData {
243 /*
244 * The scroll offset of the content from the nearest ancestor layer that
245 * represents scrollable content with a display port set.
246 */
247 ParentLayerPoint mScrollOffset;
248
249 /*
250 * The scroll offset of the content from the nearest ancestor layer that
251 * represents scrollable content with a display port set, for the last
252 * layer update transaction.
253 */
254 ParentLayerPoint mLastScrollOffset;
255
256 /*
257 * The transform matrix to go from Screen units to ParentLayer units.
258 */
259 gfx3DMatrix mTransformParentLayerToLayoutDevice;
260
261 /*
262 * The critical displayport of the content from the nearest ancestor layer
263 * that represents scrollable content with a display port set. Empty if a
264 * critical displayport is not set.
265 *
266 * This is in LayoutDevice coordinates, but is stored as an nsIntRect for
267 * convenience when intersecting with the layer's mValidRegion.
268 */
269 nsIntRect mCriticalDisplayPort;
270
271 /*
272 * The viewport of the content from the nearest ancestor layer that
273 * represents scrollable content with a display port set.
274 */
275 LayoutDeviceRect mViewport;
276
277 /*
278 * The render resolution of the document that the content this layer
279 * represents is in.
280 */
281 CSSToParentLayerScale mResolution;
282
283 /*
284 * The composition bounds of the layer, in LayoutDevice coordinates. This is
285 * used to make sure that tiled updates to regions that are visible to the
286 * user are grouped coherently.
287 */
288 LayoutDeviceRect mCompositionBounds;
289
290 /*
291 * Low precision updates are always executed a tile at a time in repeated
292 * transactions. This counter is set to 1 on the first transaction of a low
293 * precision update, and incremented for each subsequent transaction.
294 */
295 uint16_t mLowPrecisionPaintCount;
296
297 /*
298 * Whether this is the first time this layer is painting
299 */
300 bool mFirstPaint : 1;
301
302 /*
303 * Whether there is further work to complete this paint. This is used to
304 * determine whether or not to repeat the transaction when painting
305 * progressively.
306 */
307 bool mPaintFinished : 1;
308 };
309
310 class SharedFrameMetricsHelper
311 {
312 public:
313 SharedFrameMetricsHelper();
314 ~SharedFrameMetricsHelper();
315
316 /**
317 * This is called by the BasicTileLayer to determine if it is still interested
318 * in the update of this display-port to continue. We can return true here
319 * to abort the current update and continue with any subsequent ones. This
320 * is useful for slow-to-render pages when the display-port starts lagging
321 * behind enough that continuing to draw it is wasted effort.
322 */
323 bool UpdateFromCompositorFrameMetrics(ContainerLayer* aLayer,
324 bool aHasPendingNewThebesContent,
325 bool aLowPrecision,
326 ParentLayerRect& aCompositionBounds,
327 CSSToParentLayerScale& aZoom);
328
329 /**
330 * When a shared FrameMetrics can not be found for a given layer,
331 * this function is used to find the first non-empty composition bounds
332 * by traversing up the layer tree.
333 */
334 void FindFallbackContentFrameMetrics(ContainerLayer* aLayer,
335 ParentLayerRect& aCompositionBounds,
336 CSSToParentLayerScale& aZoom);
337 /**
338 * Determines if the compositor's upcoming composition bounds has fallen
339 * outside of the contents display port. If it has then the compositor
340 * will start to checker board. Checker boarding is when the compositor
341 * tries to composite a tile and it is not available. Historically
342 * a tile with a checker board pattern was used. Now a blank tile is used.
343 */
344 bool AboutToCheckerboard(const FrameMetrics& aContentMetrics,
345 const FrameMetrics& aCompositorMetrics);
346 private:
347 bool mLastProgressiveUpdateWasLowPrecision;
348 bool mProgressiveUpdateWasInDanger;
349 };
350
351 /**
352 * Provide an instance of TiledLayerBuffer backed by drawable TextureClients.
353 * This buffer provides an implementation of ValidateTile using a
354 * thebes callback and can support painting using a single paint buffer.
355 * Whether a single paint buffer is used is controlled by
356 * gfxPrefs::PerTileDrawing().
357 */
358 class ClientTiledLayerBuffer
359 : public TiledLayerBuffer<ClientTiledLayerBuffer, TileClient>
360 {
361 friend class TiledLayerBuffer<ClientTiledLayerBuffer, TileClient>;
362
363 public:
364 ClientTiledLayerBuffer(ClientTiledThebesLayer* aThebesLayer,
365 CompositableClient* aCompositableClient,
366 ClientLayerManager* aManager,
367 SharedFrameMetricsHelper* aHelper);
368 ClientTiledLayerBuffer()
369 : mThebesLayer(nullptr)
370 , mCompositableClient(nullptr)
371 , mManager(nullptr)
372 , mLastPaintOpaque(false)
373 , mSharedFrameMetricsHelper(nullptr)
374 {}
375
376 void PaintThebes(const nsIntRegion& aNewValidRegion,
377 const nsIntRegion& aPaintRegion,
378 LayerManager::DrawThebesLayerCallback aCallback,
379 void* aCallbackData);
380
381 void ReadUnlock();
382
383 void ReadLock();
384
385 void Release();
386
387 void DiscardBackBuffers();
388
389 const CSSToParentLayerScale& GetFrameResolution() { return mFrameResolution; }
390
391 void SetFrameResolution(const CSSToParentLayerScale& aResolution) { mFrameResolution = aResolution; }
392
393 bool HasFormatChanged() const;
394
395 /**
396 * Performs a progressive update of a given tiled buffer.
397 * See ComputeProgressiveUpdateRegion below for parameter documentation.
398 */
399 bool ProgressiveUpdate(nsIntRegion& aValidRegion,
400 nsIntRegion& aInvalidRegion,
401 const nsIntRegion& aOldValidRegion,
402 BasicTiledLayerPaintData* aPaintData,
403 LayerManager::DrawThebesLayerCallback aCallback,
404 void* aCallbackData);
405
406 SurfaceDescriptorTiles GetSurfaceDescriptorTiles();
407
408 protected:
409 TileClient ValidateTile(TileClient aTile,
410 const nsIntPoint& aTileRect,
411 const nsIntRegion& dirtyRect);
412
413 // If this returns true, we perform the paint operation into a single large
414 // buffer and copy it out to the tiles instead of calling PaintThebes() on
415 // each tile individually. Somewhat surprisingly, this turns out to be faster
416 // on Android.
417 bool UseSinglePaintBuffer() { return !gfxPrefs::PerTileDrawing(); }
418
419 void ReleaseTile(TileClient aTile) { aTile.Release(); }
420
421 void SwapTiles(TileClient& aTileA, TileClient& aTileB) { std::swap(aTileA, aTileB); }
422
423 TileClient GetPlaceholderTile() const { return TileClient(); }
424
425 private:
426 gfxContentType GetContentType() const;
427 ClientTiledThebesLayer* mThebesLayer;
428 CompositableClient* mCompositableClient;
429 ClientLayerManager* mManager;
430 LayerManager::DrawThebesLayerCallback mCallback;
431 void* mCallbackData;
432 CSSToParentLayerScale mFrameResolution;
433 bool mLastPaintOpaque;
434
435 // The DrawTarget we use when UseSinglePaintBuffer() above is true.
436 RefPtr<gfx::DrawTarget> mSinglePaintDrawTarget;
437 nsIntPoint mSinglePaintBufferOffset;
438 SharedFrameMetricsHelper* mSharedFrameMetricsHelper;
439
440 /**
441 * Calculates the region to update in a single progressive update transaction.
442 * This employs some heuristics to update the most 'sensible' region to
443 * update at this point in time, and how large an update should be performed
444 * at once to maintain visual coherency.
445 *
446 * aInvalidRegion is the current invalid region.
447 * aOldValidRegion is the valid region of mTiledBuffer at the beginning of the
448 * current transaction.
449 * aRegionToPaint will be filled with the region to update. This may be empty,
450 * which indicates that there is no more work to do.
451 * aIsRepeated should be true if this function has already been called during
452 * this transaction.
453 *
454 * Returns true if it should be called again, false otherwise. In the case
455 * that aRegionToPaint is empty, this will return aIsRepeated for convenience.
456 */
457 bool ComputeProgressiveUpdateRegion(const nsIntRegion& aInvalidRegion,
458 const nsIntRegion& aOldValidRegion,
459 nsIntRegion& aRegionToPaint,
460 BasicTiledLayerPaintData* aPaintData,
461 bool aIsRepeated);
462 };
463
464 class TiledContentClient : public CompositableClient
465 {
466 // XXX: for now the layer which owns us interacts directly with our buffers.
467 // We should have a content client for each tiled buffer which manages its
468 // own valid region, resolution, etc. Then we could have a much cleaner
469 // interface and tidy up BasicTiledThebesLayer::PaintThebes (bug 862547).
470 friend class ClientTiledThebesLayer;
471
472 public:
473 TiledContentClient(ClientTiledThebesLayer* aThebesLayer,
474 ClientLayerManager* aManager);
475
476 ~TiledContentClient()
477 {
478 MOZ_COUNT_DTOR(TiledContentClient);
479
480 mTiledBuffer.Release();
481 mLowPrecisionTiledBuffer.Release();
482 }
483
484 virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
485 {
486 return TextureInfo(BUFFER_TILED);
487 }
488
489 virtual void ClearCachedResources() MOZ_OVERRIDE;
490
491 enum TiledBufferType {
492 TILED_BUFFER,
493 LOW_PRECISION_TILED_BUFFER
494 };
495 void UseTiledLayerBuffer(TiledBufferType aType);
496
497 private:
498 SharedFrameMetricsHelper mSharedFrameMetricsHelper;
499 ClientTiledLayerBuffer mTiledBuffer;
500 ClientTiledLayerBuffer mLowPrecisionTiledBuffer;
501 };
502
503 }
504 }
505
506 #endif

mercurial