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 #ifndef MOZILLA_GFX_TILEDCONTENTCLIENT_H
8 #define MOZILLA_GFX_TILEDCONTENTCLIENT_H
9 
10 #include <stddef.h>   // for size_t
11 #include <stdint.h>   // for uint16_t
12 #include <algorithm>  // for swap
13 #include <limits>
14 #include "Layers.h"            // for LayerManager, etc
15 #include "TiledLayerBuffer.h"  // for TiledLayerBuffer
16 #include "Units.h"             // for CSSPoint
17 #include "gfxTypes.h"
18 #include "mozilla/Attributes.h"                      // for override
19 #include "mozilla/gfx/2D.h"                          // for gfx::Tile
20 #include "mozilla/RefPtr.h"                          // for RefPtr
21 #include "mozilla/ipc/Shmem.h"                       // for Shmem
22 #include "mozilla/ipc/SharedMemory.h"                // for SharedMemory
23 #include "mozilla/layers/AsyncCompositionManager.h"  // for ViewTransform
24 #include "mozilla/layers/CompositableClient.h"       // for CompositableClient
25 #include "mozilla/layers/CompositorTypes.h"          // for TextureInfo, etc
26 #include "mozilla/layers/LayersMessages.h"           // for TileDescriptor
27 #include "mozilla/layers/LayersTypes.h"              // for TextureDumpMode
28 #include "mozilla/layers/PaintThread.h"  // for CapturedTiledPaintState
29 #include "mozilla/layers/TextureClient.h"
30 #include "mozilla/layers/TextureClientPool.h"
31 #include "ClientLayerManager.h"
32 #include "mozilla/mozalloc.h"  // for operator delete
33 #include "nsISupportsImpl.h"   // for MOZ_COUNT_DTOR
34 #include "nsPoint.h"           // for nsIntPoint
35 #include "nsRect.h"            // for mozilla::gfx::IntRect
36 #include "nsRegion.h"          // for nsIntRegion
37 #include "nsTArray.h"          // for nsTArray, nsTArray_Impl, etc
38 #include "nsExpirationTracker.h"
39 #include "mozilla/layers/ISurfaceAllocator.h"
40 
41 namespace mozilla {
42 namespace layers {
43 
44 class ClientTiledPaintedLayer;
45 class ClientLayerManager;
46 
47 enum class TilePaintFlags : uint8_t {
48   None = 0x0,
49   Async = 0x1,
50   Progressive = 0x2,
51 };
52 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(TilePaintFlags)
53 
54 void ShutdownTileCache();
55 
56 struct AcquiredBackBuffer {
AcquiredBackBufferAcquiredBackBuffer57   AcquiredBackBuffer(gfx::DrawTarget* aTarget, gfx::DrawTargetCapture* aCapture,
58                      gfx::DrawTarget* aBackBuffer,
59                      const gfx::IntRect& aUpdatedRect,
60                      AutoTArray<RefPtr<TextureClient>, 4>&& aTextureClients)
61       : mTarget(aTarget),
62         mCapture(aCapture),
63         mBackBuffer(aBackBuffer),
64         mUpdatedRect(aUpdatedRect),
65         mTextureClients(std::move(aTextureClients)) {}
66 
67   AcquiredBackBuffer(const AcquiredBackBuffer&) = delete;
68   AcquiredBackBuffer& operator=(const AcquiredBackBuffer&) = delete;
69 
70   AcquiredBackBuffer(AcquiredBackBuffer&&) = default;
71   AcquiredBackBuffer& operator=(AcquiredBackBuffer&&) = default;
72 
73   RefPtr<gfx::DrawTarget> mTarget;
74   RefPtr<gfx::DrawTargetCapture> mCapture;
75   RefPtr<gfx::DrawTarget> mBackBuffer;
76   gfx::IntRect mUpdatedRect;
77   AutoTArray<RefPtr<TextureClient>, 4> mTextureClients;
78 };
79 
80 /**
81  * Represent a single tile in tiled buffer. The buffer keeps tiles,
82  * each tile keeps a reference to a texture client and a read-lock. This
83  * read-lock is used to help implement a copy-on-write mechanism. The tile
84  * should be locked before being sent to the compositor. The compositor should
85  * unlock the read-lock as soon as it has finished with the buffer in the
86  * TextureHost to prevent more textures being created than is necessary.
87  * Ideal place to store per tile debug information.
88  */
89 struct TileClient {
90   // Placeholder
91   TileClient();
92   ~TileClient();
93 
94   TileClient(const TileClient& o);
95 
96   TileClient& operator=(const TileClient& o);
97 
98   bool operator==(const TileClient& o) const {
99     return mFrontBuffer == o.mFrontBuffer;
100   }
101 
102   bool operator!=(const TileClient& o) const {
103     return mFrontBuffer != o.mFrontBuffer;
104   }
105 
SetTextureAllocatorTileClient106   void SetTextureAllocator(TextureClientAllocator* aAllocator) {
107     mAllocator = aAllocator;
108   }
109 
IsPlaceholderTileTileClient110   bool IsPlaceholderTile() const {
111     return mBackBuffer == nullptr && mFrontBuffer == nullptr;
112   }
113 
DiscardBuffersTileClient114   void DiscardBuffers() {
115     DiscardFrontBuffer();
116     DiscardBackBuffer();
117   }
118 
GetExpirationStateTileClient119   nsExpirationState* GetExpirationState() { return &mExpirationState; }
120 
121   TileDescriptor GetTileDescriptor();
122 
123   /**
124    * For debugging.
125    */
126   void Dump(std::stringstream& aStream);
127 
128   /**
129    * Swaps the front and back buffers.
130    */
131   void Flip();
132 
DumpTextureTileClient133   void DumpTexture(std::stringstream& aStream, TextureDumpMode aCompress) {
134     // TODO We should combine the OnWhite/OnBlack here an just output a single
135     // image.
136     CompositableClient::DumpTextureClient(aStream, mFrontBuffer, aCompress);
137   }
138 
139   void GetSyncTextureSerials(SurfaceMode aMode, nsTArray<uint64_t>& aSerials);
140 
141   /**
142    * Returns an unlocked TextureClient that can be used for writing new
143    * data to the tile. This may flip the front-buffer to the back-buffer if
144    * the front-buffer is still locked by the host, or does not have an
145    * internal buffer (and so will always be locked).
146    *
147    * If getting the back buffer required copying pixels from the front buffer
148    * then the copied region is stored in aAddPaintedRegion so the host side
149    * knows to upload it.
150    *
151    * If nullptr is returned, aTextureClientOnWhite is undefined.
152    */
153   Maybe<AcquiredBackBuffer> AcquireBackBuffer(CompositableClient&,
154                                               const nsIntRegion& aDirtyRegion,
155                                               const nsIntRegion& aVisibleRegion,
156                                               gfxContentType aContent,
157                                               SurfaceMode aMode,
158                                               TilePaintFlags aFlags);
159 
160   void DiscardFrontBuffer();
161 
162   void DiscardBackBuffer();
163 
164   /* We wrap the back buffer in a class that disallows assignment
165    * so that we can track when ever it changes so that we can update
166    * the expiry tracker for expiring the back buffers */
167   class PrivateProtector {
168    public:
169     void Set(TileClient* container, RefPtr<TextureClient>);
170     void Set(TileClient* container, TextureClient*);
171     // Implicitly convert to TextureClient* because we can't chain
172     // implicit conversion that would happen on RefPtr<TextureClient>
173     operator TextureClient*() const { return mBuffer; }
174     RefPtr<TextureClient> operator->() { return mBuffer; }
175 
176    private:
177     PrivateProtector& operator=(const PrivateProtector&);
178     RefPtr<TextureClient> mBuffer;
179   } mBackBuffer;
180   RefPtr<TextureClient> mBackBufferOnWhite;
181   RefPtr<TextureClient> mFrontBuffer;
182   RefPtr<TextureClient> mFrontBufferOnWhite;
183   RefPtr<TextureClientAllocator> mAllocator;
184   gfx::IntRect mUpdateRect;
185   bool mWasPlaceholder;
186 #ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
187   TimeStamp mLastUpdate;
188 #endif
189   nsIntRegion mInvalidFront;
190   nsIntRegion mInvalidBack;
191   nsExpirationState mExpirationState;
192 
193  private:
194   /*
195    * Copies dirty pixels from the front buffer into the back buffer,
196    * and records the copied region in aAddPaintedRegion.
197    */
198   void ValidateFromFront(const nsIntRegion& aDirtyRegion,
199                          const nsIntRegion& aVisibleRegion,
200                          gfx::DrawTarget* aBackBuffer, TilePaintFlags aFlags,
201                          gfx::IntRect* aCopiedRegion,
202                          AutoTArray<RefPtr<TextureClient>, 4>* aClients);
203 };
204 
205 /**
206  * This struct stores all the data necessary to perform a paint so that it
207  * doesn't need to be recalculated on every repeated transaction.
208  */
209 struct BasicTiledLayerPaintData {
210   /*
211    * The scroll offset of the content from the nearest ancestor layer that
212    * represents scrollable content with a display port set.
213    */
214   ParentLayerPoint mScrollOffset;
215 
216   /*
217    * The scroll offset of the content from the nearest ancestor layer that
218    * represents scrollable content with a display port set, for the last
219    * layer update transaction.
220    */
221   ParentLayerPoint mLastScrollOffset;
222 
223   /*
224    * The transform matrix to go from this layer's Layer units to
225    * the scroll ancestor's ParentLayer units. The "scroll ancestor" is
226    * the closest ancestor layer which scrolls, and is used to obtain
227    * the composition bounds that are relevant for this layer.
228    */
229   LayerToParentLayerMatrix4x4 mTransformToCompBounds;
230 
231   /*
232    * The critical displayport of the content from the nearest ancestor layer
233    * that represents scrollable content with a display port set. isNothing()
234    * if a critical displayport is not set.
235    */
236   Maybe<LayerIntRect> mCriticalDisplayPort;
237 
238   /*
239    * The render resolution of the document that the content this layer
240    * represents is in.
241    */
242   CSSToParentLayerScale2D mResolution;
243 
244   /*
245    * The composition bounds of the layer, in Layer coordinates. This is
246    * used to make sure that tiled updates to regions that are visible to the
247    * user are grouped coherently.
248    */
249   LayerRect mCompositionBounds;
250 
251   /*
252    * Low precision updates are always executed a tile at a time in repeated
253    * transactions. This counter is set to 1 on the first transaction of a low
254    * precision update, and incremented for each subsequent transaction.
255    */
256   uint16_t mLowPrecisionPaintCount;
257 
258   /*
259    * Whether this is the first time this layer is painting
260    */
261   bool mFirstPaint : 1;
262 
263   /*
264    * Whether there is further work to complete this paint. This is used to
265    * determine whether or not to repeat the transaction when painting
266    * progressively.
267    */
268   bool mPaintFinished : 1;
269 
270   /*
271    * Whether or not there is an async transform animation active
272    */
273   bool mHasTransformAnimation : 1;
274 
275   /*
276    * Initializes/clears data to prepare for paint action.
277    */
278   void ResetPaintData();
279 };
280 
281 class SharedFrameMetricsHelper {
282  public:
283   SharedFrameMetricsHelper();
284   ~SharedFrameMetricsHelper();
285 
286   /**
287    * This is called by the BasicTileLayer to determine if it is still interested
288    * in the update of this display-port to continue. We can return true here
289    * to abort the current update and continue with any subsequent ones. This
290    * is useful for slow-to-render pages when the display-port starts lagging
291    * behind enough that continuing to draw it is wasted effort.
292    */
293   bool UpdateFromCompositorFrameMetrics(const LayerMetricsWrapper& aLayer,
294                                         bool aHasPendingNewThebesContent,
295                                         bool aLowPrecision,
296                                         AsyncTransform& aViewTransform);
297 
298   /**
299    * Determines if the compositor's upcoming composition bounds has fallen
300    * outside of the contents display port. If it has then the compositor
301    * will start to checker board. Checker boarding is when the compositor
302    * tries to composite a tile and it is not available. Historically
303    * a tile with a checker board pattern was used. Now a blank tile is used.
304    */
305   bool AboutToCheckerboard(const FrameMetrics& aContentMetrics,
306                            const FrameMetrics& aCompositorMetrics);
307 
308  private:
309   bool mLastProgressiveUpdateWasLowPrecision;
310   bool mProgressiveUpdateWasInDanger;
311 };
312 
313 /**
314  * Provide an instance of TiledLayerBuffer backed by drawable TextureClients.
315  * This buffer provides an implementation of ValidateTile using a
316  * thebes callback and can support painting using a single paint buffer.
317  * Whether a single paint buffer is used is controlled by
318  * StaticPrefs::PerTileDrawing().
319  */
320 class ClientTiledLayerBuffer {
321  public:
ClientTiledLayerBuffer(ClientTiledPaintedLayer & aPaintedLayer,CompositableClient & aCompositableClient)322   ClientTiledLayerBuffer(ClientTiledPaintedLayer& aPaintedLayer,
323                          CompositableClient& aCompositableClient)
324       : mPaintedLayer(aPaintedLayer),
325         mCompositableClient(aCompositableClient),
326         mLastPaintContentType(gfxContentType::COLOR),
327         mLastPaintSurfaceMode(SurfaceMode::SURFACE_OPAQUE),
328         mWasLastPaintProgressive(false) {}
329 
330   virtual void PaintThebes(const nsIntRegion& aNewValidRegion,
331                            const nsIntRegion& aPaintRegion,
332                            const nsIntRegion& aDirtyRegion,
333                            LayerManager::DrawPaintedLayerCallback aCallback,
334                            void* aCallbackData, TilePaintFlags aFlags) = 0;
GetSyncTextureSerials(const nsIntRegion & aPaintRegion,const nsIntRegion & aDirtyRegion,nsTArray<uint64_t> & aSerials)335   virtual void GetSyncTextureSerials(const nsIntRegion& aPaintRegion,
336                                      const nsIntRegion& aDirtyRegion,
337                                      nsTArray<uint64_t>& aSerials) {
338     return;
339   }
340 
341   virtual bool SupportsProgressiveUpdate() = 0;
342   virtual bool ProgressiveUpdate(
343       const nsIntRegion& aValidRegion, const nsIntRegion& aInvalidRegion,
344       const nsIntRegion& aOldValidRegion, nsIntRegion& aOutDrawnRegion,
345       BasicTiledLayerPaintData* aPaintData,
346       LayerManager::DrawPaintedLayerCallback aCallback,
347       void* aCallbackData) = 0;
348   virtual void ResetPaintedAndValidState() = 0;
349 
350   virtual const nsIntRegion& GetValidRegion() = 0;
351 
352   virtual bool IsLowPrecision() const = 0;
353 
Dump(std::stringstream & aStream,const char * aPrefix,bool aDumpHtml,TextureDumpMode aCompress)354   virtual void Dump(std::stringstream& aStream, const char* aPrefix,
355                     bool aDumpHtml, TextureDumpMode aCompress) {}
356 
GetFrameResolution()357   const CSSToParentLayerScale2D& GetFrameResolution() {
358     return mFrameResolution;
359   }
SetFrameResolution(const CSSToParentLayerScale2D & aResolution)360   void SetFrameResolution(const CSSToParentLayerScale2D& aResolution) {
361     mFrameResolution = aResolution;
362   }
363 
364   bool HasFormatChanged() const;
365 
366  protected:
367   void UnlockTile(TileClient& aTile);
368   gfxContentType GetContentType(SurfaceMode* aMode = nullptr) const;
369 
370   ClientTiledPaintedLayer& mPaintedLayer;
371   CompositableClient& mCompositableClient;
372 
373   gfxContentType mLastPaintContentType;
374   SurfaceMode mLastPaintSurfaceMode;
375   CSSToParentLayerScale2D mFrameResolution;
376 
377   bool mWasLastPaintProgressive;
378 };
379 
380 class TiledContentClient : public CompositableClient {
381  public:
382   TiledContentClient(ClientLayerManager* aManager, const char* aName = "")
383       : CompositableClient(aManager->AsShadowForwarder()), mName(aName) {}
384 
385  protected:
~TiledContentClient()386   ~TiledContentClient() {}
387 
388  public:
389   virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix);
390 
391   void Dump(std::stringstream& aStream, const char* aPrefix = "",
392             bool aDumpHtml = false,
393             TextureDumpMode aCompress = TextureDumpMode::Compress) override;
394 
GetTextureInfo()395   TextureInfo GetTextureInfo() const override {
396     return TextureInfo(CompositableType::CONTENT_TILED);
397   }
398 
399   virtual ClientTiledLayerBuffer* GetTiledBuffer() = 0;
400   virtual ClientTiledLayerBuffer* GetLowPrecisionTiledBuffer() = 0;
401 
402   enum TiledBufferType { TILED_BUFFER, LOW_PRECISION_TILED_BUFFER };
403   virtual void UpdatedBuffer(TiledBufferType aType) = 0;
404 
405  private:
406   const char* mName;
407 };
408 
409 }  // namespace layers
410 }  // namespace mozilla
411 
412 #endif  // MOZILLA_GFX_TILEDCONTENTCLIENT_H
413