Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/layers/./../../../gfx/layers/wr/WebRenderLayerManager.cpp
Warning:line 387, column 5
Value stored to 'builderDumpIndex' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_gfx_layers9.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/layers -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/layers -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D GOOGLE_PROTOBUF_NO_RTTI -D GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER -D MOZ_APP_VERSION=157.0a1 -D D3D_DEBUG_INFO -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/gfx/layers -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/layers -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/third_party/abseil-cpp -I /root/firefox-clang/toolkit/components/telemetry -I /root/firefox-clang/xpcom/base -I /root/firefox-clang/docshell/base -I /root/firefox-clang/dom/canvas -I /root/firefox-clang/gfx/cairo/cairo/src -I /root/firefox-clang/layout/base -I /root/firefox-clang/layout/generic -I /root/firefox-clang/media/libyuv/libyuv/include -I /root/firefox-clang/third_party/drm/drm/include -I /root/firefox-clang/third_party/drm/drm/include/libdrm -I /root/firefox-clang/gfx/skia -I /root/firefox-clang/gfx/skia/skia -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -I /usr/include/gtk-3.0/unix-print -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cloudproviders -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/fribidi -I /usr/include/harfbuzz -I /usr/include/atk-1.0 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/glycin-2 -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/gio-unix-2.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c++ Unified_cpp_gfx_layers9.cpp
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#include "WebRenderLayerManager.h"
6
7#include "GeckoProfiler.h"
8#include "LayerUserData.h"
9#include "WebRenderCanvasRenderer.h"
10#include "mozilla/PerfStats.h"
11#include "mozilla/StaticPrefs_apz.h"
12#include "mozilla/StaticPrefs_layers.h"
13#include "mozilla/dom/BrowserChild.h"
14#include "mozilla/gfx/DrawEventRecorder.h"
15#include "mozilla/layers/APZTestData.h"
16#include "mozilla/layers/CompositorBridgeChild.h"
17#include "mozilla/layers/StackingContextHelper.h"
18#include "mozilla/layers/TextureClient.h"
19#include "mozilla/layers/TransactionIdAllocator.h"
20#include "mozilla/layers/WebRenderBridgeChild.h"
21#include "nsDisplayList.h"
22#include "nsLayoutUtils.h"
23
24#ifdef XP_WIN
25# include "gfxDWriteFonts.h"
26# include "mozilla/WindowsProcessMitigations.h"
27#endif
28
29namespace mozilla {
30
31namespace gfx {
32wr::PipelineId GetTemporaryWebRenderPipelineId(wr::PipelineId aMainPipeline);
33}
34
35using namespace gfx;
36
37namespace layers {
38
39bool WebRenderLayerManager::sHasInitialized = false;
40
41WebRenderLayerManager::WebRenderLayerManager(
42 nsIWidget* aWidget, already_AddRefed<WebRenderBridgeChild> aWrChild)
43 : mWidget(aWidget),
44 mWrChild(aWrChild),
45 mLatestTransactionId{0},
46 mNeedsComposite(false),
47 mIsFirstPaint(false),
48 mDestroyed(false),
49 mTarget(nullptr),
50 mPaintSequenceNumber(0),
51 mApzTestData(new APZTestData),
52 mWebRenderCommandBuilder(this) {
53 MOZ_COUNT_CTOR(WebRenderLayerManager)do { static_assert(std::is_class_v<WebRenderLayerManager>
, "Token '" "WebRenderLayerManager" "' is not a class type.")
; static_assert(!std::is_base_of_v<nsISupports, WebRenderLayerManager
>, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "WebRenderLayerManager"
, sizeof(*this)); } while (0)
;
54 MOZ_RELEASE_ASSERT(mWidget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mWidget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mWidget))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mWidget", "./../../../gfx/layers/wr/WebRenderLayerManager.cpp"
, 54); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mWidget"
")"); do { MOZ_CrashSequence(__null, 54); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
55 MOZ_RELEASE_ASSERT(mWrChild)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mWrChild)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mWrChild))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mWrChild", "./../../../gfx/layers/wr/WebRenderLayerManager.cpp"
, 55); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mWrChild"
")"); do { MOZ_CrashSequence(__null, 55); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
56 mStateManager.mLayerManager = this;
57}
58
59KnowsCompositor* WebRenderLayerManager::AsKnowsCompositor() { return mWrChild; }
60
61/* static */
62RefPtr<WebRenderLayerManager> WebRenderLayerManager::Create(
63 nsIWidget* aWidget, PCompositorBridgeChild* aCBChild,
64 wr::PipelineId aPipelineId, nsCString& aError) {
65 MOZ_RELEASE_ASSERT(aWidget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aWidget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aWidget))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aWidget", "./../../../gfx/layers/wr/WebRenderLayerManager.cpp"
, 65); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "aWidget"
")"); do { MOZ_CrashSequence(__null, 65); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
66 MOZ_RELEASE_ASSERT(aCBChild)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aCBChild)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aCBChild))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aCBChild", "./../../../gfx/layers/wr/WebRenderLayerManager.cpp"
, 66); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "aCBChild"
")"); do { MOZ_CrashSequence(__null, 66); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
67
68 WindowKind windowKind;
69 if (aWidget->GetWindowType() != widget::WindowType::Popup) {
70 windowKind = WindowKind::MAIN;
71 } else {
72 windowKind = WindowKind::SECONDARY;
73 }
74
75 LayoutDeviceIntSize size = aWidget->GetClientSize();
76 // Check widget size
77 if (!wr::WindowSizeSanityCheck(size.width, size.height)) {
78 gfxCriticalNoteOncestatic mozilla::gfx::CriticalLog sOnceAtLine78 = mozilla::gfx
::CriticalLog(mozilla::gfx::CriticalLog::DefaultOptions(false
))
<< "Widget size is not valid " << size
79 << " isParent: " << XRE_IsParentProcess();
80 }
81
82 auto bridge = MakeRefPtr<WebRenderBridgeChild>(aPipelineId);
83 if (!aCBChild->SendPWebRenderBridgeConstructor(bridge, aPipelineId, size,
84 windowKind)) {
85 // This should only fail if we attempt to access a layer we don't have
86 // permission for, or more likely, the GPU process crashed again during
87 // reinitialization. We can expect to be notified again to reinitialize
88 // (which may or may not be using WebRender).
89 gfxCriticalNotemozilla::gfx::CriticalLog(mozilla::gfx::CriticalLog::DefaultOptions
(false))
<< "Failed to send WebRenderBridgeChild.";
90 aError.Assign(sHasInitialized
91 ? "FEATURE_FAILURE_WEBRENDER_INITIALIZE_IPDL_POST"_ns
92 : "FEATURE_FAILURE_WEBRENDER_INITIALIZE_IPDL_FIRST"_ns);
93 return nullptr;
94 }
95
96 return new WebRenderLayerManager(aWidget, bridge.forget());
97}
98
99bool WebRenderLayerManager::Initialize(
100 TextureFactoryIdentifier* aTextureFactoryIdentifier, nsCString& aError) {
101 MOZ_ASSERT(aTextureFactoryIdentifier)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTextureFactoryIdentifier)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aTextureFactoryIdentifier)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("aTextureFactoryIdentifier"
, "./../../../gfx/layers/wr/WebRenderLayerManager.cpp", 101);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTextureFactoryIdentifier"
")"); do { MOZ_CrashSequence(__null, 101); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
102
103 mHasFlushedThisChild = false;
104
105 TextureFactoryIdentifier textureFactoryIdentifier;
106 wr::MaybeIdNamespace idNamespace;
107 // Sync ipc
108 if (!WrBridge()->SendEnsureConnected(&textureFactoryIdentifier, &idNamespace,
109 &aError)) {
110 gfxCriticalNotemozilla::gfx::CriticalLog(mozilla::gfx::CriticalLog::DefaultOptions
(false))
<< "Failed as lost WebRenderBridgeChild.";
111 aError.Assign(sHasInitialized
112 ? "FEATURE_FAILURE_WEBRENDER_INITIALIZE_SYNC_POST"_ns
113 : "FEATURE_FAILURE_WEBRENDER_INITIALIZE_SYNC_FIRST"_ns);
114 return false;
115 }
116
117 if (textureFactoryIdentifier.mParentBackend == LayersBackend::LAYERS_NONE ||
118 idNamespace.isNothing()) {
119 gfxCriticalNotemozilla::gfx::CriticalLog(mozilla::gfx::CriticalLog::DefaultOptions
(false))
<< "Failed to connect WebRenderBridgeChild. isParent="
120 << XRE_IsParentProcess();
121 aError.Append(sHasInitialized ? "_POST"_ns : "_FIRST"_ns);
122 return false;
123 }
124
125 WrBridge()->SetWebRenderLayerManager(this);
126 WrBridge()->IdentifyTextureHost(textureFactoryIdentifier);
127 WrBridge()->SetNamespace(idNamespace.ref());
128 *aTextureFactoryIdentifier = textureFactoryIdentifier;
129
130 mDLBuilder = MakeUnique<wr::DisplayListBuilder>(
131 WrBridge()->GetPipeline(), WrBridge()->GetWebRenderBackend());
132
133 sHasInitialized = true;
134 return true;
135}
136
137void WebRenderLayerManager::Destroy() { DoDestroy(/* aIsSync */ false); }
138
139void WebRenderLayerManager::DoDestroy(bool aIsSync) {
140 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../gfx/layers/wr/WebRenderLayerManager.cpp", 140);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"
); do { MOZ_CrashSequence(__null, 140); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
141
142 if (IsDestroyed()) {
143 return;
144 }
145
146 mDLBuilder = nullptr;
147 mUserData.Destroy();
148 mPartialPrerenderedAnimations.Clear();
149
150 mStateManager.Destroy();
151
152 mWrChild->Destroy(aIsSync);
153
154 mWebRenderCommandBuilder.Destroy();
155
156 if (mTransactionIdAllocator) {
157 // Make sure to notify the refresh driver just in case it's waiting on a
158 // pending transaction. Do this at the top of the event loop so we don't
159 // cause a paint to occur during compositor shutdown.
160 RefPtr<TransactionIdAllocator> allocator = mTransactionIdAllocator;
161 TransactionId id = mLatestTransactionId;
162
163 RefPtr<Runnable> task = NS_NewRunnableFunction(
164 "TransactionIdAllocator::NotifyTransactionCompleted",
165 [allocator, id]() -> void {
166 allocator->ClearPendingTransactions();
167 allocator->NotifyTransactionCompleted(id);
168 });
169 NS_DispatchToMainThread(task.forget());
170 }
171
172 // Forget the widget pointer in case we outlive our owning widget.
173 mWidget = nullptr;
174 mDestroyed = true;
175}
176
177WebRenderLayerManager::~WebRenderLayerManager() {
178 Destroy();
179 MOZ_COUNT_DTOR(WebRenderLayerManager)do { static_assert(std::is_class_v<WebRenderLayerManager>
, "Token '" "WebRenderLayerManager" "' is not a class type.")
; static_assert(!std::is_base_of_v<nsISupports, WebRenderLayerManager
>, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "WebRenderLayerManager"
, sizeof(*this)); } while (0)
;
180}
181
182CompositorBridgeChild* WebRenderLayerManager::GetCompositorBridgeChild() {
183 return WrBridge()->GetCompositorBridgeChild();
184}
185
186void WebRenderLayerManager::GetBackendName(nsAString& name) {
187 if (WrBridge()->UsingSoftwareWebRenderD3D11()) {
188 name.AssignLiteral("WebRender (Software D3D11)");
189 } else if (WrBridge()->UsingSoftwareWebRenderOpenGL()) {
190 name.AssignLiteral("WebRender (Software OpenGL)");
191 } else if (WrBridge()->UsingSoftwareWebRender()) {
192 name.AssignLiteral("WebRender (Software)");
193 } else if (WrBridge()->GetUseLayerCompositor()) {
194 name.AssignLiteral("WebRender Layer Compositor");
195 } else {
196 name.AssignLiteral("WebRender");
197 }
198}
199
200uint32_t WebRenderLayerManager::StartFrameTimeRecording(int32_t aBufferSize) {
201 CompositorBridgeChild* renderer = GetCompositorBridgeChild();
202 if (renderer) {
203 uint32_t startIndex;
204 renderer->SendStartFrameTimeRecording(aBufferSize, &startIndex);
205 return startIndex;
206 }
207 return -1;
208}
209
210void WebRenderLayerManager::StopFrameTimeRecording(
211 uint32_t aStartIndex, nsTArray<float>& aFrameIntervals) {
212 CompositorBridgeChild* renderer = GetCompositorBridgeChild();
213 if (renderer) {
214 renderer->SendStopFrameTimeRecording(aStartIndex, &aFrameIntervals);
215 }
216}
217
218void WebRenderLayerManager::TakeCompositionPayloads(
219 nsTArray<CompositionPayload>& aPayloads) {
220 aPayloads.Clear();
221
222 std::swap(mPayload, aPayloads);
223}
224
225bool WebRenderLayerManager::BeginTransactionWithTarget(gfxContext* aTarget,
226 const nsCString& aURL) {
227 mTarget = aTarget;
228 bool retval = BeginTransaction(aURL);
229 if (!retval) {
230 mTarget = nullptr;
231 }
232 return retval;
233}
234
235bool WebRenderLayerManager::BeginTransaction(const nsCString& aURL) {
236 if (!WrBridge()->IPCOpen()) {
237 gfxCriticalNotemozilla::gfx::CriticalLog(mozilla::gfx::CriticalLog::DefaultOptions
(false))
<< "IPC Channel is already torn down unexpectedly\n";
238 return false;
239 }
240
241 mTransactionStart = TimeStamp::Now();
242 mURL = aURL;
243
244 // Increment the paint sequence number even if test logging isn't
245 // enabled in this process; it may be enabled in the parent process,
246 // and the parent process expects unique sequence numbers.
247 ++mPaintSequenceNumber;
248 if (StaticPrefs::apz_test_logging_enabled()) {
249 mApzTestData->StartNewPaint(mPaintSequenceNumber);
250 }
251 return true;
252}
253
254bool WebRenderLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags) {
255 auto clearTarget = MakeScopeExit([&] { mTarget = nullptr; });
256
257 // If we haven't sent a display list (since creation or since the last time we
258 // sent ClearDisplayList to the parent) then we can't do an empty transaction
259 // because the parent doesn't have a display list for us and we need to send a
260 // display list first.
261 if (!WrBridge()->GetSentDisplayList()) {
262 return false;
263 }
264
265 mLatestTransactionId =
266 mTransactionIdAllocator->GetTransactionId(/*aThrottle*/ true);
267
268 if (aFlags & EndTransactionFlags::END_NO_COMPOSITE &&
269 !mWebRenderCommandBuilder.NeedsEmptyTransaction()) {
270 if (mPendingScrollUpdates.IsEmpty()) {
271 MOZ_ASSERT(!mTarget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mTarget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mTarget))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mTarget", "./../../../gfx/layers/wr/WebRenderLayerManager.cpp"
, 271); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mTarget" ")"
); do { MOZ_CrashSequence(__null, 271); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
272 WrBridge()->SendSetFocusTarget(mFocusTarget);
273 // Revoke TransactionId to trigger next paint.
274 mTransactionIdAllocator->RevokeTransactionId(mLatestTransactionId);
275 mLatestTransactionId = mLatestTransactionId.Prev();
276 return true;
277 }
278 }
279
280 LayoutDeviceIntSize size = mWidget->GetClientSize();
281 WrBridge()->BeginTransaction();
282
283 mWebRenderCommandBuilder.EmptyTransaction();
284
285 // Get the time of when the refresh driver start its tick (if available),
286 // otherwise use the time of when LayerManager::BeginTransaction was called.
287 TimeStamp refreshStart = mTransactionIdAllocator->GetTransactionStart();
288 if (!refreshStart) {
289 refreshStart = mTransactionStart;
290 }
291
292 // Skip the synchronization for buffer since we also skip the painting during
293 // device-reset status.
294 if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) {
295 if (WrBridge()->GetSyncObject() &&
296 WrBridge()->GetSyncObject()->IsSyncObjectValid()) {
297 WrBridge()->GetSyncObject()->Synchronize();
298 }
299 }
300
301 GetCompositorBridgeChild()->EndCanvasTransaction();
302
303 Maybe<TransactionData> transactionData;
304 if (mStateManager.mAsyncResourceUpdates || !mPendingScrollUpdates.IsEmpty() ||
305 WrBridge()->HasWebRenderParentCommands()) {
306 transactionData.emplace();
307 transactionData->mIdNamespace = WrBridge()->GetNamespace();
308 transactionData->mPaintSequenceNumber = mPaintSequenceNumber;
309 if (mStateManager.mAsyncResourceUpdates) {
310 mStateManager.mAsyncResourceUpdates->Flush(
311 transactionData->mResourceUpdates, transactionData->mSmallShmems,
312 transactionData->mLargeShmems);
313 }
314 transactionData->mScrollUpdates = std::move(mPendingScrollUpdates);
315 for (const auto& scrollId : transactionData->mScrollUpdates.Keys()) {
316 nsLayoutUtils::NotifyPaintSkipTransaction(/*scroll id=*/scrollId);
317 }
318 }
319
320 Maybe<wr::IpcResourceUpdateQueue> nothing;
321 WrBridge()->EndEmptyTransaction(mFocusTarget, std::move(transactionData),
322 mLatestTransactionId,
323 mTransactionIdAllocator->GetVsyncId(),
324 mTransactionIdAllocator->GetVsyncStart(),
325 refreshStart, mTransactionStart, mURL);
326 mTransactionStart = TimeStamp();
327
328 MakeSnapshotIfRequired(size);
329 return true;
330}
331
332void WebRenderLayerManager::EndTransactionWithoutLayer(
333 nsDisplayList* aDisplayList, nsDisplayListBuilder* aDisplayListBuilder,
334 WrFiltersHolder&& aFilters, WebRenderBackgroundData* aBackground,
335 const double aGeckoDLBuildTime, bool aRenderOffscreen) {
336 AUTO_PROFILER_MARKER("WrDisplayList", GRAPHICS)AutoProfilerTracing raiiObject336( "WrDisplayList", geckoprofiler
::category::GRAPHICS, mozilla::Nothing())
;
337
338 auto clearTarget = MakeScopeExit([&] { mTarget = nullptr; });
339
340 WrBridge()->BeginTransaction();
341
342 LayoutDeviceIntSize size = mWidget->GetClientSize();
343
344 UniquePtr<wr::DisplayListBuilder> offscreenBuilder;
345 wr::DisplayListBuilder* diplayListBuilder = mDLBuilder.get();
346 if (aRenderOffscreen) {
347 wr::PipelineId mainId = WrBridge()->GetPipeline();
348 wr::PipelineId tmpPipeline = gfx::GetTemporaryWebRenderPipelineId(mainId);
349 offscreenBuilder = MakeUnique<wr::DisplayListBuilder>(
350 tmpPipeline, WrBridge()->GetWebRenderBackend());
351 diplayListBuilder = offscreenBuilder.get();
352 }
353
354 // The grid this display list's coordinates are authored on. It comes from the
355 // document being painted, not the widget, because full zoom applies to
356 // content but not chrome, so the two differ within one WebRender document.
357 const int32_t appUnitsPerDevPixel =
358 aDisplayListBuilder ? aDisplayListBuilder->RootReferenceFrame()
359 ->PresContext()
360 ->AppUnitsPerDevPixel()
361 : AppUnitsPerCSSPixel();
362 diplayListBuilder->Begin(appUnitsPerDevPixel);
363
364 wr::IpcResourceUpdateQueue resourceUpdates(WrBridge());
365 wr::usize builderDumpIndex = 0;
366 bool containsSVGGroup = false;
367 bool dumpEnabled =
368 mWebRenderCommandBuilder.ShouldDumpDisplayList(aDisplayListBuilder);
369 if (dumpEnabled) {
370 printf_stderr("-- WebRender display list build --\n");
371 }
372
373 if (XRE_IsContentProcess() &&
374 StaticPrefs::gfx_webrender_debug_dl_dump_content_serialized()) {
375 diplayListBuilder->DumpSerializedDisplayList();
376 }
377
378 if (aDisplayList) {
379 MOZ_ASSERT(aDisplayListBuilder && !aBackground)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDisplayListBuilder && !aBackground)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aDisplayListBuilder && !aBackground))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aDisplayListBuilder && !aBackground"
, "./../../../gfx/layers/wr/WebRenderLayerManager.cpp", 379);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDisplayListBuilder && !aBackground"
")"); do { MOZ_CrashSequence(__null, 379); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
380
381 mWebRenderCommandBuilder.BuildWebRenderCommands(
382 *diplayListBuilder, resourceUpdates, aDisplayList, aDisplayListBuilder,
383 mScrollData, std::move(aFilters));
384
385 aDisplayListBuilder->NotifyAndClearScrollContainerFrames();
386
387 builderDumpIndex = mWebRenderCommandBuilder.GetBuilderDumpIndex();
Value stored to 'builderDumpIndex' is never read
388 containsSVGGroup = mWebRenderCommandBuilder.GetContainsSVGGroup();
389 } else {
390 // ViewToPaint does not have frame yet, then render only background clolor.
391 MOZ_ASSERT(!aDisplayListBuilder && aBackground)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aDisplayListBuilder && aBackground)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aDisplayListBuilder && aBackground))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!aDisplayListBuilder && aBackground"
, "./../../../gfx/layers/wr/WebRenderLayerManager.cpp", 391);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aDisplayListBuilder && aBackground"
")"); do { MOZ_CrashSequence(__null, 391); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
392 aBackground->AddWebRenderCommands(*diplayListBuilder);
393 if (dumpEnabled) {
394 printf_stderr("(no display list; background only)\n");
395 builderDumpIndex = diplayListBuilder->Dump(
396 /*indent*/ 1, Some(builderDumpIndex), Nothing());
397 }
398 }
399
400 if (AsyncPanZoomEnabled()) {
401 if (mIsFirstPaint) {
402 mScrollData.SetIsFirstPaint(true);
403 mIsFirstPaint = false;
404 }
405 mScrollData.SetPaintSequenceNumber(mPaintSequenceNumber);
406 if (dumpEnabled) {
407 std::stringstream str;
408 str << mScrollData;
409 print_stderr(str);
410 }
411 }
412
413 // Since we're sending a full mScrollData that will include the new scroll
414 // offsets, and we can throw away the pending scroll updates we had kept for
415 // an empty transaction.
416 ClearAndNotifyOfFullTransactionPendingScrollInfoUpdate();
417
418 mLatestTransactionId = mTransactionIdAllocator->GetTransactionId(
419 /*aThrottle*/ !aRenderOffscreen);
420
421 // Get the time of when the refresh driver start its tick (if available),
422 // otherwise use the time of when LayerManager::BeginTransaction was called.
423 TimeStamp refreshStart = mTransactionIdAllocator->GetTransactionStart();
424 if (!refreshStart) {
425 refreshStart = mTransactionStart;
426 }
427
428 if (mStateManager.mAsyncResourceUpdates) {
429 if (resourceUpdates.IsEmpty()) {
430 resourceUpdates.ReplaceResources(
431 std::move(mStateManager.mAsyncResourceUpdates.ref()));
432 } else {
433 WrBridge()->UpdateResources(mStateManager.mAsyncResourceUpdates.ref());
434 }
435 mStateManager.mAsyncResourceUpdates.reset();
436 }
437
438 if (aRenderOffscreen) {
439 // Unused images are safe to discard since we know that no display list
440 // references them. We Want to do this because in some contrived cases
441 // we can end up generating a lot of offscreen transactions that produce
442 // a lot of unused images without sending a non-offscreen transaction
443 // to clean them up.
444 mStateManager.DiscardUnusedImagesInTransaction(resourceUpdates);
445 } else {
446 // Don't discard images and fonts in an offscreen transaction. It won't
447 // replace the display list in the active scene so the images may still
448 // be used by the previous (which remains current) display list.
449 mStateManager.DiscardImagesInTransaction(resourceUpdates);
450 WrBridge()->RemoveExpiredFontKeys(resourceUpdates);
451 }
452
453 // Skip the synchronization for buffer since we also skip the painting during
454 // device-reset status.
455 if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) {
456 if (WrBridge()->GetSyncObject() &&
457 WrBridge()->GetSyncObject()->IsSyncObjectValid()) {
458 WrBridge()->GetSyncObject()->Synchronize();
459 }
460 }
461
462 GetCompositorBridgeChild()->EndCanvasTransaction();
463
464 {
465 AUTO_PROFILER_MARKER("ForwardDPTransaction", GRAPHICS)AutoProfilerTracing raiiObject465( "ForwardDPTransaction", geckoprofiler
::category::GRAPHICS, mozilla::Nothing())
;
466 DisplayListData dlData;
467 diplayListBuilder->End(dlData);
468 resourceUpdates.Flush(dlData.mResourceUpdates, dlData.mSmallShmems,
469 dlData.mLargeShmems);
470 dlData.mRect =
471 LayoutDeviceRect(LayoutDevicePoint(), LayoutDeviceSize(size));
472 dlData.mScrollData.emplace(std::move(mScrollData));
473 dlData.mDLDesc.gecko_display_list_type =
474 aDisplayListBuilder && aDisplayListBuilder->PartialBuildFailed()
475 ? wr::GeckoDisplayListType::Full(aGeckoDLBuildTime)
476 : wr::GeckoDisplayListType::Partial(aGeckoDLBuildTime);
477
478 // convert from nanoseconds to microseconds
479 auto duration = TimeDuration::FromMicroseconds(
480 double(dlData.mDLDesc.builder_finish_time -
481 dlData.mDLDesc.builder_start_time) /
482 1000.);
483 PerfStats::RecordMeasurement(PerfStats::Metric::WrDisplayListBuilding,
484 duration);
485 WrBridge()->EndTransaction(
486 std::move(dlData), mLatestTransactionId, containsSVGGroup,
487 mTransactionIdAllocator->GetVsyncId(), aRenderOffscreen,
488 mTransactionIdAllocator->GetVsyncStart(), refreshStart,
489 mTransactionStart, mURL);
490
491 WrBridge()->SendSetFocusTarget(mFocusTarget);
492 mFocusTarget = FocusTarget();
493 }
494
495 // Discard animations after calling WrBridge()->EndTransaction().
496 // It updates mWrEpoch in WebRenderBridgeParent. The updated mWrEpoch is
497 // necessary for deleting animations at the correct time.
498 mStateManager.DiscardCompositorAnimations();
499
500 mTransactionStart = TimeStamp();
501
502 MakeSnapshotIfRequired(size);
503 mNeedsComposite = false;
504}
505
506void WebRenderLayerManager::SetFocusTarget(const FocusTarget& aFocusTarget) {
507 mFocusTarget = aFocusTarget;
508}
509
510bool WebRenderLayerManager::AsyncPanZoomEnabled() const {
511 return mWidget->AsyncPanZoomEnabled();
512}
513
514IntRect ToOutsideIntRect(const gfxRect& aRect) {
515 return IntRect::RoundOut(aRect.X(), aRect.Y(), aRect.Width(), aRect.Height());
516}
517
518void WebRenderLayerManager::MakeSnapshotIfRequired(LayoutDeviceIntSize aSize) {
519 auto clearTarget = MakeScopeExit([&] { mTarget = nullptr; });
520
521 if (!mTarget || !mTarget->GetDrawTarget() || aSize.IsEmpty()) {
522 return;
523 }
524
525 // XXX Add other TextureData supports.
526 // Only BufferTexture is supported now.
527
528 // TODO: fixup for proper surface format.
529 // The GLES spec only guarantees that RGBA can be used with glReadPixels,
530 // so on Android we use RGBA.
531 SurfaceFormat format =
532#ifdef MOZ_WIDGET_ANDROID
533 SurfaceFormat::R8G8B8A8;
534#else
535 SurfaceFormat::B8G8R8A8;
536#endif
537 RefPtr<TextureClient> texture = TextureClient::CreateForRawBufferAccess(
538 WrBridge(), format, aSize.ToUnknownSize(), BackendType::SKIA,
539 TextureFlags::SNAPSHOT);
540 if (!texture) {
541 return;
542 }
543
544 // The other side knows our ContentParentId and WebRenderBridgeChild will
545 // ignore the one provided here in favour of what WebRenderBridgeParent
546 // already has.
547 texture->InitIPDLActor(WrBridge(), dom::ContentParentId());
548 if (!texture->GetIPDLActor()) {
549 return;
550 }
551
552 IntRect bounds = ToOutsideIntRect(mTarget->GetClipExtents());
553 bool needsYFlip = false;
554 if (!WrBridge()->SendGetSnapshot(WrapNotNull(texture->GetIPDLActor()),
555 &needsYFlip)) {
556 return;
557 }
558
559 TextureClientAutoLock autoLock(texture, OpenMode::OPEN_READ_ONLY);
560 if (!autoLock.Succeeded()) {
561 return;
562 }
563 RefPtr<DrawTarget> drawTarget = texture->BorrowDrawTarget();
564 if (!drawTarget || !drawTarget->IsValid()) {
565 return;
566 }
567 RefPtr<SourceSurface> snapshot = drawTarget->Snapshot();
568 /*
569 static int count = 0;
570 char filename[100];
571 snprintf(filename, 100, "output%d.png", count++);
572 printf_stderr("Writing to :%s\n", filename);
573 gfxUtils::WriteAsPNG(snapshot, filename);
574 */
575
576 Rect dst(bounds.X(), bounds.Y(), bounds.Width(), bounds.Height());
577 Rect src(0, 0, bounds.Width(), bounds.Height());
578
579 Matrix m;
580 if (needsYFlip) {
581 m = Matrix::Scaling(1.0, -1.0).PostTranslate(0.0, aSize.height);
582 }
583 SurfacePattern pattern(snapshot, ExtendMode::CLAMP, m);
584 DrawTarget* dt = mTarget->GetDrawTarget();
585 MOZ_RELEASE_ASSERT(dt)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(dt)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(dt))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("dt", "./../../../gfx/layers/wr/WebRenderLayerManager.cpp"
, 585); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "dt" ")"
); do { MOZ_CrashSequence(__null, 585); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
586 dt->FillRect(dst, pattern);
587
588 mTarget = nullptr;
589}
590
591void WebRenderLayerManager::DiscardImages() {
592 wr::IpcResourceUpdateQueue resources(WrBridge());
593 mStateManager.DiscardImagesInTransaction(resources);
594 WrBridge()->UpdateResources(resources);
595}
596
597void WebRenderLayerManager::DiscardLocalImages() {
598 mStateManager.DiscardLocalImages();
599}
600
601void WebRenderLayerManager::DidComposite(
602 TransactionId aTransactionId, const mozilla::TimeStamp& aCompositeStart,
603 const mozilla::TimeStamp& aCompositeEnd) {
604 if (IsDestroyed()) {
605 return;
606 }
607
608 MOZ_ASSERT(mWidget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mWidget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mWidget))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mWidget", "./../../../gfx/layers/wr/WebRenderLayerManager.cpp"
, 608); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWidget" ")"
); do { MOZ_CrashSequence(__null, 608); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
609
610 // Notifying the observers may tick the refresh driver which can cause
611 // a lot of different things to happen that may affect the lifetime of
612 // this layer manager. So let's make sure this object stays alive until
613 // the end of the method invocation.
614 RefPtr<WebRenderLayerManager> selfRef = this;
615
616 // |aTransactionId| will be > 0 if the compositor is acknowledging a shadow
617 // layers transaction.
618 if (aTransactionId.IsValid()) {
619 nsIWidgetListener* listener = mWidget->GetWidgetListener();
620 if (listener) {
621 listener->DidCompositeWindow(aTransactionId, aCompositeStart,
622 aCompositeEnd);
623 }
624 listener = mWidget->GetAttachedWidgetListener();
625 if (listener) {
626 listener->DidCompositeWindow(aTransactionId, aCompositeStart,
627 aCompositeEnd);
628 }
629 if (mTransactionIdAllocator) {
630 mTransactionIdAllocator->NotifyTransactionCompleted(aTransactionId);
631 }
632 }
633}
634
635void WebRenderLayerManager::ClearCachedResources() {
636 if (!WrBridge()->IPCOpen()) {
637 gfxCriticalNotemozilla::gfx::CriticalLog(mozilla::gfx::CriticalLog::DefaultOptions
(false))
<< "IPC Channel is already torn down unexpectedly\n";
638 return;
639 }
640 WrBridge()->BeginClearCachedResources();
641 // We flush any pending async resource updates before we clear the display
642 // list items because some resources (e.g. images) might be shared between
643 // multiple layer managers, not get freed here, and we want to keep their
644 // states consistent.
645 mStateManager.FlushAsyncResourceUpdates();
646 mWebRenderCommandBuilder.ClearCachedResources();
647 DiscardImages();
648 mStateManager.ClearCachedResources();
649 if (CompositorBridgeChild* compositorBridge = GetCompositorBridgeChild()) {
650 compositorBridge->ClearCachedResources();
651 }
652 WrBridge()->EndClearCachedResources();
653}
654
655void WebRenderLayerManager::WrUpdated() {
656 ClearAsyncAnimations();
657 mStateManager.mAsyncResourceUpdates.reset();
658 mWebRenderCommandBuilder.ClearCachedResources();
659 DiscardLocalImages();
660 if (mWidget) {
661 if (dom::BrowserChild* browserChild = mWidget->GetOwningBrowserChild()) {
662 browserChild->SchedulePaint();
663 }
664 }
665}
666
667void WebRenderLayerManager::UpdateTextureFactoryIdentifier(
668 const TextureFactoryIdentifier& aNewIdentifier) {
669 WrBridge()->IdentifyTextureHost(aNewIdentifier);
670}
671
672TextureFactoryIdentifier WebRenderLayerManager::GetTextureFactoryIdentifier() {
673 return WrBridge()->GetTextureFactoryIdentifier();
674}
675
676void WebRenderLayerManager::SetTransactionIdAllocator(
677 TransactionIdAllocator* aAllocator) {
678 // When changing the refresh driver, the previous refresh driver may never
679 // receive updates of pending transactions it's waiting for. So clear the
680 // waiting state before assigning another refresh driver.
681 if (mTransactionIdAllocator && (aAllocator != mTransactionIdAllocator)) {
682 mTransactionIdAllocator->ClearPendingTransactions();
683
684 // We should also reset the transaction id of the new allocator to previous
685 // allocator's last transaction id, so that completed transactions for
686 // previous allocator will be ignored and won't confuse the new allocator.
687 if (aAllocator) {
688 aAllocator->ResetInitialTransactionId(
689 mTransactionIdAllocator->LastTransactionId());
690 }
691 }
692
693 mTransactionIdAllocator = aAllocator;
694}
695
696TransactionId WebRenderLayerManager::GetLastTransactionId() {
697 return mLatestTransactionId;
698}
699
700void WebRenderLayerManager::FlushRendering(wr::RenderReasons aReasons) {
701 CompositorBridgeChild* cBridge = GetCompositorBridgeChild();
702 if (!cBridge) {
703 return;
704 }
705 MOZ_ASSERT(mWidget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mWidget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mWidget))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mWidget", "./../../../gfx/layers/wr/WebRenderLayerManager.cpp"
, 705); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mWidget" ")"
); do { MOZ_CrashSequence(__null, 705); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
706
707 // If widget bounds size is different from the last flush, consider
708 // this to be a resize. It's important to use GetClientSize here,
709 // because that has extra plumbing to support initial display cases
710 // where the widget doesn't yet have real bounds.
711 LayoutDeviceIntSize widgetSize = mWidget->GetClientSize();
712 bool resizing = widgetSize != mFlushWidgetSize;
713 mFlushWidgetSize = widgetSize;
714
715 if (resizing) {
716 aReasons = aReasons | wr::RenderReasons::RESIZE;
717 }
718
719 // Check for the conditions where we we force a sync flush. The first
720 // flush for this child should always be sync. Resizes should be
721 // sometimes be sync. Everything else can be async.
722 if (!mHasFlushedThisChild ||
723 (resizing && (mWidget->SynchronouslyRepaintOnResize() ||
724 StaticPrefs::layers_force_synchronous_resize()))) {
725 cBridge->SendFlushRendering(aReasons);
726 } else {
727 cBridge->SendFlushRenderingAsync(aReasons);
728 }
729
730 mHasFlushedThisChild = true;
731}
732
733void WebRenderLayerManager::WaitOnTransactionProcessed() {
734 CompositorBridgeChild* bridge = GetCompositorBridgeChild();
735 if (bridge) {
736 bridge->SendWaitOnTransactionProcessed();
737 }
738}
739
740void WebRenderLayerManager::SendInvalidRegion(const nsIntRegion& aRegion) {
741 // XXX Webrender does not support invalid region yet.
742
743#ifndef XP_WIN
744 WrBridge()->SendInvalidateRenderedFrame();
745#endif
746}
747
748void WebRenderLayerManager::ScheduleComposite(wr::RenderReasons aReasons) {
749 WrBridge()->SendScheduleComposite(aReasons);
750}
751
752already_AddRefed<PersistentBufferProvider>
753WebRenderLayerManager::CreatePersistentBufferProvider(
754 const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat,
755 bool aWillReadFrequently) {
756 // Only initialize devices if hardware acceleration may possibly be used.
757 // Remoting moves hardware usage out-of-process, while will-read-frequently
758 // avoids hardware acceleration entirely.
759 if (!aWillReadFrequently && !gfxPlatform::UseRemoteCanvas()) {
760#ifdef XP_WIN
761 // Any kind of hardware acceleration is incompatible with Win32k Lockdown
762 // We don't initialize devices here so that PersistentBufferProviderShared
763 // will fall back to using a piece of shared memory as a backing for the
764 // canvas
765 if (!IsWin32kLockedDown()) {
766 gfxPlatform::GetPlatform()->EnsureDevicesInitialized();
767 }
768#else
769 gfxPlatform::GetPlatform()->EnsureDevicesInitialized();
770#endif
771 }
772
773 RefPtr<PersistentBufferProvider> provider =
774 PersistentBufferProviderShared::Create(
775 aSize, aFormat, AsKnowsCompositor(), aWillReadFrequently);
776 if (provider) {
777 return provider.forget();
778 }
779
780 return WindowRenderer::CreatePersistentBufferProvider(aSize, aFormat);
781}
782
783void WebRenderLayerManager::ClearAsyncAnimations() {
784 mStateManager.ClearAsyncAnimations();
785}
786
787void WebRenderLayerManager::WrReleasedImages(
788 const nsTArray<wr::ExternalImageKeyPair>& aPairs) {
789 mStateManager.WrReleasedImages(aPairs);
790}
791
792void WebRenderLayerManager::GetFrameUniformity(FrameUniformityData* aOutData) {
793 WrBridge()->SendGetFrameUniformity(aOutData);
794}
795
796/*static*/
797void WebRenderLayerManager::LayerUserDataDestroy(void* data) {
798 delete static_cast<LayerUserData*>(data);
799}
800
801UniquePtr<LayerUserData> WebRenderLayerManager::RemoveUserData(void* aKey) {
802 UniquePtr<LayerUserData> d(static_cast<LayerUserData*>(
803 mUserData.Remove(static_cast<gfx::UserDataKey*>(aKey))));
804 return d;
805}
806
807void WebRenderLayerManager::
808 ClearAndNotifyOfFullTransactionPendingScrollInfoUpdate() {
809 for (ScrollableLayerGuid::ViewID update : mPendingScrollUpdates.Keys()) {
810 nsLayoutUtils::NotifyApzTransaction(update);
811 }
812 mPendingScrollUpdates.Clear();
813}
814
815bool WebRenderLayerManager::AddPendingScrollUpdateForNextTransaction(
816 ScrollableLayerGuid::ViewID aScrollId,
817 const ScrollPositionUpdate& aUpdateInfo) {
818 mPendingScrollUpdates.LookupOrInsert(aScrollId).AppendElement(aUpdateInfo);
819 return true;
820}
821
822// See equivalent function in ClientLayerManager
823void WebRenderLayerManager::LogTestDataForCurrentPaint(
824 ScrollableLayerGuid::ViewID aScrollId, const std::string& aKey,
825 const std::string& aValue) {
826 MOZ_ASSERT(StaticPrefs::apz_test_logging_enabled(), "don't call me")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(StaticPrefs::apz_test_logging_enabled())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(StaticPrefs::apz_test_logging_enabled()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("StaticPrefs::apz_test_logging_enabled()"
" (" "don't call me" ")", "./../../../gfx/layers/wr/WebRenderLayerManager.cpp"
, 826); AnnotateMozCrashReason("MOZ_ASSERT" "(" "StaticPrefs::apz_test_logging_enabled()"
") (" "don't call me" ")"); do { MOZ_CrashSequence(__null, 826
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
827 mApzTestData->LogTestDataForPaint(mPaintSequenceNumber, aScrollId, aKey,
828 aValue);
829}
830void WebRenderLayerManager::LogAdditionalTestData(const std::string& aKey,
831 const std::string& aValue) {
832 MOZ_ASSERT(StaticPrefs::apz_test_logging_enabled(), "don't call me")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(StaticPrefs::apz_test_logging_enabled())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(StaticPrefs::apz_test_logging_enabled()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("StaticPrefs::apz_test_logging_enabled()"
" (" "don't call me" ")", "./../../../gfx/layers/wr/WebRenderLayerManager.cpp"
, 832); AnnotateMozCrashReason("MOZ_ASSERT" "(" "StaticPrefs::apz_test_logging_enabled()"
") (" "don't call me" ")"); do { MOZ_CrashSequence(__null, 832
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
833 mApzTestData->RecordAdditionalData(aKey, aValue);
834}
835
836} // namespace layers
837} // namespace mozilla