/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//* vim: set ts=8 sts=2 et sw=2 tw=80: *//* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */#include"WebRenderLayerManager.h"#include"Layers.h"#include"GeckoProfiler.h"#include"mozilla/StaticPrefs_apz.h"#include"mozilla/StaticPrefs_layers.h"#include"mozilla/dom/BrowserChild.h"#include"mozilla/gfx/DrawEventRecorder.h"#include"mozilla/gfx/gfxVars.h"#include"mozilla/layers/CompositorBridgeChild.h"#include"mozilla/layers/StackingContextHelper.h"#include"mozilla/layers/TextureClient.h"#include"mozilla/layers/TransactionIdAllocator.h"#include"mozilla/layers/WebRenderBridgeChild.h"#include"mozilla/layers/UpdateImageHelper.h"#include"nsDisplayList.h"#include"nsLayoutUtils.h"#include"WebRenderCanvasRenderer.h"#include"LayerUserData.h"#ifdef XP_WIN# include "gfxDWriteFonts.h"#endifnamespacemozilla{usingnamespacegfx;namespacelayers{WebRenderLayerManager::WebRenderLayerManager(nsIWidget*aWidget):mWidget(aWidget),mLatestTransactionId{0},mNeedsComposite(false),mIsFirstPaint(false),mDestroyed(false),mTarget(nullptr),mPaintSequenceNumber(0),mWebRenderCommandBuilder(this){MOZ_COUNT_CTOR(WebRenderLayerManager);mStateManager.mLayerManager=this;if(XRE_IsContentProcess()&&StaticPrefs::gfx_webrender_enable_item_cache_AtStartup()){staticconstsize_tkInitialCacheSize=1024;staticconstsize_tkMaximumCacheSize=10240;mDisplayItemCache.SetCapacity(kInitialCacheSize,kMaximumCacheSize);}}KnowsCompositor*WebRenderLayerManager::AsKnowsCompositor(){returnmWrChild;}boolWebRenderLayerManager::Initialize(PCompositorBridgeChild*aCBChild,wr::PipelineIdaLayersId,TextureFactoryIdentifier*aTextureFactoryIdentifier,nsCString&aError){MOZ_ASSERT(mWrChild==nullptr);MOZ_ASSERT(aTextureFactoryIdentifier);// When we fail to initialize WebRender, it is useful to know if it has ever// succeeded, or if this is the first attempt.staticboolhasInitialized=false;WindowKindwindowKind;if(mWidget->WindowType()!=eWindowType_popup){windowKind=WindowKind::MAIN;}else{windowKind=WindowKind::SECONDARY;}LayoutDeviceIntSizesize=mWidget->GetClientSize();// Check widget sizeif(XRE_IsParentProcess()&&(size.width<0||size.width>wr::MAX_RENDER_TASK_SIZE||size.height<0||size.height>wr::MAX_RENDER_TASK_SIZE)){gfxCriticalNote<<"Widget size is not valid "<<size;}PWebRenderBridgeChild*bridge=aCBChild->SendPWebRenderBridgeConstructor(aLayersId,size,windowKind);if(!bridge){// This should only fail if we attempt to access a layer we don't have// permission for, or more likely, the GPU process crashed again during// reinitialization. We can expect to be notified again to reinitialize// (which may or may not be using WebRender).gfxCriticalNote<<"Failed to create WebRenderBridgeChild.";aError.Assign(hasInitialized?"FEATURE_FAILURE_WEBRENDER_INITIALIZE_IPDL_POST"_ns:"FEATURE_FAILURE_WEBRENDER_INITIALIZE_IPDL_FIRST"_ns);returnfalse;}TextureFactoryIdentifiertextureFactoryIdentifier;wr::MaybeIdNamespaceidNamespace;// Sync ipcif(!bridge->SendEnsureConnected(&textureFactoryIdentifier,&idNamespace,&aError)){gfxCriticalNote<<"Failed as lost WebRenderBridgeChild.";aError.Assign(hasInitialized?"FEATURE_FAILURE_WEBRENDER_INITIALIZE_SYNC_POST"_ns:"FEATURE_FAILURE_WEBRENDER_INITIALIZE_SYNC_FIRST"_ns);returnfalse;}if(textureFactoryIdentifier.mParentBackend==LayersBackend::LAYERS_NONE||idNamespace.isNothing()){gfxCriticalNote<<"Failed to connect WebRenderBridgeChild.";aError.Append(hasInitialized?"_POST"_ns:"_FIRST"_ns);returnfalse;}mWrChild=static_cast<WebRenderBridgeChild*>(bridge);WrBridge()->SetWebRenderLayerManager(this);WrBridge()->IdentifyTextureHost(textureFactoryIdentifier);WrBridge()->SetNamespace(idNamespace.ref());*aTextureFactoryIdentifier=textureFactoryIdentifier;mDLBuilder=MakeUnique<wr::DisplayListBuilder>(WrBridge()->GetPipeline(),WrBridge()->GetWebRenderBackend());hasInitialized=true;returntrue;}voidWebRenderLayerManager::Destroy(){DoDestroy(/* aIsSync */false);}voidWebRenderLayerManager::DoDestroy(boolaIsSync){MOZ_ASSERT(NS_IsMainThread());if(IsDestroyed()){return;}mDLBuilder=nullptr;mUserData.Destroy();mPartialPrerenderedAnimations.Clear();mStateManager.Destroy();if(WrBridge()){WrBridge()->Destroy(aIsSync);}mWebRenderCommandBuilder.Destroy();if(mTransactionIdAllocator){// Make sure to notify the refresh driver just in case it's waiting on a// pending transaction. Do this at the top of the event loop so we don't// cause a paint to occur during compositor shutdown.RefPtr<TransactionIdAllocator>allocator=mTransactionIdAllocator;TransactionIdid=mLatestTransactionId;RefPtr<Runnable>task=NS_NewRunnableFunction("TransactionIdAllocator::NotifyTransactionCompleted",[allocator,id]()->void{allocator->ClearPendingTransactions();allocator->NotifyTransactionCompleted(id);});NS_DispatchToMainThread(task.forget());}// Forget the widget pointer in case we outlive our owning widget.mWidget=nullptr;mDestroyed=true;}WebRenderLayerManager::~WebRenderLayerManager(){Destroy();MOZ_COUNT_DTOR(WebRenderLayerManager);}CompositorBridgeChild*WebRenderLayerManager::GetCompositorBridgeChild(){returnWrBridge()->GetCompositorBridgeChild();}voidWebRenderLayerManager::GetBackendName(nsAString&name){if(WrBridge()->UsingSoftwareWebRenderD3D11()){name.AssignLiteral("WebRender (Software D3D11)");}elseif(WrBridge()->UsingSoftwareWebRenderOpenGL()){name.AssignLiteral("WebRender (Software OpenGL)");}elseif(WrBridge()->UsingSoftwareWebRender()){name.AssignLiteral("WebRender (Software)");}else{name.AssignLiteral("WebRender");}}uint32_tWebRenderLayerManager::StartFrameTimeRecording(int32_taBufferSize){CompositorBridgeChild*renderer=GetCompositorBridgeChild();if(renderer){uint32_tstartIndex;renderer->SendStartFrameTimeRecording(aBufferSize,&startIndex);returnstartIndex;}return-1;}voidWebRenderLayerManager::StopFrameTimeRecording(uint32_taStartIndex,nsTArray<float>&aFrameIntervals){CompositorBridgeChild*renderer=GetCompositorBridgeChild();if(renderer){renderer->SendStopFrameTimeRecording(aStartIndex,&aFrameIntervals);}}voidWebRenderLayerManager::TakeCompositionPayloads(nsTArray<CompositionPayload>&aPayloads){aPayloads.Clear();std::swap(mPayload,aPayloads);}boolWebRenderLayerManager::BeginTransactionWithTarget(gfxContext*aTarget,constnsCString&aURL){mTarget=aTarget;returnBeginTransaction(aURL);}boolWebRenderLayerManager::BeginTransaction(constnsCString&aURL){if(!WrBridge()->IPCOpen()){gfxCriticalNote<<"IPC Channel is already torn down unexpectedly\n";returnfalse;}mTransactionStart=TimeStamp::Now();mURL=aURL;// Increment the paint sequence number even if test logging isn't// enabled in this process; it may be enabled in the parent process,// and the parent process expects unique sequence numbers.++mPaintSequenceNumber;if(StaticPrefs::apz_test_logging_enabled()){mApzTestData.StartNewPaint(mPaintSequenceNumber);}returntrue;}boolWebRenderLayerManager::EndEmptyTransaction(EndTransactionFlagsaFlags){// If we haven't sent a display list (since creation or since the last time we// sent ClearDisplayList to the parent) then we can't do an empty transaction// because the parent doesn't have a display list for us and we need to send a// display list first.if(!WrBridge()->GetSentDisplayList()){returnfalse;}mDisplayItemCache.SkipWaitingForPartialDisplayList();// Since we don't do repeat transactions right now, just set the timemAnimationReadyTime=TimeStamp::Now();mLatestTransactionId=mTransactionIdAllocator->GetTransactionId(/*aThrottle*/true);if(aFlags&EndTransactionFlags::END_NO_COMPOSITE&&!mWebRenderCommandBuilder.NeedsEmptyTransaction()){if(mPendingScrollUpdates.IsEmpty()){MOZ_ASSERT(!mTarget);WrBridge()->SendSetFocusTarget(mFocusTarget);// Revoke TransactionId to trigger next paint.mTransactionIdAllocator->RevokeTransactionId(mLatestTransactionId);mLatestTransactionId=mLatestTransactionId.Prev();returntrue;}}LayoutDeviceIntSizesize=mWidget->GetClientSize();WrBridge()->BeginTransaction();mWebRenderCommandBuilder.EmptyTransaction();// Get the time of when the refresh driver start its tick (if available),// otherwise use the time of when LayerManager::BeginTransaction was called.TimeStamprefreshStart=mTransactionIdAllocator->GetTransactionStart();if(!refreshStart){refreshStart=mTransactionStart;}// Skip the synchronization for buffer since we also skip the painting during// device-reset status.if(!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()){if(WrBridge()->GetSyncObject()&&WrBridge()->GetSyncObject()->IsSyncObjectValid()){WrBridge()->GetSyncObject()->Synchronize();}}GetCompositorBridgeChild()->EndCanvasTransaction();Maybe<TransactionData>transactionData;if(mStateManager.mAsyncResourceUpdates||!mPendingScrollUpdates.IsEmpty()||WrBridge()->HasWebRenderParentCommands()){transactionData.emplace();transactionData->mIdNamespace=WrBridge()->GetNamespace();transactionData->mPaintSequenceNumber=mPaintSequenceNumber;if(mStateManager.mAsyncResourceUpdates){mStateManager.mAsyncResourceUpdates->Flush(transactionData->mResourceUpdates,transactionData->mSmallShmems,transactionData->mLargeShmems);}transactionData->mScrollUpdates=std::move(mPendingScrollUpdates);for(constauto&scrollId:transactionData->mScrollUpdates.Keys()){nsLayoutUtils::NotifyPaintSkipTransaction(/*scroll id=*/scrollId);}}Maybe<wr::IpcResourceUpdateQueue>nothing;WrBridge()->EndEmptyTransaction(mFocusTarget,std::move(transactionData),mLatestTransactionId,mTransactionIdAllocator->GetVsyncId(),mTransactionIdAllocator->GetVsyncStart(),refreshStart,mTransactionStart,mURL);mTransactionStart=TimeStamp();MakeSnapshotIfRequired(size);returntrue;}voidWebRenderLayerManager::EndTransactionWithoutLayer(nsDisplayList*aDisplayList,nsDisplayListBuilder*aDisplayListBuilder,WrFiltersHolder&&aFilters,WebRenderBackgroundData*aBackground,constdoubleaGeckoDLBuildTime){AUTO_PROFILER_TRACING_MARKER("Paint","RenderLayers",GRAPHICS);// Since we don't do repeat transactions right now, just set the timemAnimationReadyTime=TimeStamp::Now();WrBridge()->BeginTransaction();LayoutDeviceIntSizesize=mWidget->GetClientSize();mDLBuilder->Begin(&mDisplayItemCache);wr::IpcResourceUpdateQueueresourceUpdates(WrBridge());wr::usizebuilderDumpIndex=0;boolcontainsSVGGroup=false;booldumpEnabled=mWebRenderCommandBuilder.ShouldDumpDisplayList(aDisplayListBuilder);Maybe<AutoDisplayItemCacheSuppressor>cacheSuppressor;if(dumpEnabled){cacheSuppressor.emplace(&mDisplayItemCache);printf_stderr("-- WebRender display list build --\n");}if(XRE_IsContentProcess()&&StaticPrefs::gfx_webrender_debug_dl_dump_content_serialized()){mDLBuilder->DumpSerializedDisplayList();}if(aDisplayList){MOZ_ASSERT(aDisplayListBuilder&&!aBackground);mDisplayItemCache.SetDisplayList(aDisplayListBuilder,aDisplayList);mWebRenderCommandBuilder.BuildWebRenderCommands(*mDLBuilder,resourceUpdates,aDisplayList,aDisplayListBuilder,mScrollData,std::move(aFilters));aDisplayListBuilder->NotifyAndClearScrollFrames();builderDumpIndex=mWebRenderCommandBuilder.GetBuilderDumpIndex();containsSVGGroup=mWebRenderCommandBuilder.GetContainsSVGGroup();}else{// ViewToPaint does not have frame yet, then render only background clolor.MOZ_ASSERT(!aDisplayListBuilder&&aBackground);aBackground->AddWebRenderCommands(*mDLBuilder);if(dumpEnabled){printf_stderr("(no display list; background only)\n");builderDumpIndex=mDLBuilder->Dump(/*indent*/1,Some(builderDumpIndex),Nothing());}}mWidget->AddWindowOverlayWebRenderCommands(WrBridge(),*mDLBuilder,resourceUpdates);if(dumpEnabled){printf_stderr("(window overlay)\n");Unused<<mDLBuilder->Dump(/*indent*/1,Some(builderDumpIndex),Nothing());}if(AsyncPanZoomEnabled()){if(mIsFirstPaint){mScrollData.SetIsFirstPaint();mIsFirstPaint=false;}mScrollData.SetPaintSequenceNumber(mPaintSequenceNumber);if(dumpEnabled){std::stringstreamstr;str<<mScrollData;print_stderr(str);}}// Since we're sending a full mScrollData that will include the new scroll// offsets, and we can throw away the pending scroll updates we had kept for// an empty transaction.autoscrollIdsUpdated=ClearPendingScrollInfoUpdate();for(ScrollableLayerGuid::ViewIDupdate:scrollIdsUpdated){nsLayoutUtils::NotifyPaintSkipTransaction(update);}mLatestTransactionId=mTransactionIdAllocator->GetTransactionId(/*aThrottle*/true);// Get the time of when the refresh driver start its tick (if available),// otherwise use the time of when LayerManager::BeginTransaction was called.TimeStamprefreshStart=mTransactionIdAllocator->GetTransactionStart();if(!refreshStart){refreshStart=mTransactionStart;}if(mStateManager.mAsyncResourceUpdates){if(resourceUpdates.IsEmpty()){resourceUpdates.ReplaceResources(std::move(mStateManager.mAsyncResourceUpdates.ref()));}else{WrBridge()->UpdateResources(mStateManager.mAsyncResourceUpdates.ref());}mStateManager.mAsyncResourceUpdates.reset();}mStateManager.DiscardImagesInTransaction(resourceUpdates);WrBridge()->RemoveExpiredFontKeys(resourceUpdates);// Skip the synchronization for buffer since we also skip the painting during// device-reset status.if(!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()){if(WrBridge()->GetSyncObject()&&WrBridge()->GetSyncObject()->IsSyncObjectValid()){WrBridge()->GetSyncObject()->Synchronize();}}GetCompositorBridgeChild()->EndCanvasTransaction();{AUTO_PROFILER_TRACING_MARKER("Paint","ForwardDPTransaction",GRAPHICS);DisplayListDatadlData;mDLBuilder->End(dlData);resourceUpdates.Flush(dlData.mResourceUpdates,dlData.mSmallShmems,dlData.mLargeShmems);dlData.mRect=LayoutDeviceRect(LayoutDevicePoint(),LayoutDeviceSize(size));dlData.mScrollData.emplace(std::move(mScrollData));dlData.mDLDesc.gecko_display_list_type=aDisplayListBuilder&&aDisplayListBuilder->PartialBuildFailed()?wr::GeckoDisplayListType::Full(aGeckoDLBuildTime):wr::GeckoDisplayListType::Partial(aGeckoDLBuildTime);boolret=WrBridge()->EndTransaction(std::move(dlData),mLatestTransactionId,containsSVGGroup,mTransactionIdAllocator->GetVsyncId(),mTransactionIdAllocator->GetVsyncStart(),refreshStart,mTransactionStart,mURL);if(!ret){// Failed to send display list, reset display item cache state.mDisplayItemCache.Clear();}WrBridge()->SendSetFocusTarget(mFocusTarget);mFocusTarget=FocusTarget();}// Discard animations after calling WrBridge()->EndTransaction().// It updates mWrEpoch in WebRenderBridgeParent. The updated mWrEpoch is// necessary for deleting animations at the correct time.mStateManager.DiscardCompositorAnimations();mTransactionStart=TimeStamp();MakeSnapshotIfRequired(size);mNeedsComposite=false;}voidWebRenderLayerManager::SetFocusTarget(constFocusTarget&aFocusTarget){mFocusTarget=aFocusTarget;}boolWebRenderLayerManager::AsyncPanZoomEnabled()const{returnmWidget->AsyncPanZoomEnabled();}voidWebRenderLayerManager::MakeSnapshotIfRequired(LayoutDeviceIntSizeaSize){if(!mTarget||aSize.IsEmpty()){return;}// XXX Add other TextureData supports.// Only BufferTexture is supported now.// TODO: fixup for proper surface format.// The GLES spec only guarantees that RGBA can be used with glReadPixels,// so on Android we use RGBA.SurfaceFormatformat=#ifdef MOZ_WIDGET_ANDROIDSurfaceFormat::R8G8B8A8;#elseSurfaceFormat::B8G8R8A8;#endifRefPtr<TextureClient>texture=TextureClient::CreateForRawBufferAccess(WrBridge(),format,aSize.ToUnknownSize(),BackendType::SKIA,TextureFlags::SNAPSHOT);if(!texture){return;}texture->InitIPDLActor(WrBridge());if(!texture->GetIPDLActor()){return;}IntRectbounds=ToOutsideIntRect(mTarget->GetClipExtents());boolneedsYFlip=false;if(!WrBridge()->SendGetSnapshot(texture->GetIPDLActor(),&needsYFlip)){return;}TextureClientAutoLockautoLock(texture,OpenMode::OPEN_READ_ONLY);if(!autoLock.Succeeded()){return;}RefPtr<DrawTarget>drawTarget=texture->BorrowDrawTarget();if(!drawTarget||!drawTarget->IsValid()){return;}RefPtr<SourceSurface>snapshot=drawTarget->Snapshot();/* static int count = 0; char filename[100]; snprintf(filename, 100, "output%d.png", count++); printf_stderr("Writing to :%s\n", filename); gfxUtils::WriteAsPNG(snapshot, filename); */Rectdst(bounds.X(),bounds.Y(),bounds.Width(),bounds.Height());Rectsrc(0,0,bounds.Width(),bounds.Height());Matrixm;if(needsYFlip){m=Matrix::Scaling(1.0,-1.0).PostTranslate(0.0,aSize.height);}SurfacePatternpattern(snapshot,ExtendMode::CLAMP,m);DrawTarget*dt=mTarget->GetDrawTarget();MOZ_RELEASE_ASSERT(dt);dt->FillRect(dst,pattern);mTarget=nullptr;}voidWebRenderLayerManager::DiscardImages(){wr::IpcResourceUpdateQueueresources(WrBridge());mStateManager.DiscardImagesInTransaction(resources);WrBridge()->UpdateResources(resources);}voidWebRenderLayerManager::DiscardLocalImages(){mStateManager.DiscardLocalImages();}voidWebRenderLayerManager::SetLayersObserverEpoch(LayersObserverEpochaEpoch){if(WrBridge()->IPCOpen()){WrBridge()->SendSetLayersObserverEpoch(aEpoch);}}voidWebRenderLayerManager::DidComposite(TransactionIdaTransactionId,constmozilla::TimeStamp&aCompositeStart,constmozilla::TimeStamp&aCompositeEnd){if(IsDestroyed()){return;}MOZ_ASSERT(mWidget);// Notifying the observers may tick the refresh driver which can cause// a lot of different things to happen that may affect the lifetime of// this layer manager. So let's make sure this object stays alive until// the end of the method invocation.RefPtr<WebRenderLayerManager>selfRef=this;// |aTransactionId| will be > 0 if the compositor is acknowledging a shadow// layers transaction.if(aTransactionId.IsValid()){nsIWidgetListener*listener=mWidget->GetWidgetListener();if(listener){listener->DidCompositeWindow(aTransactionId,aCompositeStart,aCompositeEnd);}listener=mWidget->GetAttachedWidgetListener();if(listener){listener->DidCompositeWindow(aTransactionId,aCompositeStart,aCompositeEnd);}if(mTransactionIdAllocator){mTransactionIdAllocator->NotifyTransactionCompleted(aTransactionId);}}// These observers fire whether or not we were in a transaction.for(size_ti=0;i<mDidCompositeObservers.Length();i++){mDidCompositeObservers[i]->DidComposite();}}voidWebRenderLayerManager::ClearCachedResources(Layer*aSubtree){if(!WrBridge()->IPCOpen()){gfxCriticalNote<<"IPC Channel is already torn down unexpectedly\n";return;}WrBridge()->BeginClearCachedResources();// We flush any pending async resource updates before we clear the display// list items because some resources (e.g. images) might be shared between// multiple layer managers, not get freed here, and we want to keep their// states consistent.mStateManager.FlushAsyncResourceUpdates();mWebRenderCommandBuilder.ClearCachedResources();DiscardImages();mStateManager.ClearCachedResources();WrBridge()->EndClearCachedResources();}voidWebRenderLayerManager::WrUpdated(){ClearAsyncAnimations();mStateManager.mAsyncResourceUpdates.reset();mWebRenderCommandBuilder.ClearCachedResources();DiscardLocalImages();mDisplayItemCache.Clear();if(mWidget){if(dom::BrowserChild*browserChild=mWidget->GetOwningBrowserChild()){browserChild->SchedulePaint();}}}voidWebRenderLayerManager::UpdateTextureFactoryIdentifier(constTextureFactoryIdentifier&aNewIdentifier){WrBridge()->IdentifyTextureHost(aNewIdentifier);}TextureFactoryIdentifierWebRenderLayerManager::GetTextureFactoryIdentifier(){returnWrBridge()->GetTextureFactoryIdentifier();}voidWebRenderLayerManager::SetTransactionIdAllocator(TransactionIdAllocator*aAllocator){// When changing the refresh driver, the previous refresh driver may never// receive updates of pending transactions it's waiting for. So clear the// waiting state before assigning another refresh driver.if(mTransactionIdAllocator&&(aAllocator!=mTransactionIdAllocator)){mTransactionIdAllocator->ClearPendingTransactions();// We should also reset the transaction id of the new allocator to previous// allocator's last transaction id, so that completed transactions for// previous allocator will be ignored and won't confuse the new allocator.if(aAllocator){aAllocator->ResetInitialTransactionId(mTransactionIdAllocator->LastTransactionId());}}mTransactionIdAllocator=aAllocator;}TransactionIdWebRenderLayerManager::GetLastTransactionId(){returnmLatestTransactionId;}voidWebRenderLayerManager::AddDidCompositeObserver(DidCompositeObserver*aObserver){if(!mDidCompositeObservers.Contains(aObserver)){mDidCompositeObservers.AppendElement(aObserver);}}voidWebRenderLayerManager::RemoveDidCompositeObserver(DidCompositeObserver*aObserver){mDidCompositeObservers.RemoveElement(aObserver);}voidWebRenderLayerManager::FlushRendering(){CompositorBridgeChild*cBridge=GetCompositorBridgeChild();if(!cBridge){return;}MOZ_ASSERT(mWidget);// If value of IsResizingNativeWidget() is nothing, we assume that resizing// might happen.boolresizing=mWidget&&mWidget->IsResizingNativeWidget().valueOr(true);// Limit async FlushRendering to !resizing and Win DComp.// XXX relax the limitationif(WrBridge()->GetCompositorUseDComp()&&!resizing){cBridge->SendFlushRenderingAsync();}elseif(mWidget->SynchronouslyRepaintOnResize()||StaticPrefs::layers_force_synchronous_resize()){cBridge->SendFlushRendering();}else{cBridge->SendFlushRenderingAsync();}}voidWebRenderLayerManager::WaitOnTransactionProcessed(){CompositorBridgeChild*bridge=GetCompositorBridgeChild();if(bridge){bridge->SendWaitOnTransactionProcessed();}}voidWebRenderLayerManager::SendInvalidRegion(constnsIntRegion&aRegion){// XXX Webrender does not support invalid region yet.#ifdef XP_WIN// When DWM is disabled, each window does not have own back buffer. They would// paint directly to a buffer that was to be displayed by the video card.// WM_PAINT via SendInvalidRegion() requests necessary re-paint.constboolneedsInvalidate=!gfx::gfxVars::DwmCompositionEnabled();#elseconstboolneedsInvalidate=true;#endifif(needsInvalidate&&WrBridge()){WrBridge()->SendInvalidateRenderedFrame();}}voidWebRenderLayerManager::ScheduleComposite(){WrBridge()->SendScheduleComposite();}already_AddRefed<PersistentBufferProvider>WebRenderLayerManager::CreatePersistentBufferProvider(constgfx::IntSize&aSize,gfx::SurfaceFormataFormat){// Ensure devices initialization for canvas 2d if not remote. The devices are// lazily initialized with WebRender to reduce memory usage.if(!gfxPlatform::UseRemoteCanvas()){gfxPlatform::GetPlatform()->EnsureDevicesInitialized();}RefPtr<PersistentBufferProvider>provider=PersistentBufferProviderShared::Create(aSize,aFormat,AsKnowsCompositor());if(provider){returnprovider.forget();}returnWindowRenderer::CreatePersistentBufferProvider(aSize,aFormat);}voidWebRenderLayerManager::ClearAsyncAnimations(){mStateManager.ClearAsyncAnimations();}voidWebRenderLayerManager::WrReleasedImages(constnsTArray<wr::ExternalImageKeyPair>&aPairs){mStateManager.WrReleasedImages(aPairs);}voidWebRenderLayerManager::GetFrameUniformity(FrameUniformityData*aOutData){WrBridge()->SendGetFrameUniformity(aOutData);}/*static*/voidWebRenderLayerManager::LayerUserDataDestroy(void*data){deletestatic_cast<LayerUserData*>(data);}UniquePtr<LayerUserData>WebRenderLayerManager::RemoveUserData(void*aKey){UniquePtr<LayerUserData>d(static_cast<LayerUserData*>(mUserData.Remove(static_cast<gfx::UserDataKey*>(aKey))));returnd;}std::unordered_set<ScrollableLayerGuid::ViewID>WebRenderLayerManager::ClearPendingScrollInfoUpdate(){std::unordered_set<ScrollableLayerGuid::ViewID>scrollIds(mPendingScrollUpdates.Keys().cbegin(),mPendingScrollUpdates.Keys().cend());mPendingScrollUpdates.Clear();returnscrollIds;}}// namespace layers}// namespace mozilla