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