LCOV - code coverage report
Current view: top level - gfx/layers/client - ContentClient.h (source / functions) Hit Total Coverage
Test: output.info Lines: 35 81 43.2 %
Date: 2017-07-14 16:53:18 Functions: 19 40 47.5 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       5             : 
       6             : #ifndef MOZILLA_GFX_CONTENTCLIENT_H
       7             : #define MOZILLA_GFX_CONTENTCLIENT_H
       8             : 
       9             : #include <stdint.h>                     // for uint32_t
      10             : #include "RotatedBuffer.h"              // for RotatedContentBuffer, etc
      11             : #include "gfxTypes.h"
      12             : #include "gfxPlatform.h"                // for gfxPlatform
      13             : #include "mozilla/Assertions.h"         // for MOZ_CRASH
      14             : #include "mozilla/Attributes.h"         // for override
      15             : #include "mozilla/RefPtr.h"             // for RefPtr, already_AddRefed
      16             : #include "mozilla/gfx/Point.h"          // for IntSize
      17             : #include "mozilla/layers/CompositableClient.h"  // for CompositableClient
      18             : #include "mozilla/layers/CompositableForwarder.h"
      19             : #include "mozilla/layers/CompositorTypes.h"  // for TextureInfo, etc
      20             : #include "mozilla/layers/ISurfaceAllocator.h"
      21             : #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
      22             : #include "mozilla/layers/LayersTypes.h"  // for TextureDumpMode
      23             : #include "mozilla/layers/TextureClient.h"  // for TextureClient
      24             : #include "mozilla/mozalloc.h"           // for operator delete
      25             : #include "ReadbackProcessor.h"          // For ReadbackProcessor::Update
      26             : #include "nsCOMPtr.h"                   // for already_AddRefed
      27             : #include "nsPoint.h"                    // for nsIntPoint
      28             : #include "nsRect.h"                     // for mozilla::gfx::IntRect
      29             : #include "nsRegion.h"                   // for nsIntRegion
      30             : #include "nsTArray.h"                   // for nsTArray
      31             : 
      32             : namespace mozilla {
      33             : namespace gfx {
      34             : class DrawTarget;
      35             : } // namespace gfx
      36             : 
      37             : namespace layers {
      38             : 
      39             : class PaintedLayer;
      40             : 
      41             : /**
      42             :  * A compositable client for PaintedLayers. These are different to Image/Canvas
      43             :  * clients due to sending a valid region across IPC and because we do a lot more
      44             :  * optimisation work, encapsualted in RotatedContentBuffers.
      45             :  *
      46             :  * We use content clients for OMTC and non-OMTC, basic rendering so that
      47             :  * BasicPaintedLayer has only one interface to deal with. We support single and
      48             :  * double buffered flavours. For tiled layers, we do not use a ContentClient
      49             :  * although we do have a ContentHost, and we do use texture clients and texture
      50             :  * hosts.
      51             :  *
      52             :  * The interface presented by ContentClient is used by the BasicPaintedLayer
      53             :  * methods - PaintThebes, which is the same for MT and OMTC, and PaintBuffer
      54             :  * which is different (the OMTC one does a little more). The 'buffer' in the
      55             :  * names of a lot of these method is actually the TextureClient. But, 'buffer'
      56             :  * for the RotatedContentBuffer (as in SetBuffer) means a gfxSurface. See the
      57             :  * comments for SetBuffer and SetBufferProvider in RotatedContentBuffer. To keep
      58             :  * these mapped buffers alive, we store a pointer in mOldTextures if the
      59             :  * RotatedContentBuffer's surface is not the one from our texture client, once we
      60             :  * are done painting we unmap the surface/texture client and don't need to keep
      61             :  * it alive anymore, so we clear mOldTextures.
      62             :  *
      63             :  * The sequence for painting is: call BeginPaint on the content client;
      64             :  * call BeginPaintBuffer on the content client. That will initialise the buffer
      65             :  * for painting, by calling RotatedContentBuffer::BeginPaint (usually) which
      66             :  * will call back to ContentClient::FinalizeFrame to finalize update of the
      67             :  * buffers before drawing (i.e., it finalizes the previous frame). Then call
      68             :  * BorrowDrawTargetForPainting to get a DrawTarget to paint into. Then paint.
      69             :  * Then return that DrawTarget using ReturnDrawTarget.
      70             :  * Call EndPaint on the content client;
      71             :  *
      72             :  * SwapBuffers is called in response to the transaction reply from the compositor.
      73             :  */
      74             : class ContentClient : public CompositableClient
      75             : {
      76             : public:
      77             :   /**
      78             :    * Creates, configures, and returns a new content client. If necessary, a
      79             :    * message will be sent to the compositor to create a corresponding content
      80             :    * host.
      81             :    */
      82             :   static already_AddRefed<ContentClient> CreateContentClient(CompositableForwarder* aFwd);
      83             : 
      84          79 :   explicit ContentClient(CompositableForwarder* aForwarder)
      85          79 :   : CompositableClient(aForwarder)
      86          79 :   {}
      87          73 :   virtual ~ContentClient()
      88          73 :   {}
      89             : 
      90             :   virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix);
      91             : 
      92             :   virtual void Clear() = 0;
      93             :   virtual RotatedContentBuffer::PaintState BeginPaintBuffer(PaintedLayer* aLayer,
      94             :                                                             uint32_t aFlags) = 0;
      95             :   virtual gfx::DrawTarget* BorrowDrawTargetForPainting(RotatedContentBuffer::PaintState& aPaintState,
      96             :                                                        RotatedContentBuffer::DrawIterator* aIter = nullptr) = 0;
      97             :   virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) = 0;
      98             : 
      99             :   // Called as part of the layers transation reply. Conveys data about our
     100             :   // buffer(s) from the compositor. If appropriate we should swap references
     101             :   // to our buffers.
     102           0 :   virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) {}
     103             : 
     104             :   // call before and after painting into this content client
     105           0 :   virtual void BeginPaint() {}
     106             :   virtual void EndPaint(nsTArray<ReadbackProcessor::Update>* aReadbackUpdates = nullptr);
     107             : };
     108             : 
     109             : /**
     110             :  * A ContentClient for use with OMTC.
     111             :  */
     112          19 : class ContentClientRemote : public ContentClient
     113             : {
     114             : public:
     115          22 :   explicit ContentClientRemote(CompositableForwarder* aForwarder)
     116          22 :     : ContentClient(aForwarder)
     117          22 :   {}
     118             : 
     119             :   virtual void Updated(const nsIntRegion& aRegionToDraw,
     120             :                        const nsIntRegion& aVisibleRegion,
     121             :                        bool aDidSelfCopy) = 0;
     122             : 
     123           0 :   ContentClientRemote* AsContentClientRemote() override {
     124           0 :     return this;
     125             :   }
     126             : };
     127             : 
     128             : // thin wrapper around RotatedContentBuffer, for on-mtc
     129         162 : class ContentClientBasic final : public ContentClient
     130             :                                , protected RotatedContentBuffer
     131             : {
     132             : public:
     133             :   explicit ContentClientBasic(gfx::BackendType aBackend);
     134             : 
     135             :   typedef RotatedContentBuffer::PaintState PaintState;
     136             :   typedef RotatedContentBuffer::ContentType ContentType;
     137             : 
     138          99 :   virtual void Clear() override { RotatedContentBuffer::Clear(); }
     139           0 :   virtual PaintState BeginPaintBuffer(PaintedLayer* aLayer,
     140             :                                       uint32_t aFlags) override
     141             :   {
     142           0 :     return RotatedContentBuffer::BeginPaint(aLayer, aFlags);
     143             :   }
     144           0 :   virtual gfx::DrawTarget* BorrowDrawTargetForPainting(PaintState& aPaintState,
     145             :                                                        RotatedContentBuffer::DrawIterator* aIter = nullptr) override
     146             :   {
     147           0 :     return RotatedContentBuffer::BorrowDrawTargetForPainting(aPaintState, aIter);
     148             :   }
     149           0 :   virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) override
     150             :   {
     151           0 :     BorrowDrawTarget::ReturnDrawTarget(aReturned);
     152           0 :   }
     153             : 
     154           0 :   void DrawTo(PaintedLayer* aLayer,
     155             :               gfx::DrawTarget* aTarget,
     156             :               float aOpacity,
     157             :               gfx::CompositionOp aOp,
     158             :               gfx::SourceSurface* aMask,
     159             :               const gfx::Matrix* aMaskTransform)
     160             :   {
     161           0 :     RotatedContentBuffer::DrawTo(aLayer, aTarget, aOpacity, aOp,
     162           0 :                                  aMask, aMaskTransform);
     163           0 :   }
     164             : 
     165             :   virtual void CreateBuffer(ContentType aType, const gfx::IntRect& aRect, uint32_t aFlags,
     166             :                             RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) override;
     167             : 
     168           0 :   virtual TextureInfo GetTextureInfo() const override
     169             :   {
     170           0 :     MOZ_CRASH("GFX: Should not be called on non-remote ContentClient");
     171             :   }
     172             : 
     173             : private:
     174             :   gfx::BackendType mBackend;
     175             : };
     176             : 
     177             : /**
     178             :  * A ContentClientRemote backed by a RotatedContentBuffer.
     179             :  *
     180             :  * When using a ContentClientRemote, SurfaceDescriptors are created on
     181             :  * the rendering side and destroyed on the compositing side. They are only
     182             :  * passed from one side to the other when the TextureClient/Hosts are created.
     183             :  * *Ownership* of the SurfaceDescriptor moves from the rendering side to the
     184             :  * compositing side with the create message (send from CreateBuffer) which
     185             :  * tells the compositor that TextureClients have been created and that the
     186             :  * compositor should assign the corresponding TextureHosts to our corresponding
     187             :  * ContentHost.
     188             :  *
     189             :  * If the size or type of our buffer(s) change(s), then we simply destroy and
     190             :  * create them.
     191             :  */
     192             : // Version using new texture clients
     193          19 : class ContentClientRemoteBuffer : public ContentClientRemote
     194             :                                 , protected RotatedContentBuffer
     195             : {
     196             :   using RotatedContentBuffer::BufferRect;
     197             :   using RotatedContentBuffer::BufferRotation;
     198             : public:
     199          22 :   explicit ContentClientRemoteBuffer(CompositableForwarder* aForwarder)
     200          22 :     : ContentClientRemote(aForwarder)
     201             :     , RotatedContentBuffer(ContainsVisibleBounds)
     202             :     , mIsNewBuffer(false)
     203             :     , mFrontAndBackBufferDiffer(false)
     204          22 :     , mSurfaceFormat(gfx::SurfaceFormat::B8G8R8A8)
     205          22 :   {}
     206             : 
     207             :   typedef RotatedContentBuffer::PaintState PaintState;
     208             :   typedef RotatedContentBuffer::ContentType ContentType;
     209             : 
     210           0 :   virtual void Clear() override
     211             :   {
     212           0 :     RotatedContentBuffer::Clear();
     213           0 :     mTextureClient = nullptr;
     214           0 :     mTextureClientOnWhite = nullptr;
     215           0 :   }
     216             : 
     217             :   virtual void Dump(std::stringstream& aStream,
     218             :                     const char* aPrefix="",
     219             :                     bool aDumpHtml=false,
     220             :                     TextureDumpMode aCompress=TextureDumpMode::Compress) override;
     221             : 
     222          77 :   virtual PaintState BeginPaintBuffer(PaintedLayer* aLayer,
     223             :                                       uint32_t aFlags) override
     224             :   {
     225          77 :     return RotatedContentBuffer::BeginPaint(aLayer, aFlags);
     226             :   }
     227         110 :   virtual gfx::DrawTarget* BorrowDrawTargetForPainting(PaintState& aPaintState,
     228             :                                                        RotatedContentBuffer::DrawIterator* aIter = nullptr) override
     229             :   {
     230         110 :     return RotatedContentBuffer::BorrowDrawTargetForPainting(aPaintState, aIter);
     231             :   }
     232          46 :   virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) override
     233             :   {
     234          46 :     BorrowDrawTarget::ReturnDrawTarget(aReturned);
     235          46 :   }
     236             : 
     237             :   /**
     238             :    * Begin/End Paint map a gfxASurface from the texture client
     239             :    * into the buffer of RotatedBuffer. The surface is only
     240             :    * valid when the texture client is locked, so is mapped out
     241             :    * of RotatedContentBuffer when we are done painting.
     242             :    * None of the underlying buffer attributes (rect, rotation)
     243             :    * are affected by mapping/unmapping.
     244             :    */
     245             :   virtual void BeginPaint() override;
     246             :   virtual void EndPaint(nsTArray<ReadbackProcessor::Update>* aReadbackUpdates = nullptr) override;
     247             : 
     248             :   virtual void Updated(const nsIntRegion& aRegionToDraw,
     249             :                        const nsIntRegion& aVisibleRegion,
     250             :                        bool aDidSelfCopy) override;
     251             : 
     252             :   virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) override;
     253             : 
     254             :   // Expose these protected methods from the superclass.
     255          66 :   virtual const gfx::IntRect& BufferRect() const
     256             :   {
     257          66 :     return RotatedContentBuffer::BufferRect();
     258             :   }
     259          33 :   virtual const nsIntPoint& BufferRotation() const
     260             :   {
     261          33 :     return RotatedContentBuffer::BufferRotation();
     262             :   }
     263             : 
     264             :   virtual void CreateBuffer(ContentType aType, const gfx::IntRect& aRect, uint32_t aFlags,
     265             :                             RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) override;
     266             : 
     267           9 :   virtual TextureFlags ExtraTextureFlags() const
     268             :   {
     269           9 :     return TextureFlags::IMMEDIATE_UPLOAD;
     270             :   }
     271             : 
     272             : protected:
     273             :   void DestroyBuffers();
     274             : 
     275             :   virtual nsIntRegion GetUpdatedRegion(const nsIntRegion& aRegionToDraw,
     276             :                                        const nsIntRegion& aVisibleRegion,
     277             :                                        bool aDidSelfCopy);
     278             : 
     279             :   void BuildTextureClients(gfx::SurfaceFormat aFormat,
     280             :                            const gfx::IntRect& aRect,
     281             :                            uint32_t aFlags);
     282             : 
     283             :   void CreateBackBuffer(const gfx::IntRect& aBufferRect);
     284             : 
     285             :   // Ensure we have a valid back buffer if we have a valid front buffer (i.e.
     286             :   // if a backbuffer has been created.)
     287           0 :   virtual void EnsureBackBufferIfFrontBuffer() {}
     288             : 
     289             :   // Create the front buffer for the ContentClient/Host pair if necessary
     290             :   // and notify the compositor that we have created the buffer(s).
     291           0 :   virtual void DestroyFrontBuffer() {}
     292             : 
     293           0 :   virtual void AbortTextureClientCreation()
     294             :   {
     295           0 :     mTextureClient = nullptr;
     296           0 :     mTextureClientOnWhite = nullptr;
     297           0 :     mIsNewBuffer = false;
     298           0 :   }
     299             : 
     300             :   virtual bool LockBuffers() override;
     301             :   virtual void UnlockBuffers() override;
     302             : 
     303             :   RefPtr<TextureClient> mTextureClient;
     304             :   RefPtr<TextureClient> mTextureClientOnWhite;
     305             :   // keep a record of texture clients we have created and need to keep around
     306             :   // (for RotatedBuffer to access), then unlock and remove them when we are done
     307             :   // painting.
     308             :   nsTArray<RefPtr<TextureClient> > mOldTextures;
     309             : 
     310             :   bool mIsNewBuffer;
     311             :   bool mFrontAndBackBufferDiffer;
     312             :   gfx::IntSize mSize;
     313             :   gfx::SurfaceFormat mSurfaceFormat;
     314             : };
     315             : 
     316             : /**
     317             :  * A double buffered ContentClient. mTextureClient is the back buffer, which
     318             :  * we draw into. mFrontClient is the front buffer which we may read from, but
     319             :  * not write to, when the compositor does not have the 'soft' lock. We can write
     320             :  * into mTextureClient at any time.
     321             :  *
     322             :  * The ContentHost keeps a reference to both corresponding texture hosts, in
     323             :  * response to our UpdateTextureRegion message, the compositor swaps its
     324             :  * references. In response to the compositor's reply we swap our references
     325             :  * (in SwapBuffers).
     326             :  */
     327             : class ContentClientDoubleBuffered : public ContentClientRemoteBuffer
     328             : {
     329             : public:
     330          22 :   explicit ContentClientDoubleBuffered(CompositableForwarder* aFwd)
     331          22 :     : ContentClientRemoteBuffer(aFwd)
     332          22 :   {}
     333             : 
     334          57 :   virtual ~ContentClientDoubleBuffered() {}
     335             : 
     336           0 :   virtual void Clear() override
     337             :   {
     338           0 :     ContentClientRemoteBuffer::Clear();
     339           0 :     mFrontClient = nullptr;
     340           0 :     mFrontClientOnWhite = nullptr;
     341           0 :   }
     342             : 
     343             :   virtual void Updated(const nsIntRegion& aRegionToDraw,
     344             :                        const nsIntRegion& aVisibleRegion,
     345             :                        bool aDidSelfCopy) override;
     346             : 
     347             :   virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) override;
     348             : 
     349             :   virtual void BeginPaint() override;
     350             : 
     351             :   virtual void FinalizeFrame(const nsIntRegion& aRegionToDraw) override;
     352             : 
     353             :   virtual void EnsureBackBufferIfFrontBuffer() override;
     354             : 
     355          22 :   virtual TextureInfo GetTextureInfo() const override
     356             :   {
     357          22 :     return TextureInfo(CompositableType::CONTENT_DOUBLE, mTextureFlags);
     358             :   }
     359             : 
     360             :   virtual void Dump(std::stringstream& aStream,
     361             :                     const char* aPrefix="",
     362             :                     bool aDumpHtml=false,
     363             :                     TextureDumpMode aCompress=TextureDumpMode::Compress) override;
     364             : protected:
     365             :   virtual void DestroyFrontBuffer() override;
     366             : 
     367             : private:
     368             :   void UpdateDestinationFrom(const RotatedBuffer& aSource,
     369             :                              const nsIntRegion& aUpdateRegion);
     370             : 
     371           0 :   virtual void AbortTextureClientCreation() override
     372             :   {
     373           0 :     mTextureClient = nullptr;
     374           0 :     mTextureClientOnWhite = nullptr;
     375           0 :     mFrontClient = nullptr;
     376           0 :     mFrontClientOnWhite = nullptr;
     377           0 :   }
     378             : 
     379             :   RefPtr<TextureClient> mFrontClient;
     380             :   RefPtr<TextureClient> mFrontClientOnWhite;
     381             :   nsIntRegion mFrontUpdatedRegion;
     382             :   gfx::IntRect mFrontBufferRect;
     383             :   nsIntPoint mFrontBufferRotation;
     384             : };
     385             : 
     386             : /**
     387             :  * A single buffered ContentClient. We have a single TextureClient/Host
     388             :  * which we update and then send a message to the compositor that we are
     389             :  * done updating. It is not safe for the compositor to use the corresponding
     390             :  * TextureHost's memory directly, it must upload it to video memory of some
     391             :  * kind. We are free to modify the TextureClient once we receive reply from
     392             :  * the compositor.
     393             :  */
     394             : class ContentClientSingleBuffered : public ContentClientRemoteBuffer
     395             : {
     396             : public:
     397           0 :   explicit ContentClientSingleBuffered(CompositableForwarder* aFwd)
     398           0 :     : ContentClientRemoteBuffer(aFwd)
     399             :   {
     400           0 :   }
     401           0 :   virtual ~ContentClientSingleBuffered() {}
     402             : 
     403           0 :   virtual TextureInfo GetTextureInfo() const override
     404             :   {
     405           0 :     return TextureInfo(CompositableType::CONTENT_SINGLE, mTextureFlags | ExtraTextureFlags());
     406             :   }
     407             : };
     408             : 
     409             : } // namespace layers
     410             : } // namespace mozilla
     411             : 
     412             : #endif

Generated by: LCOV version 1.13