Line data Source code
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 <limits>
13 : #include "Layers.h" // for LayerManager, etc
14 : #include "TiledLayerBuffer.h" // for TiledLayerBuffer
15 : #include "Units.h" // for CSSPoint
16 : #include "gfxTypes.h"
17 : #include "mozilla/Attributes.h" // for 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/AsyncCompositionManager.h" // for ViewTransform
22 : #include "mozilla/layers/CompositableClient.h" // for CompositableClient
23 : #include "mozilla/layers/CompositorTypes.h" // for TextureInfo, etc
24 : #include "mozilla/layers/LayersMessages.h" // for TileDescriptor
25 : #include "mozilla/layers/LayersTypes.h" // for TextureDumpMode
26 : #include "mozilla/layers/TextureClient.h"
27 : #include "mozilla/layers/TextureClientPool.h"
28 : #include "ClientLayerManager.h"
29 : #include "mozilla/mozalloc.h" // for operator delete
30 : #include "nsISupportsImpl.h" // for MOZ_COUNT_DTOR
31 : #include "nsPoint.h" // for nsIntPoint
32 : #include "nsRect.h" // for mozilla::gfx::IntRect
33 : #include "nsRegion.h" // for nsIntRegion
34 : #include "nsTArray.h" // for nsTArray, nsTArray_Impl, etc
35 : #include "nsExpirationTracker.h"
36 : #include "mozilla/layers/ISurfaceAllocator.h"
37 :
38 : namespace mozilla {
39 : namespace layers {
40 :
41 : class ClientTiledPaintedLayer;
42 : class ClientLayerManager;
43 :
44 : /**
45 : * Represent a single tile in tiled buffer. The buffer keeps tiles,
46 : * each tile keeps a reference to a texture client and a read-lock. This
47 : * read-lock is used to help implement a copy-on-write mechanism. The tile
48 : * should be locked before being sent to the compositor. The compositor should
49 : * unlock the read-lock as soon as it has finished with the buffer in the
50 : * TextureHost to prevent more textures being created than is necessary.
51 : * Ideal place to store per tile debug information.
52 : */
53 : struct TileClient
54 : {
55 : // Placeholder
56 : TileClient();
57 : ~TileClient();
58 :
59 : TileClient(const TileClient& o);
60 :
61 : TileClient& operator=(const TileClient& o);
62 :
63 : bool operator== (const TileClient& o) const
64 : {
65 : return mFrontBuffer == o.mFrontBuffer;
66 : }
67 :
68 : bool operator!= (const TileClient& o) const
69 : {
70 : return mFrontBuffer != o.mFrontBuffer;
71 : }
72 :
73 0 : void SetTextureAllocator(TextureClientAllocator* aAllocator)
74 : {
75 0 : mAllocator = aAllocator;
76 0 : }
77 :
78 0 : bool IsPlaceholderTile() const
79 : {
80 0 : return mBackBuffer == nullptr && mFrontBuffer == nullptr;
81 : }
82 :
83 0 : void DiscardBuffers()
84 : {
85 0 : DiscardFrontBuffer();
86 0 : DiscardBackBuffer();
87 0 : }
88 :
89 0 : nsExpirationState *GetExpirationState() { return &mExpirationState; }
90 :
91 : TileDescriptor GetTileDescriptor();
92 :
93 : /**
94 : * For debugging.
95 : */
96 : void Dump(std::stringstream& aStream);
97 :
98 : /**
99 : * Swaps the front and back buffers.
100 : */
101 : void Flip();
102 :
103 0 : void DumpTexture(std::stringstream& aStream, TextureDumpMode aCompress) {
104 : // TODO We should combine the OnWhite/OnBlack here an just output a single image.
105 0 : CompositableClient::DumpTextureClient(aStream, mFrontBuffer, aCompress);
106 0 : }
107 :
108 : /**
109 : * Returns an unlocked TextureClient that can be used for writing new
110 : * data to the tile. This may flip the front-buffer to the back-buffer if
111 : * the front-buffer is still locked by the host, or does not have an
112 : * internal buffer (and so will always be locked).
113 : *
114 : * If getting the back buffer required copying pixels from the front buffer
115 : * then the copied region is stored in aAddPaintedRegion so the host side
116 : * knows to upload it.
117 : *
118 : * If nullptr is returned, aTextureClientOnWhite is undefined.
119 : */
120 : TextureClient* GetBackBuffer(CompositableClient&,
121 : const nsIntRegion& aDirtyRegion,
122 : gfxContentType aContent, SurfaceMode aMode,
123 : nsIntRegion& aAddPaintedRegion,
124 : RefPtr<TextureClient>* aTextureClientOnWhite);
125 :
126 : void DiscardFrontBuffer();
127 :
128 : void DiscardBackBuffer();
129 :
130 : /* We wrap the back buffer in a class that disallows assignment
131 : * so that we can track when ever it changes so that we can update
132 : * the expiry tracker for expiring the back buffers */
133 0 : class PrivateProtector {
134 : public:
135 : void Set(TileClient * container, RefPtr<TextureClient>);
136 : void Set(TileClient * container, TextureClient*);
137 : // Implicitly convert to TextureClient* because we can't chain
138 : // implicit conversion that would happen on RefPtr<TextureClient>
139 0 : operator TextureClient*() const { return mBuffer; }
140 0 : RefPtr<TextureClient> operator ->() { return mBuffer; }
141 : private:
142 : PrivateProtector& operator=(const PrivateProtector &);
143 : RefPtr<TextureClient> mBuffer;
144 : } mBackBuffer;
145 : RefPtr<TextureClient> mBackBufferOnWhite;
146 : RefPtr<TextureClient> mFrontBuffer;
147 : RefPtr<TextureClient> mFrontBufferOnWhite;
148 : RefPtr<TextureClientAllocator> mAllocator;
149 : gfx::IntRect mUpdateRect;
150 : bool mWasPlaceholder;
151 : #ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
152 : TimeStamp mLastUpdate;
153 : #endif
154 : nsIntRegion mInvalidFront;
155 : nsIntRegion mInvalidBack;
156 : nsExpirationState mExpirationState;
157 : private:
158 : // Copies dirty pixels from the front buffer into the back buffer,
159 : // and records the copied region in aAddPaintedRegion.
160 : void ValidateBackBufferFromFront(const nsIntRegion &aDirtyRegion,
161 : nsIntRegion& aAddPaintedRegion);
162 : };
163 :
164 : /**
165 : * This struct stores all the data necessary to perform a paint so that it
166 : * doesn't need to be recalculated on every repeated transaction.
167 : */
168 0 : struct BasicTiledLayerPaintData {
169 : /*
170 : * The scroll offset of the content from the nearest ancestor layer that
171 : * represents scrollable content with a display port set.
172 : */
173 : ParentLayerPoint mScrollOffset;
174 :
175 : /*
176 : * The scroll offset of the content from the nearest ancestor layer that
177 : * represents scrollable content with a display port set, for the last
178 : * layer update transaction.
179 : */
180 : ParentLayerPoint mLastScrollOffset;
181 :
182 : /*
183 : * The transform matrix to go from this layer's Layer units to
184 : * the scroll ancestor's ParentLayer units. The "scroll ancestor" is
185 : * the closest ancestor layer which scrolls, and is used to obtain
186 : * the composition bounds that are relevant for this layer.
187 : */
188 : LayerToParentLayerMatrix4x4 mTransformToCompBounds;
189 :
190 : /*
191 : * The critical displayport of the content from the nearest ancestor layer
192 : * that represents scrollable content with a display port set. isNothing()
193 : * if a critical displayport is not set.
194 : */
195 : Maybe<LayerIntRect> mCriticalDisplayPort;
196 :
197 : /*
198 : * The render resolution of the document that the content this layer
199 : * represents is in.
200 : */
201 : CSSToParentLayerScale2D mResolution;
202 :
203 : /*
204 : * The composition bounds of the layer, in Layer coordinates. This is
205 : * used to make sure that tiled updates to regions that are visible to the
206 : * user are grouped coherently.
207 : */
208 : LayerRect mCompositionBounds;
209 :
210 : /*
211 : * Low precision updates are always executed a tile at a time in repeated
212 : * transactions. This counter is set to 1 on the first transaction of a low
213 : * precision update, and incremented for each subsequent transaction.
214 : */
215 : uint16_t mLowPrecisionPaintCount;
216 :
217 : /*
218 : * Whether this is the first time this layer is painting
219 : */
220 : bool mFirstPaint : 1;
221 :
222 : /*
223 : * Whether there is further work to complete this paint. This is used to
224 : * determine whether or not to repeat the transaction when painting
225 : * progressively.
226 : */
227 : bool mPaintFinished : 1;
228 :
229 : /*
230 : * Whether or not there is an async transform animation active
231 : */
232 : bool mHasTransformAnimation : 1;
233 :
234 : /*
235 : * Initializes/clears data to prepare for paint action.
236 : */
237 : void ResetPaintData();
238 : };
239 :
240 : class SharedFrameMetricsHelper
241 : {
242 : public:
243 : SharedFrameMetricsHelper();
244 : ~SharedFrameMetricsHelper();
245 :
246 : /**
247 : * This is called by the BasicTileLayer to determine if it is still interested
248 : * in the update of this display-port to continue. We can return true here
249 : * to abort the current update and continue with any subsequent ones. This
250 : * is useful for slow-to-render pages when the display-port starts lagging
251 : * behind enough that continuing to draw it is wasted effort.
252 : */
253 : bool UpdateFromCompositorFrameMetrics(const LayerMetricsWrapper& aLayer,
254 : bool aHasPendingNewThebesContent,
255 : bool aLowPrecision,
256 : AsyncTransform& aViewTransform);
257 :
258 : /**
259 : * Determines if the compositor's upcoming composition bounds has fallen
260 : * outside of the contents display port. If it has then the compositor
261 : * will start to checker board. Checker boarding is when the compositor
262 : * tries to composite a tile and it is not available. Historically
263 : * a tile with a checker board pattern was used. Now a blank tile is used.
264 : */
265 : bool AboutToCheckerboard(const FrameMetrics& aContentMetrics,
266 : const FrameMetrics& aCompositorMetrics);
267 : private:
268 : bool mLastProgressiveUpdateWasLowPrecision;
269 : bool mProgressiveUpdateWasInDanger;
270 : };
271 :
272 : /**
273 : * Provide an instance of TiledLayerBuffer backed by drawable TextureClients.
274 : * This buffer provides an implementation of ValidateTile using a
275 : * thebes callback and can support painting using a single paint buffer.
276 : * Whether a single paint buffer is used is controlled by
277 : * gfxPrefs::PerTileDrawing().
278 : */
279 : class ClientTiledLayerBuffer
280 : {
281 : public:
282 0 : ClientTiledLayerBuffer(ClientTiledPaintedLayer& aPaintedLayer,
283 : CompositableClient& aCompositableClient)
284 0 : : mPaintedLayer(aPaintedLayer)
285 : , mCompositableClient(aCompositableClient)
286 : , mLastPaintContentType(gfxContentType::COLOR)
287 : , mLastPaintSurfaceMode(SurfaceMode::SURFACE_OPAQUE)
288 0 : , mWasLastPaintProgressive(false)
289 0 : {}
290 :
291 : virtual void PaintThebes(const nsIntRegion& aNewValidRegion,
292 : const nsIntRegion& aPaintRegion,
293 : const nsIntRegion& aDirtyRegion,
294 : LayerManager::DrawPaintedLayerCallback aCallback,
295 : void* aCallbackData,
296 : bool aIsProgressive = false) = 0;
297 :
298 : virtual bool SupportsProgressiveUpdate() = 0;
299 : virtual bool ProgressiveUpdate(const nsIntRegion& aValidRegion,
300 : const nsIntRegion& aInvalidRegion,
301 : const nsIntRegion& aOldValidRegion,
302 : nsIntRegion& aOutDrawnRegion,
303 : BasicTiledLayerPaintData* aPaintData,
304 : LayerManager::DrawPaintedLayerCallback aCallback,
305 : void* aCallbackData) = 0;
306 : virtual void ResetPaintedAndValidState() = 0;
307 :
308 : virtual const nsIntRegion& GetValidRegion() = 0;
309 :
310 : virtual bool IsLowPrecision() const = 0;
311 :
312 0 : virtual void Dump(std::stringstream& aStream,
313 : const char* aPrefix,
314 : bool aDumpHtml,
315 0 : TextureDumpMode aCompress) {}
316 :
317 0 : const CSSToParentLayerScale2D& GetFrameResolution() { return mFrameResolution; }
318 0 : void SetFrameResolution(const CSSToParentLayerScale2D& aResolution) { mFrameResolution = aResolution; }
319 :
320 : bool HasFormatChanged() const;
321 :
322 : protected:
323 : void UnlockTile(TileClient& aTile);
324 : gfxContentType GetContentType(SurfaceMode* aMode = nullptr) const;
325 :
326 : ClientTiledPaintedLayer& mPaintedLayer;
327 : CompositableClient& mCompositableClient;
328 :
329 : gfxContentType mLastPaintContentType;
330 : SurfaceMode mLastPaintSurfaceMode;
331 : CSSToParentLayerScale2D mFrameResolution;
332 :
333 : bool mWasLastPaintProgressive;
334 : };
335 :
336 0 : class ClientMultiTiledLayerBuffer
337 : : public TiledLayerBuffer<ClientMultiTiledLayerBuffer, TileClient>
338 : , public ClientTiledLayerBuffer
339 : {
340 : friend class TiledLayerBuffer<ClientMultiTiledLayerBuffer, TileClient>;
341 : public:
342 : ClientMultiTiledLayerBuffer(ClientTiledPaintedLayer& aPaintedLayer,
343 : CompositableClient& aCompositableClient,
344 : ClientLayerManager* aManager,
345 : SharedFrameMetricsHelper* aHelper);
346 :
347 : void PaintThebes(const nsIntRegion& aNewValidRegion,
348 : const nsIntRegion& aPaintRegion,
349 : const nsIntRegion& aDirtyRegion,
350 : LayerManager::DrawPaintedLayerCallback aCallback,
351 : void* aCallbackData,
352 : bool aIsProgressive = false) override;
353 :
354 0 : virtual bool SupportsProgressiveUpdate() override { return true; }
355 : /**
356 : * Performs a progressive update of a given tiled buffer.
357 : * See ComputeProgressiveUpdateRegion below for parameter documentation.
358 : * aOutDrawnRegion is an outparameter that contains the region that was
359 : * drawn, and which can now be added to the layer's valid region.
360 : */
361 : bool ProgressiveUpdate(const nsIntRegion& aValidRegion,
362 : const nsIntRegion& aInvalidRegion,
363 : const nsIntRegion& aOldValidRegion,
364 : nsIntRegion& aOutDrawnRegion,
365 : BasicTiledLayerPaintData* aPaintData,
366 : LayerManager::DrawPaintedLayerCallback aCallback,
367 : void* aCallbackData) override;
368 :
369 0 : void ResetPaintedAndValidState() override {
370 0 : mPaintedRegion.SetEmpty();
371 0 : mValidRegion.SetEmpty();
372 0 : mTiles.mSize.width = 0;
373 0 : mTiles.mSize.height = 0;
374 0 : DiscardBuffers();
375 0 : mRetainedTiles.Clear();
376 0 : }
377 :
378 :
379 0 : const nsIntRegion& GetValidRegion() override {
380 0 : return TiledLayerBuffer::GetValidRegion();
381 : }
382 :
383 0 : bool IsLowPrecision() const override {
384 0 : return TiledLayerBuffer::IsLowPrecision();
385 : }
386 :
387 0 : void Dump(std::stringstream& aStream,
388 : const char* aPrefix,
389 : bool aDumpHtml,
390 : TextureDumpMode aCompress) override {
391 0 : TiledLayerBuffer::Dump(aStream, aPrefix, aDumpHtml, aCompress);
392 0 : }
393 :
394 : void ReadLock();
395 :
396 : void Release();
397 :
398 : void DiscardBuffers();
399 :
400 : SurfaceDescriptorTiles GetSurfaceDescriptorTiles();
401 :
402 0 : void SetResolution(float aResolution) {
403 0 : if (mResolution == aResolution) {
404 0 : return;
405 : }
406 :
407 0 : Update(nsIntRegion(), nsIntRegion(), nsIntRegion());
408 0 : mResolution = aResolution;
409 : }
410 :
411 : protected:
412 : bool ValidateTile(TileClient& aTile,
413 : const nsIntPoint& aTileRect,
414 : const nsIntRegion& dirtyRect);
415 :
416 : void Update(const nsIntRegion& aNewValidRegion,
417 : const nsIntRegion& aPaintRegion,
418 : const nsIntRegion& aDirtyRegion);
419 :
420 : TileClient GetPlaceholderTile() const { return TileClient(); }
421 :
422 : private:
423 : RefPtr<ClientLayerManager> mManager;
424 : LayerManager::DrawPaintedLayerCallback mCallback;
425 : void* mCallbackData;
426 :
427 : // The region that will be made valid during Update(). Once Update() is
428 : // completed then this is identical to mValidRegion.
429 : nsIntRegion mNewValidRegion;
430 :
431 : SharedFrameMetricsHelper* mSharedFrameMetricsHelper;
432 : // When using Moz2D's CreateTiledDrawTarget we maintain a list of gfx::Tiles
433 : std::vector<gfx::Tile> mMoz2DTiles;
434 : /**
435 : * While we're adding tiles, this is used to keep track of the position of
436 : * the top-left of the top-left-most tile. When we come to wrap the tiles in
437 : * TiledDrawTarget we subtract the value of this member from each tile's
438 : * offset so that all the tiles have a positive offset, then add a
439 : * translation to the TiledDrawTarget to compensate. This is important so
440 : * that the mRect of the TiledDrawTarget is always at a positive x/y
441 : * position, otherwise its GetSize() methods will be broken.
442 : */
443 : gfx::IntPoint mTilingOrigin;
444 : /**
445 : * Calculates the region to update in a single progressive update transaction.
446 : * This employs some heuristics to update the most 'sensible' region to
447 : * update at this point in time, and how large an update should be performed
448 : * at once to maintain visual coherency.
449 : *
450 : * aInvalidRegion is the current invalid region.
451 : * aOldValidRegion is the valid region of mTiledBuffer at the beginning of the
452 : * current transaction.
453 : * aRegionToPaint will be filled with the region to update. This may be empty,
454 : * which indicates that there is no more work to do.
455 : * aIsRepeated should be true if this function has already been called during
456 : * this transaction.
457 : *
458 : * Returns true if it should be called again, false otherwise. In the case
459 : * that aRegionToPaint is empty, this will return aIsRepeated for convenience.
460 : */
461 : bool ComputeProgressiveUpdateRegion(const nsIntRegion& aInvalidRegion,
462 : const nsIntRegion& aOldValidRegion,
463 : nsIntRegion& aRegionToPaint,
464 : BasicTiledLayerPaintData* aPaintData,
465 : bool aIsRepeated);
466 : };
467 :
468 : class TiledContentClient : public CompositableClient
469 : {
470 : public:
471 0 : TiledContentClient(ClientLayerManager* aManager,
472 : const char* aName = "")
473 0 : : CompositableClient(aManager->AsShadowForwarder())
474 0 : , mName(aName)
475 0 : {}
476 :
477 : protected:
478 0 : ~TiledContentClient()
479 0 : {}
480 :
481 : public:
482 : virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix);
483 :
484 : virtual void Dump(std::stringstream& aStream,
485 : const char* aPrefix="",
486 : bool aDumpHtml=false,
487 : TextureDumpMode aCompress=TextureDumpMode::Compress) override;
488 :
489 0 : virtual TextureInfo GetTextureInfo() const override
490 : {
491 0 : return TextureInfo(CompositableType::CONTENT_TILED);
492 : }
493 :
494 :
495 : virtual ClientTiledLayerBuffer* GetTiledBuffer() = 0;
496 : virtual ClientTiledLayerBuffer* GetLowPrecisionTiledBuffer() = 0;
497 :
498 : enum TiledBufferType {
499 : TILED_BUFFER,
500 : LOW_PRECISION_TILED_BUFFER
501 : };
502 : virtual void UpdatedBuffer(TiledBufferType aType) = 0;
503 :
504 : private:
505 : const char* mName;
506 : };
507 :
508 : /**
509 : * An implementation of TiledContentClient that supports
510 : * multiple tiles and a low precision buffer.
511 : */
512 : class MultiTiledContentClient : public TiledContentClient
513 : {
514 : public:
515 : MultiTiledContentClient(ClientTiledPaintedLayer& aPaintedLayer,
516 : ClientLayerManager* aManager);
517 :
518 : protected:
519 0 : ~MultiTiledContentClient()
520 0 : {
521 0 : MOZ_COUNT_DTOR(MultiTiledContentClient);
522 :
523 0 : mTiledBuffer.DiscardBuffers();
524 0 : mLowPrecisionTiledBuffer.DiscardBuffers();
525 0 : }
526 :
527 : public:
528 : void ClearCachedResources() override;
529 : void UpdatedBuffer(TiledBufferType aType) override;
530 :
531 0 : ClientTiledLayerBuffer* GetTiledBuffer() override { return &mTiledBuffer; }
532 0 : ClientTiledLayerBuffer* GetLowPrecisionTiledBuffer() override {
533 0 : if (mHasLowPrecision) {
534 0 : return &mLowPrecisionTiledBuffer;
535 : }
536 0 : return nullptr;
537 : }
538 :
539 : private:
540 : SharedFrameMetricsHelper mSharedFrameMetricsHelper;
541 : ClientMultiTiledLayerBuffer mTiledBuffer;
542 : ClientMultiTiledLayerBuffer mLowPrecisionTiledBuffer;
543 : bool mHasLowPrecision;
544 : };
545 :
546 : } // namespace layers
547 : } // namespace mozilla
548 :
549 : #endif
|