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_
9 #include "nsISupportsImpl.h"
11 #include "mozilla/dom/ipc/IdType.h"
12 #include "mozilla/gfx/Point.h"
13 #include "mozilla/gfx/RecordedEvent.h"
14 #include "mozilla/gfx/Rect.h"
15 #include "mozilla/MozPromise.h"
16 #include "mozilla/ipc/ByteBuf.h"
18 #include "nsTHashMap.h"
19 #include "nsHashKeys.h"
20 #include "nsRefPtrHashtable.h"
21 #include "nsTHashSet.h"
33 class CanonicalBrowsingContext
;
36 class WindowGlobalParent
;
41 class CrossProcessPaint
;
43 enum class CrossProcessPaintFlags
{
46 ResetScrollPosition
= 1 << 2,
47 UseHighQualityScaling
= 1 << 3,
50 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CrossProcessPaintFlags
)
53 * A fragment of a paint of a cross process document tree.
55 class PaintFragment final
{
57 /// Initializes an empty PaintFragment
58 PaintFragment() = default;
61 * Creates a paint fragment by recording the draw commands and dependent tabs
62 * for a BrowsingContext.
64 * @param aBrowsingContext The frame to record.
65 * @param aRect The rectangle relative to the viewport to use. If no
66 * rectangle is specified, then the whole viewport will be used.
67 * @param aScale The coordinate scale to use. The size of the resolved
68 * surface will be `aRect.Size() * aScale`, with aScale clamped to
69 * at least kMinPaintScale.
70 * @param aBackgroundColor The background color to use.
72 * @return A paint fragment. The paint fragment may be `empty` if rendering
73 * was unable to be accomplished for some reason.
75 static PaintFragment
Record(dom::BrowsingContext
* aBc
,
76 const Maybe
<IntRect
>& aRect
, float aScale
,
77 nscolor aBackgroundColor
,
78 CrossProcessPaintFlags aFlags
);
80 /// Returns whether this paint fragment contains a valid recording.
83 PaintFragment(PaintFragment
&&) = default;
84 PaintFragment
& operator=(PaintFragment
&&) = default;
87 friend struct mozilla::ipc::IPDLParamTraits
<PaintFragment
>;
88 friend CrossProcessPaint
;
90 typedef mozilla::ipc::ByteBuf ByteBuf
;
92 PaintFragment(IntSize
, ByteBuf
&&, nsTHashSet
<uint64_t>&&);
96 nsTHashSet
<uint64_t> mDependencies
;
100 * An object for painting a cross process document tree.
102 class CrossProcessPaint final
{
103 NS_INLINE_DECL_REFCOUNTING(CrossProcessPaint
);
106 typedef nsRefPtrHashtable
<nsUint64HashKey
, RecordedDependentSurface
>
108 typedef MozPromise
<ResolvedFragmentMap
, nsresult
, true> ResolvePromise
;
110 * Begin an asynchronous paint of a cross process document tree starting at
111 * a WindowGlobalParent. A maybe-async paint for the root WGP will be done,
112 * then async paints will be recursively queued for remote subframes. Once
113 * all subframes have been recorded, the final image will be resolved, and
114 * the promise will be resolved with a dom::ImageBitmap.
116 * @param aRoot The WindowGlobalParent to paint.
117 * @param aRect The rectangle relative to the viewport to use, or null to
118 * render the whole viewport.
119 * @param aScale The coordinate scale to use. The size of the resolved
120 * surface will be `aRect.Size() * aScale`, with aScale clamped to
121 * at least kMinPaintScale. See the implementation for the current
123 * @param aBackgroundColor The background color to use.
124 * @param aPromise The promise to resolve with a dom::ImageBitmap.
126 * @returns Whether the paint was able to be initiated or not.
128 static bool Start(dom::WindowGlobalParent
* aRoot
, const dom::DOMRect
* aRect
,
129 float aScale
, nscolor aBackgroundColor
,
130 CrossProcessPaintFlags aFlags
, dom::Promise
* aPromise
);
132 static RefPtr
<ResolvePromise
> Start(nsTHashSet
<uint64_t>&& aDependencies
);
134 void ReceiveFragment(dom::WindowGlobalParent
* aWGP
,
135 PaintFragment
&& aFragment
);
136 void LostFragment(dom::WindowGlobalParent
* aWGP
);
139 typedef nsTHashMap
<nsUint64HashKey
, PaintFragment
> ReceivedFragmentMap
;
141 CrossProcessPaint(float aScale
, dom::TabId aRoot
,
142 CrossProcessPaintFlags aFlags
);
143 ~CrossProcessPaint();
145 void QueueDependencies(const nsTHashSet
<uint64_t>& aDependencies
);
148 dom::WindowGlobalParent
* aWGP
, const Maybe
<IntRect
>& aRect
,
149 nscolor aBackgroundColor
= NS_RGBA(0, 0, 0, 0),
150 CrossProcessPaintFlags aFlags
= CrossProcessPaintFlags::DrawView
);
152 void QueuePaint(dom::CanonicalBrowsingContext
* aBc
);
154 /// Clear the state of this paint so that it cannot be resolved or receive
155 /// any paint fragments.
156 void Clear(nsresult aStatus
);
158 /// Returns if this paint has been cleared.
159 bool IsCleared() const;
161 /// Resolves the paint fragments if we have none pending and resolves the
164 nsresult
ResolveInternal(dom::TabId aTabId
, ResolvedFragmentMap
* aResolved
);
166 RefPtr
<ResolvePromise
> Init() {
167 MOZ_ASSERT(mPromise
.IsEmpty());
168 return mPromise
.Ensure(__func__
);
171 // UseHighQualityScaling is the only flag that dependencies inherit, and we
172 // always want to use DrawView for dependencies.
173 CrossProcessPaintFlags
GetFlagsForDependencies() const {
174 return (mFlags
& CrossProcessPaintFlags::UseHighQualityScaling
) |
175 CrossProcessPaintFlags::DrawView
;
178 MozPromiseHolder
<ResolvePromise
> mPromise
;
181 uint32_t mPendingFragments
;
182 ReceivedFragmentMap mReceivedFragments
;
183 CrossProcessPaintFlags mFlags
;
187 } // namespace mozilla
189 #endif // _include_mozilla_gfx_ipc_CrossProcessPaint_h_