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