| File: | root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/layers/./../../../gfx/layers/wr/WebRenderLayerManager.cpp |
| Warning: | line 395, column 7 Value stored to 'builderDumpIndex' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 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 | |
| 29 | namespace mozilla { |
| 30 | |
| 31 | namespace gfx { |
| 32 | wr::PipelineId GetTemporaryWebRenderPipelineId(wr::PipelineId aMainPipeline); |
| 33 | } |
| 34 | |
| 35 | using namespace gfx; |
| 36 | |
| 37 | namespace layers { |
| 38 | |
| 39 | bool WebRenderLayerManager::sHasInitialized = false; |
| 40 | |
| 41 | WebRenderLayerManager::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 | |
| 59 | KnowsCompositor* WebRenderLayerManager::AsKnowsCompositor() { return mWrChild; } |
| 60 | |
| 61 | /* static */ |
| 62 | RefPtr<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 | |
| 99 | bool 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 | |
| 137 | void WebRenderLayerManager::Destroy() { DoDestroy(/* aIsSync */ false); } |
| 138 | |
| 139 | void 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 | |
| 177 | WebRenderLayerManager::~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 | |
| 182 | CompositorBridgeChild* WebRenderLayerManager::GetCompositorBridgeChild() { |
| 183 | return WrBridge()->GetCompositorBridgeChild(); |
| 184 | } |
| 185 | |
| 186 | void 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 | |
| 200 | uint32_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 | |
| 210 | void WebRenderLayerManager::StopFrameTimeRecording( |
| 211 | uint32_t aStartIndex, nsTArray<float>& aFrameIntervals) { |
| 212 | CompositorBridgeChild* renderer = GetCompositorBridgeChild(); |
| 213 | if (renderer) { |
| 214 | renderer->SendStopFrameTimeRecording(aStartIndex, &aFrameIntervals); |
| 215 | } |
| 216 | } |
| 217 | |
| 218 | void WebRenderLayerManager::TakeCompositionPayloads( |
| 219 | nsTArray<CompositionPayload>& aPayloads) { |
| 220 | aPayloads.Clear(); |
| 221 | |
| 222 | std::swap(mPayload, aPayloads); |
| 223 | } |
| 224 | |
| 225 | bool 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 | |
| 235 | bool 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 | |
| 254 | bool 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 | |
| 332 | void 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(); |
| 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( |
Value stored to 'builderDumpIndex' is never read | |
| 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 | |
| 506 | void WebRenderLayerManager::SetFocusTarget(const FocusTarget& aFocusTarget) { |
| 507 | mFocusTarget = aFocusTarget; |
| 508 | } |
| 509 | |
| 510 | bool WebRenderLayerManager::AsyncPanZoomEnabled() const { |
| 511 | return mWidget->AsyncPanZoomEnabled(); |
| 512 | } |
| 513 | |
| 514 | IntRect ToOutsideIntRect(const gfxRect& aRect) { |
| 515 | return IntRect::RoundOut(aRect.X(), aRect.Y(), aRect.Width(), aRect.Height()); |
| 516 | } |
| 517 | |
| 518 | void 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 | |
| 591 | void WebRenderLayerManager::DiscardImages() { |
| 592 | wr::IpcResourceUpdateQueue resources(WrBridge()); |
| 593 | mStateManager.DiscardImagesInTransaction(resources); |
| 594 | WrBridge()->UpdateResources(resources); |
| 595 | } |
| 596 | |
| 597 | void WebRenderLayerManager::DiscardLocalImages() { |
| 598 | mStateManager.DiscardLocalImages(); |
| 599 | } |
| 600 | |
| 601 | void 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 | |
| 635 | void 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 | |
| 655 | void 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 | |
| 667 | void WebRenderLayerManager::UpdateTextureFactoryIdentifier( |
| 668 | const TextureFactoryIdentifier& aNewIdentifier) { |
| 669 | WrBridge()->IdentifyTextureHost(aNewIdentifier); |
| 670 | } |
| 671 | |
| 672 | TextureFactoryIdentifier WebRenderLayerManager::GetTextureFactoryIdentifier() { |
| 673 | return WrBridge()->GetTextureFactoryIdentifier(); |
| 674 | } |
| 675 | |
| 676 | void 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 | |
| 696 | TransactionId WebRenderLayerManager::GetLastTransactionId() { |
| 697 | return mLatestTransactionId; |
| 698 | } |
| 699 | |
| 700 | void 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 | |
| 733 | void WebRenderLayerManager::WaitOnTransactionProcessed() { |
| 734 | CompositorBridgeChild* bridge = GetCompositorBridgeChild(); |
| 735 | if (bridge) { |
| 736 | bridge->SendWaitOnTransactionProcessed(); |
| 737 | } |
| 738 | } |
| 739 | |
| 740 | void 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 | |
| 748 | void WebRenderLayerManager::ScheduleComposite(wr::RenderReasons aReasons) { |
| 749 | WrBridge()->SendScheduleComposite(aReasons); |
| 750 | } |
| 751 | |
| 752 | already_AddRefed<PersistentBufferProvider> |
| 753 | WebRenderLayerManager::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 | |
| 783 | void WebRenderLayerManager::ClearAsyncAnimations() { |
| 784 | mStateManager.ClearAsyncAnimations(); |
| 785 | } |
| 786 | |
| 787 | void WebRenderLayerManager::WrReleasedImages( |
| 788 | const nsTArray<wr::ExternalImageKeyPair>& aPairs) { |
| 789 | mStateManager.WrReleasedImages(aPairs); |
| 790 | } |
| 791 | |
| 792 | void WebRenderLayerManager::GetFrameUniformity(FrameUniformityData* aOutData) { |
| 793 | WrBridge()->SendGetFrameUniformity(aOutData); |
| 794 | } |
| 795 | |
| 796 | /*static*/ |
| 797 | void WebRenderLayerManager::LayerUserDataDestroy(void* data) { |
| 798 | delete static_cast<LayerUserData*>(data); |
| 799 | } |
| 800 | |
| 801 | UniquePtr<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 | |
| 807 | void WebRenderLayerManager:: |
| 808 | ClearAndNotifyOfFullTransactionPendingScrollInfoUpdate() { |
| 809 | for (ScrollableLayerGuid::ViewID update : mPendingScrollUpdates.Keys()) { |
| 810 | nsLayoutUtils::NotifyApzTransaction(update); |
| 811 | } |
| 812 | mPendingScrollUpdates.Clear(); |
| 813 | } |
| 814 | |
| 815 | bool 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 |
| 823 | void 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 | } |
| 830 | void 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 |