diff options
Diffstat (limited to 'gfx/layers/client/TiledContentClient.h')
-rw-r--r-- | gfx/layers/client/TiledContentClient.h | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/gfx/layers/client/TiledContentClient.h b/gfx/layers/client/TiledContentClient.h new file mode 100644 index 0000000000..5657572a15 --- /dev/null +++ b/gfx/layers/client/TiledContentClient.h @@ -0,0 +1,406 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef MOZILLA_GFX_TILEDCONTENTCLIENT_H +#define MOZILLA_GFX_TILEDCONTENTCLIENT_H + +#include <cstdint> // for uint64_t, uint16_t, uint8_t +#include <iosfwd> // for stringstream +#include <utility> // for move +#include "ClientLayerManager.h" // for ClientLayerManager +#include "Units.h" // for CSSToParentLayerScale2D, ParentLayerPoint, LayerIntRect, LayerRect, LayerToParent... +#include "gfxTypes.h" // for gfxContentType, gfxContentType::COLOR +#include "mozilla/Maybe.h" // for Maybe +#include "mozilla/RefPtr.h" // for RefPtr, operator==, operator!= +#include "mozilla/TypedEnumBits.h" // for CastableTypedEnumResult, UnsignedIntegerTypeForEnum, MOZ_MAKE_ENUM_CLASS_BITWISE_... +#include "mozilla/gfx/2D.h" // for DrawTarget, DrawTargetCapture +#include "mozilla/gfx/Rect.h" // for IntRect +#include "mozilla/layers/CompositableClient.h" // for CompositableClient +#include "mozilla/layers/CompositorTypes.h" // for TextureInfo, CompositableType, CompositableType::CONTENT_TILED +#include "mozilla/layers/LayerManager.h" // for LayerManager, LayerManager::DrawPaintedLayerCallback +#include "mozilla/layers/LayersMessages.h" // for TileDescriptor +#include "mozilla/layers/LayersTypes.h" // for SurfaceMode, TextureDumpMode, Compress, SurfaceMode::SURFACE_OPAQUE +#include "mozilla/layers/ShadowLayers.h" // for ShadowLayerForwarder +#include "mozilla/layers/TextureClient.h" // for TextureClient +#include "mozilla/layers/TextureClientPool.h" // for TextureClientAllocator +#include "nsExpirationTracker.h" // for nsExpirationState +#include "nsRegion.h" // for nsIntRegion +#include "nsTArray.h" // for AutoTArray, nsTArray (ptr only) + +namespace mozilla { +namespace layers { + +class ClientTiledPaintedLayer; +class LayerMetricsWrapper; +struct AsyncTransform; +struct FrameMetrics; + +enum class TilePaintFlags : uint8_t { + None = 0x0, + Async = 0x1, + Progressive = 0x2, +}; +MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(TilePaintFlags) + +void ShutdownTileCache(); + +struct AcquiredBackBuffer { + AcquiredBackBuffer(gfx::DrawTarget* aTarget, gfx::DrawTargetCapture* aCapture, + gfx::DrawTarget* aBackBuffer, + const gfx::IntRect& aUpdatedRect, + AutoTArray<RefPtr<TextureClient>, 4>&& aTextureClients) + : mTarget(aTarget), + mCapture(aCapture), + mBackBuffer(aBackBuffer), + mUpdatedRect(aUpdatedRect), + mTextureClients(std::move(aTextureClients)) {} + + AcquiredBackBuffer(const AcquiredBackBuffer&) = delete; + AcquiredBackBuffer& operator=(const AcquiredBackBuffer&) = delete; + + AcquiredBackBuffer(AcquiredBackBuffer&&) = default; + AcquiredBackBuffer& operator=(AcquiredBackBuffer&&) = default; + + RefPtr<gfx::DrawTarget> mTarget; + RefPtr<gfx::DrawTargetCapture> mCapture; + RefPtr<gfx::DrawTarget> mBackBuffer; + gfx::IntRect mUpdatedRect; + AutoTArray<RefPtr<TextureClient>, 4> mTextureClients; +}; + +/** + * Represent a single tile in tiled buffer. The buffer keeps tiles, + * each tile keeps a reference to a texture client and a read-lock. This + * read-lock is used to help implement a copy-on-write mechanism. The tile + * should be locked before being sent to the compositor. The compositor should + * unlock the read-lock as soon as it has finished with the buffer in the + * TextureHost to prevent more textures being created than is necessary. + * Ideal place to store per tile debug information. + */ +struct TileClient { + // Placeholder + TileClient(); + ~TileClient(); + + TileClient(const TileClient& o); + + TileClient& operator=(const TileClient& o); + + bool operator==(const TileClient& o) const { + return mFrontBuffer == o.mFrontBuffer; + } + + bool operator!=(const TileClient& o) const { + return mFrontBuffer != o.mFrontBuffer; + } + + void SetTextureAllocator(TextureClientAllocator* aAllocator) { + mAllocator = aAllocator; + } + + bool IsPlaceholderTile() const { + return mBackBuffer == nullptr && mFrontBuffer == nullptr; + } + + void DiscardBuffers() { + DiscardFrontBuffer(); + DiscardBackBuffer(); + } + + nsExpirationState* GetExpirationState() { return &mExpirationState; } + + TileDescriptor GetTileDescriptor(); + + /** + * For debugging. + */ + void Dump(std::stringstream& aStream); + + /** + * Swaps the front and back buffers. + */ + void Flip(); + + void DumpTexture(std::stringstream& aStream, TextureDumpMode aCompress) { + // TODO We should combine the OnWhite/OnBlack here an just output a single + // image. + CompositableClient::DumpTextureClient(aStream, mFrontBuffer, aCompress); + } + + void GetSyncTextureSerials(SurfaceMode aMode, nsTArray<uint64_t>& aSerials); + + /** + * Returns an unlocked TextureClient that can be used for writing new + * data to the tile. This may flip the front-buffer to the back-buffer if + * the front-buffer is still locked by the host, or does not have an + * internal buffer (and so will always be locked). + * + * If getting the back buffer required copying pixels from the front buffer + * then the copied region is stored in aAddPaintedRegion so the host side + * knows to upload it. + * + * If nullptr is returned, aTextureClientOnWhite is undefined. + */ + Maybe<AcquiredBackBuffer> AcquireBackBuffer(CompositableClient&, + const nsIntRegion& aDirtyRegion, + const nsIntRegion& aVisibleRegion, + gfxContentType aContent, + SurfaceMode aMode, + TilePaintFlags aFlags); + + void DiscardFrontBuffer(); + + void DiscardBackBuffer(); + + /* We wrap the back buffer in a class that disallows assignment + * so that we can track when ever it changes so that we can update + * the expiry tracker for expiring the back buffers */ + class PrivateProtector { + public: + void Set(TileClient* container, RefPtr<TextureClient>); + void Set(TileClient* container, TextureClient*); + // Implicitly convert to TextureClient* because we can't chain + // implicit conversion that would happen on RefPtr<TextureClient> + operator TextureClient*() const { return mBuffer; } + RefPtr<TextureClient> operator->() { return mBuffer; } + + private: + PrivateProtector& operator=(const PrivateProtector&); + RefPtr<TextureClient> mBuffer; + } mBackBuffer; + RefPtr<TextureClient> mBackBufferOnWhite; + RefPtr<TextureClient> mFrontBuffer; + RefPtr<TextureClient> mFrontBufferOnWhite; + RefPtr<TextureClientAllocator> mAllocator; + gfx::IntRect mUpdateRect; + bool mWasPlaceholder; +#ifdef GFX_TILEDLAYER_DEBUG_OVERLAY + TimeStamp mLastUpdate; +#endif + nsIntRegion mInvalidFront; + nsIntRegion mInvalidBack; + nsExpirationState mExpirationState; + + private: + /* + * Copies dirty pixels from the front buffer into the back buffer, + * and records the copied region in aAddPaintedRegion. + */ + void ValidateFromFront(const nsIntRegion& aDirtyRegion, + const nsIntRegion& aVisibleRegion, + gfx::DrawTarget* aBackBuffer, TilePaintFlags aFlags, + gfx::IntRect* aCopiedRegion, + AutoTArray<RefPtr<TextureClient>, 4>* aClients); +}; + +/** + * This struct stores all the data necessary to perform a paint so that it + * doesn't need to be recalculated on every repeated transaction. + */ +struct BasicTiledLayerPaintData { + /* + * The scroll offset of the content from the nearest ancestor layer that + * represents scrollable content with a display port set. + */ + ParentLayerPoint mScrollOffset; + + /* + * The scroll offset of the content from the nearest ancestor layer that + * represents scrollable content with a display port set, for the last + * layer update transaction. + */ + ParentLayerPoint mLastScrollOffset; + + /* + * The transform matrix to go from this layer's Layer units to + * the scroll ancestor's ParentLayer units. The "scroll ancestor" is + * the closest ancestor layer which scrolls, and is used to obtain + * the composition bounds that are relevant for this layer. + */ + LayerToParentLayerMatrix4x4 mTransformToCompBounds; + + /* + * The critical displayport of the content from the nearest ancestor layer + * that represents scrollable content with a display port set. isNothing() + * if a critical displayport is not set. + */ + Maybe<LayerIntRect> mCriticalDisplayPort; + + /* + * The render resolution of the document that the content this layer + * represents is in. + */ + CSSToParentLayerScale2D mResolution; + + /* + * The composition bounds of the layer, in Layer coordinates. This is + * used to make sure that tiled updates to regions that are visible to the + * user are grouped coherently. + */ + LayerRect mCompositionBounds; + + /* + * Low precision updates are always executed a tile at a time in repeated + * transactions. This counter is set to 1 on the first transaction of a low + * precision update, and incremented for each subsequent transaction. + */ + uint16_t mLowPrecisionPaintCount; + + /* + * Whether this is the first time this layer is painting + */ + bool mFirstPaint : 1; + + /* + * Whether there is further work to complete this paint. This is used to + * determine whether or not to repeat the transaction when painting + * progressively. + */ + bool mPaintFinished : 1; + + /* + * Whether or not there is an async transform animation active + */ + bool mHasTransformAnimation : 1; + + /* + * Initializes/clears data to prepare for paint action. + */ + void ResetPaintData(); +}; + +class SharedFrameMetricsHelper { + public: + SharedFrameMetricsHelper(); + ~SharedFrameMetricsHelper(); + + /** + * This is called by the BasicTileLayer to determine if it is still interested + * in the update of this display-port to continue. We can return true here + * to abort the current update and continue with any subsequent ones. This + * is useful for slow-to-render pages when the display-port starts lagging + * behind enough that continuing to draw it is wasted effort. + */ + bool UpdateFromCompositorFrameMetrics(const LayerMetricsWrapper& aLayer, + bool aHasPendingNewThebesContent, + bool aLowPrecision, + AsyncTransform& aViewTransform); + + /** + * Determines if the compositor's upcoming composition bounds has fallen + * outside of the contents display port. If it has then the compositor + * will start to checker board. Checker boarding is when the compositor + * tries to composite a tile and it is not available. Historically + * a tile with a checker board pattern was used. Now a blank tile is used. + */ + bool AboutToCheckerboard(const FrameMetrics& aContentMetrics, + const FrameMetrics& aCompositorMetrics); + + private: + bool mLastProgressiveUpdateWasLowPrecision; + bool mProgressiveUpdateWasInDanger; +}; + +/** + * Provide an instance of TiledLayerBuffer backed by drawable TextureClients. + * This buffer provides an implementation of ValidateTile using a + * thebes callback and can support painting using a single paint buffer. + * Whether a single paint buffer is used is controlled by + * StaticPrefs::PerTileDrawing(). + */ +class ClientTiledLayerBuffer { + public: + ClientTiledLayerBuffer(ClientTiledPaintedLayer& aPaintedLayer, + CompositableClient& aCompositableClient) + : mPaintedLayer(aPaintedLayer), + mCompositableClient(aCompositableClient), + mLastPaintContentType(gfxContentType::COLOR), + mLastPaintSurfaceMode(SurfaceMode::SURFACE_OPAQUE), + mWasLastPaintProgressive(false) {} + + virtual void PaintThebes(const nsIntRegion& aNewValidRegion, + const nsIntRegion& aPaintRegion, + const nsIntRegion& aDirtyRegion, + LayerManager::DrawPaintedLayerCallback aCallback, + void* aCallbackData, TilePaintFlags aFlags) = 0; + virtual void GetSyncTextureSerials(const nsIntRegion& aPaintRegion, + const nsIntRegion& aDirtyRegion, + nsTArray<uint64_t>& aSerials) { + return; + } + + virtual bool SupportsProgressiveUpdate() = 0; + virtual bool ProgressiveUpdate( + const nsIntRegion& aValidRegion, const nsIntRegion& aInvalidRegion, + const nsIntRegion& aOldValidRegion, nsIntRegion& aOutDrawnRegion, + BasicTiledLayerPaintData* aPaintData, + LayerManager::DrawPaintedLayerCallback aCallback, + void* aCallbackData) = 0; + virtual void ResetPaintedAndValidState() = 0; + + virtual const nsIntRegion& GetValidRegion() = 0; + + virtual bool IsLowPrecision() const = 0; + + virtual void Dump(std::stringstream& aStream, const char* aPrefix, + bool aDumpHtml, TextureDumpMode aCompress) {} + + const CSSToParentLayerScale2D& GetFrameResolution() { + return mFrameResolution; + } + void SetFrameResolution(const CSSToParentLayerScale2D& aResolution) { + mFrameResolution = aResolution; + } + + bool HasFormatChanged() const; + + protected: + void UnlockTile(TileClient& aTile); + gfxContentType GetContentType(SurfaceMode* aMode = nullptr) const; + + ClientTiledPaintedLayer& mPaintedLayer; + CompositableClient& mCompositableClient; + + gfxContentType mLastPaintContentType; + SurfaceMode mLastPaintSurfaceMode; + CSSToParentLayerScale2D mFrameResolution; + + bool mWasLastPaintProgressive; +}; + +class TiledContentClient : public CompositableClient { + public: + TiledContentClient(ClientLayerManager* aManager, const char* aName = "") + : CompositableClient(aManager->AsShadowForwarder()), mName(aName) {} + + protected: + ~TiledContentClient() {} + + public: + virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix); + + void Dump(std::stringstream& aStream, const char* aPrefix = "", + bool aDumpHtml = false, + TextureDumpMode aCompress = TextureDumpMode::Compress) override; + + TextureInfo GetTextureInfo() const override { + return TextureInfo(CompositableType::CONTENT_TILED); + } + + virtual ClientTiledLayerBuffer* GetTiledBuffer() = 0; + virtual ClientTiledLayerBuffer* GetLowPrecisionTiledBuffer() = 0; + + enum TiledBufferType { TILED_BUFFER, LOW_PRECISION_TILED_BUFFER }; + virtual void UpdatedBuffer(TiledBufferType aType) = 0; + + private: + const char* mName; +}; + +} // namespace layers +} // namespace mozilla + +#endif // MOZILLA_GFX_TILEDCONTENTCLIENT_H |