gfx/layers/client/ContentClient.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_CONTENTCLIENT_H
     7 #define MOZILLA_GFX_CONTENTCLIENT_H
     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 MOZ_OVERRIDE
    15 #include "mozilla/RefPtr.h"             // for RefPtr, TemporaryRef
    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/TextureClient.h"  // for TextureClient
    23 #include "mozilla/mozalloc.h"           // for operator delete
    24 #include "nsCOMPtr.h"                   // for already_AddRefed
    25 #include "nsPoint.h"                    // for nsIntPoint
    26 #include "nsRect.h"                     // for nsIntRect
    27 #include "nsRegion.h"                   // for nsIntRegion
    28 #include "nsTArray.h"                   // for nsTArray
    30 class gfxContext;
    32 namespace mozilla {
    33 namespace gfx {
    34 class DrawTarget;
    35 }
    37 namespace layers {
    39 class BasicLayerManager;
    40 class ThebesLayer;
    42 /**
    43  * A compositable client for Thebes layers. These are different to Image/Canvas
    44  * clients due to sending a valid region across IPC and because we do a lot more
    45  * optimisation work, encapsualted in RotatedContentBuffers.
    46  *
    47  * We use content clients for OMTC and non-OMTC, basic rendering so that
    48  * BasicThebesLayer has only one interface to deal with. We support single and
    49  * double buffered flavours. For tiled layers, we do not use a ContentClient
    50  * although we do have a ContentHost, and we do use texture clients and texture
    51  * hosts.
    52  *
    53  * The interface presented by ContentClient is used by the BasicThebesLayer
    54  * methods - PaintThebes, which is the same for MT and OMTC, and PaintBuffer
    55  * which is different (the OMTC one does a little more). The 'buffer' in the
    56  * names of a lot of these method is actually the TextureClient. But, 'buffer'
    57  * for the RotatedContentBuffer (as in SetBuffer) means a gfxSurface. See the
    58  * comments for SetBuffer and SetBufferProvider in RotatedContentBuffer. To keep
    59  * these mapped buffers alive, we store a pointer in mOldTextures if the
    60  * RotatedContentBuffer's surface is not the one from our texture client, once we
    61  * are done painting we unmap the surface/texture client and don't need to keep
    62  * it alive anymore, so we clear mOldTextures.
    63  *
    64  * The sequence for painting is: call BeginPaint on the content client;
    65  * call BeginPaintBuffer on the content client. That will initialise the buffer
    66  * for painting, by calling RotatedContentBuffer::BeginPaint (usually) which
    67  * will call back to ContentClient::FinalizeFrame to finalize update of the
    68  * buffers before drawing (i.e., it finalizes the previous frame). Then call
    69  * BorrowDrawTargetForPainting to get a DrawTarget to paint into. Then paint.
    70  * Then return that DrawTarget using ReturnDrawTarget.
    71  * Call EndPaint on the content client;
    72  *
    73  * SwapBuffers is called in response to the transaction reply from the compositor.
    74  */
    75 class ContentClient : public CompositableClient
    76 {
    77 public:
    78   /**
    79    * Creates, configures, and returns a new content client. If necessary, a
    80    * message will be sent to the compositor to create a corresponding content
    81    * host.
    82    */
    83   static TemporaryRef<ContentClient> CreateContentClient(CompositableForwarder* aFwd);
    85   ContentClient(CompositableForwarder* aForwarder)
    86   : CompositableClient(aForwarder)
    87   {}
    88   virtual ~ContentClient()
    89   {}
    92   virtual void Clear() = 0;
    93   virtual RotatedContentBuffer::PaintState BeginPaintBuffer(ThebesLayer* aLayer,
    94                                                             uint32_t aFlags) = 0;
    95   virtual gfx::DrawTarget* BorrowDrawTargetForPainting(const RotatedContentBuffer::PaintState& aPaintState,
    96                                                        RotatedContentBuffer::DrawIterator* aIter = nullptr) = 0;
    97   virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) = 0;
    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   virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) {}
   104   // call before and after painting into this content client
   105   virtual void BeginPaint() {}
   106   virtual void EndPaint();
   107 };
   109 /**
   110  * A ContentClient for use with OMTC.
   111  */
   112 class ContentClientRemote : public ContentClient
   113 {
   114 public:
   115   ContentClientRemote(CompositableForwarder* aForwarder)
   116     : ContentClient(aForwarder)
   117   {}
   119   virtual void Updated(const nsIntRegion& aRegionToDraw,
   120                        const nsIntRegion& aVisibleRegion,
   121                        bool aDidSelfCopy) = 0;
   122 };
   124 // thin wrapper around RotatedContentBuffer, for on-mtc
   125 class ContentClientBasic : public ContentClient
   126                          , protected RotatedContentBuffer
   127 {
   128 public:
   129   ContentClientBasic();
   131   typedef RotatedContentBuffer::PaintState PaintState;
   132   typedef RotatedContentBuffer::ContentType ContentType;
   134   virtual void Clear() { RotatedContentBuffer::Clear(); }
   135   virtual PaintState BeginPaintBuffer(ThebesLayer* aLayer,
   136                                       uint32_t aFlags) MOZ_OVERRIDE
   137   {
   138     return RotatedContentBuffer::BeginPaint(aLayer, aFlags);
   139   }
   140   virtual gfx::DrawTarget* BorrowDrawTargetForPainting(const PaintState& aPaintState,
   141                                                        RotatedContentBuffer::DrawIterator* aIter = nullptr) MOZ_OVERRIDE
   142   {
   143     return RotatedContentBuffer::BorrowDrawTargetForPainting(aPaintState, aIter);
   144   }
   145   virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) MOZ_OVERRIDE
   146   {
   147     BorrowDrawTarget::ReturnDrawTarget(aReturned);
   148   }
   150   void DrawTo(ThebesLayer* aLayer,
   151               gfx::DrawTarget* aTarget,
   152               float aOpacity,
   153               gfx::CompositionOp aOp,
   154               gfx::SourceSurface* aMask,
   155               const gfx::Matrix* aMaskTransform)
   156   {
   157     RotatedContentBuffer::DrawTo(aLayer, aTarget, aOpacity, aOp,
   158                                  aMask, aMaskTransform);
   159   }
   161   virtual void CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags,
   162                             RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) MOZ_OVERRIDE;
   164   virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
   165   {
   166     MOZ_CRASH("Should not be called on non-remote ContentClient");
   167   }
   168 };
   170 /**
   171  * A ContentClientRemote backed by a RotatedContentBuffer.
   172  *
   173  * When using a ContentClientRemote, SurfaceDescriptors are created on
   174  * the rendering side and destroyed on the compositing side. They are only
   175  * passed from one side to the other when the TextureClient/Hosts are created.
   176  * *Ownership* of the SurfaceDescriptor moves from the rendering side to the
   177  * compositing side with the create message (send from CreateBuffer) which
   178  * tells the compositor that TextureClients have been created and that the
   179  * compositor should assign the corresponding TextureHosts to our corresponding
   180  * ContentHost.
   181  *
   182  * If the size or type of our buffer(s) change(s), then we simply destroy and
   183  * create them.
   184  */
   185 // Version using new texture clients
   186 class ContentClientRemoteBuffer : public ContentClientRemote
   187                                 , protected RotatedContentBuffer
   188 {
   189   using RotatedContentBuffer::BufferRect;
   190   using RotatedContentBuffer::BufferRotation;
   191 public:
   192   ContentClientRemoteBuffer(CompositableForwarder* aForwarder)
   193     : ContentClientRemote(aForwarder)
   194     , RotatedContentBuffer(ContainsVisibleBounds)
   195     , mIsNewBuffer(false)
   196     , mFrontAndBackBufferDiffer(false)
   197     , mSurfaceFormat(gfx::SurfaceFormat::B8G8R8A8)
   198   {}
   200   typedef RotatedContentBuffer::PaintState PaintState;
   201   typedef RotatedContentBuffer::ContentType ContentType;
   203   virtual void Clear()
   204   {
   205     RotatedContentBuffer::Clear();
   206     mTextureClient = nullptr;
   207     mTextureClientOnWhite = nullptr;
   208   }
   210   virtual PaintState BeginPaintBuffer(ThebesLayer* aLayer,
   211                                       uint32_t aFlags) MOZ_OVERRIDE
   212   {
   213     return RotatedContentBuffer::BeginPaint(aLayer, aFlags);
   214   }
   215   virtual gfx::DrawTarget* BorrowDrawTargetForPainting(const PaintState& aPaintState,
   216                                                        RotatedContentBuffer::DrawIterator* aIter = nullptr) MOZ_OVERRIDE
   217   {
   218     return RotatedContentBuffer::BorrowDrawTargetForPainting(aPaintState, aIter);
   219   }
   220   virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) MOZ_OVERRIDE
   221   {
   222     BorrowDrawTarget::ReturnDrawTarget(aReturned);
   223   }
   225   /**
   226    * Begin/End Paint map a gfxASurface from the texture client
   227    * into the buffer of RotatedBuffer. The surface is only
   228    * valid when the texture client is locked, so is mapped out
   229    * of RotatedContentBuffer when we are done painting.
   230    * None of the underlying buffer attributes (rect, rotation)
   231    * are affected by mapping/unmapping.
   232    */
   233   virtual void BeginPaint() MOZ_OVERRIDE;
   234   virtual void EndPaint() MOZ_OVERRIDE;
   236   virtual void Updated(const nsIntRegion& aRegionToDraw,
   237                        const nsIntRegion& aVisibleRegion,
   238                        bool aDidSelfCopy);
   240   virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) MOZ_OVERRIDE;
   242   // Expose these protected methods from the superclass.
   243   virtual const nsIntRect& BufferRect() const
   244   {
   245     return RotatedContentBuffer::BufferRect();
   246   }
   247   virtual const nsIntPoint& BufferRotation() const
   248   {
   249     return RotatedContentBuffer::BufferRotation();
   250   }
   252   virtual void CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags,
   253                             RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) MOZ_OVERRIDE;
   255   virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
   256   {
   257     return mTextureInfo;
   258   }
   260 protected:
   261   void DestroyBuffers();
   263   virtual nsIntRegion GetUpdatedRegion(const nsIntRegion& aRegionToDraw,
   264                                        const nsIntRegion& aVisibleRegion,
   265                                        bool aDidSelfCopy);
   267   void BuildTextureClients(gfx::SurfaceFormat aFormat,
   268                            const nsIntRect& aRect,
   269                            uint32_t aFlags);
   271   // Create the front buffer for the ContentClient/Host pair if necessary
   272   // and notify the compositor that we have created the buffer(s).
   273   virtual void CreateFrontBuffer(const nsIntRect& aBufferRect) = 0;
   274   virtual void DestroyFrontBuffer() {}
   276   bool CreateAndAllocateTextureClient(RefPtr<TextureClient>& aClient,
   277                                       TextureFlags aFlags = 0);
   279   virtual void AbortTextureClientCreation()
   280   {
   281     mTextureClient = nullptr;
   282     mTextureClientOnWhite = nullptr;
   283     mIsNewBuffer = false;
   284   }
   286   RefPtr<TextureClient> mTextureClient;
   287   RefPtr<TextureClient> mTextureClientOnWhite;
   288   // keep a record of texture clients we have created and need to keep around
   289   // (for RotatedBuffer to access), then unlock and remove them when we are done
   290   // painting.
   291   nsTArray<RefPtr<TextureClient> > mOldTextures;
   293   TextureInfo mTextureInfo;
   294   bool mIsNewBuffer;
   295   bool mFrontAndBackBufferDiffer;
   296   gfx::IntSize mSize;
   297   gfx::SurfaceFormat mSurfaceFormat;
   298 };
   300 /**
   301  * A double buffered ContentClient. mTextureClient is the back buffer, which
   302  * we draw into. mFrontClient is the front buffer which we may read from, but
   303  * not write to, when the compositor does not have the 'soft' lock. We can write
   304  * into mTextureClient at any time.
   305  *
   306  * The ContentHost keeps a reference to both corresponding texture hosts, in
   307  * response to our UpdateTextureRegion message, the compositor swaps its
   308  * references. In response to the compositor's reply we swap our references
   309  * (in SwapBuffers).
   310  */
   311 class ContentClientDoubleBuffered : public ContentClientRemoteBuffer
   312 {
   313 public:
   314   ContentClientDoubleBuffered(CompositableForwarder* aFwd)
   315     : ContentClientRemoteBuffer(aFwd)
   316   {
   317     mTextureInfo.mCompositableType = COMPOSITABLE_CONTENT_DOUBLE;
   318   }
   319   virtual ~ContentClientDoubleBuffered() {}
   321   virtual void Clear() MOZ_OVERRIDE
   322   {
   323     ContentClientRemoteBuffer::Clear();
   324     mFrontClient = nullptr;
   325     mFrontClientOnWhite = nullptr;
   326   }
   328   virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) MOZ_OVERRIDE;
   330   virtual void BeginPaint() MOZ_OVERRIDE;
   332   virtual void FinalizeFrame(const nsIntRegion& aRegionToDraw) MOZ_OVERRIDE;
   334 protected:
   335   virtual void CreateFrontBuffer(const nsIntRect& aBufferRect) MOZ_OVERRIDE;
   336   virtual void DestroyFrontBuffer() MOZ_OVERRIDE;
   338 private:
   339   void UpdateDestinationFrom(const RotatedBuffer& aSource,
   340                              const nsIntRegion& aUpdateRegion);
   342   virtual void AbortTextureClientCreation() MOZ_OVERRIDE
   343   {
   344     mTextureClient = nullptr;
   345     mTextureClientOnWhite = nullptr;
   346     mFrontClient = nullptr;
   347     mFrontClientOnWhite = nullptr;
   348   }
   350   RefPtr<TextureClient> mFrontClient;
   351   RefPtr<TextureClient> mFrontClientOnWhite;
   352   nsIntRegion mFrontUpdatedRegion;
   353   nsIntRect mFrontBufferRect;
   354   nsIntPoint mFrontBufferRotation;
   355 };
   357 /**
   358  * A single buffered ContentClient. We have a single TextureClient/Host
   359  * which we update and then send a message to the compositor that we are
   360  * done updating. It is not safe for the compositor to use the corresponding
   361  * TextureHost's memory directly, it must upload it to video memory of some
   362  * kind. We are free to modify the TextureClient once we receive reply from
   363  * the compositor.
   364  */
   365 class ContentClientSingleBuffered : public ContentClientRemoteBuffer
   366 {
   367 public:
   368   ContentClientSingleBuffered(CompositableForwarder* aFwd)
   369     : ContentClientRemoteBuffer(aFwd)
   370   {
   371     mTextureInfo.mCompositableType = COMPOSITABLE_CONTENT_SINGLE;
   372   }
   373   virtual ~ContentClientSingleBuffered() {}
   375   virtual void FinalizeFrame(const nsIntRegion& aRegionToDraw) MOZ_OVERRIDE;
   377 protected:
   378   virtual void CreateFrontBuffer(const nsIntRect& aBufferRect) MOZ_OVERRIDE {}
   379 };
   381 /**
   382  * A single buffered ContentClient that creates temporary buffers which are
   383  * used to update the host-side texture. The ownership of the buffers is
   384  * passed to the host side during the transaction, and we need to create
   385  * new ones each frame.
   386  */
   387 class ContentClientIncremental : public ContentClientRemote
   388                                , public BorrowDrawTarget
   389 {
   390 public:
   391   ContentClientIncremental(CompositableForwarder* aFwd)
   392     : ContentClientRemote(aFwd)
   393     , mContentType(gfxContentType::COLOR_ALPHA)
   394     , mHasBuffer(false)
   395     , mHasBufferOnWhite(false)
   396   {
   397     mTextureInfo.mCompositableType = BUFFER_CONTENT_INC;
   398   }
   400   typedef RotatedContentBuffer::PaintState PaintState;
   401   typedef RotatedContentBuffer::ContentType ContentType;
   403   virtual TextureInfo GetTextureInfo() const
   404   {
   405     return mTextureInfo;
   406   }
   408   virtual void Clear()
   409   {
   410     mBufferRect.SetEmpty();
   411     mHasBuffer = false;
   412     mHasBufferOnWhite = false;
   413   }
   415   virtual PaintState BeginPaintBuffer(ThebesLayer* aLayer,
   416                                       uint32_t aFlags) MOZ_OVERRIDE;
   417   virtual gfx::DrawTarget* BorrowDrawTargetForPainting(const PaintState& aPaintState,
   418                                                        RotatedContentBuffer::DrawIterator* aIter = nullptr) MOZ_OVERRIDE;
   419   virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) MOZ_OVERRIDE
   420   {
   421     BorrowDrawTarget::ReturnDrawTarget(aReturned);
   422   }
   424   virtual void Updated(const nsIntRegion& aRegionToDraw,
   425                        const nsIntRegion& aVisibleRegion,
   426                        bool aDidSelfCopy);
   428   virtual void EndPaint()
   429   {
   430     if (IsSurfaceDescriptorValid(mUpdateDescriptor)) {
   431       mForwarder->DestroySharedSurface(&mUpdateDescriptor);
   432     }
   433     if (IsSurfaceDescriptorValid(mUpdateDescriptorOnWhite)) {
   434       mForwarder->DestroySharedSurface(&mUpdateDescriptorOnWhite);
   435     }
   436     ContentClientRemote::EndPaint();
   437   }
   439 private:
   441   enum BufferType{
   442     BUFFER_BLACK,
   443     BUFFER_WHITE
   444   };
   446   void NotifyBufferCreated(ContentType aType, uint32_t aFlags)
   447   {
   448     mTextureInfo.mTextureFlags = aFlags & ~TEXTURE_DEALLOCATE_CLIENT;
   449     mContentType = aType;
   451     mForwarder->CreatedIncrementalBuffer(this,
   452                                          mTextureInfo,
   453                                          mBufferRect);
   455   }
   457   TemporaryRef<gfx::DrawTarget> GetUpdateSurface(BufferType aType,
   458                                                  const nsIntRegion& aUpdateRegion);
   460   TextureInfo mTextureInfo;
   461   nsIntRect mBufferRect;
   462   nsIntPoint mBufferRotation;
   464   SurfaceDescriptor mUpdateDescriptor;
   465   SurfaceDescriptor mUpdateDescriptorOnWhite;
   467   ContentType mContentType;
   469   bool mHasBuffer;
   470   bool mHasBufferOnWhite;
   471 };
   473 }
   474 }
   476 #endif

mercurial