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_