tor-browser

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

CrossProcessPaint.h (6293B)


      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 #ifndef _include_mozilla_gfx_ipc_CrossProcessPaint_h_
      7 #define _include_mozilla_gfx_ipc_CrossProcessPaint_h_
      8 
      9 #include "nsISupportsImpl.h"
     10 
     11 #include "mozilla/dom/ipc/IdType.h"
     12 #include "mozilla/gfx/Point.h"
     13 #include "mozilla/gfx/Rect.h"
     14 #include "mozilla/MozPromise.h"
     15 #include "mozilla/ipc/ByteBuf.h"
     16 #include "nsColor.h"
     17 #include "nsTHashMap.h"
     18 #include "nsHashKeys.h"
     19 #include "nsRefPtrHashtable.h"
     20 #include "nsTHashSet.h"
     21 
     22 class nsIDocShell;
     23 
     24 namespace IPC {
     25 template <typename T>
     26 struct ParamTraits;
     27 }  // namespace IPC
     28 
     29 namespace mozilla {
     30 
     31 namespace dom {
     32 class CanonicalBrowsingContext;
     33 class DOMRect;
     34 class Promise;
     35 class WindowGlobalParent;
     36 }  // namespace dom
     37 
     38 namespace gfx {
     39 
     40 class CrossProcessPaint;
     41 
     42 enum class CrossProcessPaintFlags {
     43  None = 0,
     44  DrawView = 1 << 1,
     45  ResetScrollPosition = 1 << 2,
     46  UseHighQualityScaling = 1 << 3,
     47 };
     48 
     49 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CrossProcessPaintFlags)
     50 
     51 /**
     52 * A fragment of a paint of a cross process document tree.
     53 */
     54 class PaintFragment final {
     55 public:
     56  /// Initializes an empty PaintFragment
     57  PaintFragment() = default;
     58 
     59  /**
     60   * Creates a paint fragment by recording the draw commands and dependent tabs
     61   * for a BrowsingContext.
     62   *
     63   * @param aBrowsingContext The frame to record.
     64   * @param aRect The rectangle relative to the viewport to use. If no
     65   *   rectangle is specified, then the whole viewport will be used.
     66   * @param aScale The coordinate scale to use. The size of the resolved
     67   *   surface will be `aRect.Size() * aScale`, with aScale clamped to
     68   *   at least kMinPaintScale.
     69   * @param aBackgroundColor The background color to use.
     70   *
     71   * @return A paint fragment. The paint fragment may be `empty` if rendering
     72   *         was unable to be accomplished for some reason.
     73   */
     74  static PaintFragment Record(dom::BrowsingContext* aBc,
     75                              const Maybe<IntRect>& aRect, float aScale,
     76                              nscolor aBackgroundColor,
     77                              CrossProcessPaintFlags aFlags);
     78 
     79  /// Returns whether this paint fragment contains a valid recording.
     80  bool IsEmpty() const;
     81 
     82  PaintFragment(PaintFragment&&) = default;
     83  PaintFragment& operator=(PaintFragment&&) = default;
     84 
     85 protected:
     86  friend struct IPC::ParamTraits<PaintFragment>;
     87  friend CrossProcessPaint;
     88 
     89  typedef mozilla::ipc::ByteBuf ByteBuf;
     90 
     91  PaintFragment(IntSize, ByteBuf&&, nsTHashSet<uint64_t>&&);
     92 
     93  IntSize mSize;
     94  ByteBuf mRecording;
     95  nsTHashSet<uint64_t> mDependencies;
     96 };
     97 
     98 struct RecordedDependentSurface;
     99 
    100 /**
    101 * An object for painting a cross process document tree.
    102 */
    103 class CrossProcessPaint final {
    104  NS_INLINE_DECL_REFCOUNTING(CrossProcessPaint);
    105 
    106 public:
    107  typedef nsRefPtrHashtable<nsUint64HashKey, RecordedDependentSurface>
    108      ResolvedFragmentMap;
    109  typedef MozPromise<ResolvedFragmentMap, nsresult, true> ResolvePromise;
    110  /**
    111   * Begin an asynchronous paint of a cross process document tree starting at
    112   * a WindowGlobalParent. A maybe-async paint for the root WGP will be done,
    113   * then async paints will be recursively queued for remote subframes. Once
    114   * all subframes have been recorded, the final image will be resolved, and
    115   * the promise will be resolved with a dom::ImageBitmap.
    116   *
    117   * @param aRoot The WindowGlobalParent to paint.
    118   * @param aRect The rectangle relative to the viewport to use, or null to
    119   *   render the whole viewport.
    120   * @param aScale The coordinate scale to use. The size of the resolved
    121   *   surface will be `aRect.Size() * aScale`, with aScale clamped to
    122   *   at least kMinPaintScale. See the implementation for the current
    123   *   minimum value.
    124   * @param aBackgroundColor The background color to use.
    125   * @param aPromise The promise to resolve with a dom::ImageBitmap.
    126   *
    127   * @returns Whether the paint was able to be initiated or not.
    128   */
    129  static bool Start(dom::WindowGlobalParent* aRoot, const dom::DOMRect* aRect,
    130                    float aScale, nscolor aBackgroundColor,
    131                    CrossProcessPaintFlags aFlags, dom::Promise* aPromise);
    132 
    133  static RefPtr<ResolvePromise> Start(nsTHashSet<uint64_t>&& aDependencies);
    134 
    135  void ReceiveFragment(dom::WindowGlobalParent* aWGP,
    136                       PaintFragment&& aFragment);
    137  void LostFragment(dom::WindowGlobalParent* aWGP);
    138 
    139 private:
    140  typedef nsTHashMap<nsUint64HashKey, PaintFragment> ReceivedFragmentMap;
    141 
    142  CrossProcessPaint(float aScale, dom::TabId aRoot,
    143                    CrossProcessPaintFlags aFlags);
    144  ~CrossProcessPaint();
    145 
    146  void QueueDependencies(const nsTHashSet<uint64_t>& aDependencies);
    147 
    148  void QueuePaint(
    149      dom::WindowGlobalParent* aWGP, const Maybe<IntRect>& aRect,
    150      nscolor aBackgroundColor = NS_RGBA(0, 0, 0, 0),
    151      CrossProcessPaintFlags aFlags = CrossProcessPaintFlags::DrawView);
    152 
    153  void QueuePaint(dom::CanonicalBrowsingContext* aBc);
    154 
    155  /// Clear the state of this paint so that it cannot be resolved or receive
    156  /// any paint fragments.
    157  void Clear(nsresult aStatus);
    158 
    159  /// Returns if this paint has been cleared.
    160  bool IsCleared() const;
    161 
    162  /// Resolves the paint fragments if we have none pending and resolves the
    163  /// promise.
    164  void MaybeResolve();
    165  nsresult ResolveInternal(dom::TabId aTabId, ResolvedFragmentMap* aResolved);
    166 
    167  RefPtr<ResolvePromise> Init() {
    168    MOZ_ASSERT(mPromise.IsEmpty());
    169    return mPromise.Ensure(__func__);
    170  }
    171 
    172  // UseHighQualityScaling is the only flag that dependencies inherit, and we
    173  // always want to use DrawView for dependencies.
    174  CrossProcessPaintFlags GetFlagsForDependencies() const {
    175    return (mFlags & CrossProcessPaintFlags::UseHighQualityScaling) |
    176           CrossProcessPaintFlags::DrawView;
    177  }
    178 
    179  MozPromiseHolder<ResolvePromise> mPromise;
    180  dom::TabId mRoot;
    181  float mScale;
    182  uint32_t mPendingFragments;
    183  ReceivedFragmentMap mReceivedFragments;
    184  CrossProcessPaintFlags mFlags;
    185 };
    186 
    187 }  // namespace gfx
    188 }  // namespace mozilla
    189 
    190 #endif  // _include_mozilla_gfx_ipc_CrossProcessPaint_h_