зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 91760460f914 (bug 1620005) for build bustages on a CLOSED TREE
This commit is contained in:
Родитель
ccd17c0d43
Коммит
b154619cbb
|
@ -9,157 +9,134 @@
|
|||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
static const size_t kInitialCacheSize = 1024;
|
||||
static const size_t kMaximumCacheSize = 10240;
|
||||
static const size_t kCacheThreshold = 1;
|
||||
|
||||
DisplayItemCache::DisplayItemCache()
|
||||
: mMaximumSize(0), mConsecutivePartialDisplayLists(0) {
|
||||
if (XRE_IsContentProcess() &&
|
||||
StaticPrefs::gfx_webrender_enable_item_cache_AtStartup()) {
|
||||
SetCapacity(kInitialCacheSize, kMaximumCacheSize);
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayItemCache::ClearCache() {
|
||||
memset(mSlots.Elements(), 0, mSlots.Length() * sizeof(Slot));
|
||||
mFreeSlots.ClearAndRetainStorage();
|
||||
|
||||
for (size_t i = 0; i < CurrentSize(); ++i) {
|
||||
mFreeSlots.AppendElement(i);
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<uint16_t> DisplayItemCache::GetNextFreeSlot() {
|
||||
if (mFreeSlots.IsEmpty() && !GrowIfPossible()) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
return Some(mFreeSlots.PopLastElement());
|
||||
}
|
||||
|
||||
bool DisplayItemCache::GrowIfPossible() {
|
||||
if (IsFull()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto currentSize = CurrentSize();
|
||||
MOZ_ASSERT(currentSize <= mMaximumSize);
|
||||
|
||||
// New slots are added one by one, which is amortized O(1) time complexity due
|
||||
// to underlying storage implementation.
|
||||
mSlots.AppendElement();
|
||||
mFreeSlots.AppendElement(currentSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DisplayItemCache::FreeUnusedSlots() {
|
||||
for (size_t i = 0; i < CurrentSize(); ++i) {
|
||||
auto& slot = mSlots[i];
|
||||
|
||||
if (!slot.mUsed && slot.mOccupied) {
|
||||
// This entry contained a cached item, but was not used.
|
||||
slot.mOccupied = false;
|
||||
mFreeSlots.AppendElement(i);
|
||||
}
|
||||
|
||||
slot.mUsed = false;
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayItemCache::SetCapacity(const size_t aInitialSize,
|
||||
const size_t aMaximumSize) {
|
||||
mMaximumSize = aMaximumSize;
|
||||
mSlots.SetCapacity(aMaximumSize);
|
||||
mSlots.SetLength(aInitialSize);
|
||||
mFreeSlots.SetCapacity(aMaximumSize);
|
||||
ClearCache();
|
||||
}
|
||||
|
||||
Maybe<uint16_t> DisplayItemCache::AssignSlot(nsPaintedDisplayItem* aItem) {
|
||||
if (kCacheThreshold > mConsecutivePartialDisplayLists) {
|
||||
// Wait for |kCacheThreshold| partial display list builds, before caching
|
||||
// display items. This is meant to avoid caching overhead for interactions
|
||||
// or pages that do not work well with retained display lists.
|
||||
// TODO: This is a speculative optimization to minimize regressions.
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
if (!aItem->CanBeReused()) {
|
||||
// Do not try to cache items that cannot be reused.
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
auto& slot = aItem->CacheIndex();
|
||||
if (!slot) {
|
||||
slot = GetNextFreeSlot();
|
||||
if (!slot) {
|
||||
// The item does not fit in the cache.
|
||||
return Nothing();
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(slot && CurrentSize() > *slot);
|
||||
return slot;
|
||||
}
|
||||
|
||||
void DisplayItemCache::MarkSlotOccupied(
|
||||
uint16_t aSlotIndex, const wr::WrSpaceAndClipChain& aSpaceAndClip) {
|
||||
// Caching of the item succeeded, update the slot state.
|
||||
auto& slot = mSlots[aSlotIndex];
|
||||
MOZ_ASSERT(!slot.mOccupied);
|
||||
slot.mOccupied = true;
|
||||
MOZ_ASSERT(!slot.mUsed);
|
||||
slot.mUsed = true;
|
||||
slot.mSpaceAndClip = aSpaceAndClip;
|
||||
}
|
||||
|
||||
Maybe<uint16_t> DisplayItemCache::CanReuseItem(
|
||||
nsPaintedDisplayItem* aItem, const wr::WrSpaceAndClipChain& aSpaceAndClip) {
|
||||
auto& slotIndex = aItem->CacheIndex();
|
||||
if (!slotIndex) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(slotIndex && CurrentSize() > *slotIndex);
|
||||
|
||||
auto& slot = mSlots[*slotIndex];
|
||||
if (!slot.mOccupied) {
|
||||
// The display item has a stale cache slot. Recache the item.
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
// Spatial id and clip id can change between display lists.
|
||||
if (!(aSpaceAndClip == slot.mSpaceAndClip)) {
|
||||
// Mark the cache slot inactive and recache the item.
|
||||
slot.mOccupied = false;
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
slot.mUsed = true;
|
||||
return slotIndex;
|
||||
}
|
||||
|
||||
void DisplayItemCache::UpdateState(const bool aPartialDisplayListBuildFailed,
|
||||
const wr::PipelineId& aPipelineId) {
|
||||
const bool pipelineIdChanged = UpdatePipelineId(aPipelineId);
|
||||
const bool invalidate = pipelineIdChanged || aPartialDisplayListBuildFailed;
|
||||
|
||||
mConsecutivePartialDisplayLists =
|
||||
invalidate ? 0 : mConsecutivePartialDisplayLists + 1;
|
||||
|
||||
if (IsEmpty()) {
|
||||
// The cache is empty so nothing needs to be updated.
|
||||
if (!IsEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear the cache if the partial display list build failed, or if the
|
||||
// pipeline id changed.
|
||||
if (invalidate) {
|
||||
ClearCache();
|
||||
} else {
|
||||
FreeUnusedSlots();
|
||||
const bool clearCache =
|
||||
UpdatePipelineId(aPipelineId) || aPartialDisplayListBuildFailed;
|
||||
|
||||
if (clearCache) {
|
||||
memset(mCachedItemState.Elements(), 0,
|
||||
mCachedItemState.Length() * sizeof(CacheEntry));
|
||||
mNextIndex = 0;
|
||||
mFreeList.Clear();
|
||||
}
|
||||
|
||||
PopulateFreeList(clearCache);
|
||||
}
|
||||
|
||||
void DisplayItemCache::PopulateFreeList(const bool aAddAll) {
|
||||
uint16_t index = 0;
|
||||
for (auto& state : mCachedItemState) {
|
||||
if (aAddAll || (!state.mUsed && state.mCached)) {
|
||||
// This entry contained a cached item, but was not used.
|
||||
state.mCached = false;
|
||||
mFreeList.AppendElement(index);
|
||||
}
|
||||
|
||||
state.mUsed = false;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
static bool CanCacheItem(const nsPaintedDisplayItem* aItem) {
|
||||
// Only cache leaf display items that can be reused.
|
||||
if (!aItem->CanBeReused()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return aItem->CanBeCached();
|
||||
}
|
||||
|
||||
void DisplayItemCache::MaybeStartCaching(nsPaintedDisplayItem* aItem,
|
||||
wr::DisplayListBuilder& aBuilder) {
|
||||
if (!IsEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Stats().AddTotal();
|
||||
|
||||
auto& index = aItem->CacheIndex();
|
||||
if (!index) {
|
||||
if (!CanCacheItem(aItem)) {
|
||||
// The item cannot be cached.
|
||||
return;
|
||||
}
|
||||
|
||||
index = GetNextCacheIndex();
|
||||
if (!index) {
|
||||
// The item does not fit in the cache.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the current cache index, which is used by |MaybeEndCaching()| below.
|
||||
MOZ_ASSERT(!mCurrentIndex);
|
||||
mCurrentIndex = index;
|
||||
|
||||
MOZ_ASSERT(CanCacheItem(aItem));
|
||||
MOZ_ASSERT(mCurrentIndex && CurrentCacheSize() > *mCurrentIndex);
|
||||
|
||||
aBuilder.StartCachedItem(*mCurrentIndex);
|
||||
}
|
||||
|
||||
void DisplayItemCache::MaybeEndCaching(wr::DisplayListBuilder& aBuilder) {
|
||||
if (!IsEnabled() || !mCurrentIndex) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aBuilder.EndCachedItem(*mCurrentIndex)) {
|
||||
// Caching of the item succeeded, update the cached item state.
|
||||
auto& state = mCachedItemState[*mCurrentIndex];
|
||||
MOZ_ASSERT(!state.mCached);
|
||||
state.mCached = true;
|
||||
MOZ_ASSERT(!state.mUsed);
|
||||
state.mUsed = true;
|
||||
state.mSpaceAndClip = aBuilder.CurrentSpaceAndClipChain();
|
||||
|
||||
Stats().AddCached();
|
||||
}
|
||||
|
||||
mCurrentIndex = Nothing();
|
||||
}
|
||||
|
||||
bool DisplayItemCache::ReuseItem(nsPaintedDisplayItem* aItem,
|
||||
wr::DisplayListBuilder& aBuilder) {
|
||||
if (!IsEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& index = aItem->CacheIndex();
|
||||
if (!index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& state = mCachedItemState[*index];
|
||||
if (!state.mCached) {
|
||||
// The display item has a stale cache state.
|
||||
return false; // Recache item.
|
||||
}
|
||||
|
||||
// Spatial id and clip id can change between display lists.
|
||||
if (!(aBuilder.CurrentSpaceAndClipChain() == state.mSpaceAndClip)) {
|
||||
// TODO(miko): Technically we might be able to update just the changed data
|
||||
// here but it adds a lot of complexity.
|
||||
// Mark the cache state false and recache the item.
|
||||
state.mCached = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
Stats().AddReused();
|
||||
Stats().AddTotal();
|
||||
|
||||
state.mUsed = true;
|
||||
aBuilder.ReuseItem(*index);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -28,17 +28,7 @@ class CacheStats {
|
|||
void Reset() { mCached = mReused = mTotal = 0; }
|
||||
|
||||
void Print() {
|
||||
static uint64_t avgC = 1;
|
||||
static uint64_t avgR = 1;
|
||||
static uint64_t avgT = 1;
|
||||
|
||||
avgC += mCached;
|
||||
avgR += mReused;
|
||||
avgT += mTotal;
|
||||
|
||||
printf("Cached: %zu (avg: %f), Reused: %zu (avg: %f), Total: %zu\n",
|
||||
mCached, (double)avgC / (double)avgT, mReused,
|
||||
(double)avgR / (double)avgT, mTotal);
|
||||
printf("Cached: %zu, Reused: %zu, Total: %zu\n", mCached, mReused, mTotal);
|
||||
}
|
||||
|
||||
void AddCached() { mCached++; }
|
||||
|
@ -62,24 +52,9 @@ class CacheStats {
|
|||
*/
|
||||
class DisplayItemCache final {
|
||||
public:
|
||||
DisplayItemCache();
|
||||
DisplayItemCache() : mMaxCacheSize(0), mNextIndex(0) {}
|
||||
|
||||
/**
|
||||
* Returns true if display item caching is enabled, otherwise false.
|
||||
*/
|
||||
bool IsEnabled() const { return mMaximumSize > 0; }
|
||||
|
||||
/**
|
||||
* Returns true if there are no cached items, otherwise false.
|
||||
*/
|
||||
bool IsEmpty() const { return mFreeSlots.Length() == CurrentSize(); }
|
||||
|
||||
/**
|
||||
* Returns true if the cache has reached the maximum size, otherwise false.
|
||||
*/
|
||||
bool IsFull() const {
|
||||
return mFreeSlots.IsEmpty() && CurrentSize() == mMaximumSize;
|
||||
}
|
||||
bool IsEnabled() const { return mMaxCacheSize > 0; }
|
||||
|
||||
/**
|
||||
* Updates the cache state based on the given display list build information
|
||||
|
@ -94,50 +69,69 @@ class DisplayItemCache final {
|
|||
/**
|
||||
* Returns the current cache size.
|
||||
*/
|
||||
size_t CurrentSize() const { return mSlots.Length(); }
|
||||
size_t CurrentCacheSize() const {
|
||||
return IsEnabled() ? mCachedItemState.Length() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* If there are free slots in the cache, assigns a cache slot to the given
|
||||
* display item |aItem| and returns it. Otherwise returns Nothing().
|
||||
* Sets the initial and max cache size to given |aInitialSize| and |aMaxSize|.
|
||||
*
|
||||
* Currently the cache size is constant, but a good improvement would be to
|
||||
* set the initial and maximum size based on the display list length.
|
||||
*/
|
||||
Maybe<uint16_t> AssignSlot(nsPaintedDisplayItem* aItem);
|
||||
void SetCapacity(const size_t aInitialSize, const size_t aMaxSize) {
|
||||
mMaxCacheSize = aMaxSize;
|
||||
mCachedItemState.SetCapacity(aMaxSize);
|
||||
mCachedItemState.SetLength(aInitialSize);
|
||||
mFreeList.SetCapacity(aMaxSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the slot with the given |slotIndex| occupied and used.
|
||||
* Also stores the current space and clipchain |aSpaceAndClip|.
|
||||
* If the given display item |aItem| can be cached, update the cache state of
|
||||
* the item and tell WR DisplayListBuilder |aBuilder| to cache WR display
|
||||
* items until |EndCaching()| is called.
|
||||
*
|
||||
* If the display item cannot be cached, this function does nothing.
|
||||
*/
|
||||
void MarkSlotOccupied(uint16_t slotIndex,
|
||||
const wr::WrSpaceAndClipChain& aSpaceAndClip);
|
||||
void MaybeStartCaching(nsPaintedDisplayItem* aItem,
|
||||
wr::DisplayListBuilder& aBuilder);
|
||||
|
||||
/**
|
||||
* Returns the slot index of the the given display item |aItem|, if the item
|
||||
* can be reused. The current space and clipchain |aSpaceAndClip| is used to
|
||||
* check whether the cached item is still valid.
|
||||
* If the item cannot be reused, returns Nothing().
|
||||
* Tell WR DisplayListBuilder |aBuilder| to stop caching WR display items.
|
||||
*
|
||||
* If the display item cannot be cached, this function does nothing.
|
||||
*/
|
||||
Maybe<uint16_t> CanReuseItem(nsPaintedDisplayItem* aItem,
|
||||
const wr::WrSpaceAndClipChain& aSpaceAndClip);
|
||||
void MaybeEndCaching(wr::DisplayListBuilder& aBuilder);
|
||||
|
||||
/**
|
||||
* If the given |aItem| has been cached, tell WR DisplayListBuilder |aBuilder|
|
||||
* to reuse it.
|
||||
* Returns true if the item was reused, otherwise returns false.
|
||||
*/
|
||||
bool ReuseItem(nsPaintedDisplayItem* aItem, wr::DisplayListBuilder& aBuilder);
|
||||
|
||||
CacheStats& Stats() { return mCacheStats; }
|
||||
|
||||
private:
|
||||
struct Slot {
|
||||
Slot() : mSpaceAndClip{}, mOccupied(false), mUsed(false) {}
|
||||
|
||||
struct CacheEntry {
|
||||
wr::WrSpaceAndClipChain mSpaceAndClip;
|
||||
bool mOccupied;
|
||||
bool mCached;
|
||||
bool mUsed;
|
||||
};
|
||||
|
||||
void ClearCache();
|
||||
void FreeUnusedSlots();
|
||||
bool GrowIfPossible();
|
||||
Maybe<uint16_t> GetNextFreeSlot();
|
||||
Maybe<uint16_t> GetNextCacheIndex() {
|
||||
if (mFreeList.IsEmpty()) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
return Some(mFreeList.PopLastElement());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the initial and max cache size to given |aInitialSize| and |aMaxSize|.
|
||||
* Iterates through |mCachedItemState| and adds unused entries to free list.
|
||||
* If |aAddAll| is true, adds every entry regardless of the state.
|
||||
*/
|
||||
void SetCapacity(const size_t aInitialSize, const size_t aMaximumSize);
|
||||
void PopulateFreeList(const bool aAddAll);
|
||||
|
||||
/**
|
||||
* Returns true if the given |aPipelineId| is different from the previous one,
|
||||
|
@ -149,11 +143,12 @@ class DisplayItemCache final {
|
|||
return !isSame;
|
||||
}
|
||||
|
||||
size_t mMaximumSize;
|
||||
nsTArray<Slot> mSlots;
|
||||
nsTArray<uint16_t> mFreeSlots;
|
||||
nsTArray<CacheEntry> mCachedItemState;
|
||||
nsTArray<uint16_t> mFreeList;
|
||||
size_t mMaxCacheSize;
|
||||
uint16_t mNextIndex;
|
||||
Maybe<uint16_t> mCurrentIndex;
|
||||
Maybe<wr::PipelineId> mPreviousPipelineId;
|
||||
size_t mConsecutivePartialDisplayLists;
|
||||
CacheStats mCacheStats;
|
||||
};
|
||||
|
||||
|
|
|
@ -1552,7 +1552,12 @@ WebRenderCommandBuilder::WebRenderCommandBuilder(
|
|||
mLastAsr(nullptr),
|
||||
mDumpIndent(0),
|
||||
mDoGrouping(false),
|
||||
mContainsSVGGroup(false) {}
|
||||
mContainsSVGGroup(false) {
|
||||
if (XRE_IsContentProcess() &&
|
||||
StaticPrefs::gfx_webrender_enable_item_cache_AtStartup()) {
|
||||
mDisplayItemCache.SetCapacity(10000, 10000);
|
||||
}
|
||||
}
|
||||
|
||||
void WebRenderCommandBuilder::Destroy() {
|
||||
mLastCanvasDatas.Clear();
|
||||
|
@ -1598,6 +1603,13 @@ void WebRenderCommandBuilder::BuildWebRenderCommands(
|
|||
mContainsSVGGroup = false;
|
||||
MOZ_ASSERT(mDumpIndent == 0);
|
||||
|
||||
if (mDisplayItemCache.IsEnabled()) {
|
||||
mDisplayItemCache.UpdateState(aDisplayListBuilder->PartialBuildFailed(),
|
||||
aBuilder.CurrentPipelineId());
|
||||
aBuilder.SetDisplayListCacheSize(mDisplayItemCache.CurrentCacheSize());
|
||||
// mDisplayItemCache.Stats().Reset();
|
||||
}
|
||||
|
||||
{
|
||||
nsPresContext* presContext =
|
||||
aDisplayListBuilder->RootReferenceFrame()->PresContext();
|
||||
|
@ -1667,6 +1679,10 @@ void WebRenderCommandBuilder::BuildWebRenderCommands(
|
|||
// Remove the user data those are not displayed on the screen and
|
||||
// also reset the data to unused for next transaction.
|
||||
RemoveUnusedAndResetWebRenderUserData();
|
||||
|
||||
if (mDisplayItemCache.IsEnabled()) {
|
||||
// mDisplayItemCache.Stats().Print();
|
||||
}
|
||||
}
|
||||
|
||||
bool WebRenderCommandBuilder::ShouldDumpDisplayList(
|
||||
|
@ -1686,11 +1702,13 @@ void WebRenderCommandBuilder::CreateWebRenderCommands(
|
|||
auto* item = aItem->AsPaintedDisplayItem();
|
||||
MOZ_RELEASE_ASSERT(item, "Tried to paint item that cannot be painted");
|
||||
|
||||
if (aBuilder.ReuseItem(item)) {
|
||||
if (mDisplayItemCache.ReuseItem(item, aBuilder)) {
|
||||
// No further processing should be needed, since the item was reused.
|
||||
return;
|
||||
}
|
||||
|
||||
mDisplayItemCache.MaybeStartCaching(item, aBuilder);
|
||||
|
||||
aItem->SetPaintRect(aItem->GetBuildingRect());
|
||||
RenderRootStateManager* manager =
|
||||
mManager->GetRenderRootStateManager(aBuilder.GetRenderRoot());
|
||||
|
@ -1703,6 +1721,8 @@ void WebRenderCommandBuilder::CreateWebRenderCommands(
|
|||
if (!createdWRCommands) {
|
||||
PushItemAsImage(aItem, aBuilder, aResources, aSc, aDisplayListBuilder);
|
||||
}
|
||||
|
||||
mDisplayItemCache.MaybeEndCaching(aBuilder);
|
||||
}
|
||||
|
||||
void WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList(
|
||||
|
|
|
@ -255,6 +255,8 @@ class WebRenderCommandBuilder final {
|
|||
wr::RenderRootArray<wr::usize> mBuilderDumpIndex;
|
||||
wr::usize mDumpIndent;
|
||||
|
||||
DisplayItemCache mDisplayItemCache;
|
||||
|
||||
public:
|
||||
// Whether consecutive inactive display items should be grouped into one
|
||||
// blob image.
|
||||
|
|
|
@ -317,13 +317,11 @@ void WebRenderLayerManager::EndTransactionWithoutLayer(
|
|||
|
||||
wr::DisplayListBuilder builder(
|
||||
WrBridge()->GetPipeline(), wrRects[wr::RenderRoot::Default].size,
|
||||
mLastDisplayListSizes[wr::RenderRoot::Default], &mDisplayItemCache);
|
||||
|
||||
mLastDisplayListSizes[wr::RenderRoot::Default]);
|
||||
for (auto renderRoot : wr::kNonDefaultRenderRoots) {
|
||||
if (!rects[renderRoot].IsEmpty()) {
|
||||
builder.CreateSubBuilder(wrRects[renderRoot].size,
|
||||
mLastDisplayListSizes[renderRoot], nullptr,
|
||||
renderRoot);
|
||||
mLastDisplayListSizes[renderRoot], renderRoot);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -347,14 +345,9 @@ void WebRenderLayerManager::EndTransactionWithoutLayer(
|
|||
// generating the WR display list is the closest equivalent
|
||||
PaintTelemetry::AutoRecord record(PaintTelemetry::Metric::Layerization);
|
||||
|
||||
builder.UpdateCacheState(aDisplayListBuilder->PartialBuildFailed());
|
||||
|
||||
mWebRenderCommandBuilder.BuildWebRenderCommands(
|
||||
builder, resourceUpdates, aDisplayList, aDisplayListBuilder,
|
||||
mScrollDatas, std::move(aFilters));
|
||||
|
||||
builder.UpdateCacheSize();
|
||||
|
||||
builderDumpIndex =
|
||||
mWebRenderCommandBuilder.GetBuilderDumpIndex(builder.GetRenderRoot());
|
||||
containsSVGGroup = mWebRenderCommandBuilder.GetContainsSVGGroup();
|
||||
|
|
|
@ -238,7 +238,6 @@ class WebRenderLayerManager final : public LayerManager {
|
|||
|
||||
wr::RenderRootArray<size_t> mLastDisplayListSizes;
|
||||
wr::RenderRootArray<RenderRootStateManager> mStateManagers;
|
||||
DisplayItemCache mDisplayItemCache;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -924,16 +924,13 @@ void WebRenderAPI::RunOnRenderThread(UniquePtr<RendererEvent> aEvent) {
|
|||
|
||||
DisplayListBuilder::DisplayListBuilder(PipelineId aId,
|
||||
const wr::LayoutSize& aContentSize,
|
||||
size_t aCapacity,
|
||||
layers::DisplayItemCache* aCache,
|
||||
RenderRoot aRenderRoot)
|
||||
size_t aCapacity, RenderRoot aRenderRoot)
|
||||
: mCurrentSpaceAndClipChain(wr::RootScrollNodeWithChain()),
|
||||
mActiveFixedPosTracker(nullptr),
|
||||
mPipelineId(aId),
|
||||
mContentSize(aContentSize),
|
||||
mRenderRoot(aRenderRoot),
|
||||
mSendSubBuilderDisplayList(aRenderRoot == wr::RenderRoot::Default),
|
||||
mDisplayItemCache(aCache) {
|
||||
mSendSubBuilderDisplayList(aRenderRoot == wr::RenderRoot::Default) {
|
||||
MOZ_COUNT_CTOR(DisplayListBuilder);
|
||||
mWrState = wr_state_new(aId, aContentSize, aCapacity);
|
||||
}
|
||||
|
@ -949,11 +946,11 @@ void DisplayListBuilder::ClearSave() { wr_dp_clear_save(mWrState); }
|
|||
|
||||
DisplayListBuilder& DisplayListBuilder::CreateSubBuilder(
|
||||
const wr::LayoutSize& aContentSize, size_t aCapacity,
|
||||
layers::DisplayItemCache* aCache, wr::RenderRoot aRenderRoot) {
|
||||
wr::RenderRoot aRenderRoot) {
|
||||
MOZ_ASSERT(mRenderRoot == wr::RenderRoot::Default);
|
||||
MOZ_ASSERT(!mSubBuilders[aRenderRoot]);
|
||||
mSubBuilders[aRenderRoot] = MakeUnique<DisplayListBuilder>(
|
||||
mPipelineId, aContentSize, aCapacity, aCache, aRenderRoot);
|
||||
mPipelineId, aContentSize, aCapacity, aRenderRoot);
|
||||
return *mSubBuilders[aRenderRoot];
|
||||
}
|
||||
|
||||
|
@ -1488,83 +1485,20 @@ void DisplayListBuilder::PushBoxShadow(
|
|||
aBorderRadius, aClipMode);
|
||||
}
|
||||
|
||||
void DisplayListBuilder::StartGroup(nsPaintedDisplayItem* aItem) {
|
||||
if (!mDisplayItemCache || mDisplayItemCache->IsFull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mCurrentCacheSlot);
|
||||
mCurrentCacheSlot = mDisplayItemCache->AssignSlot(aItem);
|
||||
|
||||
if (mCurrentCacheSlot) {
|
||||
wr_dp_start_item_group(mWrState, mCurrentCacheSlot.ref());
|
||||
}
|
||||
void DisplayListBuilder::ReuseItem(wr::ItemKey aKey) {
|
||||
wr_dp_push_reuse_item(mWrState, aKey);
|
||||
}
|
||||
|
||||
void DisplayListBuilder::CancelGroup() {
|
||||
if (!mDisplayItemCache || !mCurrentCacheSlot) {
|
||||
return;
|
||||
}
|
||||
|
||||
wr_dp_cancel_item_group(mWrState);
|
||||
mCurrentCacheSlot = Nothing();
|
||||
void DisplayListBuilder::StartCachedItem(wr::ItemKey aKey) {
|
||||
wr_dp_start_cached_item(mWrState, aKey);
|
||||
}
|
||||
|
||||
void DisplayListBuilder::FinishGroup() {
|
||||
if (!mDisplayItemCache || !mCurrentCacheSlot) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mCurrentCacheSlot);
|
||||
|
||||
if (wr_dp_finish_item_group(mWrState, mCurrentCacheSlot.ref())) {
|
||||
mDisplayItemCache->MarkSlotOccupied(mCurrentCacheSlot.ref(),
|
||||
CurrentSpaceAndClipChain());
|
||||
mDisplayItemCache->Stats().AddCached();
|
||||
}
|
||||
|
||||
mCurrentCacheSlot = Nothing();
|
||||
bool DisplayListBuilder::EndCachedItem(wr::ItemKey aKey) {
|
||||
return wr_dp_end_cached_item(mWrState, aKey);
|
||||
}
|
||||
|
||||
bool DisplayListBuilder::ReuseItem(nsPaintedDisplayItem* aItem) {
|
||||
if (!mDisplayItemCache) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mDisplayItemCache->Stats().AddTotal();
|
||||
|
||||
if (mDisplayItemCache->IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Maybe<uint16_t> slot =
|
||||
mDisplayItemCache->CanReuseItem(aItem, CurrentSpaceAndClipChain());
|
||||
|
||||
if (slot) {
|
||||
mDisplayItemCache->Stats().AddReused();
|
||||
wr_dp_push_reuse_items(mWrState, slot.ref());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void DisplayListBuilder::UpdateCacheState(
|
||||
const bool aPartialDisplayListBuildFailed) {
|
||||
if (mDisplayItemCache && mDisplayItemCache->IsEnabled()) {
|
||||
mDisplayItemCache->UpdateState(aPartialDisplayListBuildFailed,
|
||||
CurrentPipelineId());
|
||||
#if 0
|
||||
mDisplayItemCache->Stats().Print();
|
||||
mDisplayItemCache->Stats().Reset();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayListBuilder::UpdateCacheSize() {
|
||||
if (mDisplayItemCache && mDisplayItemCache->IsEnabled()) {
|
||||
wr_dp_set_cache_size(mWrState, mDisplayItemCache->CurrentSize());
|
||||
}
|
||||
void DisplayListBuilder::SetDisplayListCacheSize(const size_t aCacheSize) {
|
||||
wr_dp_set_cache_size(mWrState, aCacheSize);
|
||||
}
|
||||
|
||||
Maybe<layers::ScrollableLayerGuid::ViewID>
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include "Units.h"
|
||||
|
||||
class nsDisplayItem;
|
||||
class nsPaintedDisplayItem;
|
||||
class nsDisplayTransform;
|
||||
|
||||
#undef None
|
||||
|
@ -40,7 +39,6 @@ class CompositorWidget;
|
|||
|
||||
namespace layers {
|
||||
class CompositorBridgeParent;
|
||||
class DisplayItemCache;
|
||||
class WebRenderBridgeParent;
|
||||
class RenderRootStateManager;
|
||||
struct RenderRootDisplayListData;
|
||||
|
@ -413,7 +411,6 @@ class DisplayListBuilder final {
|
|||
public:
|
||||
DisplayListBuilder(wr::PipelineId aId, const wr::LayoutSize& aContentSize,
|
||||
size_t aCapacity = 0,
|
||||
layers::DisplayItemCache* aCache = nullptr,
|
||||
RenderRoot aRenderRoot = RenderRoot::Default);
|
||||
DisplayListBuilder(DisplayListBuilder&&) = default;
|
||||
|
||||
|
@ -435,7 +432,6 @@ class DisplayListBuilder final {
|
|||
bool HasSubBuilder(RenderRoot aRenderRoot);
|
||||
DisplayListBuilder& CreateSubBuilder(const wr::LayoutSize& aContentSize,
|
||||
size_t aCapacity,
|
||||
layers::DisplayItemCache* aCache,
|
||||
RenderRoot aRenderRoot);
|
||||
DisplayListBuilder& SubBuilder(RenderRoot aRenderRoot);
|
||||
|
||||
|
@ -626,33 +622,10 @@ class DisplayListBuilder final {
|
|||
const wr::BorderRadius& aBorderRadius,
|
||||
const wr::BoxShadowClipMode& aClipMode);
|
||||
|
||||
/**
|
||||
* Notifies the DisplayListBuilder that it can group together WR display items
|
||||
* that are pushed until |CancelGroup()| or |FinishGroup()| call.
|
||||
*/
|
||||
void StartGroup(nsPaintedDisplayItem* aItem);
|
||||
|
||||
/**
|
||||
* Cancels grouping of the display items and discards all the display items
|
||||
* pushed between the |StartGroup()| and |CancelGroup()| calls.
|
||||
*/
|
||||
void CancelGroup();
|
||||
|
||||
/**
|
||||
* Finishes the display item group. The group is stored in WebRender backend,
|
||||
* and can be reused with |ReuseItem()|, if the Gecko display item is reused.
|
||||
*/
|
||||
void FinishGroup();
|
||||
|
||||
/**
|
||||
* Try to reuse the previously created WebRender display items for the given
|
||||
* Gecko display item |aItem|.
|
||||
* Returns true if the items were reused, otherwise returns false.
|
||||
*/
|
||||
bool ReuseItem(nsPaintedDisplayItem* aItem);
|
||||
|
||||
void UpdateCacheState(const bool aPartialDisplayListBuildFailed);
|
||||
void UpdateCacheSize();
|
||||
void StartCachedItem(wr::ItemKey aKey);
|
||||
bool EndCachedItem(wr::ItemKey aKey);
|
||||
void ReuseItem(wr::ItemKey aKey);
|
||||
void SetDisplayListCacheSize(const size_t aCacheSize);
|
||||
|
||||
uint64_t CurrentClipChainId() const {
|
||||
return mCurrentSpaceAndClipChain.clip_chain;
|
||||
|
@ -759,9 +732,6 @@ class DisplayListBuilder final {
|
|||
RenderRoot mRenderRoot;
|
||||
bool mSendSubBuilderDisplayList;
|
||||
|
||||
layers::DisplayItemCache* mDisplayItemCache;
|
||||
Maybe<uint16_t> mCurrentCacheSlot;
|
||||
|
||||
friend class WebRenderAPI;
|
||||
friend class SpaceAndClipChainHelper;
|
||||
};
|
||||
|
|
|
@ -33,11 +33,11 @@ use program_cache::{remove_disk_cache, WrProgramCache};
|
|||
use rayon;
|
||||
use thread_profiler::register_thread_with_profiler;
|
||||
use webrender::{
|
||||
api::units::*, api::*, set_profiler_hooks, ApiRecordingReceiver, AsyncPropertySampler, AsyncScreenshotHandle,
|
||||
BinaryRecorder, Compositor, CompositorCapabilities, CompositorConfig, DebugFlags, Device, NativeSurfaceId,
|
||||
NativeSurfaceInfo, NativeTileId, PipelineInfo, ProfilerHooks, RecordedFrameHandle, Renderer, RendererOptions,
|
||||
RendererStats, SceneBuilderHooks, ShaderPrecacheFlags, Shaders, ThreadListener, UploadMethod, VertexUsageHint,
|
||||
WrShaders,
|
||||
api::*, api::units::*, ApiRecordingReceiver, AsyncPropertySampler, AsyncScreenshotHandle,
|
||||
BinaryRecorder, Compositor, CompositorCapabilities, DebugFlags, Device,
|
||||
NativeSurfaceId, PipelineInfo, ProfilerHooks, RecordedFrameHandle, Renderer, RendererOptions, RendererStats,
|
||||
SceneBuilderHooks, ShaderPrecacheFlags, Shaders, ThreadListener, UploadMethod, VertexUsageHint,
|
||||
WrShaders, set_profiler_hooks, CompositorConfig, NativeSurfaceInfo, NativeTileId
|
||||
};
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
|
@ -972,7 +972,9 @@ pub struct WrHitTester {
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_api_request_hit_tester(dh: &DocumentHandle) -> *mut WrHitTester {
|
||||
pub extern "C" fn wr_api_request_hit_tester(
|
||||
dh: &DocumentHandle,
|
||||
) -> *mut WrHitTester {
|
||||
let hit_tester = dh.api.request_hit_tester(dh.document_id);
|
||||
Box::into_raw(Box::new(WrHitTester { ptr: hit_tester }))
|
||||
}
|
||||
|
@ -983,15 +985,20 @@ pub unsafe extern "C" fn wr_hit_tester_clone(hit_tester: *mut WrHitTester) -> *m
|
|||
Box::into_raw(Box::new(WrHitTester { ptr: new_ref }))
|
||||
}
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_hit_tester_hit_test(
|
||||
hit_tester: &WrHitTester,
|
||||
point: WorldPoint,
|
||||
out_pipeline_id: &mut WrPipelineId,
|
||||
out_scroll_id: &mut u64,
|
||||
out_hit_info: &mut u16,
|
||||
out_hit_info: &mut u16
|
||||
) -> bool {
|
||||
let result = hit_tester.ptr.hit_test(None, point, HitTestFlags::empty());
|
||||
let result = hit_tester.ptr.hit_test(
|
||||
None,
|
||||
point,
|
||||
HitTestFlags::empty()
|
||||
);
|
||||
|
||||
for item in &result.items {
|
||||
// For now we should never be getting results back for which the tag is
|
||||
|
@ -1205,8 +1212,13 @@ extern "C" {
|
|||
clip_rect: DeviceIntRect,
|
||||
);
|
||||
fn wr_compositor_end_frame(compositor: *mut c_void);
|
||||
fn wr_compositor_enable_native_compositor(compositor: *mut c_void, enable: bool);
|
||||
fn wr_compositor_get_capabilities(compositor: *mut c_void) -> CompositorCapabilities;
|
||||
fn wr_compositor_enable_native_compositor(
|
||||
compositor: *mut c_void,
|
||||
enable: bool,
|
||||
);
|
||||
fn wr_compositor_get_capabilities(
|
||||
compositor: *mut c_void,
|
||||
) -> CompositorCapabilities;
|
||||
}
|
||||
|
||||
pub struct WrCompositor(*mut c_void);
|
||||
|
@ -1220,7 +1232,13 @@ impl Compositor for WrCompositor {
|
|||
is_opaque: bool,
|
||||
) {
|
||||
unsafe {
|
||||
wr_compositor_create_surface(self.0, id, virtual_offset, tile_size, is_opaque);
|
||||
wr_compositor_create_surface(
|
||||
self.0,
|
||||
id,
|
||||
virtual_offset,
|
||||
tile_size,
|
||||
is_opaque,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1293,7 +1311,9 @@ impl Compositor for WrCompositor {
|
|||
}
|
||||
|
||||
fn get_capabilities(&self) -> CompositorCapabilities {
|
||||
unsafe { wr_compositor_get_capabilities(self.0) }
|
||||
unsafe {
|
||||
wr_compositor_get_capabilities(self.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2546,7 +2566,10 @@ pub extern "C" fn wr_dp_push_iframe(
|
|||
}
|
||||
|
||||
// A helper fn to construct a PrimitiveFlags
|
||||
fn prim_flags(is_backface_visible: bool, prefer_compositor_surface: bool) -> PrimitiveFlags {
|
||||
fn prim_flags(
|
||||
is_backface_visible: bool,
|
||||
prefer_compositor_surface: bool,
|
||||
) -> PrimitiveFlags {
|
||||
let mut flags = PrimitiveFlags::empty();
|
||||
|
||||
if is_backface_visible {
|
||||
|
@ -2796,18 +2819,16 @@ pub extern "C" fn wr_dp_push_clear_rect_with_parent_clip(
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_dp_push_image(
|
||||
state: &mut WrState,
|
||||
bounds: LayoutRect,
|
||||
clip: LayoutRect,
|
||||
is_backface_visible: bool,
|
||||
parent: &WrSpaceAndClipChain,
|
||||
image_rendering: ImageRendering,
|
||||
key: WrImageKey,
|
||||
premultiplied_alpha: bool,
|
||||
color: ColorF,
|
||||
prefer_compositor_surface: bool,
|
||||
) {
|
||||
pub extern "C" fn wr_dp_push_image(state: &mut WrState,
|
||||
bounds: LayoutRect,
|
||||
clip: LayoutRect,
|
||||
is_backface_visible: bool,
|
||||
parent: &WrSpaceAndClipChain,
|
||||
image_rendering: ImageRendering,
|
||||
key: WrImageKey,
|
||||
premultiplied_alpha: bool,
|
||||
color: ColorF,
|
||||
prefer_compositor_surface: bool) {
|
||||
debug_assert!(unsafe { is_in_main_thread() || is_in_compositor_thread() });
|
||||
|
||||
let space_and_clip = parent.to_webrender(state.pipeline_id);
|
||||
|
@ -2880,21 +2901,19 @@ pub extern "C" fn wr_dp_push_repeating_image(
|
|||
|
||||
/// Push a 3 planar yuv image.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_dp_push_yuv_planar_image(
|
||||
state: &mut WrState,
|
||||
bounds: LayoutRect,
|
||||
clip: LayoutRect,
|
||||
is_backface_visible: bool,
|
||||
parent: &WrSpaceAndClipChain,
|
||||
image_key_0: WrImageKey,
|
||||
image_key_1: WrImageKey,
|
||||
image_key_2: WrImageKey,
|
||||
color_depth: WrColorDepth,
|
||||
color_space: WrYuvColorSpace,
|
||||
color_range: WrColorRange,
|
||||
image_rendering: ImageRendering,
|
||||
prefer_compositor_surface: bool,
|
||||
) {
|
||||
pub extern "C" fn wr_dp_push_yuv_planar_image(state: &mut WrState,
|
||||
bounds: LayoutRect,
|
||||
clip: LayoutRect,
|
||||
is_backface_visible: bool,
|
||||
parent: &WrSpaceAndClipChain,
|
||||
image_key_0: WrImageKey,
|
||||
image_key_1: WrImageKey,
|
||||
image_key_2: WrImageKey,
|
||||
color_depth: WrColorDepth,
|
||||
color_space: WrYuvColorSpace,
|
||||
color_range: WrColorRange,
|
||||
image_rendering: ImageRendering,
|
||||
prefer_compositor_surface: bool) {
|
||||
debug_assert!(unsafe { is_in_main_thread() || is_in_compositor_thread() });
|
||||
|
||||
let space_and_clip = parent.to_webrender(state.pipeline_id);
|
||||
|
@ -2921,20 +2940,18 @@ pub extern "C" fn wr_dp_push_yuv_planar_image(
|
|||
|
||||
/// Push a 2 planar NV12 image.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_dp_push_yuv_NV12_image(
|
||||
state: &mut WrState,
|
||||
bounds: LayoutRect,
|
||||
clip: LayoutRect,
|
||||
is_backface_visible: bool,
|
||||
parent: &WrSpaceAndClipChain,
|
||||
image_key_0: WrImageKey,
|
||||
image_key_1: WrImageKey,
|
||||
color_depth: WrColorDepth,
|
||||
color_space: WrYuvColorSpace,
|
||||
color_range: WrColorRange,
|
||||
image_rendering: ImageRendering,
|
||||
prefer_compositor_surface: bool,
|
||||
) {
|
||||
pub extern "C" fn wr_dp_push_yuv_NV12_image(state: &mut WrState,
|
||||
bounds: LayoutRect,
|
||||
clip: LayoutRect,
|
||||
is_backface_visible: bool,
|
||||
parent: &WrSpaceAndClipChain,
|
||||
image_key_0: WrImageKey,
|
||||
image_key_1: WrImageKey,
|
||||
color_depth: WrColorDepth,
|
||||
color_space: WrYuvColorSpace,
|
||||
color_range: WrColorRange,
|
||||
image_rendering: ImageRendering,
|
||||
prefer_compositor_surface: bool) {
|
||||
debug_assert!(unsafe { is_in_main_thread() || is_in_compositor_thread() });
|
||||
|
||||
let space_and_clip = parent.to_webrender(state.pipeline_id);
|
||||
|
@ -2961,19 +2978,17 @@ pub extern "C" fn wr_dp_push_yuv_NV12_image(
|
|||
|
||||
/// Push a yuv interleaved image.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_dp_push_yuv_interleaved_image(
|
||||
state: &mut WrState,
|
||||
bounds: LayoutRect,
|
||||
clip: LayoutRect,
|
||||
is_backface_visible: bool,
|
||||
parent: &WrSpaceAndClipChain,
|
||||
image_key_0: WrImageKey,
|
||||
color_depth: WrColorDepth,
|
||||
color_space: WrYuvColorSpace,
|
||||
color_range: WrColorRange,
|
||||
image_rendering: ImageRendering,
|
||||
prefer_compositor_surface: bool,
|
||||
) {
|
||||
pub extern "C" fn wr_dp_push_yuv_interleaved_image(state: &mut WrState,
|
||||
bounds: LayoutRect,
|
||||
clip: LayoutRect,
|
||||
is_backface_visible: bool,
|
||||
parent: &WrSpaceAndClipChain,
|
||||
image_key_0: WrImageKey,
|
||||
color_depth: WrColorDepth,
|
||||
color_space: WrYuvColorSpace,
|
||||
color_range: WrColorRange,
|
||||
image_rendering: ImageRendering,
|
||||
prefer_compositor_surface: bool) {
|
||||
debug_assert!(unsafe { is_in_main_thread() || is_in_compositor_thread() });
|
||||
|
||||
let space_and_clip = parent.to_webrender(state.pipeline_id);
|
||||
|
@ -3543,26 +3558,25 @@ pub extern "C" fn wr_dp_start_cached_item(state: &mut WrState, key: ItemKey) {
|
|||
debug_assert!(state.current_item_key.is_none(), "Nested item keys");
|
||||
state.current_item_key = Some(key);
|
||||
|
||||
state.frame_builder.dl_builder.start_item_group(key);
|
||||
state.frame_builder.dl_builder.start_extra_data_chunk();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_dp_cancel_item_group(state: &mut WrState) {
|
||||
state.current_item_key = None;
|
||||
pub extern "C" fn wr_dp_end_cached_item(state: &mut WrState, key: ItemKey) -> bool {
|
||||
let _previous = state.current_item_key.take().expect("Nested item keys");
|
||||
debug_assert!(_previous == key, "Item key changed during caching");
|
||||
|
||||
state.frame_builder.dl_builder.cancel_item_group();
|
||||
if !state.frame_builder.dl_builder.end_extra_data_chunk() {
|
||||
return false;
|
||||
}
|
||||
|
||||
state.frame_builder.dl_builder.push_reuse_item(key);
|
||||
true
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_dp_finish_item_group(state: &mut WrState, key: ItemKey) -> bool {
|
||||
state.current_item_key = None;
|
||||
|
||||
state.frame_builder.dl_builder.finish_item_group(key)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_dp_push_reuse_items(state: &mut WrState, key: ItemKey) {
|
||||
state.frame_builder.dl_builder.push_reuse_items(key);
|
||||
pub extern "C" fn wr_dp_push_reuse_item(state: &mut WrState, key: ItemKey) {
|
||||
state.frame_builder.dl_builder.push_reuse_item(key);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
|
|
@ -68,8 +68,8 @@ impl DisplayItemCache {
|
|||
) {
|
||||
if capacity > self.items.len() {
|
||||
self.items.resize_with(capacity, || None::<CachedDisplayItem>);
|
||||
// println!("Current cache size: {:?} elements, {:?} bytes",
|
||||
// capacity, std::mem::size_of::<CachedDisplayItem>() * capacity);
|
||||
// println!("Current cache size: {:?}",
|
||||
// mem::size_of::<CachedDisplayItem>() * capacity);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -911,7 +911,7 @@ pub struct DisplayListBuilder {
|
|||
pub pipeline_id: PipelineId,
|
||||
|
||||
extra_data: Vec<u8>,
|
||||
extra_data_chunk_start: usize,
|
||||
extra_data_chunk_len: usize,
|
||||
writing_extra_data_chunk: bool,
|
||||
|
||||
next_clip_index: usize,
|
||||
|
@ -945,7 +945,7 @@ impl DisplayListBuilder {
|
|||
pipeline_id,
|
||||
|
||||
extra_data: Vec::new(),
|
||||
extra_data_chunk_start: 0,
|
||||
extra_data_chunk_len: 0,
|
||||
writing_extra_data_chunk: false,
|
||||
|
||||
next_clip_index: FIRST_CLIP_NODE_INDEX,
|
||||
|
@ -1744,38 +1744,29 @@ impl DisplayListBuilder {
|
|||
self.push_item(&di::DisplayItem::PopAllShadows);
|
||||
}
|
||||
|
||||
fn truncate_extra_data_chunk(&mut self) {
|
||||
self.extra_data.truncate(self.extra_data_chunk_start)
|
||||
}
|
||||
|
||||
pub fn start_item_group(&mut self, _key: di::ItemKey) {
|
||||
pub fn start_extra_data_chunk(&mut self) {
|
||||
self.writing_extra_data_chunk = true;
|
||||
self.extra_data_chunk_start = self.extra_data.len();
|
||||
self.extra_data_chunk_len = self.extra_data.len();
|
||||
}
|
||||
|
||||
pub fn finish_item_group(&mut self, key: di::ItemKey) -> bool {
|
||||
/// Returns true, if any bytes were written to extra data buffer.
|
||||
pub fn end_extra_data_chunk(&mut self) -> bool {
|
||||
self.writing_extra_data_chunk = false;
|
||||
|
||||
let chunk_size = self.extra_data.len() - self.extra_data_chunk_start;
|
||||
if chunk_size > 0 {
|
||||
self.push_reuse_items(key);
|
||||
return true
|
||||
}
|
||||
|
||||
false
|
||||
(self.extra_data.len() - self.extra_data_chunk_len) > 0
|
||||
}
|
||||
|
||||
pub fn cancel_item_group(&mut self) {
|
||||
debug_assert!(self.writing_extra_data_chunk);
|
||||
self.writing_extra_data_chunk = false;
|
||||
self.truncate_extra_data_chunk();
|
||||
pub fn push_reuse_item(
|
||||
&mut self,
|
||||
key: di::ItemKey,
|
||||
) {
|
||||
let item = di::DisplayItem::ReuseItem(key);
|
||||
self.push_item(&item);
|
||||
}
|
||||
|
||||
pub fn push_reuse_items(&mut self, key: di::ItemKey) {
|
||||
self.push_item(&di::DisplayItem::ReuseItem(key));
|
||||
}
|
||||
|
||||
pub fn set_cache_size(&mut self, cache_size: usize) {
|
||||
pub fn set_cache_size(
|
||||
&mut self,
|
||||
cache_size: usize,
|
||||
) {
|
||||
self.cache_size = cache_size;
|
||||
}
|
||||
|
||||
|
|
|
@ -5185,10 +5185,8 @@ bool nsDisplayBackgroundColor::CreateWebRenderCommands(
|
|||
aBuilder.PushRectWithAnimation(r, r, !BackfaceIsHidden(),
|
||||
wr::ToColorF(ToDeviceColor(mColor)), &prop);
|
||||
} else {
|
||||
aBuilder.StartGroup(this);
|
||||
aBuilder.PushRect(r, r, !BackfaceIsHidden(),
|
||||
wr::ToColorF(ToDeviceColor(mColor)));
|
||||
aBuilder.FinishGroup();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -5542,9 +5540,7 @@ bool nsDisplayCompositorHitTestInfo::CreateWebRenderCommands(
|
|||
|
||||
const wr::LayoutRect rect = wr::ToLayoutRect(devRect);
|
||||
|
||||
aBuilder.StartGroup(this);
|
||||
aBuilder.PushHitTest(rect, rect, !BackfaceIsHidden());
|
||||
aBuilder.FinishGroup();
|
||||
aBuilder.ClearHitTestInfo();
|
||||
|
||||
return true;
|
||||
|
|
|
@ -3215,6 +3215,16 @@ class nsPaintedDisplayItem : public nsDisplayItem {
|
|||
MOZ_ASSERT_UNREACHABLE("Paint() is not implemented!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Display items that are guaranteed to produce the same output from
|
||||
* |CreateWebRenderCommands()|, regardless of the surrounding state,
|
||||
* can return true. This allows |DisplayItemCache| to cache the output of
|
||||
* |CreateWebRenderCommands()|, and avoid the call for successive paints, if
|
||||
* the item is reused. If calling |CreateWebRenderCommands()| would not create
|
||||
* any WebRender display items, |CanBeCached()| should return false.
|
||||
*/
|
||||
virtual bool CanBeCached() const { return false; }
|
||||
|
||||
/**
|
||||
* External storage used by |DisplayItemCache| to avoid hashmap lookups.
|
||||
* If an item is reused and has the cache index set, it means that
|
||||
|
@ -4913,6 +4923,8 @@ class nsDisplayBackgroundColor : public nsPaintedDisplayItem {
|
|||
}
|
||||
}
|
||||
|
||||
bool CanBeCached() const final { return !HasBackgroundClipText(); }
|
||||
|
||||
NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR)
|
||||
|
||||
void RestoreState() override {
|
||||
|
@ -5303,6 +5315,12 @@ class nsDisplayCompositorHitTestInfo : public nsDisplayHitTestInfoBase {
|
|||
|
||||
MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayCompositorHitTestInfo)
|
||||
|
||||
bool CanBeCached() const final {
|
||||
// Do not try to cache gecko hit test items with empty hit test area,
|
||||
// because they would not create any WebRender display items.
|
||||
return !HitTestArea().IsEmpty();
|
||||
}
|
||||
|
||||
NS_DISPLAY_DECL_NAME("CompositorHitTestInfo", TYPE_COMPOSITOR_HITTEST_INFO)
|
||||
|
||||
void InitializeScrollTarget(nsDisplayListBuilder* aBuilder);
|
||||
|
|
Загрузка…
Ссылка в новой задаче