1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/layers/client/TiledContentClient.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,506 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef MOZILLA_GFX_TILEDCONTENTCLIENT_H 1.10 +#define MOZILLA_GFX_TILEDCONTENTCLIENT_H 1.11 + 1.12 +#include <stddef.h> // for size_t 1.13 +#include <stdint.h> // for uint16_t 1.14 +#include <algorithm> // for swap 1.15 +#include "Layers.h" // for LayerManager, etc 1.16 +#include "TiledLayerBuffer.h" // for TiledLayerBuffer 1.17 +#include "Units.h" // for CSSPoint 1.18 +#include "gfx3DMatrix.h" // for gfx3DMatrix 1.19 +#include "gfxTypes.h" 1.20 +#include "mozilla/Attributes.h" // for MOZ_OVERRIDE 1.21 +#include "mozilla/RefPtr.h" // for RefPtr 1.22 +#include "mozilla/ipc/Shmem.h" // for Shmem 1.23 +#include "mozilla/ipc/SharedMemory.h" // for SharedMemory 1.24 +#include "mozilla/layers/CompositableClient.h" // for CompositableClient 1.25 +#include "mozilla/layers/CompositorTypes.h" // for TextureInfo, etc 1.26 +#include "mozilla/layers/LayersMessages.h" // for TileDescriptor 1.27 +#include "mozilla/layers/TextureClient.h" 1.28 +#include "mozilla/layers/TextureClientPool.h" 1.29 +#include "ClientLayerManager.h" 1.30 +#include "mozilla/mozalloc.h" // for operator delete 1.31 +#include "nsAutoPtr.h" // for nsRefPtr 1.32 +#include "nsISupportsImpl.h" // for MOZ_COUNT_DTOR 1.33 +#include "nsPoint.h" // for nsIntPoint 1.34 +#include "nsRect.h" // for nsIntRect 1.35 +#include "nsRegion.h" // for nsIntRegion 1.36 +#include "nsTArray.h" // for nsTArray, nsTArray_Impl, etc 1.37 +#include "mozilla/layers/ISurfaceAllocator.h" 1.38 +#include "gfxReusableSurfaceWrapper.h" 1.39 +#include "pratom.h" // For PR_ATOMIC_INCREMENT/DECREMENT 1.40 +#include "gfxPrefs.h" 1.41 + 1.42 +namespace mozilla { 1.43 +namespace layers { 1.44 + 1.45 +class BasicTileDescriptor; 1.46 +class ClientTiledThebesLayer; 1.47 +class ClientLayerManager; 1.48 + 1.49 + 1.50 +// A class to help implement copy-on-write semantics for shared tiles. 1.51 +class gfxSharedReadLock { 1.52 +protected: 1.53 + virtual ~gfxSharedReadLock() {} 1.54 + 1.55 +public: 1.56 + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxSharedReadLock) 1.57 + 1.58 + virtual int32_t ReadLock() = 0; 1.59 + virtual int32_t ReadUnlock() = 0; 1.60 + virtual int32_t GetReadCount() = 0; 1.61 + virtual bool IsValid() const = 0; 1.62 + 1.63 + enum gfxSharedReadLockType { 1.64 + TYPE_MEMORY, 1.65 + TYPE_SHMEM 1.66 + }; 1.67 + virtual gfxSharedReadLockType GetType() = 0; 1.68 + 1.69 +protected: 1.70 + NS_DECL_OWNINGTHREAD 1.71 +}; 1.72 + 1.73 +class gfxMemorySharedReadLock : public gfxSharedReadLock { 1.74 +public: 1.75 + gfxMemorySharedReadLock(); 1.76 + 1.77 + ~gfxMemorySharedReadLock(); 1.78 + 1.79 + virtual int32_t ReadLock() MOZ_OVERRIDE; 1.80 + 1.81 + virtual int32_t ReadUnlock() MOZ_OVERRIDE; 1.82 + 1.83 + virtual int32_t GetReadCount() MOZ_OVERRIDE; 1.84 + 1.85 + virtual gfxSharedReadLockType GetType() MOZ_OVERRIDE { return TYPE_MEMORY; } 1.86 + 1.87 + virtual bool IsValid() const MOZ_OVERRIDE { return true; }; 1.88 + 1.89 +private: 1.90 + int32_t mReadCount; 1.91 +}; 1.92 + 1.93 +class gfxShmSharedReadLock : public gfxSharedReadLock { 1.94 +private: 1.95 + struct ShmReadLockInfo { 1.96 + int32_t readCount; 1.97 + }; 1.98 + 1.99 +public: 1.100 + gfxShmSharedReadLock(ISurfaceAllocator* aAllocator); 1.101 + 1.102 + ~gfxShmSharedReadLock(); 1.103 + 1.104 + virtual int32_t ReadLock() MOZ_OVERRIDE; 1.105 + 1.106 + virtual int32_t ReadUnlock() MOZ_OVERRIDE; 1.107 + 1.108 + virtual int32_t GetReadCount() MOZ_OVERRIDE; 1.109 + 1.110 + virtual bool IsValid() const MOZ_OVERRIDE { return mAllocSuccess; }; 1.111 + 1.112 + virtual gfxSharedReadLockType GetType() MOZ_OVERRIDE { return TYPE_SHMEM; } 1.113 + 1.114 + mozilla::layers::ShmemSection& GetShmemSection() { return mShmemSection; } 1.115 + 1.116 + static already_AddRefed<gfxShmSharedReadLock> 1.117 + Open(mozilla::layers::ISurfaceAllocator* aAllocator, const mozilla::layers::ShmemSection& aShmemSection) 1.118 + { 1.119 + nsRefPtr<gfxShmSharedReadLock> readLock = new gfxShmSharedReadLock(aAllocator, aShmemSection); 1.120 + return readLock.forget(); 1.121 + } 1.122 + 1.123 +private: 1.124 + gfxShmSharedReadLock(ISurfaceAllocator* aAllocator, const mozilla::layers::ShmemSection& aShmemSection) 1.125 + : mAllocator(aAllocator) 1.126 + , mShmemSection(aShmemSection) 1.127 + , mAllocSuccess(true) 1.128 + { 1.129 + MOZ_COUNT_CTOR(gfxShmSharedReadLock); 1.130 + } 1.131 + 1.132 + ShmReadLockInfo* GetShmReadLockInfoPtr() 1.133 + { 1.134 + return reinterpret_cast<ShmReadLockInfo*> 1.135 + (mShmemSection.shmem().get<char>() + mShmemSection.offset()); 1.136 + } 1.137 + 1.138 + RefPtr<ISurfaceAllocator> mAllocator; 1.139 + mozilla::layers::ShmemSection mShmemSection; 1.140 + bool mAllocSuccess; 1.141 +}; 1.142 + 1.143 +/** 1.144 + * Represent a single tile in tiled buffer. The buffer keeps tiles, 1.145 + * each tile keeps a reference to a texture client and a read-lock. This 1.146 + * read-lock is used to help implement a copy-on-write mechanism. The tile 1.147 + * should be locked before being sent to the compositor. The compositor should 1.148 + * unlock the read-lock as soon as it has finished with the buffer in the 1.149 + * TextureHost to prevent more textures being created than is necessary. 1.150 + * Ideal place to store per tile debug information. 1.151 + */ 1.152 +struct TileClient 1.153 +{ 1.154 + // Placeholder 1.155 + TileClient(); 1.156 + 1.157 + TileClient(const TileClient& o); 1.158 + 1.159 + TileClient& operator=(const TileClient& o); 1.160 + 1.161 + bool operator== (const TileClient& o) const 1.162 + { 1.163 + return mFrontBuffer == o.mFrontBuffer; 1.164 + } 1.165 + 1.166 + bool operator!= (const TileClient& o) const 1.167 + { 1.168 + return mFrontBuffer != o.mFrontBuffer; 1.169 + } 1.170 + 1.171 + void SetLayerManager(ClientLayerManager *aManager) 1.172 + { 1.173 + mManager = aManager; 1.174 + } 1.175 + 1.176 + bool IsPlaceholderTile() 1.177 + { 1.178 + return mBackBuffer == nullptr && mFrontBuffer == nullptr; 1.179 + } 1.180 + 1.181 + void ReadUnlock() 1.182 + { 1.183 + MOZ_ASSERT(mFrontLock, "ReadLock with no gfxSharedReadLock"); 1.184 + if (mFrontLock) { 1.185 + mFrontLock->ReadUnlock(); 1.186 + } 1.187 + } 1.188 + 1.189 + void ReadLock() 1.190 + { 1.191 + MOZ_ASSERT(mFrontLock, "ReadLock with no gfxSharedReadLock"); 1.192 + if (mFrontLock) { 1.193 + mFrontLock->ReadLock(); 1.194 + } 1.195 + } 1.196 + 1.197 + void Release() 1.198 + { 1.199 + DiscardFrontBuffer(); 1.200 + DiscardBackBuffer(); 1.201 + } 1.202 + 1.203 + TileDescriptor GetTileDescriptor(); 1.204 + 1.205 + /** 1.206 + * Swaps the front and back buffers. 1.207 + */ 1.208 + void Flip(); 1.209 + 1.210 + /** 1.211 + * Returns an unlocked TextureClient that can be used for writing new 1.212 + * data to the tile. This may flip the front-buffer to the back-buffer if 1.213 + * the front-buffer is still locked by the host, or does not have an 1.214 + * internal buffer (and so will always be locked). 1.215 + */ 1.216 + TextureClient* GetBackBuffer(const nsIntRegion& aDirtyRegion, 1.217 + TextureClientPool *aPool, 1.218 + bool *aCreatedTextureClient, 1.219 + bool aCanRerasterizeValidRegion); 1.220 + 1.221 + void DiscardFrontBuffer(); 1.222 + 1.223 + void DiscardBackBuffer(); 1.224 + 1.225 + RefPtr<TextureClient> mBackBuffer; 1.226 + RefPtr<TextureClient> mFrontBuffer; 1.227 + RefPtr<gfxSharedReadLock> mBackLock; 1.228 + RefPtr<gfxSharedReadLock> mFrontLock; 1.229 + RefPtr<ClientLayerManager> mManager; 1.230 +#ifdef GFX_TILEDLAYER_DEBUG_OVERLAY 1.231 + TimeStamp mLastUpdate; 1.232 +#endif 1.233 + nsIntRegion mInvalidFront; 1.234 + nsIntRegion mInvalidBack; 1.235 + 1.236 +private: 1.237 + void ValidateBackBufferFromFront(const nsIntRegion &aDirtyRegion, 1.238 + bool aCanRerasterizeValidRegion); 1.239 +}; 1.240 + 1.241 +/** 1.242 + * This struct stores all the data necessary to perform a paint so that it 1.243 + * doesn't need to be recalculated on every repeated transaction. 1.244 + */ 1.245 +struct BasicTiledLayerPaintData { 1.246 + /* 1.247 + * The scroll offset of the content from the nearest ancestor layer that 1.248 + * represents scrollable content with a display port set. 1.249 + */ 1.250 + ParentLayerPoint mScrollOffset; 1.251 + 1.252 + /* 1.253 + * The scroll offset of the content from the nearest ancestor layer that 1.254 + * represents scrollable content with a display port set, for the last 1.255 + * layer update transaction. 1.256 + */ 1.257 + ParentLayerPoint mLastScrollOffset; 1.258 + 1.259 + /* 1.260 + * The transform matrix to go from Screen units to ParentLayer units. 1.261 + */ 1.262 + gfx3DMatrix mTransformParentLayerToLayoutDevice; 1.263 + 1.264 + /* 1.265 + * The critical displayport of the content from the nearest ancestor layer 1.266 + * that represents scrollable content with a display port set. Empty if a 1.267 + * critical displayport is not set. 1.268 + * 1.269 + * This is in LayoutDevice coordinates, but is stored as an nsIntRect for 1.270 + * convenience when intersecting with the layer's mValidRegion. 1.271 + */ 1.272 + nsIntRect mCriticalDisplayPort; 1.273 + 1.274 + /* 1.275 + * The viewport of the content from the nearest ancestor layer that 1.276 + * represents scrollable content with a display port set. 1.277 + */ 1.278 + LayoutDeviceRect mViewport; 1.279 + 1.280 + /* 1.281 + * The render resolution of the document that the content this layer 1.282 + * represents is in. 1.283 + */ 1.284 + CSSToParentLayerScale mResolution; 1.285 + 1.286 + /* 1.287 + * The composition bounds of the layer, in LayoutDevice coordinates. This is 1.288 + * used to make sure that tiled updates to regions that are visible to the 1.289 + * user are grouped coherently. 1.290 + */ 1.291 + LayoutDeviceRect mCompositionBounds; 1.292 + 1.293 + /* 1.294 + * Low precision updates are always executed a tile at a time in repeated 1.295 + * transactions. This counter is set to 1 on the first transaction of a low 1.296 + * precision update, and incremented for each subsequent transaction. 1.297 + */ 1.298 + uint16_t mLowPrecisionPaintCount; 1.299 + 1.300 + /* 1.301 + * Whether this is the first time this layer is painting 1.302 + */ 1.303 + bool mFirstPaint : 1; 1.304 + 1.305 + /* 1.306 + * Whether there is further work to complete this paint. This is used to 1.307 + * determine whether or not to repeat the transaction when painting 1.308 + * progressively. 1.309 + */ 1.310 + bool mPaintFinished : 1; 1.311 +}; 1.312 + 1.313 +class SharedFrameMetricsHelper 1.314 +{ 1.315 +public: 1.316 + SharedFrameMetricsHelper(); 1.317 + ~SharedFrameMetricsHelper(); 1.318 + 1.319 + /** 1.320 + * This is called by the BasicTileLayer to determine if it is still interested 1.321 + * in the update of this display-port to continue. We can return true here 1.322 + * to abort the current update and continue with any subsequent ones. This 1.323 + * is useful for slow-to-render pages when the display-port starts lagging 1.324 + * behind enough that continuing to draw it is wasted effort. 1.325 + */ 1.326 + bool UpdateFromCompositorFrameMetrics(ContainerLayer* aLayer, 1.327 + bool aHasPendingNewThebesContent, 1.328 + bool aLowPrecision, 1.329 + ParentLayerRect& aCompositionBounds, 1.330 + CSSToParentLayerScale& aZoom); 1.331 + 1.332 + /** 1.333 + * When a shared FrameMetrics can not be found for a given layer, 1.334 + * this function is used to find the first non-empty composition bounds 1.335 + * by traversing up the layer tree. 1.336 + */ 1.337 + void FindFallbackContentFrameMetrics(ContainerLayer* aLayer, 1.338 + ParentLayerRect& aCompositionBounds, 1.339 + CSSToParentLayerScale& aZoom); 1.340 + /** 1.341 + * Determines if the compositor's upcoming composition bounds has fallen 1.342 + * outside of the contents display port. If it has then the compositor 1.343 + * will start to checker board. Checker boarding is when the compositor 1.344 + * tries to composite a tile and it is not available. Historically 1.345 + * a tile with a checker board pattern was used. Now a blank tile is used. 1.346 + */ 1.347 + bool AboutToCheckerboard(const FrameMetrics& aContentMetrics, 1.348 + const FrameMetrics& aCompositorMetrics); 1.349 +private: 1.350 + bool mLastProgressiveUpdateWasLowPrecision; 1.351 + bool mProgressiveUpdateWasInDanger; 1.352 +}; 1.353 + 1.354 +/** 1.355 + * Provide an instance of TiledLayerBuffer backed by drawable TextureClients. 1.356 + * This buffer provides an implementation of ValidateTile using a 1.357 + * thebes callback and can support painting using a single paint buffer. 1.358 + * Whether a single paint buffer is used is controlled by 1.359 + * gfxPrefs::PerTileDrawing(). 1.360 + */ 1.361 +class ClientTiledLayerBuffer 1.362 + : public TiledLayerBuffer<ClientTiledLayerBuffer, TileClient> 1.363 +{ 1.364 + friend class TiledLayerBuffer<ClientTiledLayerBuffer, TileClient>; 1.365 + 1.366 +public: 1.367 + ClientTiledLayerBuffer(ClientTiledThebesLayer* aThebesLayer, 1.368 + CompositableClient* aCompositableClient, 1.369 + ClientLayerManager* aManager, 1.370 + SharedFrameMetricsHelper* aHelper); 1.371 + ClientTiledLayerBuffer() 1.372 + : mThebesLayer(nullptr) 1.373 + , mCompositableClient(nullptr) 1.374 + , mManager(nullptr) 1.375 + , mLastPaintOpaque(false) 1.376 + , mSharedFrameMetricsHelper(nullptr) 1.377 + {} 1.378 + 1.379 + void PaintThebes(const nsIntRegion& aNewValidRegion, 1.380 + const nsIntRegion& aPaintRegion, 1.381 + LayerManager::DrawThebesLayerCallback aCallback, 1.382 + void* aCallbackData); 1.383 + 1.384 + void ReadUnlock(); 1.385 + 1.386 + void ReadLock(); 1.387 + 1.388 + void Release(); 1.389 + 1.390 + void DiscardBackBuffers(); 1.391 + 1.392 + const CSSToParentLayerScale& GetFrameResolution() { return mFrameResolution; } 1.393 + 1.394 + void SetFrameResolution(const CSSToParentLayerScale& aResolution) { mFrameResolution = aResolution; } 1.395 + 1.396 + bool HasFormatChanged() const; 1.397 + 1.398 + /** 1.399 + * Performs a progressive update of a given tiled buffer. 1.400 + * See ComputeProgressiveUpdateRegion below for parameter documentation. 1.401 + */ 1.402 + bool ProgressiveUpdate(nsIntRegion& aValidRegion, 1.403 + nsIntRegion& aInvalidRegion, 1.404 + const nsIntRegion& aOldValidRegion, 1.405 + BasicTiledLayerPaintData* aPaintData, 1.406 + LayerManager::DrawThebesLayerCallback aCallback, 1.407 + void* aCallbackData); 1.408 + 1.409 + SurfaceDescriptorTiles GetSurfaceDescriptorTiles(); 1.410 + 1.411 +protected: 1.412 + TileClient ValidateTile(TileClient aTile, 1.413 + const nsIntPoint& aTileRect, 1.414 + const nsIntRegion& dirtyRect); 1.415 + 1.416 + // If this returns true, we perform the paint operation into a single large 1.417 + // buffer and copy it out to the tiles instead of calling PaintThebes() on 1.418 + // each tile individually. Somewhat surprisingly, this turns out to be faster 1.419 + // on Android. 1.420 + bool UseSinglePaintBuffer() { return !gfxPrefs::PerTileDrawing(); } 1.421 + 1.422 + void ReleaseTile(TileClient aTile) { aTile.Release(); } 1.423 + 1.424 + void SwapTiles(TileClient& aTileA, TileClient& aTileB) { std::swap(aTileA, aTileB); } 1.425 + 1.426 + TileClient GetPlaceholderTile() const { return TileClient(); } 1.427 + 1.428 +private: 1.429 + gfxContentType GetContentType() const; 1.430 + ClientTiledThebesLayer* mThebesLayer; 1.431 + CompositableClient* mCompositableClient; 1.432 + ClientLayerManager* mManager; 1.433 + LayerManager::DrawThebesLayerCallback mCallback; 1.434 + void* mCallbackData; 1.435 + CSSToParentLayerScale mFrameResolution; 1.436 + bool mLastPaintOpaque; 1.437 + 1.438 + // The DrawTarget we use when UseSinglePaintBuffer() above is true. 1.439 + RefPtr<gfx::DrawTarget> mSinglePaintDrawTarget; 1.440 + nsIntPoint mSinglePaintBufferOffset; 1.441 + SharedFrameMetricsHelper* mSharedFrameMetricsHelper; 1.442 + 1.443 + /** 1.444 + * Calculates the region to update in a single progressive update transaction. 1.445 + * This employs some heuristics to update the most 'sensible' region to 1.446 + * update at this point in time, and how large an update should be performed 1.447 + * at once to maintain visual coherency. 1.448 + * 1.449 + * aInvalidRegion is the current invalid region. 1.450 + * aOldValidRegion is the valid region of mTiledBuffer at the beginning of the 1.451 + * current transaction. 1.452 + * aRegionToPaint will be filled with the region to update. This may be empty, 1.453 + * which indicates that there is no more work to do. 1.454 + * aIsRepeated should be true if this function has already been called during 1.455 + * this transaction. 1.456 + * 1.457 + * Returns true if it should be called again, false otherwise. In the case 1.458 + * that aRegionToPaint is empty, this will return aIsRepeated for convenience. 1.459 + */ 1.460 + bool ComputeProgressiveUpdateRegion(const nsIntRegion& aInvalidRegion, 1.461 + const nsIntRegion& aOldValidRegion, 1.462 + nsIntRegion& aRegionToPaint, 1.463 + BasicTiledLayerPaintData* aPaintData, 1.464 + bool aIsRepeated); 1.465 +}; 1.466 + 1.467 +class TiledContentClient : public CompositableClient 1.468 +{ 1.469 + // XXX: for now the layer which owns us interacts directly with our buffers. 1.470 + // We should have a content client for each tiled buffer which manages its 1.471 + // own valid region, resolution, etc. Then we could have a much cleaner 1.472 + // interface and tidy up BasicTiledThebesLayer::PaintThebes (bug 862547). 1.473 + friend class ClientTiledThebesLayer; 1.474 + 1.475 +public: 1.476 + TiledContentClient(ClientTiledThebesLayer* aThebesLayer, 1.477 + ClientLayerManager* aManager); 1.478 + 1.479 + ~TiledContentClient() 1.480 + { 1.481 + MOZ_COUNT_DTOR(TiledContentClient); 1.482 + 1.483 + mTiledBuffer.Release(); 1.484 + mLowPrecisionTiledBuffer.Release(); 1.485 + } 1.486 + 1.487 + virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE 1.488 + { 1.489 + return TextureInfo(BUFFER_TILED); 1.490 + } 1.491 + 1.492 + virtual void ClearCachedResources() MOZ_OVERRIDE; 1.493 + 1.494 + enum TiledBufferType { 1.495 + TILED_BUFFER, 1.496 + LOW_PRECISION_TILED_BUFFER 1.497 + }; 1.498 + void UseTiledLayerBuffer(TiledBufferType aType); 1.499 + 1.500 +private: 1.501 + SharedFrameMetricsHelper mSharedFrameMetricsHelper; 1.502 + ClientTiledLayerBuffer mTiledBuffer; 1.503 + ClientTiledLayerBuffer mLowPrecisionTiledBuffer; 1.504 +}; 1.505 + 1.506 +} 1.507 +} 1.508 + 1.509 +#endif