gfx/layers/Compositor.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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_COMPOSITOR_H
     7 #define MOZILLA_GFX_COMPOSITOR_H
     9 #include "Units.h"                      // for ScreenPoint
    10 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
    11 #include "mozilla/RefPtr.h"             // for TemporaryRef, RefCounted
    12 #include "mozilla/gfx/Point.h"          // for IntSize, Point
    13 #include "mozilla/gfx/Rect.h"           // for Rect, IntRect
    14 #include "mozilla/gfx/Types.h"          // for Float
    15 #include "mozilla/layers/CompositorTypes.h"  // for DiagnosticTypes, etc
    16 #include "mozilla/layers/LayersTypes.h"  // for LayersBackend
    17 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
    18 #include "nsRegion.h"
    19 #include <vector>
    20 #include "mozilla/WidgetUtils.h"
    22 /**
    23  * Different elements of a web pages are rendered into separate "layers" before
    24  * they are flattened into the final image that is brought to the screen.
    25  * See Layers.h for more informations about layers and why we use retained
    26  * structures.
    27  * Most of the documentation for layers is directly in the source code in the
    28  * form of doc comments. An overview can also be found in the the wiki:
    29  * https://wiki.mozilla.org/Gecko:Overview#Graphics
    30  *
    31  *
    32  * # Main interfaces and abstractions
    33  *
    34  *  - Layer, ShadowableLayer and LayerComposite
    35  *    (see Layers.h and ipc/ShadowLayers.h)
    36  *  - CompositableClient and CompositableHost
    37  *    (client/CompositableClient.h composite/CompositableHost.h)
    38  *  - TextureClient and TextureHost
    39  *    (client/TextureClient.h composite/TextureHost.h)
    40  *  - TextureSource
    41  *    (composite/TextureHost.h)
    42  *  - Forwarders
    43  *    (ipc/CompositableForwarder.h ipc/ShadowLayers.h)
    44  *  - Compositor
    45  *    (this file)
    46  *  - IPDL protocols
    47  *    (.ipdl files under the gfx/layers/ipc directory)
    48  *
    49  * The *Client and Shadowable* classes are always used on the content thread.
    50  * Forwarders are always used on the content thread.
    51  * The *Host and Shadow* classes are always used on the compositor thread.
    52  * Compositors, TextureSource, and Effects are always used on the compositor
    53  * thread.
    54  * Most enums and constants are declared in LayersTypes.h and CompositorTypes.h.
    55  *
    56  *
    57  * # Texture transfer
    58  *
    59  * Most layer classes own a Compositable plus some extra information like
    60  * transforms and clip rects. They are platform independent.
    61  * Compositable classes manipulate Texture objects and are reponsible for
    62  * things like tiling, buffer rotation or double buffering. Compositables
    63  * are also platform-independent. Examples of compositable classes are:
    64  *  - ImageClient
    65  *  - CanvasClient
    66  *  - ContentHost
    67  *  - etc.
    68  * Texture classes (TextureClient and TextureHost) are thin abstractions over
    69  * platform-dependent texture memory. They are maniplulated by compositables
    70  * and don't know about buffer rotations and such. The purposes of TextureClient
    71  * and TextureHost are to synchronize, serialize and deserialize texture data.
    72  * TextureHosts provide access to TextureSources that are views on the
    73  * Texture data providing the necessary api for Compositor backend to composite
    74  * them.
    75  *
    76  * Compositable and Texture clients and hosts are created using factory methods.
    77  * They should only be created by using their constructor in exceptional
    78  * circumstances. The factory methods are located:
    79  *    TextureClient       - CompositableClient::CreateTextureClient
    80  *    TextureHost         - TextureHost::CreateTextureHost, which calls a
    81  *                          platform-specific function, e.g., CreateTextureHostOGL
    82  *    CompositableClient  - in the appropriate subclass, e.g.,
    83  *                          CanvasClient::CreateCanvasClient
    84  *    CompositableHost    - CompositableHost::Create
    85  *
    86  *
    87  * # IPDL
    88  *
    89  * If off-main-thread compositing (OMTC) is enabled, compositing is performed
    90  * in a dedicated thread. In some setups compositing happens in a dedicated
    91  * process. Documentation may refer to either the compositor thread or the
    92  * compositor process.
    93  * See explanations in ShadowLayers.h.
    94  *
    95  *
    96  * # Backend implementations
    97  *
    98  * Compositor backends like OpenGL or flavours of D3D live in their own directory
    99  * under gfx/layers/. To add a new backend, implement at least the following
   100  * interfaces:
   101  * - Compositor (ex. CompositorOGL)
   102  * - TextureHost (ex. SharedTextureHostOGL)
   103  * Depending on the type of data that needs to be serialized, you may need to
   104  * add specific TextureClient implementations.
   105  */
   107 class nsIWidget;
   108 struct nsIntSize;
   109 class nsIntRegion;
   111 namespace mozilla {
   112 namespace gfx {
   113 class Matrix;
   114 class Matrix4x4;
   115 class DrawTarget;
   116 }
   118 namespace layers {
   120 struct Effect;
   121 struct EffectChain;
   122 class Image;
   123 class ISurfaceAllocator;
   124 class Layer;
   125 class NewTextureSource;
   126 class DataTextureSource;
   127 class CompositingRenderTarget;
   128 class PCompositorParent;
   129 class LayerManagerComposite;
   131 enum SurfaceInitMode
   132 {
   133   INIT_MODE_NONE,
   134   INIT_MODE_CLEAR
   135 };
   137 /**
   138  * A base class for a platform-dependent helper for use by TextureHost.
   139  */
   140 class CompositorBackendSpecificData
   141 {
   142   NS_INLINE_DECL_REFCOUNTING(CompositorBackendSpecificData)
   144 protected:
   145   virtual ~CompositorBackendSpecificData() {}
   146 };
   148 /**
   149  * Common interface for compositor backends.
   150  *
   151  * Compositor provides a cross-platform interface to a set of operations for
   152  * compositing quads. Compositor knows nothing about the layer tree. It must be
   153  * told everything about each composited quad - contents, location, transform,
   154  * opacity, etc.
   155  *
   156  * In theory it should be possible for different widgets to use the same
   157  * compositor. In practice, we use one compositor per window.
   158  *
   159  * # Usage
   160  *
   161  * For an example of a user of Compositor, see LayerManagerComposite.
   162  *
   163  * Initialization: create a Compositor object, call Initialize().
   164  *
   165  * Destruction: destroy any resources associated with the compositor, call
   166  * Destroy(), delete the Compositor object.
   167  *
   168  * Composition:
   169  *  call BeginFrame,
   170  *  for each quad to be composited:
   171  *    call MakeCurrent if necessary (not necessary if no other context has been
   172  *      made current),
   173  *    take care of any texture upload required to composite the quad, this step
   174  *      is backend-dependent,
   175  *    construct an EffectChain for the quad,
   176  *    call DrawQuad,
   177  *  call EndFrame.
   178  * If the user has to stop compositing at any point before EndFrame, call
   179  * AbortFrame.
   180  * If the compositor is usually used for compositing but compositing is
   181  * temporarily done without the compositor, call EndFrameForExternalComposition
   182  * after compositing each frame so the compositor can remain internally
   183  * consistent.
   184  *
   185  * By default, the compositor will render to the screen, to render to a target,
   186  * call SetTargetContext or SetRenderTarget, the latter with a target created
   187  * by CreateRenderTarget or CreateRenderTargetFromSource.
   188  *
   189  * The target and viewport methods can be called before any DrawQuad call and
   190  * affect any subsequent DrawQuad calls.
   191  */
   192 class Compositor
   193 {
   194 protected:
   195   virtual ~Compositor() {}
   197 public:
   198   NS_INLINE_DECL_REFCOUNTING(Compositor)
   200   Compositor(PCompositorParent* aParent = nullptr)
   201     : mCompositorID(0)
   202     , mDiagnosticTypes(DIAGNOSTIC_NONE)
   203     , mParent(aParent)
   204     , mScreenRotation(ROTATION_0)
   205   {
   206   }
   208   virtual TemporaryRef<DataTextureSource> CreateDataTextureSource(TextureFlags aFlags = 0) = 0;
   209   virtual bool Initialize() = 0;
   210   virtual void Destroy() = 0;
   212   /**
   213    * Return true if the effect type is supported.
   214    *
   215    * By default Compositor implementations should support all effects but in
   216    * some rare cases it is not possible to support an effect efficiently.
   217    * This is the case for BasicCompositor with EffectYCbCr.
   218    */
   219   virtual bool SupportsEffect(EffectTypes aEffect) { return true; }
   221   /**
   222    * Request a texture host identifier that may be used for creating textures
   223    * across process or thread boundaries that are compatible with this
   224    * compositor.
   225    */
   226   virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() = 0;
   228   /**
   229    * Properties of the compositor.
   230    */
   231   virtual bool CanUseCanvasLayerForSize(const gfx::IntSize& aSize) = 0;
   232   virtual int32_t GetMaxTextureSize() const = 0;
   234   /**
   235    * Set the target for rendering. Results will have been written to aTarget by
   236    * the time that EndFrame returns.
   237    *
   238    * If this method is not used, or we pass in nullptr, we target the compositor's
   239    * usual swap chain and render to the screen.
   240    */
   241   virtual void SetTargetContext(gfx::DrawTarget* aTarget) = 0;
   243   typedef uint32_t MakeCurrentFlags;
   244   static const MakeCurrentFlags ForceMakeCurrent = 0x1;
   245   /**
   246    * Make this compositor's rendering context the current context for the
   247    * underlying graphics API. This may be a global operation, depending on the
   248    * API. Our context will remain the current one until someone else changes it.
   249    *
   250    * Clients of the compositor should call this at the start of the compositing
   251    * process, it might be required by texture uploads etc.
   252    *
   253    * If aFlags == ForceMakeCurrent then we will (re-)set our context on the
   254    * underlying API even if it is already the current context.
   255    */
   256   virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) = 0;
   258   /**
   259    * Creates a Surface that can be used as a rendering target by this
   260    * compositor.
   261    */
   262   virtual TemporaryRef<CompositingRenderTarget>
   263   CreateRenderTarget(const gfx::IntRect& aRect, SurfaceInitMode aInit) = 0;
   265   /**
   266    * Creates a Surface that can be used as a rendering target by this
   267    * compositor, and initializes the surface by copying from aSource.
   268    * If aSource is null, then the current screen buffer is used as source.
   269    *
   270    * aSourcePoint specifies the point in aSource to copy data from.
   271    */
   272   virtual TemporaryRef<CompositingRenderTarget>
   273   CreateRenderTargetFromSource(const gfx::IntRect& aRect,
   274                                const CompositingRenderTarget* aSource,
   275                                const gfx::IntPoint& aSourcePoint) = 0;
   277   /**
   278    * Sets the given surface as the target for subsequent calls to DrawQuad.
   279    * Passing null as aSurface sets the screen as the target.
   280    */
   281   virtual void SetRenderTarget(CompositingRenderTarget* aSurface) = 0;
   283   /**
   284    * Returns the current target for rendering. Will return null if we are
   285    * rendering to the screen.
   286    */
   287   virtual CompositingRenderTarget* GetCurrentRenderTarget() const = 0;
   289   /**
   290    * Mostly the compositor will pull the size from a widget and this method will
   291    * be ignored, but compositor implementations are free to use it if they like.
   292    */
   293   virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) = 0;
   295   /**
   296    * Declare an offset to use when rendering layers. This will be ignored when
   297    * rendering to a target instead of the screen.
   298    */
   299   virtual void SetScreenRenderOffset(const ScreenPoint& aOffset) = 0;
   301   /**
   302    * Tell the compositor to draw a quad. What to do draw and how it is
   303    * drawn is specified by aEffectChain. aRect is the quad to draw, in user space.
   304    * aTransform transforms from user space to screen space. If texture coords are
   305    * required, these will be in the primary effect in the effect chain.
   306    */
   307   virtual void DrawQuad(const gfx::Rect& aRect, const gfx::Rect& aClipRect,
   308                         const EffectChain& aEffectChain,
   309                         gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform) = 0;
   311   /**
   312    * Tell the compositor to draw lines connecting the points. Behaves like
   313    * DrawQuad.
   314    */
   315   virtual void DrawLines(const std::vector<gfx::Point>& aLines, const gfx::Rect& aClipRect,
   316                          const gfx::Color& aColor,
   317                          gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform)
   318   { /* Should turn into pure virtual once implemented in D3D */ }
   320   /*
   321    * Clear aRect on current render target.
   322    */
   323   virtual void ClearRect(const gfx::Rect& aRect) { }
   325   /**
   326    * Start a new frame.
   327    *
   328    * aInvalidRect is the invalid region of the screen; it can be ignored for
   329    * compositors where the performance for compositing the entire window is
   330    * sufficient.
   331    *
   332    * aClipRectIn is the clip rect for the window in window space (optional).
   333    * aTransform is the transform from user space to window space.
   334    * aRenderBounds bounding rect for rendering, in user space.
   335    *
   336    * If aClipRectIn is null, this method sets *aClipRectOut to the clip rect
   337    * actually used for rendering (if aClipRectIn is non-null, we will use that
   338    * for the clip rect).
   339    *
   340    * If aRenderBoundsOut is non-null, it will be set to the render bounds
   341    * actually used by the compositor in window space. If aRenderBoundsOut
   342    * is returned empty, composition should be aborted.
   343    */
   344   virtual void BeginFrame(const nsIntRegion& aInvalidRegion,
   345                           const gfx::Rect* aClipRectIn,
   346                           const gfx::Matrix& aTransform,
   347                           const gfx::Rect& aRenderBounds,
   348                           gfx::Rect* aClipRectOut = nullptr,
   349                           gfx::Rect* aRenderBoundsOut = nullptr) = 0;
   351   /**
   352    * Flush the current frame to the screen and tidy up.
   353    */
   354   virtual void EndFrame() = 0;
   356   virtual void SetFBAcquireFence(Layer* aLayer) {}
   358   /**
   359    * Post-rendering stuff if the rendering is done outside of this Compositor
   360    * e.g., by Composer2D.
   361    * aTransform is the transform from user space to window space.
   362    */
   363   virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) = 0;
   365   /**
   366    * Tidy up if BeginFrame has been called, but EndFrame won't be.
   367    */
   368   virtual void AbortFrame() = 0;
   370   /**
   371    * Setup the viewport and projection matrix for rendering to a target of the
   372    * given dimensions. The size and transform here will override those set in
   373    * BeginFrame. BeginFrame sets a size and transform for the default render
   374    * target, usually the screen. Calling this method prepares the compositor to
   375    * render using a different viewport (that is, size and transform), usually
   376    * associated with a new render target.
   377    * aWorldTransform is the transform from user space to the new viewport's
   378    * coordinate space.
   379    */
   380   virtual void PrepareViewport(const gfx::IntSize& aSize,
   381                                const gfx::Matrix& aWorldTransform) = 0;
   383   /**
   384    * Whether textures created by this compositor can receive partial updates.
   385    */
   386   virtual bool SupportsPartialTextureUpdate() = 0;
   388   void SetDiagnosticTypes(DiagnosticTypes aDiagnostics)
   389   {
   390     mDiagnosticTypes = aDiagnostics;
   391   }
   393   DiagnosticTypes GetDiagnosticTypes() const
   394   {
   395     return mDiagnosticTypes;
   396   }
   398   void DrawDiagnostics(DiagnosticFlags aFlags,
   399                        const gfx::Rect& visibleRect,
   400                        const gfx::Rect& aClipRect,
   401                        const gfx::Matrix4x4& transform,
   402                        uint32_t aFlashCounter = DIAGNOSTIC_FLASH_COUNTER_MAX);
   404   void DrawDiagnostics(DiagnosticFlags aFlags,
   405                        const nsIntRegion& visibleRegion,
   406                        const gfx::Rect& aClipRect,
   407                        const gfx::Matrix4x4& transform,
   408                        uint32_t aFlashCounter = DIAGNOSTIC_FLASH_COUNTER_MAX);
   410 #ifdef MOZ_DUMP_PAINTING
   411   virtual const char* Name() const = 0;
   412 #endif // MOZ_DUMP_PAINTING
   414   virtual LayersBackend GetBackendType() const = 0;
   416   /**
   417    * Each Compositor has a unique ID.
   418    * This ID is used to keep references to each Compositor in a map accessed
   419    * from the compositor thread only, so that async compositables can find
   420    * the right compositor parent and schedule compositing even if the compositor
   421    * changed.
   422    */
   423   uint32_t GetCompositorID() const
   424   {
   425     return mCompositorID;
   426   }
   427   void SetCompositorID(uint32_t aID)
   428   {
   429     MOZ_ASSERT(mCompositorID == 0, "The compositor ID must be set only once.");
   430     mCompositorID = aID;
   431   }
   433   /**
   434    * Notify the compositor that composition is being paused. This allows the
   435    * compositor to temporarily release any resources.
   436    * Between calling Pause and Resume, compositing may fail.
   437    */
   438   virtual void Pause() {}
   439   /**
   440    * Notify the compositor that composition is being resumed. The compositor
   441    * regain any resources it requires for compositing.
   442    * Returns true if succeeded.
   443    */
   444   virtual bool Resume() { return true; }
   446   /**
   447    * Call before rendering begins to ensure the compositor is ready to
   448    * composite. Returns false if rendering should be aborted.
   449    */
   450   virtual bool Ready() { return true; }
   452   // XXX I expect we will want to move mWidget into this class and implement
   453   // these methods properly.
   454   virtual nsIWidget* GetWidget() const { return nullptr; }
   456   /**
   457    * Debug-build assertion that can be called to ensure code is running on the
   458    * compositor thread.
   459    */
   460   static void AssertOnCompositorThread();
   462   /**
   463    * We enforce that there can only be one Compositor backend type off the main
   464    * thread at the same time. The backend type in use can be checked with this
   465    * static method. We need this for creating texture clients/hosts etc. when we
   466    * don't have a reference to a Compositor.
   467    *
   468    * This can only be used from the compositor thread!
   469    */
   470   static LayersBackend GetBackend();
   472   size_t GetFillRatio() {
   473     float fillRatio = 0;
   474     if (mPixelsFilled > 0 && mPixelsPerFrame > 0) {
   475       fillRatio = 100.0f * float(mPixelsFilled) / float(mPixelsPerFrame);
   476       if (fillRatio > 999.0f) {
   477         fillRatio = 999.0f;
   478       }
   479     }
   480     return fillRatio;
   481   }
   483   virtual CompositorBackendSpecificData* GetCompositorBackendSpecificData() {
   484     return nullptr;
   485   }
   487   ScreenRotation GetScreenRotation() const {
   488     return mScreenRotation;
   489   }
   491   void SetScreenRotation(ScreenRotation aRotation) {
   492     mScreenRotation = aRotation;
   493   }
   495   // On b2g the clip rect is in the coordinate space of the physical screen
   496   // independently of its rotation, while the coordinate space of the layers,
   497   // on the other hand, depends on the screen orientation.
   498   // This only applies to b2g as with other platforms, orientation is handled
   499   // at the OS level rather than in Gecko.
   500   // In addition, the clip rect needs to be offset by the rendering origin.
   501   // This becomes important if intermediate surfaces are used.
   502   gfx::Rect ClipRectInLayersCoordinates(gfx::Rect aClip) const;
   504 protected:
   505   void DrawDiagnosticsInternal(DiagnosticFlags aFlags,
   506                                const gfx::Rect& aVisibleRect,
   507                                const gfx::Rect& aClipRect,
   508                                const gfx::Matrix4x4& transform,
   509                                uint32_t aFlashCounter);
   511   bool ShouldDrawDiagnostics(DiagnosticFlags);
   513   /**
   514    * Set the global Compositor backend, checking that one isn't already set.
   515    */
   516   static void SetBackend(LayersBackend backend);
   518   uint32_t mCompositorID;
   519   DiagnosticTypes mDiagnosticTypes;
   520   PCompositorParent* mParent;
   522   /**
   523    * We keep track of the total number of pixels filled as we composite the
   524    * current frame. This value is an approximation and is not accurate,
   525    * especially in the presence of transforms.
   526    */
   527   size_t mPixelsPerFrame;
   528   size_t mPixelsFilled;
   530   ScreenRotation mScreenRotation;
   532   virtual gfx::IntSize GetWidgetSize() const = 0;
   534 private:
   535   static LayersBackend sBackend;
   537 };
   539 } // namespace layers
   540 } // namespace mozilla
   542 #endif /* MOZILLA_GFX_COMPOSITOR_H */

mercurial