gfx/layers/client/TiledContentClient.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     2  * This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef MOZILLA_GFX_TILEDCONTENTCLIENT_H
     7 #define MOZILLA_GFX_TILEDCONTENTCLIENT_H
     9 #include <stddef.h>                     // for size_t
    10 #include <stdint.h>                     // for uint16_t
    11 #include <algorithm>                    // for swap
    12 #include "Layers.h"                     // for LayerManager, etc
    13 #include "TiledLayerBuffer.h"           // for TiledLayerBuffer
    14 #include "Units.h"                      // for CSSPoint
    15 #include "gfx3DMatrix.h"                // for gfx3DMatrix
    16 #include "gfxTypes.h"
    17 #include "mozilla/Attributes.h"         // for MOZ_OVERRIDE
    18 #include "mozilla/RefPtr.h"             // for RefPtr
    19 #include "mozilla/ipc/Shmem.h"          // for Shmem
    20 #include "mozilla/ipc/SharedMemory.h"   // for SharedMemory
    21 #include "mozilla/layers/CompositableClient.h"  // for CompositableClient
    22 #include "mozilla/layers/CompositorTypes.h"  // for TextureInfo, etc
    23 #include "mozilla/layers/LayersMessages.h" // for TileDescriptor
    24 #include "mozilla/layers/TextureClient.h"
    25 #include "mozilla/layers/TextureClientPool.h"
    26 #include "ClientLayerManager.h"
    27 #include "mozilla/mozalloc.h"           // for operator delete
    28 #include "nsAutoPtr.h"                  // for nsRefPtr
    29 #include "nsISupportsImpl.h"            // for MOZ_COUNT_DTOR
    30 #include "nsPoint.h"                    // for nsIntPoint
    31 #include "nsRect.h"                     // for nsIntRect
    32 #include "nsRegion.h"                   // for nsIntRegion
    33 #include "nsTArray.h"                   // for nsTArray, nsTArray_Impl, etc
    34 #include "mozilla/layers/ISurfaceAllocator.h"
    35 #include "gfxReusableSurfaceWrapper.h"
    36 #include "pratom.h"                     // For PR_ATOMIC_INCREMENT/DECREMENT
    37 #include "gfxPrefs.h"
    39 namespace mozilla {
    40 namespace layers {
    42 class BasicTileDescriptor;
    43 class ClientTiledThebesLayer;
    44 class ClientLayerManager;
    47 // A class to help implement copy-on-write semantics for shared tiles.
    48 class gfxSharedReadLock {
    49 protected:
    50   virtual ~gfxSharedReadLock() {}
    52 public:
    53   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxSharedReadLock)
    55   virtual int32_t ReadLock() = 0;
    56   virtual int32_t ReadUnlock() = 0;
    57   virtual int32_t GetReadCount() = 0;
    58   virtual bool IsValid() const = 0;
    60   enum gfxSharedReadLockType {
    61     TYPE_MEMORY,
    62     TYPE_SHMEM
    63   };
    64   virtual gfxSharedReadLockType GetType() = 0;
    66 protected:
    67   NS_DECL_OWNINGTHREAD
    68 };
    70 class gfxMemorySharedReadLock : public gfxSharedReadLock {
    71 public:
    72   gfxMemorySharedReadLock();
    74   ~gfxMemorySharedReadLock();
    76   virtual int32_t ReadLock() MOZ_OVERRIDE;
    78   virtual int32_t ReadUnlock() MOZ_OVERRIDE;
    80   virtual int32_t GetReadCount() MOZ_OVERRIDE;
    82   virtual gfxSharedReadLockType GetType() MOZ_OVERRIDE { return TYPE_MEMORY; }
    84   virtual bool IsValid() const MOZ_OVERRIDE { return true; };
    86 private:
    87   int32_t mReadCount;
    88 };
    90 class gfxShmSharedReadLock : public gfxSharedReadLock {
    91 private:
    92   struct ShmReadLockInfo {
    93     int32_t readCount;
    94   };
    96 public:
    97   gfxShmSharedReadLock(ISurfaceAllocator* aAllocator);
    99   ~gfxShmSharedReadLock();
   101   virtual int32_t ReadLock() MOZ_OVERRIDE;
   103   virtual int32_t ReadUnlock() MOZ_OVERRIDE;
   105   virtual int32_t GetReadCount() MOZ_OVERRIDE;
   107   virtual bool IsValid() const MOZ_OVERRIDE { return mAllocSuccess; };
   109   virtual gfxSharedReadLockType GetType() MOZ_OVERRIDE { return TYPE_SHMEM; }
   111   mozilla::layers::ShmemSection& GetShmemSection() { return mShmemSection; }
   113   static already_AddRefed<gfxShmSharedReadLock>
   114   Open(mozilla::layers::ISurfaceAllocator* aAllocator, const mozilla::layers::ShmemSection& aShmemSection)
   115   {
   116     nsRefPtr<gfxShmSharedReadLock> readLock = new gfxShmSharedReadLock(aAllocator, aShmemSection);
   117     return readLock.forget();
   118   }
   120 private:
   121   gfxShmSharedReadLock(ISurfaceAllocator* aAllocator, const mozilla::layers::ShmemSection& aShmemSection)
   122     : mAllocator(aAllocator)
   123     , mShmemSection(aShmemSection)
   124     , mAllocSuccess(true)
   125   {
   126     MOZ_COUNT_CTOR(gfxShmSharedReadLock);
   127   }
   129   ShmReadLockInfo* GetShmReadLockInfoPtr()
   130   {
   131     return reinterpret_cast<ShmReadLockInfo*>
   132       (mShmemSection.shmem().get<char>() + mShmemSection.offset());
   133   }
   135   RefPtr<ISurfaceAllocator> mAllocator;
   136   mozilla::layers::ShmemSection mShmemSection;
   137   bool mAllocSuccess;
   138 };
   140 /**
   141  * Represent a single tile in tiled buffer. The buffer keeps tiles,
   142  * each tile keeps a reference to a texture client and a read-lock. This
   143  * read-lock is used to help implement a copy-on-write mechanism. The tile
   144  * should be locked before being sent to the compositor. The compositor should
   145  * unlock the read-lock as soon as it has finished with the buffer in the
   146  * TextureHost to prevent more textures being created than is necessary.
   147  * Ideal place to store per tile debug information.
   148  */
   149 struct TileClient
   150 {
   151   // Placeholder
   152   TileClient();
   154   TileClient(const TileClient& o);
   156   TileClient& operator=(const TileClient& o);
   158   bool operator== (const TileClient& o) const
   159   {
   160     return mFrontBuffer == o.mFrontBuffer;
   161   }
   163   bool operator!= (const TileClient& o) const
   164   {
   165     return mFrontBuffer != o.mFrontBuffer;
   166   }
   168   void SetLayerManager(ClientLayerManager *aManager)
   169   {
   170     mManager = aManager;
   171   }
   173   bool IsPlaceholderTile()
   174   {
   175     return mBackBuffer == nullptr && mFrontBuffer == nullptr;
   176   }
   178   void ReadUnlock()
   179   {
   180     MOZ_ASSERT(mFrontLock, "ReadLock with no gfxSharedReadLock");
   181     if (mFrontLock) {
   182       mFrontLock->ReadUnlock();
   183     }
   184   }
   186   void ReadLock()
   187   {
   188     MOZ_ASSERT(mFrontLock, "ReadLock with no gfxSharedReadLock");
   189     if (mFrontLock) {
   190       mFrontLock->ReadLock();
   191     }
   192   }
   194   void Release()
   195   {
   196     DiscardFrontBuffer();
   197     DiscardBackBuffer();
   198   }
   200   TileDescriptor GetTileDescriptor();
   202   /**
   203   * Swaps the front and back buffers.
   204   */
   205   void Flip();
   207   /**
   208   * Returns an unlocked TextureClient that can be used for writing new
   209   * data to the tile. This may flip the front-buffer to the back-buffer if
   210   * the front-buffer is still locked by the host, or does not have an
   211   * internal buffer (and so will always be locked).
   212   */
   213   TextureClient* GetBackBuffer(const nsIntRegion& aDirtyRegion,
   214                                TextureClientPool *aPool,
   215                                bool *aCreatedTextureClient,
   216                                bool aCanRerasterizeValidRegion);
   218   void DiscardFrontBuffer();
   220   void DiscardBackBuffer();
   222   RefPtr<TextureClient> mBackBuffer;
   223   RefPtr<TextureClient> mFrontBuffer;
   224   RefPtr<gfxSharedReadLock> mBackLock;
   225   RefPtr<gfxSharedReadLock> mFrontLock;
   226   RefPtr<ClientLayerManager> mManager;
   227 #ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
   228   TimeStamp        mLastUpdate;
   229 #endif
   230   nsIntRegion mInvalidFront;
   231   nsIntRegion mInvalidBack;
   233 private:
   234   void ValidateBackBufferFromFront(const nsIntRegion &aDirtyRegion,
   235                                    bool aCanRerasterizeValidRegion);
   236 };
   238 /**
   239  * This struct stores all the data necessary to perform a paint so that it
   240  * doesn't need to be recalculated on every repeated transaction.
   241  */
   242 struct BasicTiledLayerPaintData {
   243   /*
   244    * The scroll offset of the content from the nearest ancestor layer that
   245    * represents scrollable content with a display port set.
   246    */
   247   ParentLayerPoint mScrollOffset;
   249   /*
   250    * The scroll offset of the content from the nearest ancestor layer that
   251    * represents scrollable content with a display port set, for the last
   252    * layer update transaction.
   253    */
   254   ParentLayerPoint mLastScrollOffset;
   256   /*
   257    * The transform matrix to go from Screen units to ParentLayer units.
   258    */
   259   gfx3DMatrix mTransformParentLayerToLayoutDevice;
   261   /*
   262    * The critical displayport of the content from the nearest ancestor layer
   263    * that represents scrollable content with a display port set. Empty if a
   264    * critical displayport is not set.
   265    *
   266    * This is in LayoutDevice coordinates, but is stored as an nsIntRect for
   267    * convenience when intersecting with the layer's mValidRegion.
   268    */
   269   nsIntRect mCriticalDisplayPort;
   271   /*
   272    * The viewport of the content from the nearest ancestor layer that
   273    * represents scrollable content with a display port set.
   274    */
   275   LayoutDeviceRect mViewport;
   277   /*
   278    * The render resolution of the document that the content this layer
   279    * represents is in.
   280    */
   281   CSSToParentLayerScale mResolution;
   283   /*
   284    * The composition bounds of the layer, in LayoutDevice coordinates. This is
   285    * used to make sure that tiled updates to regions that are visible to the
   286    * user are grouped coherently.
   287    */
   288   LayoutDeviceRect mCompositionBounds;
   290   /*
   291    * Low precision updates are always executed a tile at a time in repeated
   292    * transactions. This counter is set to 1 on the first transaction of a low
   293    * precision update, and incremented for each subsequent transaction.
   294    */
   295   uint16_t mLowPrecisionPaintCount;
   297   /*
   298    * Whether this is the first time this layer is painting
   299    */
   300   bool mFirstPaint : 1;
   302   /*
   303    * Whether there is further work to complete this paint. This is used to
   304    * determine whether or not to repeat the transaction when painting
   305    * progressively.
   306    */
   307   bool mPaintFinished : 1;
   308 };
   310 class SharedFrameMetricsHelper
   311 {
   312 public:
   313   SharedFrameMetricsHelper();
   314   ~SharedFrameMetricsHelper();
   316   /**
   317    * This is called by the BasicTileLayer to determine if it is still interested
   318    * in the update of this display-port to continue. We can return true here
   319    * to abort the current update and continue with any subsequent ones. This
   320    * is useful for slow-to-render pages when the display-port starts lagging
   321    * behind enough that continuing to draw it is wasted effort.
   322    */
   323   bool UpdateFromCompositorFrameMetrics(ContainerLayer* aLayer,
   324                                         bool aHasPendingNewThebesContent,
   325                                         bool aLowPrecision,
   326                                         ParentLayerRect& aCompositionBounds,
   327                                         CSSToParentLayerScale& aZoom);
   329   /**
   330    * When a shared FrameMetrics can not be found for a given layer,
   331    * this function is used to find the first non-empty composition bounds
   332    * by traversing up the layer tree.
   333    */
   334   void FindFallbackContentFrameMetrics(ContainerLayer* aLayer,
   335                                        ParentLayerRect& aCompositionBounds,
   336                                        CSSToParentLayerScale& aZoom);
   337   /**
   338    * Determines if the compositor's upcoming composition bounds has fallen
   339    * outside of the contents display port. If it has then the compositor
   340    * will start to checker board. Checker boarding is when the compositor
   341    * tries to composite a tile and it is not available. Historically
   342    * a tile with a checker board pattern was used. Now a blank tile is used.
   343    */
   344   bool AboutToCheckerboard(const FrameMetrics& aContentMetrics,
   345                            const FrameMetrics& aCompositorMetrics);
   346 private:
   347   bool mLastProgressiveUpdateWasLowPrecision;
   348   bool mProgressiveUpdateWasInDanger;
   349 };
   351 /**
   352  * Provide an instance of TiledLayerBuffer backed by drawable TextureClients.
   353  * This buffer provides an implementation of ValidateTile using a
   354  * thebes callback and can support painting using a single paint buffer.
   355  * Whether a single paint buffer is used is controlled by
   356  * gfxPrefs::PerTileDrawing().
   357  */
   358 class ClientTiledLayerBuffer
   359   : public TiledLayerBuffer<ClientTiledLayerBuffer, TileClient>
   360 {
   361   friend class TiledLayerBuffer<ClientTiledLayerBuffer, TileClient>;
   363 public:
   364   ClientTiledLayerBuffer(ClientTiledThebesLayer* aThebesLayer,
   365                          CompositableClient* aCompositableClient,
   366                          ClientLayerManager* aManager,
   367                          SharedFrameMetricsHelper* aHelper);
   368   ClientTiledLayerBuffer()
   369     : mThebesLayer(nullptr)
   370     , mCompositableClient(nullptr)
   371     , mManager(nullptr)
   372     , mLastPaintOpaque(false)
   373     , mSharedFrameMetricsHelper(nullptr)
   374   {}
   376   void PaintThebes(const nsIntRegion& aNewValidRegion,
   377                    const nsIntRegion& aPaintRegion,
   378                    LayerManager::DrawThebesLayerCallback aCallback,
   379                    void* aCallbackData);
   381   void ReadUnlock();
   383   void ReadLock();
   385   void Release();
   387   void DiscardBackBuffers();
   389   const CSSToParentLayerScale& GetFrameResolution() { return mFrameResolution; }
   391   void SetFrameResolution(const CSSToParentLayerScale& aResolution) { mFrameResolution = aResolution; }
   393   bool HasFormatChanged() const;
   395   /**
   396    * Performs a progressive update of a given tiled buffer.
   397    * See ComputeProgressiveUpdateRegion below for parameter documentation.
   398    */
   399   bool ProgressiveUpdate(nsIntRegion& aValidRegion,
   400                          nsIntRegion& aInvalidRegion,
   401                          const nsIntRegion& aOldValidRegion,
   402                          BasicTiledLayerPaintData* aPaintData,
   403                          LayerManager::DrawThebesLayerCallback aCallback,
   404                          void* aCallbackData);
   406   SurfaceDescriptorTiles GetSurfaceDescriptorTiles();
   408 protected:
   409   TileClient ValidateTile(TileClient aTile,
   410                           const nsIntPoint& aTileRect,
   411                           const nsIntRegion& dirtyRect);
   413   // If this returns true, we perform the paint operation into a single large
   414   // buffer and copy it out to the tiles instead of calling PaintThebes() on
   415   // each tile individually. Somewhat surprisingly, this turns out to be faster
   416   // on Android.
   417   bool UseSinglePaintBuffer() { return !gfxPrefs::PerTileDrawing(); }
   419   void ReleaseTile(TileClient aTile) { aTile.Release(); }
   421   void SwapTiles(TileClient& aTileA, TileClient& aTileB) { std::swap(aTileA, aTileB); }
   423   TileClient GetPlaceholderTile() const { return TileClient(); }
   425 private:
   426   gfxContentType GetContentType() const;
   427   ClientTiledThebesLayer* mThebesLayer;
   428   CompositableClient* mCompositableClient;
   429   ClientLayerManager* mManager;
   430   LayerManager::DrawThebesLayerCallback mCallback;
   431   void* mCallbackData;
   432   CSSToParentLayerScale mFrameResolution;
   433   bool mLastPaintOpaque;
   435   // The DrawTarget we use when UseSinglePaintBuffer() above is true.
   436   RefPtr<gfx::DrawTarget>       mSinglePaintDrawTarget;
   437   nsIntPoint                    mSinglePaintBufferOffset;
   438   SharedFrameMetricsHelper*  mSharedFrameMetricsHelper;
   440   /**
   441    * Calculates the region to update in a single progressive update transaction.
   442    * This employs some heuristics to update the most 'sensible' region to
   443    * update at this point in time, and how large an update should be performed
   444    * at once to maintain visual coherency.
   445    *
   446    * aInvalidRegion is the current invalid region.
   447    * aOldValidRegion is the valid region of mTiledBuffer at the beginning of the
   448    * current transaction.
   449    * aRegionToPaint will be filled with the region to update. This may be empty,
   450    * which indicates that there is no more work to do.
   451    * aIsRepeated should be true if this function has already been called during
   452    * this transaction.
   453    *
   454    * Returns true if it should be called again, false otherwise. In the case
   455    * that aRegionToPaint is empty, this will return aIsRepeated for convenience.
   456    */
   457   bool ComputeProgressiveUpdateRegion(const nsIntRegion& aInvalidRegion,
   458                                       const nsIntRegion& aOldValidRegion,
   459                                       nsIntRegion& aRegionToPaint,
   460                                       BasicTiledLayerPaintData* aPaintData,
   461                                       bool aIsRepeated);
   462 };
   464 class TiledContentClient : public CompositableClient
   465 {
   466   // XXX: for now the layer which owns us interacts directly with our buffers.
   467   // We should have a content client for each tiled buffer which manages its
   468   // own valid region, resolution, etc. Then we could have a much cleaner
   469   // interface and tidy up BasicTiledThebesLayer::PaintThebes (bug 862547).
   470   friend class ClientTiledThebesLayer;
   472 public:
   473   TiledContentClient(ClientTiledThebesLayer* aThebesLayer,
   474                      ClientLayerManager* aManager);
   476   ~TiledContentClient()
   477   {
   478     MOZ_COUNT_DTOR(TiledContentClient);
   480     mTiledBuffer.Release();
   481     mLowPrecisionTiledBuffer.Release();
   482   }
   484   virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
   485   {
   486     return TextureInfo(BUFFER_TILED);
   487   }
   489   virtual void ClearCachedResources() MOZ_OVERRIDE;
   491   enum TiledBufferType {
   492     TILED_BUFFER,
   493     LOW_PRECISION_TILED_BUFFER
   494   };
   495   void UseTiledLayerBuffer(TiledBufferType aType);
   497 private:
   498   SharedFrameMetricsHelper mSharedFrameMetricsHelper;
   499   ClientTiledLayerBuffer mTiledBuffer;
   500   ClientTiledLayerBuffer mLowPrecisionTiledBuffer;
   501 };
   503 }
   504 }
   506 #endif

mercurial