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