| ☠☠ backed out by 40ca68bfea62 ☠ ☠ | |
| author | Sean Feng <sefeng@mozilla.com> |
| Fri, 14 Feb 2020 15:26:35 +0000 | |
| changeset 513931 | 80c254f460f5dcab9b3d111511a52ad97ccb4b32 |
| parent 513930 | 4a95f898cab860303e46df90d25f48e3f909bf5a |
| child 513932 | 59147c470b04a9541dc59ee5df1c3ecf879b2f9d |
| push id | 37125 |
| push user | shindli@mozilla.com |
| push date | Sat, 15 Feb 2020 09:56:17 +0000 |
| treeherder | mozilla-central@02b1aa498dd2 [default view] [failures only] |
| perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
| reviewers | botond, jrmuizel |
| bugs | 1600793 |
| milestone | 75.0a1 |
| first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
| last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/gfx/layers/apz/public/APZSampler.h +++ b/gfx/layers/apz/public/APZSampler.h @@ -53,23 +53,25 @@ class APZSampler { /** * This function is invoked from rust on the render backend thread when it * is created. It effectively tells the APZSampler "the current thread is * the sampler thread for this window id" and allows APZSampler to remember * which thread it is. */ static void SetSamplerThread(const wr::WrWindowId& aWindowId); - static void SampleForWebRender(const wr::WrWindowId& aWindowId, - wr::Transaction* aTxn, - const wr::DocumentId& aRenderRootId); + static void SampleForWebRender( + const wr::WrWindowId& aWindowId, wr::Transaction* aTxn, + const wr::DocumentId& aRenderRootId, + const wr::WrPipelineIdEpochs& aEpochsBeingRendered); void SetSampleTime(const TimeStamp& aSampleTime); void SampleForWebRender(wr::TransactionWrapper& aTxn, - wr::RenderRoot aRenderRoot); + wr::RenderRoot aRenderRoot, + const wr::WrPipelineIdEpochs& aEpochsBeingRendered); bool SampleAnimations(const LayerMetricsWrapper& aLayer, const TimeStamp& aSampleTime); /** * Compute the updated shadow transform for a scroll thumb layer that * reflects async scrolling of the associated scroll frame. *
--- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -684,19 +684,20 @@ void APZCTreeManager::UpdateHitTestingTr const WebRenderScrollDataWrapper& aScrollWrapper, bool aIsFirstPaint, WRRootId aOriginatingWrRootId, uint32_t aPaintSequenceNumber) { AssertOnUpdaterThread(); UpdateHitTestingTreeImpl(aScrollWrapper, aIsFirstPaint, aOriginatingWrRootId, aPaintSequenceNumber); } -void APZCTreeManager::SampleForWebRender(wr::TransactionWrapper& aTxn, - const TimeStamp& aSampleTime, - wr::RenderRoot aRenderRoot) { +void APZCTreeManager::SampleForWebRender( + wr::TransactionWrapper& aTxn, const TimeStamp& aSampleTime, + wr::RenderRoot aRenderRoot, + const wr::WrPipelineIdEpochs& aEpochsBeingRendered) { AssertOnSamplerThread(); MutexAutoLock lock(mMapLock); nsTArray<wr::WrTransformProperty> transforms; // Sample async transforms on scrollable layers. for (const auto& mapping : mApzcMap) { AsyncPanZoomController* apzc = mapping.second; @@ -709,16 +710,37 @@ void APZCTreeManager::SampleForWebRender apzc->GetZoomAnimationId() ? AsyncTransformComponents{AsyncTransformComponent::eLayout} : LayoutAndVisual; ParentLayerPoint layerTranslation = apzc->GetCurrentAsyncTransform(AsyncPanZoomController::eForCompositing, asyncTransformComponents) .mTranslation; + if (Maybe<CompositionPayload> payload = apzc->NotifyScrollSampling()) { + RefPtr<WebRenderBridgeParent> wrBridgeParent; + LayersId layersId = apzc->GetGuid().mLayersId; + CompositorBridgeParent::CallWithIndirectShadowTree( + layersId, [&](LayerTreeState& aState) -> void { + wrBridgeParent = aState.mWrBridge; + }); + + if (wrBridgeParent) { + wr::PipelineId pipelineId = wr::AsPipelineId(layersId); + for (size_t i = 0; i < aEpochsBeingRendered.length; i++) { + if (aEpochsBeingRendered.data[i].pipeline_id == pipelineId) { + auto& epoch = aEpochsBeingRendered.data[i].epoch; + std::pair<wr::PipelineId, wr::Epoch> key(pipelineId, epoch); + wrBridgeParent->AddPendingScrollPayload(*payload, key); + break; + } + } + } + } + if (Maybe<uint64_t> zoomAnimationId = apzc->GetZoomAnimationId()) { // for now we only support zooming on root content APZCs MOZ_ASSERT(apzc->IsRootContent()); LayoutDeviceToParentLayerScale zoom = apzc->GetCurrentPinchZoomScale(AsyncPanZoomController::eForCompositing); AsyncTransform asyncVisualTransform = apzc->GetCurrentAsyncTransform(
--- a/gfx/layers/apz/src/APZCTreeManager.h +++ b/gfx/layers/apz/src/APZCTreeManager.h @@ -197,17 +197,18 @@ class APZCTreeManager : public IAPZCTree * AsyncCompositionManager. * In the WebRender world a single "layer tree" might get split into multiple * render roots; the aRenderRoot argument indicates which render root we are * sampling in this call. The transaction should only be updated with samples * from APZC instances in that render root. */ void SampleForWebRender(wr::TransactionWrapper& aTxn, const TimeStamp& aSampleTime, - wr::RenderRoot aRenderRoot); + wr::RenderRoot aRenderRoot, + const wr::WrPipelineIdEpochs& aEpochsBeingRendered); /** * Refer to the documentation of APZInputBridge::ReceiveInputEvent() and * APZEventResult. */ APZEventResult ReceiveInputEvent(InputData& aEvent) override; /**
--- a/gfx/layers/apz/src/APZSampler.cpp +++ b/gfx/layers/apz/src/APZSampler.cpp @@ -60,45 +60,48 @@ void APZSampler::SetWebRenderWindowId(co void APZSampler::SetSamplerThread(const wr::WrWindowId& aWindowId) { if (RefPtr<APZSampler> sampler = GetSampler(aWindowId)) { MutexAutoLock lock(sampler->mThreadIdLock); sampler->mSamplerThreadId = Some(PlatformThread::CurrentId()); } } /*static*/ -void APZSampler::SampleForWebRender(const wr::WrWindowId& aWindowId, - wr::Transaction* aTransaction, - const wr::DocumentId& aRenderRootId) { +void APZSampler::SampleForWebRender( + const wr::WrWindowId& aWindowId, wr::Transaction* aTransaction, + const wr::DocumentId& aRenderRootId, + const wr::WrPipelineIdEpochs& aEpochsBeingRendered) { if (RefPtr<APZSampler> sampler = GetSampler(aWindowId)) { wr::TransactionWrapper txn(aTransaction); - sampler->SampleForWebRender(txn, wr::RenderRootFromId(aRenderRootId)); + sampler->SampleForWebRender(txn, wr::RenderRootFromId(aRenderRootId), + aEpochsBeingRendered); } } void APZSampler::SetSampleTime(const TimeStamp& aSampleTime) { MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); MutexAutoLock lock(mSampleTimeLock); mSampleTime = aSampleTime; } -void APZSampler::SampleForWebRender(wr::TransactionWrapper& aTxn, - wr::RenderRoot aRenderRoot) { +void APZSampler::SampleForWebRender( + wr::TransactionWrapper& aTxn, wr::RenderRoot aRenderRoot, + const wr::WrPipelineIdEpochs& aEpochsBeingRendered) { AssertOnSamplerThread(); TimeStamp sampleTime; { // scope lock MutexAutoLock lock(mSampleTimeLock); // If mSampleTime is null we're in a startup phase where the // WebRenderBridgeParent hasn't yet provided us with a sample time. // If we're that early there probably aren't any APZ animations happening // anyway, so using Timestamp::Now() should be fine. sampleTime = mSampleTime.IsNull() ? TimeStamp::Now() : mSampleTime; } - mApz->SampleForWebRender(aTxn, sampleTime, aRenderRoot); + mApz->SampleForWebRender(aTxn, sampleTime, aRenderRoot, aEpochsBeingRendered); } bool APZSampler::SampleAnimations(const LayerMetricsWrapper& aLayer, const TimeStamp& aSampleTime) { MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); AssertOnSamplerThread(); // TODO: eventually we can drop the aLayer argument and just walk the APZ @@ -261,16 +264,18 @@ already_AddRefed<APZSampler> APZSampler: } // namespace layers } // namespace mozilla void apz_register_sampler(mozilla::wr::WrWindowId aWindowId) { mozilla::layers::APZSampler::SetSamplerThread(aWindowId); } -void apz_sample_transforms(mozilla::wr::WrWindowId aWindowId, - mozilla::wr::Transaction* aTransaction, - mozilla::wr::DocumentId aDocumentId) { - mozilla::layers::APZSampler::SampleForWebRender(aWindowId, aTransaction, - aDocumentId); +void apz_sample_transforms( + mozilla::wr::WrWindowId aWindowId, mozilla::wr::Transaction* aTransaction, + mozilla::wr::DocumentId aDocumentId, + mozilla::wr::WrPipelineIdEpochs aEpochsBeingRendered) { + mozilla::layers::APZSampler::SampleForWebRender( + aWindowId, aTransaction, aDocumentId, aEpochsBeingRendered); + wr_pipelineid_and_epoch_delete(aEpochsBeingRendered); } void apz_deregister_sampler(mozilla::wr::WrWindowId aWindowId) {}
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp +++ b/gfx/layers/ipc/CompositorBridgeParent.cpp @@ -2326,16 +2326,23 @@ void CompositorBridgeParent::NotifyPipel mWrBridge->RemoveEpochDataPriorTo(aEpoch); if (!mPaused) { if (mIsForcedFirstPaint) { uiController->NotifyFirstPaint(); mIsForcedFirstPaint = false; } + std::pair<wr::PipelineId, wr::Epoch> key(aPipelineId, aEpoch); + if (nsTArray<CompositionPayload>* payloads = + mWrBridge->GetPendingScrollPayload(key)) { + RecordCompositionPayloadsPresented(*payloads); + mWrBridge->RemovePendingScrollPayload(key); + } + TransactionId transactionId = mWrBridge->FlushTransactionIdsForEpoch( aEpoch, aCompositeStartId, aCompositeStart, aRenderStart, aCompositeEnd, uiController); Unused << SendDidComposite(LayersId{0}, transactionId, aCompositeStart, aCompositeEnd); nsTArray<ImageCompositeNotificationInfo> notifications; mWrBridge->ExtractImageCompositeNotifications(¬ifications); @@ -2346,16 +2353,23 @@ void CompositorBridgeParent::NotifyPipel return; } auto wrBridge = mAsyncImageManager->GetWrBridge(aPipelineId); if (wrBridge && wrBridge->GetCompositorBridge()) { MOZ_ASSERT(!wrBridge->IsRootWebRenderBridgeParent()); wrBridge->RemoveEpochDataPriorTo(aEpoch); if (!mPaused) { + std::pair<wr::PipelineId, wr::Epoch> key(aPipelineId, aEpoch); + if (nsTArray<CompositionPayload>* payloads = + wrBridge->GetPendingScrollPayload(key)) { + RecordCompositionPayloadsPresented(*payloads); + wrBridge->RemovePendingScrollPayload(key); + } + TransactionId transactionId = wrBridge->FlushTransactionIdsForEpoch( aEpoch, aCompositeStartId, aCompositeStart, aRenderStart, aCompositeEnd, uiController, aStats, &stats); Unused << wrBridge->GetCompositorBridge()->SendDidComposite( wrBridge->GetLayersId(), transactionId, aCompositeStart, aCompositeEnd); } }
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp +++ b/gfx/layers/wr/WebRenderBridgeParent.cpp @@ -1042,16 +1042,34 @@ WebRenderBridgeParent::WriteCollectedFra return Api(wr::RenderRoot::Default)->WriteCollectedFrames(); } RefPtr<wr::WebRenderAPI::GetCollectedFramesPromise> WebRenderBridgeParent::GetCollectedFrames() { return Api(wr::RenderRoot::Default)->GetCollectedFrames(); } +void WebRenderBridgeParent::AddPendingScrollPayload( + CompositionPayload& aPayload, + const std::pair<wr::PipelineId, wr::Epoch>& aKey) { + nsTArray<CompositionPayload>* payloads = + mPendingScrollPayloads.LookupOrAdd(aKey); + payloads->AppendElement(aPayload); +} + +nsTArray<CompositionPayload>* WebRenderBridgeParent::GetPendingScrollPayload( + const std::pair<wr::PipelineId, wr::Epoch>& aKey) const { + return mPendingScrollPayloads.Get(aKey); +} + +bool WebRenderBridgeParent::RemovePendingScrollPayload( + const std::pair<wr::PipelineId, wr::Epoch>& aKey) { + return mPendingScrollPayloads.Remove(aKey); +} + CompositorBridgeParent* WebRenderBridgeParent::GetRootCompositorBridgeParent() const { if (!mCompositorBridge) { return nullptr; } if (IsRootWebRenderBridgeParent()) { // This WebRenderBridgeParent is attached to the root
--- a/gfx/layers/wr/WebRenderBridgeParent.h +++ b/gfx/layers/wr/WebRenderBridgeParent.h @@ -47,16 +47,52 @@ namespace layers { class Compositor; class CompositorAnimationStorage; class CompositorBridgeParentBase; class CompositorVsyncScheduler; class AsyncImagePipelineManager; class WebRenderImageHost; +class PipelineIdAndEpochHashEntry : public PLDHashEntryHdr { + public: + typedef const std::pair<wr::PipelineId, wr::Epoch>& KeyType; + typedef const std::pair<wr::PipelineId, wr::Epoch>* KeyTypePointer; + enum { ALLOW_MEMMOVE = true }; + + explicit PipelineIdAndEpochHashEntry(wr::PipelineId aPipelineId, + wr::Epoch aEpoch) + : mValue(aPipelineId, aEpoch) {} + + PipelineIdAndEpochHashEntry(PipelineIdAndEpochHashEntry&& aOther) = default; + + explicit PipelineIdAndEpochHashEntry(KeyTypePointer aKey) + : mValue(aKey->first, aKey->second) {} + + ~PipelineIdAndEpochHashEntry() {} + + KeyType GetKey() const { return mValue; } + + bool KeyEquals(KeyTypePointer aKey) const { + return mValue.first.mHandle == aKey->first.mHandle && + mValue.first.mNamespace == aKey->first.mNamespace && + mValue.second.mHandle == aKey->second.mHandle; + }; + + static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; } + + static PLDHashNumber HashKey(KeyTypePointer aKey) { + return mozilla::HashGeneric(aKey->first.mHandle, aKey->first.mNamespace, + aKey->second.mHandle); + } + + private: + std::pair<wr::PipelineId, wr::Epoch> mValue; +}; + class WebRenderBridgeParent final : public PWebRenderBridgeParent, public CompositorVsyncSchedulerOwner, public CompositableParentManager, public layers::FrameRecorder, public SupportsWeakPtr<WebRenderBridgeParent> { public: MOZ_DECLARE_WEAKREFERENCE_TYPENAME(WebRenderBridgeParent) @@ -314,16 +350,25 @@ class WebRenderBridgeParent final * as data URIs. * * If there is not currently a recorder, this is a no-op and the promise will * be rejected. */ RefPtr<wr::WebRenderAPI::GetCollectedFramesPromise> GetCollectedFrames(); void DisableNativeCompositor(); + void AddPendingScrollPayload( + CompositionPayload& aPayload, + const std::pair<wr::PipelineId, wr::Epoch>& aKey); + + nsTArray<CompositionPayload>* GetPendingScrollPayload( + const std::pair<wr::PipelineId, wr::Epoch>& aKey) const; + + bool RemovePendingScrollPayload( + const std::pair<wr::PipelineId, wr::Epoch>& aKey); private: class ScheduleSharedSurfaceRelease; explicit WebRenderBridgeParent(const wr::PipelineId& aPipelineId); virtual ~WebRenderBridgeParent(); wr::WebRenderAPI* Api(wr::RenderRoot aRenderRoot) { @@ -552,16 +597,20 @@ class WebRenderBridgeParent final // These fields keep track of the latest layer observer epoch values in the // child and the parent. mChildLayersObserverEpoch is the latest epoch value // received from the child. mParentLayersObserverEpoch is the latest epoch // value that we have told BrowserParent about (via ObserveLayerUpdate). LayersObserverEpoch mChildLayersObserverEpoch; LayersObserverEpoch mParentLayersObserverEpoch; std::deque<PendingTransactionId> mPendingTransactionIds; + // These payloads are being used for SCROLL_PRESENT_LATENCY telemetry + nsClassHashtable<PipelineIdAndEpochHashEntry, nsTArray<CompositionPayload>> + mPendingScrollPayloads; + std::queue<CompositorAnimationIdsForEpoch> mCompositorAnimationsToDelete; wr::Epoch mWrEpoch; wr::IdNamespace mIdNamespace; VsyncId mSkippedCompositeId; TimeStamp mMostRecentComposite; // Kind of clunky, but I can't sort out a more elegant way of getting this to
--- a/gfx/webrender_bindings/src/bindings.rs +++ b/gfx/webrender_bindings/src/bindings.rs @@ -24,17 +24,17 @@ use std::os::raw::{c_int}; use std::time::Duration; use gleam::gl; use webrender::{ api::*, api::units::*, ApiRecordingReceiver, AsyncPropertySampler, AsyncScreenshotHandle, BinaryRecorder, Compositor, DebugFlags, Device, NativeSurfaceId, PipelineInfo, ProfilerHooks, RecordedFrameHandle, Renderer, RendererOptions, RendererStats, SceneBuilderHooks, ShaderPrecacheFlags, Shaders, ThreadListener, UploadMethod, VertexUsageHint, - WrShaders, set_profiler_hooks, CompositorConfig, NativeSurfaceInfo, NativeTileId + WrShaders, set_profiler_hooks, CompositorConfig, NativeSurfaceInfo, NativeTileId, FastHashMap }; use thread_profiler::register_thread_with_profiler; use moz2d_renderer::Moz2dBlobImageHandler; use program_cache::{WrProgramCache, remove_disk_cache}; use rayon; use num_cpus; use euclid::SideOffsets2D; use nsstring::nsAString; @@ -808,16 +808,39 @@ impl<'a> From<(&'a(WrPipelineId, WrDocum pipeline_id: (tuple.0).0, document_id: (tuple.0).1, epoch: *tuple.1 } } } #[repr(C)] +pub struct WrPipelineIdAndEpoch { + pipeline_id: WrPipelineId, + epoch: WrEpoch +} + +impl<'a> From<(&WrPipelineId, &WrEpoch)> for WrPipelineIdAndEpoch { + fn from(tuple: (&WrPipelineId, &WrEpoch)) -> WrPipelineIdAndEpoch { + WrPipelineIdAndEpoch { + pipeline_id: *tuple.0, + epoch: *tuple.1, + } + } +} + +type WrPipelineIdEpochs = FfiVec<WrPipelineIdAndEpoch>; + +#[no_mangle] +pub unsafe extern "C" fn wr_pipelineid_and_epoch_delete(_result: WrPipelineIdEpochs) { + // _result will be dropped here, and the drop impl on FfiVec will free + // the underlying vec memory +} + +#[repr(C)] pub struct WrRemovedPipeline { pipeline_id: WrPipelineId, document_id: WrDocumentId, } impl<'a> From<&'a (WrPipelineId, WrDocumentId)> for WrRemovedPipeline { fn from(tuple: &(WrPipelineId, WrDocumentId)) -> WrRemovedPipeline { WrRemovedPipeline { @@ -917,17 +940,18 @@ extern "C" { fn apz_post_scene_swap(window_id: WrWindowId, pipeline_info: WrPipelineInfo); fn apz_run_updater(window_id: WrWindowId); fn apz_deregister_updater(window_id: WrWindowId); // These callbacks are invoked from the render backend thread (aka the APZ // sampler thread) fn apz_register_sampler(window_id: WrWindowId); fn apz_sample_transforms(window_id: WrWindowId, transaction: &mut Transaction, - document_id: WrDocumentId); + document_id: WrDocumentId, + epochs_being_rendered: WrPipelineIdEpochs); fn apz_deregister_sampler(window_id: WrWindowId); } struct APZCallbacks { window_id: WrWindowId, } impl APZCallbacks { @@ -999,19 +1023,24 @@ impl SamplerCallback { } } impl AsyncPropertySampler for SamplerCallback { fn register(&self) { unsafe { apz_register_sampler(self.window_id) } } - fn sample(&self, document_id: DocumentId) -> Vec<FrameMsg> { + fn sample(&self, document_id: DocumentId, + epochs_being_rendered: &FastHashMap<PipelineId, Epoch>) -> Vec<FrameMsg> { let mut transaction = Transaction::new(); - unsafe { apz_sample_transforms(self.window_id, &mut transaction, document_id) }; + unsafe { apz_sample_transforms( + self.window_id, &mut transaction, + document_id, FfiVec::from_vec(epochs_being_rendered.iter() + .map(WrPipelineIdAndEpoch::from).collect()) + )}; // TODO: also omta_sample_transforms(...) transaction.get_frame_ops() } fn deregister(&self) { unsafe { apz_deregister_sampler(self.window_id) } } }
--- a/gfx/webrender_bindings/webrender_ffi.h +++ b/gfx/webrender_bindings/webrender_ffi.h @@ -5,16 +5,22 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef WR_h #define WR_h #include "mozilla/gfx/Types.h" #include "nsTArray.h" +namespace mozilla { +namespace wr { +template<typename T> +struct FfiVec; +} +} extern "C" { // ---- // Functions invoked from Rust code // ---- bool is_in_compositor_thread(); bool is_in_main_thread(); @@ -68,32 +74,36 @@ struct InternerSubReport { #undef DECLARE_MEMBER struct Transaction; struct WrWindowId; struct DocumentId; struct WrPipelineInfo; +struct WrPipelineIdAndEpoch; +using WrPipelineIdEpochs = FfiVec<WrPipelineIdAndEpoch>; + const uint64_t ROOT_CLIP_CHAIN = ~0; } // namespace wr } // namespace mozilla void apz_register_updater(mozilla::wr::WrWindowId aWindowId); void apz_pre_scene_swap(mozilla::wr::WrWindowId aWindowId); void apz_post_scene_swap(mozilla::wr::WrWindowId aWindowId, mozilla::wr::WrPipelineInfo aInfo); void apz_run_updater(mozilla::wr::WrWindowId aWindowId); void apz_deregister_updater(mozilla::wr::WrWindowId aWindowId); void apz_register_sampler(mozilla::wr::WrWindowId aWindowId); void apz_sample_transforms(mozilla::wr::WrWindowId aWindowId, mozilla::wr::Transaction* aTransaction, - mozilla::wr::DocumentId aRenderRootId); + mozilla::wr::DocumentId aRenderRootId, + mozilla::wr::WrPipelineIdEpochs aPipelineEpochs); void apz_deregister_sampler(mozilla::wr::WrWindowId aWindowId); } // extern "C" // Work-around wingdi.h define which conflcits with WR color constant #pragma push_macro("TRANSPARENT") #undef TRANSPARENT #include "webrender_ffi_generated.h"
--- a/gfx/wr/webrender/src/lib.rs +++ b/gfx/wr/webrender/src/lib.rs @@ -212,16 +212,17 @@ pub use crate::frame_builder::ChasePrimi pub use crate::prim_store::PrimitiveDebugId; pub use crate::profiler::{ProfilerHooks, set_profiler_hooks}; pub use crate::renderer::{ AsyncPropertySampler, CpuProfile, DebugFlags, RendererKind, GpuProfile, GraphicsApi, GraphicsApiInfo, PipelineInfo, Renderer, RendererError, RendererOptions, RenderResults, RendererStats, SceneBuilderHooks, ThreadListener, ShaderPrecacheFlags, MAX_VERTEX_TEXTURE_WIDTH, }; +pub use crate::internal_types::FastHashMap; pub use crate::screen_capture::{AsyncScreenshotHandle, RecordedFrameHandle}; pub use crate::shade::{Shaders, WrShaders}; pub use api as webrender_api; pub use webrender_build::shader::ProgramSourceDigest; pub use crate::picture::{TileDescriptor, TileId, InvalidationReason}; pub use crate::picture::{PrimitiveCompareResult, PrimitiveCompareResultDetail, CompareHelperResult}; pub use crate::picture::{TileNode, TileNodeKind, TileSerializer, TileCacheInstanceSerializer, TileOffset, TileCacheLoggerUpdateLists}; pub use crate::intern::{Update, UpdateKind, ItemUid};
--- a/gfx/wr/webrender/src/render_backend.rs +++ b/gfx/wr/webrender/src/render_backend.rs @@ -1480,29 +1480,30 @@ impl RenderBackend { mut render_frame: bool, invalidate_rendered_frame: bool, frame_counter: &mut u32, profile_counters: &mut BackendProfileCounters, has_built_scene: bool, ) { let requested_frame = render_frame; + let requires_frame_build = self.requires_frame_build(); + let doc = self.documents.get_mut(&document_id).unwrap(); // If we have a sampler, get more frame ops from it and add them // to the transaction. This is a hook to allow the WR user code to // fiddle with things after a potentially long scene build, but just // before rendering. This is useful for rendering with the latest // async transforms. if requested_frame || has_built_scene { if let Some(ref sampler) = self.sampler { - frame_ops.append(&mut sampler.sample(document_id)); + frame_ops.append(&mut sampler.sample(document_id, + &doc.scene.pipeline_epochs)); } } - let requires_frame_build = self.requires_frame_build(); - let doc = self.documents.get_mut(&document_id).unwrap(); doc.has_built_scene |= has_built_scene; // If there are any additions or removals of clip modes // during the scene build, apply them to the data store now. if let Some(updates) = interner_updates { #[cfg(feature = "capture")] { if self.debug_flags.contains(DebugFlags::TILE_CACHE_LOGGING_DBG) {
--- a/gfx/wr/webrender/src/renderer.rs +++ b/gfx/wr/webrender/src/renderer.rs @@ -6201,17 +6201,18 @@ pub trait SceneBuilderHooks { /// are all called from the render backend thread. pub trait AsyncPropertySampler { /// This is called exactly once, when the render backend thread is started /// and before it processes anything. fn register(&self); /// This is called for each transaction with the generate_frame flag set /// (i.e. that will trigger a render). The list of frame messages returned /// are processed as though they were part of the original transaction. - fn sample(&self, document_id: DocumentId) -> Vec<FrameMsg>; + fn sample(&self, document_id: DocumentId, + doc: &FastHashMap<PipelineId, Epoch>) -> Vec<FrameMsg>; /// This is called exactly once, when the render backend thread is about to /// terminate. fn deregister(&self); } bitflags! { /// Flags that control how shaders are pre-cached, if at all. #[derive(Default)]