tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Compositor.h (15143B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef MOZILLA_GFX_COMPOSITOR_H
      8 #define MOZILLA_GFX_COMPOSITOR_H
      9 
     10 #include "Units.h"                           // for ScreenPoint
     11 #include "mozilla/Assertions.h"              // for MOZ_ASSERT, etc
     12 #include "mozilla/gfx/2D.h"                  // for DrawTarget
     13 #include "mozilla/gfx/MatrixFwd.h"           // for Matrix, Matrix4x4
     14 #include "mozilla/gfx/Point.h"               // for IntSize, Point
     15 #include "mozilla/gfx/Polygon.h"             // for Polygon
     16 #include "mozilla/gfx/Rect.h"                // for Rect, IntRect
     17 #include "mozilla/gfx/Types.h"               // for Float
     18 #include "mozilla/gfx/Triangle.h"            // for Triangle, TexturedTriangle
     19 #include "mozilla/layers/CompositorTypes.h"  // for DiagnosticTypes, etc
     20 #include "mozilla/layers/LayersTypes.h"      // for LayersBackend
     21 #include "mozilla/layers/SurfacePool.h"      // for SurfacePoolHandle
     22 #include "mozilla/layers/TextureSourceProvider.h"
     23 #include "mozilla/widget/CompositorWidget.h"
     24 #include "nsISupportsImpl.h"  // for MOZ_COUNT_CTOR, etc
     25 #include "nsRegion.h"
     26 #include "mozilla/WidgetUtils.h"
     27 
     28 /**
     29 * Different elements of a web pages are rendered into separate "layers" before
     30 * they are flattened into the final image that is brought to the screen.
     31 * See Layers.h for more informations about layers and why we use retained
     32 * structures.
     33 * Most of the documentation for layers is directly in the source code in the
     34 * form of doc comments. An overview can also be found in the the wiki:
     35 * https://wiki.mozilla.org/Gecko:Overview#Graphics
     36 *
     37 *
     38 * # Main interfaces and abstractions
     39 *
     40 *  - CompositableClient and CompositableHost
     41 *    (client/CompositableClient.h composite/CompositableHost.h)
     42 *  - TextureClient and TextureHost
     43 *    (client/TextureClient.h composite/TextureHost.h)
     44 *  - TextureSource
     45 *    (composite/TextureHost.h)
     46 *  - Forwarders
     47 *    (ipc/CompositableForwarder.h ipc/ShadowLayers.h)
     48 *  - Compositor
     49 *    (this file)
     50 *  - IPDL protocols
     51 *    (.ipdl files under the gfx/layers/ipc directory)
     52 *
     53 * The *Client and Shadowable* classes are always used on the content thread.
     54 * Forwarders are always used on the content thread.
     55 * The *Host and Shadow* classes are always used on the compositor thread.
     56 * Compositors, TextureSource, and Effects are always used on the compositor
     57 * thread.
     58 * Most enums and constants are declared in LayersTypes.h and CompositorTypes.h.
     59 *
     60 *
     61 * # Texture transfer
     62 *
     63 * Most layer classes own a Compositable plus some extra information like
     64 * transforms and clip rects. They are platform independent.
     65 * Compositable classes manipulate Texture objects and are reponsible for
     66 * things like tiling, buffer rotation or double buffering. Compositables
     67 * are also platform-independent. Examples of compositable classes are:
     68 *  - ImageClient
     69 *  - CanvasClient
     70 *  - etc.
     71 * Texture classes (TextureClient and TextureHost) are thin abstractions over
     72 * platform-dependent texture memory. They are maniplulated by compositables
     73 * and don't know about buffer rotations and such. The purposes of TextureClient
     74 * and TextureHost are to synchronize, serialize and deserialize texture data.
     75 * TextureHosts provide access to TextureSources that are views on the
     76 * Texture data providing the necessary api for Compositor backend to composite
     77 * them.
     78 *
     79 * Compositable and Texture clients and hosts are created using factory methods.
     80 * They should only be created by using their constructor in exceptional
     81 * circumstances. The factory methods are located:
     82 *    TextureClient       - CompositableClient::CreateTextureClient
     83 *    TextureHost         - TextureHost::CreateTextureHost, which calls a
     84 *                          platform-specific function, e.g.,
     85 * CreateTextureHostOGL CompositableClient  - in the appropriate subclass, e.g.,
     86 *                          CanvasClient::CreateCanvasClient
     87 *    CompositableHost    - CompositableHost::Create
     88 *
     89 *
     90 * # IPDL
     91 *
     92 * If off-main-thread compositing (OMTC) is enabled, compositing is performed
     93 * in a dedicated thread. In some setups compositing happens in a dedicated
     94 * process. Documentation may refer to either the compositor thread or the
     95 * compositor process.
     96 * See explanations in ShadowLayers.h.
     97 *
     98 *
     99 * # Backend implementations
    100 *
    101 * Compositor backends like OpenGL or flavours of D3D live in their own
    102 * directory under gfx/layers/. To add a new backend, implement at least the
    103 * following interfaces:
    104 * - Compositor (ex. CompositorOGL)
    105 * - TextureHost (ex. SurfaceTextureHost)
    106 * Depending on the type of data that needs to be serialized, you may need to
    107 * add specific TextureClient implementations.
    108 */
    109 
    110 class nsIWidget;
    111 
    112 namespace mozilla {
    113 namespace gfx {
    114 class DrawTarget;
    115 class DataSourceSurface;
    116 }  // namespace gfx
    117 
    118 namespace layers {
    119 
    120 struct Effect;
    121 struct EffectChain;
    122 class Image;
    123 class Layer;
    124 class TextureSource;
    125 class DataTextureSource;
    126 class CompositingRenderTarget;
    127 class CompositorBridgeParent;
    128 class NativeLayer;
    129 class CompositorOGL;
    130 class CompositorD3D11;
    131 class TextureReadLock;
    132 struct GPUStats;
    133 class AsyncReadbackBuffer;
    134 class RecordedFrame;
    135 
    136 enum SurfaceInitMode { INIT_MODE_NONE, INIT_MODE_CLEAR };
    137 
    138 /**
    139 * Common interface for compositor backends.
    140 *
    141 * Compositor provides a cross-platform interface to a set of operations for
    142 * compositing quads. Compositor knows nothing about the layer tree. It must be
    143 * told everything about each composited quad - contents, location, transform,
    144 * opacity, etc.
    145 *
    146 * In theory it should be possible for different widgets to use the same
    147 * compositor. In practice, we use one compositor per window.
    148 *
    149 * # Usage
    150 *
    151 * For an example of a user of Compositor, see LayerManagerComposite.
    152 *
    153 * Initialization: create a Compositor object, call Initialize().
    154 *
    155 * Destruction: destroy any resources associated with the compositor, call
    156 * Destroy(), delete the Compositor object.
    157 *
    158 * Composition:
    159 *  call BeginFrame,
    160 *  for each quad to be composited:
    161 *    call MakeCurrent if necessary (not necessary if no other context has been
    162 *      made current),
    163 *    take care of any texture upload required to composite the quad, this step
    164 *      is backend-dependent,
    165 *    construct an EffectChain for the quad,
    166 *    call DrawQuad,
    167 *  call EndFrame.
    168 *
    169 * By default, the compositor will render to the screen if BeginFrameForWindow
    170 * is called. To render to a target, call BeginFrameForTarget or
    171 * or SetRenderTarget, the latter with a target created
    172 * by CreateRenderTarget or CreateRenderTargetFromSource.
    173 *
    174 * The target and viewport methods can be called before any DrawQuad call and
    175 * affect any subsequent DrawQuad calls.
    176 */
    177 class Compositor : public TextureSourceProvider {
    178 protected:
    179  virtual ~Compositor();
    180 
    181 public:
    182  explicit Compositor(widget::CompositorWidget* aWidget);
    183 
    184  bool IsValid() const override { return true; }
    185 
    186  virtual bool Initialize(nsCString* const out_failureReason) = 0;
    187  void Destroy() override;
    188  bool IsDestroyed() const { return mIsDestroyed; }
    189 
    190  /**
    191   * Creates a Surface that can be used as a rendering target by this
    192   * compositor.
    193   */
    194  virtual already_AddRefed<CompositingRenderTarget> CreateRenderTarget(
    195      const gfx::IntRect& aRect, SurfaceInitMode aInit) = 0;
    196 
    197  /**
    198   * Grab a snapshot of aSource and store it in aDest, so that the pixels can
    199   * be read on the CPU by mapping aDest at some point in the future.
    200   * aSource and aDest must have the same size.
    201   * If this is a GPU compositor, this call must not block on the GPU.
    202   * Returns whether the operation was successful.
    203   */
    204  virtual bool ReadbackRenderTarget(CompositingRenderTarget* aSource,
    205                                    AsyncReadbackBuffer* aDest) = 0;
    206 
    207  /**
    208   * Create an AsyncReadbackBuffer of the specified size. Can return null.
    209   */
    210  virtual already_AddRefed<AsyncReadbackBuffer> CreateAsyncReadbackBuffer(
    211      const gfx::IntSize& aSize) = 0;
    212 
    213  /**
    214   * Draw a part of aSource into the current render target.
    215   * Scaling is done with linear filtering.
    216   * Returns whether the operation was successful.
    217   */
    218  virtual bool BlitRenderTarget(CompositingRenderTarget* aSource,
    219                                const gfx::IntSize& aSourceSize,
    220                                const gfx::IntSize& aDestSize) = 0;
    221 
    222  /**
    223   * Sets the given surface as the target for subsequent calls to DrawQuad.
    224   * Passing null as aSurface sets the screen as the target.
    225   */
    226  virtual void SetRenderTarget(CompositingRenderTarget* aSurface) = 0;
    227 
    228  /**
    229   * Returns the current target for rendering. Will return null if we are
    230   * rendering to the screen.
    231   */
    232  virtual already_AddRefed<CompositingRenderTarget> GetCurrentRenderTarget()
    233      const = 0;
    234 
    235  /**
    236   * Returns a render target which contains the entire window's drawing.
    237   * On platforms where no such render target is used during compositing (e.g.
    238   * with buffered BasicCompositor, where only the invalid area is drawn to a
    239   * render target), this will return null.
    240   */
    241  virtual already_AddRefed<CompositingRenderTarget> GetWindowRenderTarget()
    242      const = 0;
    243 
    244  /**
    245   * Mostly the compositor will pull the size from a widget and this method will
    246   * be ignored, but compositor implementations are free to use it if they like.
    247   */
    248  virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) = 0;
    249 
    250  /**
    251   * Tell the compositor to draw a quad. What to do draw and how it is
    252   * drawn is specified by aEffectChain. aRect is the quad to draw, in user
    253   * space. aTransform transforms from user space to screen space. If texture
    254   * coords are required, these will be in the primary effect in the effect
    255   * chain. aVisibleRect is used to determine which edges should be antialiased,
    256   * without applying the effect to the inner edges of a tiled layer.
    257   */
    258  virtual void DrawQuad(const gfx::Rect& aRect, const gfx::IntRect& aClipRect,
    259                        const EffectChain& aEffectChain, gfx::Float aOpacity,
    260                        const gfx::Matrix4x4& aTransform,
    261                        const gfx::Rect& aVisibleRect) = 0;
    262 
    263  void SetClearColor(const gfx::DeviceColor& aColor) { mClearColor = aColor; }
    264 
    265  /**
    266   * Start a new frame for rendering to the window.
    267   * Needs to be paired with a call to EndFrame() if the return value is not
    268   * Nothing().
    269   *
    270   * aInvalidRegion is the invalid region of the window.
    271   * aClipRect is the clip rect for all drawing (optional).
    272   * aRenderBounds is the bounding rect for rendering.
    273   * aOpaqueRegion is the area that contains opaque content.
    274   * All coordinates are in window space.
    275   *
    276   * Returns the non-empty render bounds actually used by the compositor in
    277   * window space, or Nothing() if composition should be aborted.
    278   */
    279  virtual Maybe<gfx::IntRect> BeginFrameForWindow(
    280      const nsIntRegion& aInvalidRegion, const Maybe<gfx::IntRect>& aClipRect,
    281      const gfx::IntRect& aRenderBounds, const nsIntRegion& aOpaqueRegion) = 0;
    282 
    283  /**
    284   * Flush the current frame to the screen and tidy up.
    285   *
    286   * Derived class overriding this should call Compositor::EndFrame.
    287   */
    288  virtual void EndFrame();
    289 
    290  virtual void CancelFrame(bool aNeedFlush = true) {}
    291 
    292 #ifdef MOZ_DUMP_PAINTING
    293  virtual const char* Name() const = 0;
    294 #endif  // MOZ_DUMP_PAINTING
    295 
    296  virtual CompositorD3D11* AsCompositorD3D11() { return nullptr; }
    297 
    298  Compositor* AsCompositor() override { return this; }
    299 
    300  TimeStamp GetLastCompositionEndTime() const override {
    301    return mLastCompositionEndTime;
    302  }
    303 
    304  /**
    305   * Notify the compositor that composition is being paused. This allows the
    306   * compositor to temporarily release any resources.
    307   * Between calling Pause and Resume, compositing may fail.
    308   */
    309  virtual void Pause() {}
    310  /**
    311   * Notify the compositor that composition is being resumed. The compositor
    312   * regain any resources it requires for compositing.
    313   * Returns true if succeeded.
    314   */
    315  virtual bool Resume() { return true; }
    316 
    317  widget::CompositorWidget* GetWidget() const { return mWidget; }
    318 
    319  /**
    320   * Request the compositor to allow recording its frames.
    321   *
    322   * This is a noop on |CompositorOGL|.
    323   */
    324  virtual void RequestAllowFrameRecording(bool aWillRecord) {
    325    mRecordFrames = aWillRecord;
    326  }
    327 
    328 protected:
    329  /**
    330   * Whether or not the compositor should be prepared to record frames. While
    331   * this returns true, compositors are expected to maintain a full window
    332   * render target that they return from GetWindowRenderTarget() between
    333   * NormalDrawingDone() and EndFrame().
    334   *
    335   * This will be true when either we are recording a profile with screenshots
    336   * enabled or the |LayerManagerComposite| has requested us to record frames
    337   * for the |CompositionRecorder|.
    338   */
    339  bool ShouldRecordFrames() const;
    340 
    341  /**
    342   * Last Composition end time.
    343   */
    344  TimeStamp mLastCompositionEndTime;
    345 
    346  widget::CompositorWidget* mWidget;
    347 
    348  bool mIsDestroyed;
    349 
    350  gfx::DeviceColor mClearColor;
    351 
    352  bool mRecordFrames = false;
    353 
    354 private:
    355  static LayersBackend sBackend;
    356 };
    357 
    358 // Returns the number of rects. (Up to 4)
    359 typedef gfx::Rect decomposedRectArrayT[4];
    360 size_t DecomposeIntoNoRepeatRects(const gfx::Rect& aRect,
    361                                  const gfx::Rect& aTexCoordRect,
    362                                  decomposedRectArrayT* aLayerRects,
    363                                  decomposedRectArrayT* aTextureRects);
    364 
    365 static inline bool BlendOpIsMixBlendMode(gfx::CompositionOp aOp) {
    366  switch (aOp) {
    367    case gfx::CompositionOp::OP_MULTIPLY:
    368    case gfx::CompositionOp::OP_SCREEN:
    369    case gfx::CompositionOp::OP_OVERLAY:
    370    case gfx::CompositionOp::OP_DARKEN:
    371    case gfx::CompositionOp::OP_LIGHTEN:
    372    case gfx::CompositionOp::OP_COLOR_DODGE:
    373    case gfx::CompositionOp::OP_COLOR_BURN:
    374    case gfx::CompositionOp::OP_HARD_LIGHT:
    375    case gfx::CompositionOp::OP_SOFT_LIGHT:
    376    case gfx::CompositionOp::OP_DIFFERENCE:
    377    case gfx::CompositionOp::OP_EXCLUSION:
    378    case gfx::CompositionOp::OP_HUE:
    379    case gfx::CompositionOp::OP_SATURATION:
    380    case gfx::CompositionOp::OP_COLOR:
    381    case gfx::CompositionOp::OP_LUMINOSITY:
    382      return true;
    383    default:
    384      return false;
    385  }
    386 }
    387 
    388 class AsyncReadbackBuffer {
    389 public:
    390  NS_INLINE_DECL_REFCOUNTING(AsyncReadbackBuffer)
    391 
    392  gfx::IntSize GetSize() const { return mSize; }
    393  virtual bool MapAndCopyInto(gfx::DataSourceSurface* aSurface,
    394                              const gfx::IntSize& aReadSize) const = 0;
    395 
    396 protected:
    397  explicit AsyncReadbackBuffer(const gfx::IntSize& aSize) : mSize(aSize) {}
    398  virtual ~AsyncReadbackBuffer() = default;
    399 
    400  gfx::IntSize mSize;
    401 };
    402 
    403 struct TexturedVertex {
    404  float position[2];
    405  float texCoords[2];
    406 };
    407 
    408 nsTArray<TexturedVertex> TexturedTrianglesToVertexArray(
    409    const nsTArray<gfx::TexturedTriangle>& aTriangles);
    410 
    411 }  // namespace layers
    412 }  // namespace mozilla
    413 
    414 #endif /* MOZILLA_GFX_COMPOSITOR_H */