зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to inbound. a=merge CLOSED TREE
This commit is contained in:
Коммит
1981ff9293
|
@ -105,9 +105,12 @@ bool BasicLayerManager::PushGroupForLayer(gfxContext* aContext, Layer* aLayer,
|
|||
ToRect(rect).ToIntRect(&surfRect);
|
||||
|
||||
if (!surfRect.IsEmpty()) {
|
||||
RefPtr<DrawTarget> dt =
|
||||
aContext->GetDrawTarget()->CreateSimilarDrawTarget(
|
||||
surfRect.Size(), SurfaceFormat::B8G8R8A8);
|
||||
RefPtr<DrawTarget> dt;
|
||||
if (aContext->GetDrawTarget()->CanCreateSimilarDrawTarget(
|
||||
surfRect.Size(), SurfaceFormat::B8G8R8A8)) {
|
||||
dt = aContext->GetDrawTarget()->CreateSimilarDrawTarget(
|
||||
surfRect.Size(), SurfaceFormat::B8G8R8A8);
|
||||
}
|
||||
|
||||
RefPtr<gfxContext> ctx =
|
||||
gfxContext::CreateOrNull(dt, ToRect(rect).TopLeft());
|
||||
|
|
|
@ -399,7 +399,7 @@ void AsyncImagePipelineManager::ApplyAsyncImageForPipeline(
|
|||
wr::DisplayListBuilder builder(aPipelineId, contentSize);
|
||||
|
||||
float opacity = 1.0f;
|
||||
Maybe<wr::WrClipId> referenceFrameId = builder.PushStackingContext(
|
||||
Maybe<wr::WrSpatialId> referenceFrameId = builder.PushStackingContext(
|
||||
wr::ToRoundedLayoutRect(aPipeline->mScBounds), nullptr, nullptr, &opacity,
|
||||
aPipeline->mScTransform.IsIdentity() ? nullptr : &aPipeline->mScTransform,
|
||||
wr::TransformStyle::Flat, nullptr, aPipeline->mMixBlendMode,
|
||||
|
@ -407,6 +407,11 @@ void AsyncImagePipelineManager::ApplyAsyncImageForPipeline(
|
|||
// This is fine to do unconditionally because we only push images here.
|
||||
wr::RasterSpace::Screen());
|
||||
|
||||
Maybe<wr::SpaceAndClipChainHelper> spaceAndClipChainHelper;
|
||||
if (referenceFrameId) {
|
||||
spaceAndClipChainHelper.emplace(builder, referenceFrameId.ref());
|
||||
}
|
||||
|
||||
if (aPipeline->mCurrentTexture && !keys.IsEmpty()) {
|
||||
LayoutDeviceRect rect(0, 0, aPipeline->mCurrentTexture->GetSize().width,
|
||||
aPipeline->mCurrentTexture->GetSize().height);
|
||||
|
@ -431,6 +436,7 @@ void AsyncImagePipelineManager::ApplyAsyncImageForPipeline(
|
|||
}
|
||||
}
|
||||
|
||||
spaceAndClipChainHelper.reset();
|
||||
builder.PopStackingContext(referenceFrameId.isSome());
|
||||
|
||||
wr::BuiltDisplayList dl;
|
||||
|
|
|
@ -17,12 +17,10 @@
|
|||
#include "UnitTransforms.h"
|
||||
|
||||
#define CLIP_LOG(...)
|
||||
/*
|
||||
#define CLIP_LOG(...) printf_stderr("CLIP: " __VA_ARGS__)
|
||||
#define CLIP_LOG(...) if (XRE_IsContentProcess()) { \
|
||||
printf_stderr("CLIP: " __VA_ARGS__) \
|
||||
}
|
||||
*/
|
||||
|
||||
//#define CLIP_LOG(...) printf_stderr("CLIP: " __VA_ARGS__)
|
||||
|
||||
//#define CLIP_LOG(...) if (XRE_IsContentProcess()) printf_stderr("CLIP: " __VA_ARGS__)
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
@ -66,12 +64,17 @@ void ClipManager::BeginList(const StackingContextHelper& aStackingContext) {
|
|||
if (!mItemClipStack.empty()) {
|
||||
clips.CopyOutputsFrom(mItemClipStack.top());
|
||||
}
|
||||
|
||||
if (aStackingContext.ReferenceFrameId()) {
|
||||
clips.mScrollId = aStackingContext.ReferenceFrameId().ref();
|
||||
}
|
||||
|
||||
mItemClipStack.push(clips);
|
||||
}
|
||||
|
||||
void ClipManager::EndList(const StackingContextHelper& aStackingContext) {
|
||||
MOZ_ASSERT(!mItemClipStack.empty());
|
||||
mItemClipStack.top().Unapply(mBuilder);
|
||||
mBuilder->SetClipChainLeaf(Nothing());
|
||||
mItemClipStack.pop();
|
||||
|
||||
if (aStackingContext.AffectsClipPositioning()) {
|
||||
|
@ -86,14 +89,16 @@ void ClipManager::EndList(const StackingContextHelper& aStackingContext) {
|
|||
}
|
||||
|
||||
void ClipManager::PushOverrideForASR(const ActiveScrolledRoot* aASR,
|
||||
const wr::WrClipId& aClipId) {
|
||||
Maybe<wr::WrClipId> scrollId = GetScrollLayer(aASR);
|
||||
MOZ_ASSERT(scrollId.isSome());
|
||||
const wr::WrSpatialId& aSpatialId) {
|
||||
Maybe<wr::WrSpaceAndClip> spaceAndClip = GetScrollLayer(aASR);
|
||||
MOZ_ASSERT(spaceAndClip.isSome());
|
||||
|
||||
CLIP_LOG("Pushing override %zu -> %s\n", scrollId->id,
|
||||
Stringify(aClipId.id).c_str());
|
||||
auto it = mASROverride.insert({*scrollId, std::stack<wr::WrClipId>()});
|
||||
it.first->second.push(aClipId);
|
||||
CLIP_LOG("Pushing %p override %zu -> %s\n", aASR, spaceAndClip->space.id,
|
||||
Stringify(aSpatialId.id).c_str());
|
||||
|
||||
auto it =
|
||||
mASROverride.insert({spaceAndClip->space, std::stack<wr::WrSpatialId>()});
|
||||
it.first->second.push(aSpatialId);
|
||||
|
||||
// Start a new cache
|
||||
mCacheStack.emplace();
|
||||
|
@ -103,41 +108,39 @@ void ClipManager::PopOverrideForASR(const ActiveScrolledRoot* aASR) {
|
|||
MOZ_ASSERT(!mCacheStack.empty());
|
||||
mCacheStack.pop();
|
||||
|
||||
Maybe<wr::WrClipId> scrollId = GetScrollLayer(aASR);
|
||||
MOZ_ASSERT(scrollId.isSome());
|
||||
Maybe<wr::WrSpaceAndClip> spaceAndClip = GetScrollLayer(aASR);
|
||||
MOZ_ASSERT(spaceAndClip.isSome());
|
||||
|
||||
auto it = mASROverride.find(*scrollId);
|
||||
MOZ_ASSERT(it != mASROverride.end());
|
||||
MOZ_ASSERT(!(it->second.empty()));
|
||||
CLIP_LOG("Popping override %zu -> %s\n", scrollId->id,
|
||||
auto it = mASROverride.find(spaceAndClip->space);
|
||||
CLIP_LOG("Popping %p override %zu -> %s\n", aASR, spaceAndClip->space.id,
|
||||
Stringify(it->second.top().id).c_str());
|
||||
|
||||
it->second.pop();
|
||||
if (it->second.empty()) {
|
||||
mASROverride.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<wr::WrClipId> ClipManager::ClipIdAfterOverride(
|
||||
const Maybe<wr::WrClipId>& aClipId) {
|
||||
if (!aClipId) {
|
||||
return Nothing();
|
||||
}
|
||||
auto it = mASROverride.find(*aClipId);
|
||||
wr::WrSpatialId ClipManager::SpatialIdAfterOverride(
|
||||
const wr::WrSpatialId& aSpatialId) {
|
||||
auto it = mASROverride.find(aSpatialId);
|
||||
if (it == mASROverride.end()) {
|
||||
return aClipId;
|
||||
return aSpatialId;
|
||||
}
|
||||
MOZ_ASSERT(!it->second.empty());
|
||||
CLIP_LOG("Overriding %zu with %s\n", aClipId->id,
|
||||
CLIP_LOG("Overriding %zu with %s\n", aSpatialId.id,
|
||||
Stringify(it->second.top().id).c_str());
|
||||
return Some(it->second.top());
|
||||
|
||||
return it->second.top();
|
||||
}
|
||||
|
||||
void ClipManager::BeginItem(nsDisplayItem* aItem,
|
||||
const StackingContextHelper& aStackingContext) {
|
||||
CLIP_LOG("processing item %p\n", aItem);
|
||||
|
||||
wr::WrSpaceAndClipChain ClipManager::SwitchItem(
|
||||
nsDisplayItem* aItem, const StackingContextHelper& aStackingContext) {
|
||||
const DisplayItemClipChain* clip = aItem->GetClipChain();
|
||||
const ActiveScrolledRoot* asr = aItem->GetActiveScrolledRoot();
|
||||
CLIP_LOG("processing item %p (%s) asr %p\n", aItem,
|
||||
DisplayItemTypeName(aItem->GetType()), asr);
|
||||
|
||||
DisplayItemType type = aItem->GetType();
|
||||
if (type == DisplayItemType::TYPE_STICKY_POSITION) {
|
||||
// For sticky position items, the ASR is computed differently depending
|
||||
|
@ -174,13 +177,12 @@ void ClipManager::BeginItem(nsDisplayItem* aItem,
|
|||
// have a previous sibling, that means BeginList would have been called
|
||||
// just before this, which will have pushed a ItemClips(nullptr, nullptr)
|
||||
// onto mItemClipStack, so the HasSameInputs check should return false.
|
||||
CLIP_LOG("early-exit for %p\n", aItem);
|
||||
return;
|
||||
CLIP_LOG("\tearly-exit for %p\n", aItem);
|
||||
return mItemClipStack.top().GetSpaceAndClipChain();
|
||||
}
|
||||
|
||||
// Pop aItem's previous sibling's stuff from mBuilder in preparation for
|
||||
// pushing aItem's stuff.
|
||||
mItemClipStack.top().Unapply(mBuilder);
|
||||
mItemClipStack.pop();
|
||||
|
||||
// Zoom display items report their bounds etc using the parent document's
|
||||
|
@ -197,6 +199,7 @@ void ClipManager::BeginItem(nsDisplayItem* aItem,
|
|||
// If the leaf of the clip chain is going to be merged with the display item's
|
||||
// clip rect, then we should create a clip chain id from the leaf's parent.
|
||||
if (separateLeaf) {
|
||||
CLIP_LOG("\tseparate leaf detected, ignoring the last clip\n");
|
||||
clip = clip->mParent;
|
||||
}
|
||||
|
||||
|
@ -211,44 +214,36 @@ void ClipManager::BeginItem(nsDisplayItem* aItem,
|
|||
if (clip) {
|
||||
leafmostASR = ActiveScrolledRoot::PickDescendant(leafmostASR, clip->mASR);
|
||||
}
|
||||
Maybe<wr::WrClipId> leafmostId =
|
||||
Maybe<wr::WrSpaceAndClip> leafmostId =
|
||||
DefineScrollLayers(leafmostASR, aItem, aStackingContext);
|
||||
|
||||
// Define all the clips in the item's clip chain, and obtain a clip chain id
|
||||
// for it.
|
||||
clips.mClipChainId = DefineClipChain(clip, auPerDevPixel, aStackingContext);
|
||||
|
||||
if (clip) {
|
||||
// If the clip's ASR is different, then we need to set the scroll id
|
||||
// explicitly to match the desired ASR.
|
||||
Maybe<wr::WrClipId> scrollId = GetScrollLayer(asr);
|
||||
MOZ_ASSERT(scrollId.isSome());
|
||||
clips.mScrollId = ClipIdAfterOverride(scrollId);
|
||||
} else {
|
||||
// If we don't have a clip at all, then we don't want to explicitly push
|
||||
// the ASR either, because as with the first clause of this if condition,
|
||||
// the item might get hoisted out of a stacking context that was pushed
|
||||
// between the |asr| and this |aItem|. Instead we just leave clips.mScrollId
|
||||
// empty and things seem to work out.
|
||||
// XXX: there might be cases where things don't just "work out", in which
|
||||
// case we might need to do something smarter here.
|
||||
}
|
||||
Maybe<wr::WrSpaceAndClip> spaceAndClip = GetScrollLayer(asr);
|
||||
MOZ_ASSERT(spaceAndClip.isSome());
|
||||
clips.mScrollId = SpatialIdAfterOverride(spaceAndClip->space);
|
||||
CLIP_LOG("\tassigning %d -> %d\n", (int)spaceAndClip->space.id,
|
||||
(int)clips.mScrollId.id);
|
||||
|
||||
// Now that we have the scroll id and a clip id for the item, push it onto
|
||||
// the WR stack.
|
||||
clips.Apply(mBuilder, auPerDevPixel);
|
||||
clips.UpdateSeparateLeaf(*mBuilder, auPerDevPixel);
|
||||
auto spaceAndClipChain = clips.GetSpaceAndClipChain();
|
||||
mItemClipStack.push(clips);
|
||||
|
||||
CLIP_LOG("done setup for %p\n", aItem);
|
||||
return spaceAndClipChain;
|
||||
}
|
||||
|
||||
Maybe<wr::WrClipId> ClipManager::GetScrollLayer(
|
||||
Maybe<wr::WrSpaceAndClip> ClipManager::GetScrollLayer(
|
||||
const ActiveScrolledRoot* aASR) {
|
||||
for (const ActiveScrolledRoot* asr = aASR; asr; asr = asr->mParent) {
|
||||
Maybe<wr::WrClipId> scrollId =
|
||||
Maybe<wr::WrSpaceAndClip> spaceAndClip =
|
||||
mBuilder->GetScrollIdForDefinedScrollLayer(asr->GetViewId());
|
||||
if (scrollId) {
|
||||
return scrollId;
|
||||
if (spaceAndClip) {
|
||||
return spaceAndClip;
|
||||
}
|
||||
|
||||
// If this ASR doesn't have a scroll ID, then we should check its ancestor.
|
||||
|
@ -256,13 +251,14 @@ Maybe<wr::WrClipId> ClipManager::GetScrollLayer(
|
|||
// failed to get the scroll metadata.
|
||||
}
|
||||
|
||||
Maybe<wr::WrClipId> scrollId = mBuilder->GetScrollIdForDefinedScrollLayer(
|
||||
ScrollableLayerGuid::NULL_SCROLL_ID);
|
||||
MOZ_ASSERT(scrollId.isSome());
|
||||
return scrollId;
|
||||
Maybe<wr::WrSpaceAndClip> spaceAndClip =
|
||||
mBuilder->GetScrollIdForDefinedScrollLayer(
|
||||
ScrollableLayerGuid::NULL_SCROLL_ID);
|
||||
MOZ_ASSERT(spaceAndClip.isSome());
|
||||
return spaceAndClip;
|
||||
}
|
||||
|
||||
Maybe<wr::WrClipId> ClipManager::DefineScrollLayers(
|
||||
Maybe<wr::WrSpaceAndClip> ClipManager::DefineScrollLayers(
|
||||
const ActiveScrolledRoot* aASR, nsDisplayItem* aItem,
|
||||
const StackingContextHelper& aSc) {
|
||||
if (!aASR) {
|
||||
|
@ -270,14 +266,14 @@ Maybe<wr::WrClipId> ClipManager::DefineScrollLayers(
|
|||
return Nothing();
|
||||
}
|
||||
ScrollableLayerGuid::ViewID viewId = aASR->GetViewId();
|
||||
Maybe<wr::WrClipId> scrollId =
|
||||
Maybe<wr::WrSpaceAndClip> spaceAndClip =
|
||||
mBuilder->GetScrollIdForDefinedScrollLayer(viewId);
|
||||
if (scrollId) {
|
||||
if (spaceAndClip) {
|
||||
// If we've already defined this scroll layer before, we can early-exit
|
||||
return scrollId;
|
||||
return spaceAndClip;
|
||||
}
|
||||
// Recurse to define the ancestors
|
||||
Maybe<wr::WrClipId> ancestorScrollId =
|
||||
Maybe<wr::WrSpaceAndClip> ancestorSpaceAndClip =
|
||||
DefineScrollLayers(aASR->mParent, aItem, aSc);
|
||||
|
||||
Maybe<ScrollMetadata> metadata =
|
||||
|
@ -285,13 +281,13 @@ Maybe<wr::WrClipId> ClipManager::DefineScrollLayers(
|
|||
mManager, aItem->ReferenceFrame(), Nothing(), nullptr);
|
||||
if (!metadata) {
|
||||
MOZ_ASSERT_UNREACHABLE("Expected scroll metadata to be available!");
|
||||
return ancestorScrollId;
|
||||
return ancestorSpaceAndClip;
|
||||
}
|
||||
|
||||
FrameMetrics& metrics = metadata->GetMetrics();
|
||||
if (!metrics.IsScrollable()) {
|
||||
// This item is a scrolling no-op, skip over it in the ASR chain.
|
||||
return ancestorScrollId;
|
||||
return ancestorSpaceAndClip;
|
||||
}
|
||||
|
||||
LayoutDeviceRect contentRect =
|
||||
|
@ -309,12 +305,13 @@ Maybe<wr::WrClipId> ClipManager::DefineScrollLayers(
|
|||
// bounds.
|
||||
contentRect.MoveTo(clipBounds.TopLeft());
|
||||
|
||||
Maybe<wr::WrClipId> parent = ClipIdAfterOverride(ancestorScrollId);
|
||||
scrollId = Some(mBuilder->DefineScrollLayer(
|
||||
viewId, parent, wr::ToRoundedLayoutRect(contentRect),
|
||||
wr::ToRoundedLayoutRect(clipBounds)));
|
||||
|
||||
return scrollId;
|
||||
Maybe<wr::WrSpaceAndClip> parent = ancestorSpaceAndClip;
|
||||
if (parent) {
|
||||
parent->space = SpatialIdAfterOverride(parent->space);
|
||||
}
|
||||
return Some(mBuilder->DefineScrollLayer(viewId, parent,
|
||||
wr::ToRoundedLayoutRect(contentRect),
|
||||
wr::ToRoundedLayoutRect(clipBounds)));
|
||||
}
|
||||
|
||||
Maybe<wr::WrClipChainId> ClipManager::DefineClipChain(
|
||||
|
@ -345,15 +342,15 @@ Maybe<wr::WrClipChainId> ClipManager::DefineClipChain(
|
|||
chain->mClip.ToComplexClipRegions(aAppUnitsPerDevPixel, aSc,
|
||||
wrRoundedRects);
|
||||
|
||||
Maybe<wr::WrClipId> scrollId = GetScrollLayer(chain->mASR);
|
||||
Maybe<wr::WrSpaceAndClip> spaceAndClip = GetScrollLayer(chain->mASR);
|
||||
// Before calling DefineClipChain we defined the ASRs by calling
|
||||
// DefineScrollLayers, so we must have a scrollId here.
|
||||
MOZ_ASSERT(scrollId.isSome());
|
||||
MOZ_ASSERT(spaceAndClip.isSome());
|
||||
|
||||
// Define the clip
|
||||
Maybe<wr::WrClipId> parent = ClipIdAfterOverride(scrollId);
|
||||
spaceAndClip->space = SpatialIdAfterOverride(spaceAndClip->space);
|
||||
wr::WrClipId clipId = mBuilder->DefineClip(
|
||||
parent, wr::ToRoundedLayoutRect(clip), &wrRoundedRects);
|
||||
spaceAndClip, wr::ToRoundedLayoutRect(clip), &wrRoundedRects);
|
||||
clipIds.AppendElement(clipId);
|
||||
cache[chain] = clipId;
|
||||
CLIP_LOG("cache[%p] <= %zu\n", chain, clipId.id);
|
||||
|
@ -386,16 +383,12 @@ ClipManager::~ClipManager() {
|
|||
ClipManager::ItemClips::ItemClips(const ActiveScrolledRoot* aASR,
|
||||
const DisplayItemClipChain* aChain,
|
||||
bool aSeparateLeaf)
|
||||
: mASR(aASR),
|
||||
mChain(aChain),
|
||||
mSeparateLeaf(aSeparateLeaf),
|
||||
mApplied(false) {}
|
||||
|
||||
void ClipManager::ItemClips::Apply(wr::DisplayListBuilder* aBuilder,
|
||||
int32_t aAppUnitsPerDevPixel) {
|
||||
MOZ_ASSERT(!mApplied);
|
||||
mApplied = true;
|
||||
: mASR(aASR), mChain(aChain), mSeparateLeaf(aSeparateLeaf) {
|
||||
mScrollId.id = 0;
|
||||
}
|
||||
|
||||
void ClipManager::ItemClips::UpdateSeparateLeaf(
|
||||
wr::DisplayListBuilder& aBuilder, int32_t aAppUnitsPerDevPixel) {
|
||||
Maybe<wr::LayoutRect> clipLeaf;
|
||||
if (mSeparateLeaf) {
|
||||
MOZ_ASSERT(mChain);
|
||||
|
@ -403,15 +396,7 @@ void ClipManager::ItemClips::Apply(wr::DisplayListBuilder* aBuilder,
|
|||
mChain->mClip.GetClipRect(), aAppUnitsPerDevPixel)));
|
||||
}
|
||||
|
||||
aBuilder->PushClipAndScrollInfo(mScrollId.ptrOr(nullptr),
|
||||
mClipChainId.ptrOr(nullptr), clipLeaf);
|
||||
}
|
||||
|
||||
void ClipManager::ItemClips::Unapply(wr::DisplayListBuilder* aBuilder) {
|
||||
if (mApplied) {
|
||||
mApplied = false;
|
||||
aBuilder->PopClipAndScrollInfo(mScrollId.ptrOr(nullptr));
|
||||
}
|
||||
aBuilder.SetClipChainLeaf(clipLeaf);
|
||||
}
|
||||
|
||||
bool ClipManager::ItemClips::HasSameInputs(const ItemClips& aOther) {
|
||||
|
@ -424,5 +409,14 @@ void ClipManager::ItemClips::CopyOutputsFrom(const ItemClips& aOther) {
|
|||
mClipChainId = aOther.mClipChainId;
|
||||
}
|
||||
|
||||
wr::WrSpaceAndClipChain ClipManager::ItemClips::GetSpaceAndClipChain() const {
|
||||
auto spaceAndClipChain = wr::RootScrollNodeWithChain();
|
||||
spaceAndClipChain.space = mScrollId;
|
||||
if (mClipChainId) {
|
||||
spaceAndClipChain.clip_chain = mClipChainId->id;
|
||||
}
|
||||
return spaceAndClipChain;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -60,22 +60,22 @@ class ClipManager {
|
|||
void BeginList(const StackingContextHelper& aStackingContext);
|
||||
void EndList(const StackingContextHelper& aStackingContext);
|
||||
|
||||
void BeginItem(nsDisplayItem* aItem,
|
||||
const StackingContextHelper& aStackingContext);
|
||||
wr::WrSpaceAndClipChain SwitchItem(
|
||||
nsDisplayItem* aItem, const StackingContextHelper& aStackingContext);
|
||||
~ClipManager();
|
||||
|
||||
void PushOverrideForASR(const ActiveScrolledRoot* aASR,
|
||||
const wr::WrClipId& aClipId);
|
||||
const wr::WrSpatialId& aSpatialId);
|
||||
void PopOverrideForASR(const ActiveScrolledRoot* aASR);
|
||||
|
||||
private:
|
||||
Maybe<wr::WrClipId> ClipIdAfterOverride(const Maybe<wr::WrClipId>& aClipId);
|
||||
wr::WrSpatialId SpatialIdAfterOverride(const wr::WrSpatialId& aSpatialId);
|
||||
|
||||
Maybe<wr::WrClipId> GetScrollLayer(const ActiveScrolledRoot* aASR);
|
||||
Maybe<wr::WrSpaceAndClip> GetScrollLayer(const ActiveScrolledRoot* aASR);
|
||||
|
||||
Maybe<wr::WrClipId> DefineScrollLayers(const ActiveScrolledRoot* aASR,
|
||||
nsDisplayItem* aItem,
|
||||
const StackingContextHelper& aSc);
|
||||
Maybe<wr::WrSpaceAndClip> DefineScrollLayers(
|
||||
const ActiveScrolledRoot* aASR, nsDisplayItem* aItem,
|
||||
const StackingContextHelper& aSc);
|
||||
|
||||
Maybe<wr::WrClipChainId> DefineClipChain(const DisplayItemClipChain* aChain,
|
||||
int32_t aAppUnitsPerDevPixel,
|
||||
|
@ -116,7 +116,7 @@ class ClipManager {
|
|||
// ClipManager to do the necessary lookup. Note that there theoretically might
|
||||
// be multiple different "Y" clips (in case of nested cache overrides), which
|
||||
// is why we need a stack.
|
||||
std::unordered_map<wr::WrClipId, std::stack<wr::WrClipId>> mASROverride;
|
||||
std::unordered_map<wr::WrSpatialId, std::stack<wr::WrSpatialId>> mASROverride;
|
||||
|
||||
// This holds some clip state for a single nsDisplayItem
|
||||
struct ItemClips {
|
||||
|
@ -129,16 +129,14 @@ class ClipManager {
|
|||
bool mSeparateLeaf;
|
||||
|
||||
// These are the "outputs" - they are pushed to WR as needed
|
||||
Maybe<wr::WrClipId> mScrollId;
|
||||
wr::WrSpatialId mScrollId;
|
||||
Maybe<wr::WrClipChainId> mClipChainId;
|
||||
|
||||
// State tracking
|
||||
bool mApplied;
|
||||
|
||||
void Apply(wr::DisplayListBuilder* aBuilder, int32_t aAppUnitsPerDevPixel);
|
||||
void Unapply(wr::DisplayListBuilder* aBuilder);
|
||||
void UpdateSeparateLeaf(wr::DisplayListBuilder& aBuilder,
|
||||
int32_t aAppUnitsPerDevPixel);
|
||||
bool HasSameInputs(const ItemClips& aOther);
|
||||
void CopyOutputsFrom(const ItemClips& aOther);
|
||||
wr::WrSpaceAndClipChain GetSpaceAndClipChain() const;
|
||||
};
|
||||
|
||||
// A stack of ItemClips corresponding to the nsDisplayItem ancestry. Each
|
||||
|
|
|
@ -74,6 +74,10 @@ StackingContextHelper::StackingContextHelper(
|
|||
aPerspectivePtr, wr::ToMixBlendMode(aMixBlendMode), aFilters,
|
||||
aBackfaceVisible, rasterSpace);
|
||||
|
||||
if (mReferenceFrameId) {
|
||||
mSpaceAndClipChainHelper.emplace(aBuilder, mReferenceFrameId.ref());
|
||||
}
|
||||
|
||||
mAffectsClipPositioning =
|
||||
mReferenceFrameId.isSome() || (aBounds.TopLeft() != LayoutDevicePoint());
|
||||
|
||||
|
@ -98,6 +102,7 @@ StackingContextHelper::StackingContextHelper(
|
|||
|
||||
StackingContextHelper::~StackingContextHelper() {
|
||||
if (mBuilder) {
|
||||
mSpaceAndClipChainHelper.reset();
|
||||
mBuilder->PopStackingContext(mReferenceFrameId.isSome());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ class MOZ_RAII StackingContextHelper {
|
|||
Maybe<gfx::Matrix4x4> GetDeferredTransformMatrix() const;
|
||||
|
||||
bool AffectsClipPositioning() const { return mAffectsClipPositioning; }
|
||||
Maybe<wr::WrClipId> ReferenceFrameId() const { return mReferenceFrameId; }
|
||||
Maybe<wr::WrSpatialId> ReferenceFrameId() const { return mReferenceFrameId; }
|
||||
|
||||
private:
|
||||
wr::DisplayListBuilder* mBuilder;
|
||||
|
@ -81,7 +81,8 @@ class MOZ_RAII StackingContextHelper {
|
|||
// existence of a non-animated identity transform does not affect snapping.
|
||||
gfx::Matrix mSnappingSurfaceTransform;
|
||||
bool mAffectsClipPositioning;
|
||||
Maybe<wr::WrClipId> mReferenceFrameId;
|
||||
Maybe<wr::WrSpatialId> mReferenceFrameId;
|
||||
Maybe<wr::SpaceAndClipChainHelper> mSpaceAndClipChainHelper;
|
||||
|
||||
// The deferred transform item is used when building the WebRenderScrollData
|
||||
// structure. The backstory is that APZ needs to know about transforms that
|
||||
|
|
|
@ -1126,18 +1126,24 @@ void Grouper::ConstructGroups(nsDisplayListBuilder* aDisplayListBuilder,
|
|||
currentGroup->EndGroup(aCommandBuilder->mManager, aDisplayListBuilder,
|
||||
aBuilder, aResources, this, startOfCurrentGroup,
|
||||
item);
|
||||
mClipManager.BeginItem(item, aSc);
|
||||
sIndent++;
|
||||
// Note: this call to CreateWebRenderCommands can recurse back into
|
||||
// this function.
|
||||
RenderRootStateManager* manager =
|
||||
aCommandBuilder->mManager->GetRenderRootStateManager();
|
||||
bool createdWRCommands = item->CreateWebRenderCommands(
|
||||
aBuilder, aResources, aSc, manager, mDisplayListBuilder);
|
||||
sIndent--;
|
||||
MOZ_RELEASE_ASSERT(createdWRCommands,
|
||||
"active transforms should always succeed at creating "
|
||||
"WebRender commands");
|
||||
|
||||
{
|
||||
auto spaceAndClipChain = mClipManager.SwitchItem(item, aSc);
|
||||
wr::SpaceAndClipChainHelper saccHelper(aBuilder, spaceAndClipChain);
|
||||
|
||||
sIndent++;
|
||||
// Note: this call to CreateWebRenderCommands can recurse back into
|
||||
// this function.
|
||||
RenderRootStateManager* manager =
|
||||
aCommandBuilder->mManager->GetRenderRootStateManager();
|
||||
bool createdWRCommands = item->CreateWebRenderCommands(
|
||||
aBuilder, aResources, aSc, manager, mDisplayListBuilder);
|
||||
sIndent--;
|
||||
MOZ_RELEASE_ASSERT(
|
||||
createdWRCommands,
|
||||
"active transforms should always succeed at creating "
|
||||
"WebRender commands");
|
||||
}
|
||||
|
||||
RefPtr<WebRenderGroupData> groupData =
|
||||
aCommandBuilder->CreateOrRecycleWebRenderUserData<WebRenderGroupData>(
|
||||
|
@ -1594,7 +1600,10 @@ void WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList(
|
|||
}
|
||||
}
|
||||
|
||||
mClipManager.BeginItem(item, aSc);
|
||||
// This is where we emulate the clip/scroll stack that was previously
|
||||
// implemented on the WR display list side.
|
||||
auto spaceAndClipChain = mClipManager.SwitchItem(item, aSc);
|
||||
wr::SpaceAndClipChainHelper saccHelper(aBuilder, spaceAndClipChain);
|
||||
|
||||
{ // scope restoreDoGrouping
|
||||
AutoRestore<bool> restoreDoGrouping(mDoGrouping);
|
||||
|
@ -1705,9 +1714,9 @@ void WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList(
|
|||
mClipManager.EndList(aSc);
|
||||
}
|
||||
|
||||
void WebRenderCommandBuilder::PushOverrideForASR(const ActiveScrolledRoot* aASR,
|
||||
const wr::WrClipId& aClipId) {
|
||||
mClipManager.PushOverrideForASR(aASR, aClipId);
|
||||
void WebRenderCommandBuilder::PushOverrideForASR(
|
||||
const ActiveScrolledRoot* aASR, const wr::WrSpatialId& aSpatialId) {
|
||||
mClipManager.PushOverrideForASR(aASR, aSpatialId);
|
||||
}
|
||||
|
||||
void WebRenderCommandBuilder::PopOverrideForASR(
|
||||
|
|
|
@ -60,7 +60,7 @@ class WebRenderCommandBuilder {
|
|||
const nsTArray<wr::WrFilterOp>& aFilters);
|
||||
|
||||
void PushOverrideForASR(const ActiveScrolledRoot* aASR,
|
||||
const wr::WrClipId& aClipId);
|
||||
const wr::WrSpatialId& aSpatialId);
|
||||
void PopOverrideForASR(const ActiveScrolledRoot* aASR);
|
||||
|
||||
Maybe<wr::ImageKey> CreateImageKey(
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<style>
|
||||
#a { scale: 47 9 }
|
||||
#b {
|
||||
font: 31em Ahem, serif;
|
||||
border-top-left-radius: 2vmin;
|
||||
mix-blend-mode: color-burn;
|
||||
-webkit-background-clip: text;
|
||||
}
|
||||
</style>
|
||||
<pre id="a">
|
||||
<textarea id="b">
|
|
@ -177,6 +177,7 @@ load 1505426-1.html
|
|||
load 1508811.html
|
||||
load 1508822.html
|
||||
load 1509099.html
|
||||
load 1513133.html
|
||||
load 1496194.html
|
||||
load 1509123.html
|
||||
load texture-allocator-zero-region.html
|
||||
|
|
|
@ -17,12 +17,10 @@
|
|||
#include "TextDrawTarget.h"
|
||||
|
||||
#define WRDL_LOG(...)
|
||||
/*
|
||||
#define WRDL_LOG(...) printf_stderr("WRDL(%p): " __VA_ARGS__)
|
||||
#define WRDL_LOG(...) if (XRE_IsContentProcess()) { \
|
||||
printf_stderr("WRDL(%p): " __VA_ARGS__); \
|
||||
}
|
||||
*/
|
||||
|
||||
//#define WRDL_LOG(...) printf_stderr("WRDL(%p): " __VA_ARGS__)
|
||||
|
||||
//#define WRDL_LOG(...) if (XRE_IsContentProcess()) printf_stderr("WRDL(%p): " __VA_ARGS__)
|
||||
|
||||
namespace mozilla {
|
||||
namespace wr {
|
||||
|
@ -646,7 +644,8 @@ void WebRenderAPI::RunOnRenderThread(UniquePtr<RendererEvent> aEvent) {
|
|||
DisplayListBuilder::DisplayListBuilder(PipelineId aId,
|
||||
const wr::LayoutSize& aContentSize,
|
||||
size_t aCapacity)
|
||||
: mActiveFixedPosTracker(nullptr) {
|
||||
: mCurrentSpaceAndClipChain(wr::RootScrollNodeWithChain()),
|
||||
mActiveFixedPosTracker(nullptr) {
|
||||
MOZ_COUNT_CTOR(DisplayListBuilder);
|
||||
mWrState = wr_state_new(aId, aContentSize, aCapacity);
|
||||
}
|
||||
|
@ -672,7 +671,7 @@ void DisplayListBuilder::Finalize(wr::LayoutSize& aOutContentSize,
|
|||
&aOutDisplayList.dl.inner);
|
||||
}
|
||||
|
||||
Maybe<wr::WrClipId> DisplayListBuilder::PushStackingContext(
|
||||
Maybe<wr::WrSpatialId> DisplayListBuilder::PushStackingContext(
|
||||
const wr::LayoutRect& aBounds, const wr::WrClipId* aClipNodeId,
|
||||
const WrAnimationProperty* aAnimation, const float* aOpacity,
|
||||
const gfx::Matrix4x4* aTransform, wr::TransformStyle aTransformStyle,
|
||||
|
@ -698,15 +697,13 @@ Maybe<wr::WrClipId> DisplayListBuilder::PushStackingContext(
|
|||
Stringify(aBounds).c_str(),
|
||||
aTransform ? Stringify(*aTransform).c_str() : "none");
|
||||
|
||||
bool outIsReferenceFrame = false;
|
||||
uintptr_t outReferenceFrameId = 0;
|
||||
wr_dp_push_stacking_context(
|
||||
mWrState, aBounds, aClipNodeId, aAnimation, aOpacity, maybeTransform,
|
||||
aTransformStyle, maybePerspective, aMixBlendMode, aFilters.Elements(),
|
||||
aFilters.Length(), aIsBackfaceVisible, aRasterSpace, &outIsReferenceFrame,
|
||||
&outReferenceFrameId);
|
||||
return outIsReferenceFrame ? Some(wr::WrClipId{outReferenceFrameId})
|
||||
: Nothing();
|
||||
auto spatialId = wr_dp_push_stacking_context(
|
||||
mWrState, aBounds, mCurrentSpaceAndClipChain.space, aClipNodeId,
|
||||
aAnimation, aOpacity, maybeTransform, aTransformStyle, maybePerspective,
|
||||
aMixBlendMode, aFilters.Elements(), aFilters.Length(), aIsBackfaceVisible,
|
||||
aRasterSpace);
|
||||
|
||||
return spatialId.id != 0 ? Some(spatialId) : Nothing();
|
||||
}
|
||||
|
||||
void DisplayListBuilder::PopStackingContext(bool aIsReferenceFrame) {
|
||||
|
@ -727,42 +724,44 @@ wr::WrClipChainId DisplayListBuilder::DefineClipChain(
|
|||
}
|
||||
|
||||
wr::WrClipId DisplayListBuilder::DefineClip(
|
||||
const Maybe<wr::WrClipId>& aParentId, const wr::LayoutRect& aClipRect,
|
||||
const Maybe<wr::WrSpaceAndClip>& aParent, const wr::LayoutRect& aClipRect,
|
||||
const nsTArray<wr::ComplexClipRegion>* aComplex,
|
||||
const wr::WrImageMask* aMask) {
|
||||
size_t clip_id =
|
||||
wr_dp_define_clip(mWrState, aParentId.ptrOr(nullptr), aClipRect,
|
||||
aComplex ? aComplex->Elements() : nullptr,
|
||||
aComplex ? aComplex->Length() : 0, aMask);
|
||||
WrClipId clipId;
|
||||
if (aParent) {
|
||||
clipId = wr_dp_define_clip_with_parent_clip(
|
||||
mWrState, aParent.ptr(), aClipRect,
|
||||
aComplex ? aComplex->Elements() : nullptr,
|
||||
aComplex ? aComplex->Length() : 0, aMask);
|
||||
} else {
|
||||
clipId = wr_dp_define_clip_with_parent_clip_chain(
|
||||
mWrState, &mCurrentSpaceAndClipChain, aClipRect,
|
||||
aComplex ? aComplex->Elements() : nullptr,
|
||||
aComplex ? aComplex->Length() : 0, aMask);
|
||||
}
|
||||
|
||||
WRDL_LOG("DefineClip id=%zu p=%s r=%s m=%p b=%s complex=%zu\n", mWrState,
|
||||
clip_id, aParentId ? Stringify(aParentId->id).c_str() : "(nil)",
|
||||
clipId.id, aParent ? Stringify(aParent->clip.id).c_str() : "(nil)",
|
||||
Stringify(aClipRect).c_str(), aMask,
|
||||
aMask ? Stringify(aMask->rect).c_str() : "none",
|
||||
aComplex ? aComplex->Length() : 0);
|
||||
return wr::WrClipId{clip_id};
|
||||
|
||||
return clipId;
|
||||
}
|
||||
|
||||
void DisplayListBuilder::PushClip(const wr::WrClipId& aClipId) {
|
||||
WRDL_LOG("PushClip id=%zu\n", mWrState, aClipId.id);
|
||||
wr_dp_push_clip(mWrState, aClipId);
|
||||
}
|
||||
|
||||
void DisplayListBuilder::PopClip() {
|
||||
WRDL_LOG("PopClip\n", mWrState);
|
||||
wr_dp_pop_clip(mWrState);
|
||||
}
|
||||
|
||||
wr::WrClipId DisplayListBuilder::DefineStickyFrame(
|
||||
wr::WrSpatialId DisplayListBuilder::DefineStickyFrame(
|
||||
const wr::LayoutRect& aContentRect, const float* aTopMargin,
|
||||
const float* aRightMargin, const float* aBottomMargin,
|
||||
const float* aLeftMargin, const StickyOffsetBounds& aVerticalBounds,
|
||||
const StickyOffsetBounds& aHorizontalBounds,
|
||||
const wr::LayoutVector2D& aAppliedOffset) {
|
||||
size_t id = wr_dp_define_sticky_frame(
|
||||
mWrState, aContentRect, aTopMargin, aRightMargin, aBottomMargin,
|
||||
aLeftMargin, aVerticalBounds, aHorizontalBounds, aAppliedOffset);
|
||||
auto spatialId = wr_dp_define_sticky_frame(
|
||||
mWrState, mCurrentSpaceAndClipChain.space, aContentRect, aTopMargin,
|
||||
aRightMargin, aBottomMargin, aLeftMargin, aVerticalBounds,
|
||||
aHorizontalBounds, aAppliedOffset);
|
||||
|
||||
WRDL_LOG("DefineSticky id=%zu c=%s t=%s r=%s b=%s l=%s v=%s h=%s a=%s\n",
|
||||
mWrState, id, Stringify(aContentRect).c_str(),
|
||||
mWrState, spatialId.id, Stringify(aContentRect).c_str(),
|
||||
aTopMargin ? Stringify(*aTopMargin).c_str() : "none",
|
||||
aRightMargin ? Stringify(*aRightMargin).c_str() : "none",
|
||||
aBottomMargin ? Stringify(*aBottomMargin).c_str() : "none",
|
||||
|
@ -770,10 +769,11 @@ wr::WrClipId DisplayListBuilder::DefineStickyFrame(
|
|||
Stringify(aVerticalBounds).c_str(),
|
||||
Stringify(aHorizontalBounds).c_str(),
|
||||
Stringify(aAppliedOffset).c_str());
|
||||
return wr::WrClipId{id};
|
||||
|
||||
return spatialId;
|
||||
}
|
||||
|
||||
Maybe<wr::WrClipId> DisplayListBuilder::GetScrollIdForDefinedScrollLayer(
|
||||
Maybe<wr::WrSpaceAndClip> DisplayListBuilder::GetScrollIdForDefinedScrollLayer(
|
||||
layers::ScrollableLayerGuid::ViewID aViewId) const {
|
||||
if (aViewId == layers::ScrollableLayerGuid::NULL_SCROLL_ID) {
|
||||
return Some(wr::RootScrollNode());
|
||||
|
@ -787,47 +787,28 @@ Maybe<wr::WrClipId> DisplayListBuilder::GetScrollIdForDefinedScrollLayer(
|
|||
return Some(it->second);
|
||||
}
|
||||
|
||||
wr::WrClipId DisplayListBuilder::DefineScrollLayer(
|
||||
wr::WrSpaceAndClip DisplayListBuilder::DefineScrollLayer(
|
||||
const layers::ScrollableLayerGuid::ViewID& aViewId,
|
||||
const Maybe<wr::WrClipId>& aParentId, const wr::LayoutRect& aContentRect,
|
||||
const wr::LayoutRect& aClipRect) {
|
||||
const Maybe<wr::WrSpaceAndClip>& aParent,
|
||||
const wr::LayoutRect& aContentRect, const wr::LayoutRect& aClipRect) {
|
||||
auto it = mScrollIds.find(aViewId);
|
||||
if (it != mScrollIds.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
auto rootSpaceAndClip = wr::RootScrollNode();
|
||||
// We haven't defined aViewId before, so let's define it now.
|
||||
size_t numericScrollId = wr_dp_define_scroll_layer(
|
||||
mWrState, aViewId, aParentId.ptrOr(nullptr), aContentRect, aClipRect);
|
||||
auto spaceAndClip = wr_dp_define_scroll_layer(
|
||||
mWrState, aViewId, aParent ? aParent.ptr() : &rootSpaceAndClip,
|
||||
aContentRect, aClipRect);
|
||||
|
||||
WRDL_LOG("DefineScrollLayer id=%" PRIu64 "/%zu p=%s co=%s cl=%s\n", mWrState,
|
||||
aViewId, numericScrollId,
|
||||
aParentId ? Stringify(aParentId->id).c_str() : "(nil)",
|
||||
aViewId, spaceAndClip.space.id,
|
||||
aParent ? Stringify(aParent->space.id).c_str() : "(nil)",
|
||||
Stringify(aContentRect).c_str(), Stringify(aClipRect).c_str());
|
||||
|
||||
auto clipId = wr::WrClipId{numericScrollId};
|
||||
mScrollIds[aViewId] = clipId;
|
||||
return clipId;
|
||||
}
|
||||
|
||||
void DisplayListBuilder::PushClipAndScrollInfo(
|
||||
const wr::WrClipId* aScrollId, const wr::WrClipChainId* aClipChainId,
|
||||
const Maybe<wr::LayoutRect>& aClipChainLeaf) {
|
||||
if (aScrollId) {
|
||||
WRDL_LOG("PushClipAndScroll s=%zu c=%s\n", mWrState, aScrollId->id,
|
||||
aClipChainId ? Stringify(aClipChainId->id).c_str() : "none");
|
||||
wr_dp_push_clip_and_scroll_info(
|
||||
mWrState, *aScrollId, aClipChainId ? &(aClipChainId->id) : nullptr);
|
||||
}
|
||||
mClipChainLeaf = aClipChainLeaf;
|
||||
}
|
||||
|
||||
void DisplayListBuilder::PopClipAndScrollInfo(const wr::WrClipId* aScrollId) {
|
||||
if (aScrollId) {
|
||||
WRDL_LOG("PopClipAndScroll\n", mWrState);
|
||||
wr_dp_pop_clip_and_scroll_info(mWrState);
|
||||
}
|
||||
mClipChainLeaf.reset();
|
||||
mScrollIds[aViewId] = spaceAndClip;
|
||||
return spaceAndClip;
|
||||
}
|
||||
|
||||
void DisplayListBuilder::PushRect(const wr::LayoutRect& aBounds,
|
||||
|
@ -837,14 +818,48 @@ void DisplayListBuilder::PushRect(const wr::LayoutRect& aBounds,
|
|||
wr::LayoutRect clip = MergeClipLeaf(aClip);
|
||||
WRDL_LOG("PushRect b=%s cl=%s c=%s\n", mWrState, Stringify(aBounds).c_str(),
|
||||
Stringify(clip).c_str(), Stringify(aColor).c_str());
|
||||
wr_dp_push_rect(mWrState, aBounds, clip, aIsBackfaceVisible, aColor);
|
||||
wr_dp_push_rect(mWrState, aBounds, clip, aIsBackfaceVisible,
|
||||
&mCurrentSpaceAndClipChain, aColor);
|
||||
}
|
||||
|
||||
void DisplayListBuilder::PushRoundedRect(const wr::LayoutRect& aBounds,
|
||||
const wr::LayoutRect& aClip,
|
||||
bool aIsBackfaceVisible,
|
||||
const wr::ColorF& aColor) {
|
||||
wr::LayoutRect clip = MergeClipLeaf(aClip);
|
||||
WRDL_LOG("PushRoundedRect b=%s cl=%s c=%s\n", mWrState,
|
||||
Stringify(aBounds).c_str(), Stringify(clip).c_str(),
|
||||
Stringify(aColor).c_str());
|
||||
|
||||
AutoTArray<wr::ComplexClipRegion, 1> clips;
|
||||
clips.AppendElement(wr::SimpleRadii(aBounds, aBounds.size.width / 2));
|
||||
// TODO: use `mCurrentSpaceAndClipChain.clip_chain` as a parent?
|
||||
auto clipId = DefineClip(Nothing(), aBounds, &clips, nullptr);
|
||||
auto spaceAndClip = WrSpaceAndClip{mCurrentSpaceAndClipChain.space, clipId};
|
||||
|
||||
wr_dp_push_rect_with_parent_clip(mWrState, aBounds, clip, aIsBackfaceVisible,
|
||||
&spaceAndClip, aColor);
|
||||
}
|
||||
|
||||
void DisplayListBuilder::PushClearRect(const wr::LayoutRect& aBounds) {
|
||||
wr::LayoutRect clip = MergeClipLeaf(aBounds);
|
||||
WRDL_LOG("PushClearRect b=%s c=%s\n", mWrState, Stringify(aBounds).c_str(),
|
||||
Stringify(clip).c_str());
|
||||
wr_dp_push_clear_rect(mWrState, aBounds, clip);
|
||||
wr_dp_push_clear_rect(mWrState, aBounds, clip, &mCurrentSpaceAndClipChain);
|
||||
}
|
||||
|
||||
void DisplayListBuilder::PushClearRectWithComplexRegion(
|
||||
const wr::LayoutRect& aBounds, const wr::ComplexClipRegion& aRegion) {
|
||||
wr::LayoutRect clip = MergeClipLeaf(aBounds);
|
||||
WRDL_LOG("PushClearRectWithComplexRegion b=%s c=%s\n", mWrState,
|
||||
Stringify(aBounds).c_str(), Stringify(clip).c_str());
|
||||
|
||||
AutoTArray<wr::ComplexClipRegion, 1> clips;
|
||||
auto clipId = DefineClip(Nothing(), aBounds, &clips, nullptr);
|
||||
auto spaceAndClip = WrSpaceAndClip{mCurrentSpaceAndClipChain.space, clipId};
|
||||
|
||||
wr_dp_push_clear_rect_with_parent_clip(mWrState, aBounds, clip,
|
||||
&spaceAndClip);
|
||||
}
|
||||
|
||||
void DisplayListBuilder::PushLinearGradient(
|
||||
|
@ -853,10 +868,10 @@ void DisplayListBuilder::PushLinearGradient(
|
|||
const wr::LayoutPoint& aEndPoint, const nsTArray<wr::GradientStop>& aStops,
|
||||
wr::ExtendMode aExtendMode, const wr::LayoutSize aTileSize,
|
||||
const wr::LayoutSize aTileSpacing) {
|
||||
wr_dp_push_linear_gradient(mWrState, aBounds, MergeClipLeaf(aClip),
|
||||
aIsBackfaceVisible, aStartPoint, aEndPoint,
|
||||
aStops.Elements(), aStops.Length(), aExtendMode,
|
||||
aTileSize, aTileSpacing);
|
||||
wr_dp_push_linear_gradient(
|
||||
mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible,
|
||||
&mCurrentSpaceAndClipChain, aStartPoint, aEndPoint, aStops.Elements(),
|
||||
aStops.Length(), aExtendMode, aTileSize, aTileSpacing);
|
||||
}
|
||||
|
||||
void DisplayListBuilder::PushRadialGradient(
|
||||
|
@ -865,10 +880,10 @@ void DisplayListBuilder::PushRadialGradient(
|
|||
const wr::LayoutSize& aRadius, const nsTArray<wr::GradientStop>& aStops,
|
||||
wr::ExtendMode aExtendMode, const wr::LayoutSize aTileSize,
|
||||
const wr::LayoutSize aTileSpacing) {
|
||||
wr_dp_push_radial_gradient(mWrState, aBounds, MergeClipLeaf(aClip),
|
||||
aIsBackfaceVisible, aCenter, aRadius,
|
||||
aStops.Elements(), aStops.Length(), aExtendMode,
|
||||
aTileSize, aTileSpacing);
|
||||
wr_dp_push_radial_gradient(
|
||||
mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible,
|
||||
&mCurrentSpaceAndClipChain, aCenter, aRadius, aStops.Elements(),
|
||||
aStops.Length(), aExtendMode, aTileSize, aTileSpacing);
|
||||
}
|
||||
|
||||
void DisplayListBuilder::PushImage(
|
||||
|
@ -891,8 +906,9 @@ void DisplayListBuilder::PushImage(
|
|||
WRDL_LOG("PushImage b=%s cl=%s s=%s t=%s\n", mWrState,
|
||||
Stringify(aBounds).c_str(), Stringify(clip).c_str(),
|
||||
Stringify(aStretchSize).c_str(), Stringify(aTileSpacing).c_str());
|
||||
wr_dp_push_image(mWrState, aBounds, clip, aIsBackfaceVisible, aStretchSize,
|
||||
aTileSpacing, aFilter, aImage, aPremultipliedAlpha, aColor);
|
||||
wr_dp_push_image(mWrState, aBounds, clip, aIsBackfaceVisible,
|
||||
&mCurrentSpaceAndClipChain, aStretchSize, aTileSpacing,
|
||||
aFilter, aImage, aPremultipliedAlpha, aColor);
|
||||
}
|
||||
|
||||
void DisplayListBuilder::PushYCbCrPlanarImage(
|
||||
|
@ -902,9 +918,9 @@ void DisplayListBuilder::PushYCbCrPlanarImage(
|
|||
wr::WrColorDepth aColorDepth, wr::WrYuvColorSpace aColorSpace,
|
||||
wr::ImageRendering aRendering) {
|
||||
wr_dp_push_yuv_planar_image(mWrState, aBounds, MergeClipLeaf(aClip),
|
||||
aIsBackfaceVisible, aImageChannel0,
|
||||
aImageChannel1, aImageChannel2, aColorDepth,
|
||||
aColorSpace, aRendering);
|
||||
aIsBackfaceVisible, &mCurrentSpaceAndClipChain,
|
||||
aImageChannel0, aImageChannel1, aImageChannel2,
|
||||
aColorDepth, aColorSpace, aRendering);
|
||||
}
|
||||
|
||||
void DisplayListBuilder::PushNV12Image(
|
||||
|
@ -913,8 +929,9 @@ void DisplayListBuilder::PushNV12Image(
|
|||
wr::ImageKey aImageChannel1, wr::WrColorDepth aColorDepth,
|
||||
wr::WrYuvColorSpace aColorSpace, wr::ImageRendering aRendering) {
|
||||
wr_dp_push_yuv_NV12_image(mWrState, aBounds, MergeClipLeaf(aClip),
|
||||
aIsBackfaceVisible, aImageChannel0, aImageChannel1,
|
||||
aColorDepth, aColorSpace, aRendering);
|
||||
aIsBackfaceVisible, &mCurrentSpaceAndClipChain,
|
||||
aImageChannel0, aImageChannel1, aColorDepth,
|
||||
aColorSpace, aRendering);
|
||||
}
|
||||
|
||||
void DisplayListBuilder::PushYCbCrInterleavedImage(
|
||||
|
@ -923,7 +940,8 @@ void DisplayListBuilder::PushYCbCrInterleavedImage(
|
|||
wr::WrColorDepth aColorDepth, wr::WrYuvColorSpace aColorSpace,
|
||||
wr::ImageRendering aRendering) {
|
||||
wr_dp_push_yuv_interleaved_image(mWrState, aBounds, MergeClipLeaf(aClip),
|
||||
aIsBackfaceVisible, aImageChannel0,
|
||||
aIsBackfaceVisible,
|
||||
&mCurrentSpaceAndClipChain, aImageChannel0,
|
||||
aColorDepth, aColorSpace, aRendering);
|
||||
}
|
||||
|
||||
|
@ -932,7 +950,8 @@ void DisplayListBuilder::PushIFrame(const wr::LayoutRect& aBounds,
|
|||
PipelineId aPipeline,
|
||||
bool aIgnoreMissingPipeline) {
|
||||
wr_dp_push_iframe(mWrState, aBounds, MergeClipLeaf(aBounds),
|
||||
aIsBackfaceVisible, aPipeline, aIgnoreMissingPipeline);
|
||||
aIsBackfaceVisible, &mCurrentSpaceAndClipChain, aPipeline,
|
||||
aIgnoreMissingPipeline);
|
||||
}
|
||||
|
||||
void DisplayListBuilder::PushBorder(const wr::LayoutRect& aBounds,
|
||||
|
@ -947,8 +966,8 @@ void DisplayListBuilder::PushBorder(const wr::LayoutRect& aBounds,
|
|||
return;
|
||||
}
|
||||
wr_dp_push_border(mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible,
|
||||
aAntialias, aWidths, aSides[0], aSides[1], aSides[2],
|
||||
aSides[3], aRadius);
|
||||
&mCurrentSpaceAndClipChain, aAntialias, aWidths, aSides[0],
|
||||
aSides[1], aSides[2], aSides[3], aRadius);
|
||||
}
|
||||
|
||||
void DisplayListBuilder::PushBorderImage(
|
||||
|
@ -960,8 +979,9 @@ void DisplayListBuilder::PushBorderImage(
|
|||
const wr::RepeatMode& aRepeatHorizontal,
|
||||
const wr::RepeatMode& aRepeatVertical) {
|
||||
wr_dp_push_border_image(mWrState, aBounds, MergeClipLeaf(aClip),
|
||||
aIsBackfaceVisible, aWidths, aImage, aWidth, aHeight,
|
||||
aSlice, aOutset, aRepeatHorizontal, aRepeatVertical);
|
||||
aIsBackfaceVisible, &mCurrentSpaceAndClipChain,
|
||||
aWidths, aImage, aWidth, aHeight, aSlice, aOutset,
|
||||
aRepeatHorizontal, aRepeatVertical);
|
||||
}
|
||||
|
||||
void DisplayListBuilder::PushBorderGradient(
|
||||
|
@ -972,10 +992,10 @@ void DisplayListBuilder::PushBorderGradient(
|
|||
const wr::LayoutPoint& aStartPoint, const wr::LayoutPoint& aEndPoint,
|
||||
const nsTArray<wr::GradientStop>& aStops, wr::ExtendMode aExtendMode,
|
||||
const wr::SideOffsets2D<float>& aOutset) {
|
||||
wr_dp_push_border_gradient(mWrState, aBounds, MergeClipLeaf(aClip),
|
||||
aIsBackfaceVisible, aWidths, aWidth, aHeight,
|
||||
aSlice, aStartPoint, aEndPoint, aStops.Elements(),
|
||||
aStops.Length(), aExtendMode, aOutset);
|
||||
wr_dp_push_border_gradient(
|
||||
mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible,
|
||||
&mCurrentSpaceAndClipChain, aWidths, aWidth, aHeight, aSlice, aStartPoint,
|
||||
aEndPoint, aStops.Elements(), aStops.Length(), aExtendMode, aOutset);
|
||||
}
|
||||
|
||||
void DisplayListBuilder::PushBorderRadialGradient(
|
||||
|
@ -984,10 +1004,10 @@ void DisplayListBuilder::PushBorderRadialGradient(
|
|||
const wr::LayoutPoint& aCenter, const wr::LayoutSize& aRadius,
|
||||
const nsTArray<wr::GradientStop>& aStops, wr::ExtendMode aExtendMode,
|
||||
const wr::SideOffsets2D<float>& aOutset) {
|
||||
wr_dp_push_border_radial_gradient(mWrState, aBounds, MergeClipLeaf(aClip),
|
||||
aIsBackfaceVisible, aWidths, aCenter,
|
||||
aRadius, aStops.Elements(), aStops.Length(),
|
||||
aExtendMode, aOutset);
|
||||
wr_dp_push_border_radial_gradient(
|
||||
mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible,
|
||||
&mCurrentSpaceAndClipChain, aWidths, aCenter, aRadius, aStops.Elements(),
|
||||
aStops.Length(), aExtendMode, aOutset);
|
||||
}
|
||||
|
||||
void DisplayListBuilder::PushText(const wr::LayoutRect& aBounds,
|
||||
|
@ -998,15 +1018,16 @@ void DisplayListBuilder::PushText(const wr::LayoutRect& aBounds,
|
|||
Range<const wr::GlyphInstance> aGlyphBuffer,
|
||||
const wr::GlyphOptions* aGlyphOptions) {
|
||||
wr_dp_push_text(mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible,
|
||||
aColor, aFontKey, &aGlyphBuffer[0], aGlyphBuffer.length(),
|
||||
aGlyphOptions);
|
||||
&mCurrentSpaceAndClipChain, aColor, aFontKey,
|
||||
&aGlyphBuffer[0], aGlyphBuffer.length(), aGlyphOptions);
|
||||
}
|
||||
|
||||
void DisplayListBuilder::PushLine(const wr::LayoutRect& aClip,
|
||||
bool aIsBackfaceVisible,
|
||||
const wr::Line& aLine) {
|
||||
wr::LayoutRect clip = MergeClipLeaf(aClip);
|
||||
wr_dp_push_line(mWrState, &clip, aIsBackfaceVisible, &aLine.bounds,
|
||||
wr_dp_push_line(mWrState, &clip, aIsBackfaceVisible,
|
||||
&mCurrentSpaceAndClipChain, &aLine.bounds,
|
||||
aLine.wavyLineThickness, aLine.orientation, &aLine.color,
|
||||
aLine.style);
|
||||
}
|
||||
|
@ -1016,7 +1037,7 @@ void DisplayListBuilder::PushShadow(const wr::LayoutRect& aRect,
|
|||
bool aIsBackfaceVisible,
|
||||
const wr::Shadow& aShadow) {
|
||||
wr_dp_push_shadow(mWrState, aRect, MergeClipLeaf(aClip), aIsBackfaceVisible,
|
||||
aShadow);
|
||||
&mCurrentSpaceAndClipChain, aShadow);
|
||||
}
|
||||
|
||||
void DisplayListBuilder::PopAllShadows() { wr_dp_pop_all_shadows(mWrState); }
|
||||
|
@ -1029,8 +1050,9 @@ void DisplayListBuilder::PushBoxShadow(
|
|||
const wr::BorderRadius& aBorderRadius,
|
||||
const wr::BoxShadowClipMode& aClipMode) {
|
||||
wr_dp_push_box_shadow(mWrState, aRect, MergeClipLeaf(aClip),
|
||||
aIsBackfaceVisible, aBoxBounds, aOffset, aColor,
|
||||
aBlurRadius, aSpreadRadius, aBorderRadius, aClipMode);
|
||||
aIsBackfaceVisible, &mCurrentSpaceAndClipChain,
|
||||
aBoxBounds, aOffset, aColor, aBlurRadius, aSpreadRadius,
|
||||
aBorderRadius, aClipMode);
|
||||
}
|
||||
|
||||
Maybe<layers::ScrollableLayerGuid::ViewID>
|
||||
|
|
|
@ -328,7 +328,7 @@ class DisplayListBuilder {
|
|||
void Finalize(wr::LayoutSize& aOutContentSize,
|
||||
wr::BuiltDisplayList& aOutDisplayList);
|
||||
|
||||
Maybe<wr::WrClipId> PushStackingContext(
|
||||
Maybe<wr::WrSpatialId> PushStackingContext(
|
||||
const wr::LayoutRect&
|
||||
aBounds, // TODO: We should work with strongly typed rects
|
||||
const wr::WrClipId* aClipNodeId,
|
||||
|
@ -343,39 +343,37 @@ class DisplayListBuilder {
|
|||
const nsTArray<wr::WrClipId>& aClips);
|
||||
|
||||
wr::WrClipId DefineClip(
|
||||
const Maybe<wr::WrClipId>& aParentId, const wr::LayoutRect& aClipRect,
|
||||
const Maybe<wr::WrSpaceAndClip>& aParent, const wr::LayoutRect& aClipRect,
|
||||
const nsTArray<wr::ComplexClipRegion>* aComplex = nullptr,
|
||||
const wr::WrImageMask* aMask = nullptr);
|
||||
void PushClip(const wr::WrClipId& aClipId);
|
||||
void PopClip();
|
||||
|
||||
wr::WrClipId DefineStickyFrame(const wr::LayoutRect& aContentRect,
|
||||
const float* aTopMargin,
|
||||
const float* aRightMargin,
|
||||
const float* aBottomMargin,
|
||||
const float* aLeftMargin,
|
||||
const StickyOffsetBounds& aVerticalBounds,
|
||||
const StickyOffsetBounds& aHorizontalBounds,
|
||||
const wr::LayoutVector2D& aAppliedOffset);
|
||||
wr::WrSpatialId DefineStickyFrame(const wr::LayoutRect& aContentRect,
|
||||
const float* aTopMargin,
|
||||
const float* aRightMargin,
|
||||
const float* aBottomMargin,
|
||||
const float* aLeftMargin,
|
||||
const StickyOffsetBounds& aVerticalBounds,
|
||||
const StickyOffsetBounds& aHorizontalBounds,
|
||||
const wr::LayoutVector2D& aAppliedOffset);
|
||||
|
||||
Maybe<wr::WrClipId> GetScrollIdForDefinedScrollLayer(
|
||||
Maybe<wr::WrSpaceAndClip> GetScrollIdForDefinedScrollLayer(
|
||||
layers::ScrollableLayerGuid::ViewID aViewId) const;
|
||||
wr::WrClipId DefineScrollLayer(
|
||||
wr::WrSpaceAndClip DefineScrollLayer(
|
||||
const layers::ScrollableLayerGuid::ViewID& aViewId,
|
||||
const Maybe<wr::WrClipId>& aParentId,
|
||||
const Maybe<wr::WrSpaceAndClip>& aParent,
|
||||
const wr::LayoutRect&
|
||||
aContentRect, // TODO: We should work with strongly typed rects
|
||||
const wr::LayoutRect& aClipRect);
|
||||
|
||||
void PushClipAndScrollInfo(const wr::WrClipId* aScrollId,
|
||||
const wr::WrClipChainId* aClipChainId,
|
||||
const Maybe<wr::LayoutRect>& aClipChainLeaf);
|
||||
void PopClipAndScrollInfo(const wr::WrClipId* aScrollId);
|
||||
|
||||
void PushRect(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
|
||||
bool aIsBackfaceVisible, const wr::ColorF& aColor);
|
||||
void PushRoundedRect(const wr::LayoutRect& aBounds,
|
||||
const wr::LayoutRect& aClip, bool aIsBackfaceVisible,
|
||||
const wr::ColorF& aColor);
|
||||
|
||||
void PushClearRect(const wr::LayoutRect& aBounds);
|
||||
void PushClearRectWithComplexRegion(const wr::LayoutRect& aBounds,
|
||||
const wr::ComplexClipRegion& aRegion);
|
||||
|
||||
void PushLinearGradient(const wr::LayoutRect& aBounds,
|
||||
const wr::LayoutRect& aClip, bool aIsBackfaceVisible,
|
||||
|
@ -510,6 +508,10 @@ class DisplayListBuilder {
|
|||
// Try to avoid using this when possible.
|
||||
wr::WrState* Raw() { return mWrState; }
|
||||
|
||||
void SetClipChainLeaf(const Maybe<wr::LayoutRect>& aClipRect) {
|
||||
mClipChainLeaf = aClipRect;
|
||||
}
|
||||
|
||||
// A chain of RAII objects, each holding a (ASR, ViewID) tuple of data. The
|
||||
// topmost object is pointed to by the mActiveFixedPosTracker pointer in
|
||||
// the wr::DisplayListBuilder.
|
||||
|
@ -542,9 +544,11 @@ class DisplayListBuilder {
|
|||
// Track each scroll id that we encountered. We use this structure to
|
||||
// ensure that we don't define a particular scroll layer multiple times,
|
||||
// as that results in undefined behaviour in WR.
|
||||
std::unordered_map<layers::ScrollableLayerGuid::ViewID, wr::WrClipId>
|
||||
std::unordered_map<layers::ScrollableLayerGuid::ViewID, wr::WrSpaceAndClip>
|
||||
mScrollIds;
|
||||
|
||||
wr::WrSpaceAndClipChain mCurrentSpaceAndClipChain;
|
||||
|
||||
// Contains the current leaf of the clip chain to be merged with the
|
||||
// display item's clip rect when pushing an item. May be set to Nothing() if
|
||||
// there is no clip rect to merge with.
|
||||
|
@ -556,6 +560,40 @@ class DisplayListBuilder {
|
|||
FixedPosScrollTargetTracker* mActiveFixedPosTracker;
|
||||
|
||||
friend class WebRenderAPI;
|
||||
friend class SpaceAndClipChainHelper;
|
||||
};
|
||||
|
||||
// This is a RAII class that overrides the current Wr's SpatialId and
|
||||
// ClipChainId.
|
||||
class MOZ_RAII SpaceAndClipChainHelper {
|
||||
public:
|
||||
SpaceAndClipChainHelper(DisplayListBuilder& aBuilder,
|
||||
wr::WrSpaceAndClipChain aSpaceAndClipChain
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: mBuilder(aBuilder),
|
||||
mOldSpaceAndClipChain(aBuilder.mCurrentSpaceAndClipChain) {
|
||||
aBuilder.mCurrentSpaceAndClipChain = aSpaceAndClipChain;
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
SpaceAndClipChainHelper(DisplayListBuilder& aBuilder,
|
||||
wr::WrSpatialId aSpatialId
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: mBuilder(aBuilder),
|
||||
mOldSpaceAndClipChain(aBuilder.mCurrentSpaceAndClipChain) {
|
||||
aBuilder.mCurrentSpaceAndClipChain.space = aSpatialId;
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
~SpaceAndClipChainHelper() {
|
||||
mBuilder.mCurrentSpaceAndClipChain = mOldSpaceAndClipChain;
|
||||
}
|
||||
|
||||
private:
|
||||
SpaceAndClipChainHelper(const SpaceAndClipChainHelper&) = delete;
|
||||
|
||||
DisplayListBuilder& mBuilder;
|
||||
wr::WrSpaceAndClipChain mOldSpaceAndClipChain;
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
Maybe<wr::ImageFormat> SurfaceFormatToImageFormat(gfx::SurfaceFormat aFormat);
|
||||
|
|
|
@ -28,8 +28,18 @@ void Assign_WrVecU8(wr::WrVecU8& aVec, mozilla::ipc::ByteBuf&& aOther) {
|
|||
aOther.mCapacity = 0;
|
||||
}
|
||||
|
||||
/*static*/ WrClipId RootScrollNode() {
|
||||
return WrClipId{wr_root_scroll_node_id()};
|
||||
WrSpaceAndClip RootScrollNode() {
|
||||
WrSpaceAndClip sac;
|
||||
sac.clip = wr_root_clip_id();
|
||||
sac.space = wr_root_scroll_node_id();
|
||||
return sac;
|
||||
}
|
||||
|
||||
WrSpaceAndClipChain RootScrollNodeWithChain() {
|
||||
WrSpaceAndClipChain sacc;
|
||||
sacc.clip_chain = wr::ROOT_CLIP_CHAIN;
|
||||
sacc.space = wr_root_scroll_node_id();
|
||||
return sacc;
|
||||
}
|
||||
|
||||
} // namespace wr
|
||||
|
|
|
@ -798,7 +798,6 @@ static inline wr::WrFilterOpType ToWrFilterOpType(uint32_t type) {
|
|||
return wr::WrFilterOpType::Grayscale;
|
||||
}
|
||||
|
||||
extern WrClipId RootScrollNode();
|
||||
|
||||
// Corresponds to a clip id for a clip chain in webrender. Similar to
|
||||
// WrClipId but a separate struct so we don't get them mixed up in C++.
|
||||
|
@ -806,8 +805,16 @@ struct WrClipChainId {
|
|||
uint64_t id;
|
||||
|
||||
bool operator==(const WrClipChainId& other) const { return id == other.id; }
|
||||
|
||||
static WrClipChainId Empty() {
|
||||
WrClipChainId id = {0};
|
||||
return id;
|
||||
}
|
||||
};
|
||||
|
||||
WrSpaceAndClip RootScrollNode();
|
||||
WrSpaceAndClipChain RootScrollNodeWithChain();
|
||||
|
||||
enum class WebRenderError : int8_t {
|
||||
INITIALIZE = 0,
|
||||
MAKE_CURRENT,
|
||||
|
@ -857,8 +864,8 @@ static inline wr::SyntheticItalics DegreesToSyntheticItalics(float aDegrees) {
|
|||
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<mozilla::wr::WrClipId> {
|
||||
std::size_t operator()(mozilla::wr::WrClipId const& aKey) const noexcept {
|
||||
struct hash<mozilla::wr::WrSpatialId> {
|
||||
std::size_t operator()(mozilla::wr::WrSpatialId const& aKey) const noexcept {
|
||||
return std::hash<size_t>{}(aKey.id);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1 +1 @@
|
|||
9019124fdccab50096ef5af76d1acbd251c1ad07
|
||||
fb4b9342aa1b047ac46b89cb7a70987816bee686
|
||||
|
|
|
@ -44,6 +44,9 @@ extern "C" {
|
|||
/// The unique id for WR resource identification.
|
||||
static NEXT_NAMESPACE_ID: AtomicUsize = AtomicUsize::new(1);
|
||||
|
||||
/// Special value handled in this wrapper layer to signify a redundant clip chain.
|
||||
pub const ROOT_CLIP_CHAIN: u64 = !0;
|
||||
|
||||
fn next_namespace_id() -> IdNamespace {
|
||||
IdNamespace(NEXT_NAMESPACE_ID.fetch_add(1, Ordering::Relaxed) as u32)
|
||||
}
|
||||
|
@ -114,6 +117,50 @@ type WrYuvColorSpace = YuvColorSpace;
|
|||
/// cbindgen:field-names=[mNamespace, mHandle]
|
||||
type WrColorDepth = ColorDepth;
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
pub struct WrSpaceAndClip {
|
||||
space: WrSpatialId,
|
||||
clip: WrClipId,
|
||||
}
|
||||
|
||||
impl WrSpaceAndClip {
|
||||
fn from_webrender(sac: SpaceAndClipInfo) -> Self {
|
||||
WrSpaceAndClip {
|
||||
space: WrSpatialId { id: sac.spatial_id.0 },
|
||||
clip: WrClipId::from_webrender(sac.clip_id),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_webrender(&self, pipeline_id: WrPipelineId) -> SpaceAndClipInfo {
|
||||
SpaceAndClipInfo {
|
||||
spatial_id: self.space.to_webrender(pipeline_id),
|
||||
clip_id: self.clip.to_webrender(pipeline_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct WrSpaceAndClipChain {
|
||||
space: WrSpatialId,
|
||||
clip_chain: u64,
|
||||
}
|
||||
|
||||
impl WrSpaceAndClipChain {
|
||||
fn to_webrender(&self, pipeline_id: WrPipelineId) -> SpaceAndClipInfo {
|
||||
//Warning: special case here to support dummy clip chain
|
||||
SpaceAndClipInfo {
|
||||
spatial_id: self.space.to_webrender(pipeline_id),
|
||||
clip_id: if self.clip_chain == ROOT_CLIP_CHAIN {
|
||||
ClipId::root(pipeline_id)
|
||||
} else {
|
||||
ClipId::ClipChain(ClipChainId(self.clip_chain, pipeline_id))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn make_slice<'a, T>(ptr: *const T, len: usize) -> &'a [T] {
|
||||
if ptr.is_null() {
|
||||
&[]
|
||||
|
@ -1859,6 +1906,7 @@ pub extern "C" fn wr_dp_clear_save(state: &mut WrState) {
|
|||
#[no_mangle]
|
||||
pub extern "C" fn wr_dp_push_stacking_context(state: &mut WrState,
|
||||
mut bounds: LayoutRect,
|
||||
spatial_id: WrSpatialId,
|
||||
clip_node_id: *const WrClipId,
|
||||
animation: *const WrAnimationProperty,
|
||||
opacity: *const f32,
|
||||
|
@ -1870,8 +1918,7 @@ pub extern "C" fn wr_dp_push_stacking_context(state: &mut WrState,
|
|||
filter_count: usize,
|
||||
is_backface_visible: bool,
|
||||
glyph_raster_space: RasterSpace,
|
||||
out_is_reference_frame: &mut bool,
|
||||
out_reference_frame_id: &mut usize) {
|
||||
) -> WrSpatialId {
|
||||
debug_assert!(unsafe { !is_in_render_thread() });
|
||||
|
||||
let c_filters = make_slice(filters, filter_count);
|
||||
|
@ -1896,10 +1943,6 @@ pub extern "C" fn wr_dp_push_stacking_context(state: &mut WrState,
|
|||
}).collect();
|
||||
|
||||
let clip_node_id_ref = unsafe { clip_node_id.as_ref() };
|
||||
let clip_node_id = match clip_node_id_ref {
|
||||
Some(clip_node_id) => Some(unpack_clip_id(*clip_node_id, state.pipeline_id)),
|
||||
None => None,
|
||||
};
|
||||
|
||||
let transform_ref = unsafe { transform.as_ref() };
|
||||
let mut transform_binding = match transform_ref {
|
||||
|
@ -1944,15 +1987,27 @@ pub extern "C" fn wr_dp_push_stacking_context(state: &mut WrState,
|
|||
None => None,
|
||||
};
|
||||
|
||||
*out_is_reference_frame = transform_binding.is_some() || perspective.is_some();
|
||||
if *out_is_reference_frame {
|
||||
let ref_frame_id = state.frame_builder
|
||||
.dl_builder
|
||||
.push_reference_frame(&bounds, transform_style, transform_binding, perspective);
|
||||
*out_reference_frame_id = pack_clip_id(ref_frame_id);
|
||||
let mut wr_spatial_id = spatial_id.to_webrender(state.pipeline_id);
|
||||
let wr_clip_id = clip_node_id_ref.map(|id| id.to_webrender(state.pipeline_id));
|
||||
|
||||
let is_reference_frame = transform_binding.is_some() || perspective.is_some();
|
||||
// Note: 0 has special meaning in WR land, standing for ROOT_REFERENCE_FRAME.
|
||||
// However, it is never returned by `push_reference_frame`, and we need to return
|
||||
// an option here across FFI, so we take that 0 value for the None semantics.
|
||||
// This is resolved into proper `Maybe<WrSpatialId>` inside `WebRenderAPI::PushStackingContext`.
|
||||
let mut result = WrSpatialId { id: 0 };
|
||||
if is_reference_frame {
|
||||
wr_spatial_id = state.frame_builder.dl_builder.push_reference_frame(
|
||||
&bounds,
|
||||
wr_spatial_id,
|
||||
transform_style,
|
||||
transform_binding,
|
||||
perspective,
|
||||
);
|
||||
|
||||
bounds.origin = LayoutPoint::zero();
|
||||
state.frame_builder.dl_builder.push_clip_id(ref_frame_id);
|
||||
result.id = wr_spatial_id.0;
|
||||
assert_ne!(wr_spatial_id.0, 0);
|
||||
}
|
||||
|
||||
let prim_info = LayoutPrimitiveInfo {
|
||||
|
@ -1964,11 +2019,14 @@ pub extern "C" fn wr_dp_push_stacking_context(state: &mut WrState,
|
|||
state.frame_builder
|
||||
.dl_builder
|
||||
.push_stacking_context(&prim_info,
|
||||
clip_node_id,
|
||||
wr_spatial_id,
|
||||
wr_clip_id,
|
||||
transform_style,
|
||||
mix_blend_mode,
|
||||
&filters,
|
||||
glyph_raster_space);
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -1977,7 +2035,6 @@ pub extern "C" fn wr_dp_pop_stacking_context(state: &mut WrState,
|
|||
debug_assert!(unsafe { !is_in_render_thread() });
|
||||
state.frame_builder.dl_builder.pop_stacking_context();
|
||||
if is_reference_frame {
|
||||
state.frame_builder.dl_builder.pop_clip_id();
|
||||
state.frame_builder.dl_builder.pop_reference_frame();
|
||||
}
|
||||
}
|
||||
|
@ -1989,11 +2046,13 @@ pub extern "C" fn wr_dp_define_clipchain(state: &mut WrState,
|
|||
clips_count: usize)
|
||||
-> u64 {
|
||||
debug_assert!(unsafe { is_in_main_thread() });
|
||||
let parent = unsafe { parent_clipchain_id.as_ref() }.map(|id| ClipChainId(*id, state.pipeline_id));
|
||||
let parent = unsafe { parent_clipchain_id.as_ref() }
|
||||
.map(|id| ClipChainId(*id, state.pipeline_id));
|
||||
|
||||
let pipeline_id = state.pipeline_id;
|
||||
let clips = make_slice(clips, clips_count)
|
||||
.iter()
|
||||
.map(|id| unpack_clip_id(*id, pipeline_id));
|
||||
.map(|clip_id| clip_id.to_webrender(pipeline_id));
|
||||
|
||||
let clipchain_id = state.frame_builder.dl_builder.define_clip_chain(parent, clips);
|
||||
assert!(clipchain_id.1 == state.pipeline_id);
|
||||
|
@ -2001,45 +2060,61 @@ pub extern "C" fn wr_dp_define_clipchain(state: &mut WrState,
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_dp_define_clip(state: &mut WrState,
|
||||
parent_id: *const WrClipId,
|
||||
clip_rect: LayoutRect,
|
||||
complex: *const ComplexClipRegion,
|
||||
complex_count: usize,
|
||||
mask: *const WrImageMask)
|
||||
-> usize {
|
||||
debug_assert!(unsafe { is_in_main_thread() });
|
||||
|
||||
let parent_id = unsafe { parent_id.as_ref() };
|
||||
let complex_slice = make_slice(complex, complex_count);
|
||||
let complex_iter = complex_slice.iter().cloned();
|
||||
let mask : Option<ImageMask> = unsafe { mask.as_ref() }.map(|x| x.into());
|
||||
|
||||
let clip_id = if let Some(&pid) = parent_id {
|
||||
state.frame_builder.dl_builder.define_clip_with_parent(
|
||||
unpack_clip_id(pid, state.pipeline_id),
|
||||
clip_rect, complex_iter, mask)
|
||||
} else {
|
||||
state.frame_builder.dl_builder.define_clip(clip_rect, complex_iter, mask)
|
||||
};
|
||||
pack_clip_id(clip_id)
|
||||
pub extern "C" fn wr_dp_define_clip_with_parent_clip(
|
||||
state: &mut WrState,
|
||||
parent: &WrSpaceAndClip,
|
||||
clip_rect: LayoutRect,
|
||||
complex: *const ComplexClipRegion,
|
||||
complex_count: usize,
|
||||
mask: *const WrImageMask,
|
||||
) -> WrClipId {
|
||||
wr_dp_define_clip_impl(
|
||||
&mut state.frame_builder,
|
||||
parent.to_webrender(state.pipeline_id),
|
||||
clip_rect,
|
||||
make_slice(complex, complex_count),
|
||||
unsafe { mask.as_ref() }.map(|m| m.into()),
|
||||
)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_dp_push_clip(state: &mut WrState,
|
||||
clip_id: WrClipId) {
|
||||
debug_assert!(unsafe { is_in_main_thread() });
|
||||
state.frame_builder.dl_builder.push_clip_id(unpack_clip_id(clip_id, state.pipeline_id));
|
||||
pub extern "C" fn wr_dp_define_clip_with_parent_clip_chain(
|
||||
state: &mut WrState,
|
||||
parent: &WrSpaceAndClipChain,
|
||||
clip_rect: LayoutRect,
|
||||
complex: *const ComplexClipRegion,
|
||||
complex_count: usize,
|
||||
mask: *const WrImageMask,
|
||||
) -> WrClipId {
|
||||
wr_dp_define_clip_impl(
|
||||
&mut state.frame_builder,
|
||||
parent.to_webrender(state.pipeline_id),
|
||||
clip_rect,
|
||||
make_slice(complex, complex_count),
|
||||
unsafe { mask.as_ref() }.map(|m| m.into()),
|
||||
)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_dp_pop_clip(state: &mut WrState) {
|
||||
debug_assert!(unsafe { !is_in_render_thread() });
|
||||
state.frame_builder.dl_builder.pop_clip_id();
|
||||
fn wr_dp_define_clip_impl(
|
||||
frame_builder: &mut WebRenderFrameBuilder,
|
||||
parent: SpaceAndClipInfo,
|
||||
clip_rect: LayoutRect,
|
||||
complex_regions: &[ComplexClipRegion],
|
||||
mask: Option<ImageMask>,
|
||||
) -> WrClipId {
|
||||
debug_assert!(unsafe { is_in_main_thread() });
|
||||
let clip_id = frame_builder.dl_builder.define_clip(
|
||||
&parent,
|
||||
clip_rect,
|
||||
complex_regions.iter().cloned(),
|
||||
mask,
|
||||
);
|
||||
WrClipId::from_webrender(clip_id)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_dp_define_sticky_frame(state: &mut WrState,
|
||||
parent_spatial_id: WrSpatialId,
|
||||
content_rect: LayoutRect,
|
||||
top_margin: *const f32,
|
||||
right_margin: *const f32,
|
||||
|
@ -2048,89 +2123,45 @@ pub extern "C" fn wr_dp_define_sticky_frame(state: &mut WrState,
|
|||
vertical_bounds: StickyOffsetBounds,
|
||||
horizontal_bounds: StickyOffsetBounds,
|
||||
applied_offset: LayoutVector2D)
|
||||
-> usize {
|
||||
-> WrSpatialId {
|
||||
assert!(unsafe { is_in_main_thread() });
|
||||
let clip_id = state.frame_builder.dl_builder.define_sticky_frame(
|
||||
content_rect, SideOffsets2D::new(
|
||||
let spatial_id = state.frame_builder.dl_builder.define_sticky_frame(
|
||||
parent_spatial_id.to_webrender(state.pipeline_id),
|
||||
content_rect,
|
||||
SideOffsets2D::new(
|
||||
unsafe { top_margin.as_ref() }.cloned(),
|
||||
unsafe { right_margin.as_ref() }.cloned(),
|
||||
unsafe { bottom_margin.as_ref() }.cloned(),
|
||||
unsafe { left_margin.as_ref() }.cloned()
|
||||
),
|
||||
vertical_bounds, horizontal_bounds, applied_offset);
|
||||
pack_clip_id(clip_id)
|
||||
vertical_bounds,
|
||||
horizontal_bounds,
|
||||
applied_offset,
|
||||
);
|
||||
|
||||
WrSpatialId { id: spatial_id.0 }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_dp_define_scroll_layer(state: &mut WrState,
|
||||
scroll_id: u64,
|
||||
parent_id: *const WrClipId,
|
||||
external_scroll_id: u64,
|
||||
parent: &WrSpaceAndClip,
|
||||
content_rect: LayoutRect,
|
||||
clip_rect: LayoutRect)
|
||||
-> usize {
|
||||
-> WrSpaceAndClip {
|
||||
assert!(unsafe { is_in_main_thread() });
|
||||
|
||||
let parent_id = unsafe { parent_id.as_ref() };
|
||||
let space_and_clip = state.frame_builder.dl_builder.define_scroll_frame(
|
||||
&parent.to_webrender(state.pipeline_id),
|
||||
Some(ExternalScrollId(external_scroll_id, state.pipeline_id)),
|
||||
content_rect,
|
||||
clip_rect,
|
||||
vec![],
|
||||
None,
|
||||
ScrollSensitivity::Script
|
||||
);
|
||||
|
||||
let new_id = if let Some(&pid) = parent_id {
|
||||
state.frame_builder.dl_builder.define_scroll_frame_with_parent(
|
||||
unpack_clip_id(pid, state.pipeline_id),
|
||||
Some(ExternalScrollId(scroll_id, state.pipeline_id)),
|
||||
content_rect,
|
||||
clip_rect,
|
||||
vec![],
|
||||
None,
|
||||
ScrollSensitivity::Script
|
||||
)
|
||||
} else {
|
||||
state.frame_builder.dl_builder.define_scroll_frame(
|
||||
Some(ExternalScrollId(scroll_id, state.pipeline_id)),
|
||||
content_rect,
|
||||
clip_rect,
|
||||
vec![],
|
||||
None,
|
||||
ScrollSensitivity::Script
|
||||
)
|
||||
};
|
||||
|
||||
pack_clip_id(new_id)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_dp_push_scroll_layer(state: &mut WrState,
|
||||
scroll_id: WrClipId) {
|
||||
debug_assert!(unsafe { is_in_main_thread() });
|
||||
let clip_id = unpack_clip_id(scroll_id, state.pipeline_id);
|
||||
state.frame_builder.dl_builder.push_clip_id(clip_id);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_dp_pop_scroll_layer(state: &mut WrState) {
|
||||
debug_assert!(unsafe { is_in_main_thread() });
|
||||
state.frame_builder.dl_builder.pop_clip_id();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_dp_push_clip_and_scroll_info(state: &mut WrState,
|
||||
scroll_id: WrClipId,
|
||||
clip_chain_id: *const u64) {
|
||||
debug_assert!(unsafe { is_in_main_thread() });
|
||||
|
||||
let clip_chain_id = unsafe { clip_chain_id.as_ref() };
|
||||
let info = if let Some(&ccid) = clip_chain_id {
|
||||
ClipAndScrollInfo::new(
|
||||
unpack_clip_id(scroll_id, state.pipeline_id),
|
||||
ClipId::ClipChain(ClipChainId(ccid, state.pipeline_id)))
|
||||
} else {
|
||||
ClipAndScrollInfo::simple(unpack_clip_id(scroll_id, state.pipeline_id))
|
||||
};
|
||||
state.frame_builder.dl_builder.push_clip_and_scroll_info(info);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_dp_pop_clip_and_scroll_info(state: &mut WrState) {
|
||||
debug_assert!(unsafe { is_in_main_thread() });
|
||||
state.frame_builder.dl_builder.pop_clip_id();
|
||||
WrSpaceAndClip::from_webrender(space_and_clip)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -2138,6 +2169,7 @@ pub extern "C" fn wr_dp_push_iframe(state: &mut WrState,
|
|||
rect: LayoutRect,
|
||||
clip: LayoutRect,
|
||||
is_backface_visible: bool,
|
||||
parent: &WrSpaceAndClipChain,
|
||||
pipeline_id: WrPipelineId,
|
||||
ignore_missing_pipeline: bool) {
|
||||
debug_assert!(unsafe { is_in_main_thread() });
|
||||
|
@ -2145,7 +2177,12 @@ pub extern "C" fn wr_dp_push_iframe(state: &mut WrState,
|
|||
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
|
||||
prim_info.is_backface_visible = is_backface_visible;
|
||||
prim_info.tag = state.current_tag;
|
||||
state.frame_builder.dl_builder.push_iframe(&prim_info, pipeline_id, ignore_missing_pipeline);
|
||||
state.frame_builder.dl_builder.push_iframe(
|
||||
&prim_info,
|
||||
&parent.to_webrender(state.pipeline_id),
|
||||
pipeline_id,
|
||||
ignore_missing_pipeline,
|
||||
);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -2153,24 +2190,69 @@ pub extern "C" fn wr_dp_push_rect(state: &mut WrState,
|
|||
rect: LayoutRect,
|
||||
clip: LayoutRect,
|
||||
is_backface_visible: bool,
|
||||
parent: &WrSpaceAndClipChain,
|
||||
color: ColorF) {
|
||||
debug_assert!(unsafe { !is_in_render_thread() });
|
||||
|
||||
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
|
||||
prim_info.is_backface_visible = is_backface_visible;
|
||||
prim_info.tag = state.current_tag;
|
||||
state.frame_builder.dl_builder.push_rect(&prim_info,
|
||||
color);
|
||||
state.frame_builder.dl_builder.push_rect(
|
||||
&prim_info,
|
||||
&parent.to_webrender(state.pipeline_id),
|
||||
color,
|
||||
);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_dp_push_rect_with_parent_clip(
|
||||
state: &mut WrState,
|
||||
rect: LayoutRect,
|
||||
clip: LayoutRect,
|
||||
is_backface_visible: bool,
|
||||
parent: &WrSpaceAndClip,
|
||||
color: ColorF,
|
||||
) {
|
||||
debug_assert!(unsafe { !is_in_render_thread() });
|
||||
|
||||
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
|
||||
prim_info.is_backface_visible = is_backface_visible;
|
||||
prim_info.tag = state.current_tag;
|
||||
state.frame_builder.dl_builder.push_rect(
|
||||
&prim_info,
|
||||
&parent.to_webrender(state.pipeline_id),
|
||||
color,
|
||||
);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_dp_push_clear_rect(state: &mut WrState,
|
||||
rect: LayoutRect,
|
||||
clip: LayoutRect) {
|
||||
clip: LayoutRect,
|
||||
parent: &WrSpaceAndClipChain) {
|
||||
debug_assert!(unsafe { !is_in_render_thread() });
|
||||
|
||||
let prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
|
||||
state.frame_builder.dl_builder.push_clear_rect(&prim_info);
|
||||
state.frame_builder.dl_builder.push_clear_rect(
|
||||
&prim_info,
|
||||
&parent.to_webrender(state.pipeline_id),
|
||||
);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_dp_push_clear_rect_with_parent_clip(
|
||||
state: &mut WrState,
|
||||
rect: LayoutRect,
|
||||
clip: LayoutRect,
|
||||
parent: &WrSpaceAndClip,
|
||||
) {
|
||||
debug_assert!(unsafe { !is_in_render_thread() });
|
||||
|
||||
let prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
|
||||
state.frame_builder.dl_builder.push_clear_rect(
|
||||
&prim_info,
|
||||
&parent.to_webrender(state.pipeline_id),
|
||||
);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -2178,6 +2260,7 @@ pub extern "C" fn wr_dp_push_image(state: &mut WrState,
|
|||
bounds: LayoutRect,
|
||||
clip: LayoutRect,
|
||||
is_backface_visible: bool,
|
||||
parent: &WrSpaceAndClipChain,
|
||||
stretch_size: LayoutSize,
|
||||
tile_spacing: LayoutSize,
|
||||
image_rendering: ImageRendering,
|
||||
|
@ -2197,6 +2280,7 @@ pub extern "C" fn wr_dp_push_image(state: &mut WrState,
|
|||
state.frame_builder
|
||||
.dl_builder
|
||||
.push_image(&prim_info,
|
||||
&parent.to_webrender(state.pipeline_id),
|
||||
stretch_size,
|
||||
tile_spacing,
|
||||
image_rendering,
|
||||
|
@ -2211,6 +2295,7 @@ 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,
|
||||
|
@ -2225,6 +2310,7 @@ pub extern "C" fn wr_dp_push_yuv_planar_image(state: &mut WrState,
|
|||
state.frame_builder
|
||||
.dl_builder
|
||||
.push_yuv_image(&prim_info,
|
||||
&parent.to_webrender(state.pipeline_id),
|
||||
YuvData::PlanarYCbCr(image_key_0, image_key_1, image_key_2),
|
||||
color_depth,
|
||||
color_space,
|
||||
|
@ -2237,6 +2323,7 @@ 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,
|
||||
|
@ -2250,6 +2337,7 @@ pub extern "C" fn wr_dp_push_yuv_NV12_image(state: &mut WrState,
|
|||
state.frame_builder
|
||||
.dl_builder
|
||||
.push_yuv_image(&prim_info,
|
||||
&parent.to_webrender(state.pipeline_id),
|
||||
YuvData::NV12(image_key_0, image_key_1),
|
||||
color_depth,
|
||||
color_space,
|
||||
|
@ -2262,6 +2350,7 @@ 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,
|
||||
|
@ -2274,6 +2363,7 @@ pub extern "C" fn wr_dp_push_yuv_interleaved_image(state: &mut WrState,
|
|||
state.frame_builder
|
||||
.dl_builder
|
||||
.push_yuv_image(&prim_info,
|
||||
&parent.to_webrender(state.pipeline_id),
|
||||
YuvData::InterleavedYCbCr(image_key_0),
|
||||
color_depth,
|
||||
color_space,
|
||||
|
@ -2285,6 +2375,7 @@ pub extern "C" fn wr_dp_push_text(state: &mut WrState,
|
|||
bounds: LayoutRect,
|
||||
clip: LayoutRect,
|
||||
is_backface_visible: bool,
|
||||
parent: &WrSpaceAndClipChain,
|
||||
color: ColorF,
|
||||
font_key: WrFontInstanceKey,
|
||||
glyphs: *const GlyphInstance,
|
||||
|
@ -2300,6 +2391,7 @@ pub extern "C" fn wr_dp_push_text(state: &mut WrState,
|
|||
state.frame_builder
|
||||
.dl_builder
|
||||
.push_text(&prim_info,
|
||||
&parent.to_webrender(state.pipeline_id),
|
||||
&glyph_slice,
|
||||
font_key,
|
||||
color,
|
||||
|
@ -2311,13 +2403,18 @@ pub extern "C" fn wr_dp_push_shadow(state: &mut WrState,
|
|||
bounds: LayoutRect,
|
||||
clip: LayoutRect,
|
||||
is_backface_visible: bool,
|
||||
parent: &WrSpaceAndClipChain,
|
||||
shadow: Shadow) {
|
||||
debug_assert!(unsafe { is_in_main_thread() });
|
||||
|
||||
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(bounds, clip.into());
|
||||
prim_info.is_backface_visible = is_backface_visible;
|
||||
prim_info.tag = state.current_tag;
|
||||
state.frame_builder.dl_builder.push_shadow(&prim_info, shadow.into());
|
||||
state.frame_builder.dl_builder.push_shadow(
|
||||
&prim_info,
|
||||
&parent.to_webrender(state.pipeline_id),
|
||||
shadow.into(),
|
||||
);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -2331,6 +2428,7 @@ pub extern "C" fn wr_dp_pop_all_shadows(state: &mut WrState) {
|
|||
pub extern "C" fn wr_dp_push_line(state: &mut WrState,
|
||||
clip: &LayoutRect,
|
||||
is_backface_visible: bool,
|
||||
parent: &WrSpaceAndClipChain,
|
||||
bounds: &LayoutRect,
|
||||
wavy_line_thickness: f32,
|
||||
orientation: LineOrientation,
|
||||
|
@ -2344,6 +2442,7 @@ pub extern "C" fn wr_dp_push_line(state: &mut WrState,
|
|||
state.frame_builder
|
||||
.dl_builder
|
||||
.push_line(&prim_info,
|
||||
&parent.to_webrender(state.pipeline_id),
|
||||
wavy_line_thickness,
|
||||
orientation,
|
||||
color,
|
||||
|
@ -2356,6 +2455,7 @@ pub extern "C" fn wr_dp_push_border(state: &mut WrState,
|
|||
rect: LayoutRect,
|
||||
clip: LayoutRect,
|
||||
is_backface_visible: bool,
|
||||
parent: &WrSpaceAndClipChain,
|
||||
do_aa: AntialiasBorder,
|
||||
widths: LayoutSideOffsets,
|
||||
top: BorderSide,
|
||||
|
@ -2380,6 +2480,7 @@ pub extern "C" fn wr_dp_push_border(state: &mut WrState,
|
|||
state.frame_builder
|
||||
.dl_builder
|
||||
.push_border(&prim_info,
|
||||
&parent.to_webrender(state.pipeline_id),
|
||||
widths,
|
||||
border_details);
|
||||
}
|
||||
|
@ -2389,6 +2490,7 @@ pub extern "C" fn wr_dp_push_border_image(state: &mut WrState,
|
|||
rect: LayoutRect,
|
||||
clip: LayoutRect,
|
||||
is_backface_visible: bool,
|
||||
parent: &WrSpaceAndClipChain,
|
||||
widths: LayoutSideOffsets,
|
||||
image: WrImageKey,
|
||||
width: i32,
|
||||
|
@ -2411,8 +2513,12 @@ pub extern "C" fn wr_dp_push_border_image(state: &mut WrState,
|
|||
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
|
||||
prim_info.is_backface_visible = is_backface_visible;
|
||||
prim_info.tag = state.current_tag;
|
||||
state.frame_builder .dl_builder
|
||||
.push_border(&prim_info, widths.into(), border_details);
|
||||
state.frame_builder.dl_builder.push_border(
|
||||
&prim_info,
|
||||
&parent.to_webrender(state.pipeline_id),
|
||||
widths.into(),
|
||||
border_details,
|
||||
);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -2420,6 +2526,7 @@ pub extern "C" fn wr_dp_push_border_gradient(state: &mut WrState,
|
|||
rect: LayoutRect,
|
||||
clip: LayoutRect,
|
||||
is_backface_visible: bool,
|
||||
parent: &WrSpaceAndClipChain,
|
||||
widths: LayoutSideOffsets,
|
||||
width: i32,
|
||||
height: i32,
|
||||
|
@ -2456,9 +2563,12 @@ pub extern "C" fn wr_dp_push_border_gradient(state: &mut WrState,
|
|||
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
|
||||
prim_info.is_backface_visible = is_backface_visible;
|
||||
prim_info.tag = state.current_tag;
|
||||
state.frame_builder
|
||||
.dl_builder
|
||||
.push_border(&prim_info, widths.into(), border_details);
|
||||
state.frame_builder.dl_builder.push_border(
|
||||
&prim_info,
|
||||
&parent.to_webrender(state.pipeline_id),
|
||||
widths.into(),
|
||||
border_details,
|
||||
);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -2466,6 +2576,7 @@ pub extern "C" fn wr_dp_push_border_radial_gradient(state: &mut WrState,
|
|||
rect: LayoutRect,
|
||||
clip: LayoutRect,
|
||||
is_backface_visible: bool,
|
||||
parent: &WrSpaceAndClipChain,
|
||||
widths: LayoutSideOffsets,
|
||||
center: LayoutPoint,
|
||||
radius: LayoutSize,
|
||||
|
@ -2505,9 +2616,12 @@ pub extern "C" fn wr_dp_push_border_radial_gradient(state: &mut WrState,
|
|||
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
|
||||
prim_info.is_backface_visible = is_backface_visible;
|
||||
prim_info.tag = state.current_tag;
|
||||
state.frame_builder
|
||||
.dl_builder
|
||||
.push_border(&prim_info, widths.into(), border_details);
|
||||
state.frame_builder.dl_builder.push_border(
|
||||
&prim_info,
|
||||
&parent.to_webrender(state.pipeline_id),
|
||||
widths.into(),
|
||||
border_details,
|
||||
);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -2515,6 +2629,7 @@ pub extern "C" fn wr_dp_push_linear_gradient(state: &mut WrState,
|
|||
rect: LayoutRect,
|
||||
clip: LayoutRect,
|
||||
is_backface_visible: bool,
|
||||
parent: &WrSpaceAndClipChain,
|
||||
start_point: LayoutPoint,
|
||||
end_point: LayoutPoint,
|
||||
stops: *const GradientStop,
|
||||
|
@ -2536,12 +2651,13 @@ pub extern "C" fn wr_dp_push_linear_gradient(state: &mut WrState,
|
|||
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
|
||||
prim_info.is_backface_visible = is_backface_visible;
|
||||
prim_info.tag = state.current_tag;
|
||||
state.frame_builder
|
||||
.dl_builder
|
||||
.push_gradient(&prim_info,
|
||||
gradient,
|
||||
tile_size.into(),
|
||||
tile_spacing.into());
|
||||
state.frame_builder.dl_builder.push_gradient(
|
||||
&prim_info,
|
||||
&parent.to_webrender(state.pipeline_id),
|
||||
gradient,
|
||||
tile_size.into(),
|
||||
tile_spacing.into(),
|
||||
);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -2549,6 +2665,7 @@ pub extern "C" fn wr_dp_push_radial_gradient(state: &mut WrState,
|
|||
rect: LayoutRect,
|
||||
clip: LayoutRect,
|
||||
is_backface_visible: bool,
|
||||
parent: &WrSpaceAndClipChain,
|
||||
center: LayoutPoint,
|
||||
radius: LayoutSize,
|
||||
stops: *const GradientStop,
|
||||
|
@ -2570,12 +2687,12 @@ pub extern "C" fn wr_dp_push_radial_gradient(state: &mut WrState,
|
|||
let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(rect, clip.into());
|
||||
prim_info.is_backface_visible = is_backface_visible;
|
||||
prim_info.tag = state.current_tag;
|
||||
state.frame_builder
|
||||
.dl_builder
|
||||
.push_radial_gradient(&prim_info,
|
||||
gradient,
|
||||
tile_size,
|
||||
tile_spacing);
|
||||
state.frame_builder.dl_builder.push_radial_gradient(
|
||||
&prim_info,
|
||||
&parent.to_webrender(state.pipeline_id),
|
||||
gradient,
|
||||
tile_size,
|
||||
tile_spacing);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -2583,6 +2700,7 @@ pub extern "C" fn wr_dp_push_box_shadow(state: &mut WrState,
|
|||
rect: LayoutRect,
|
||||
clip: LayoutRect,
|
||||
is_backface_visible: bool,
|
||||
parent: &WrSpaceAndClipChain,
|
||||
box_bounds: LayoutRect,
|
||||
offset: LayoutVector2D,
|
||||
color: ColorF,
|
||||
|
@ -2598,6 +2716,7 @@ pub extern "C" fn wr_dp_push_box_shadow(state: &mut WrState,
|
|||
state.frame_builder
|
||||
.dl_builder
|
||||
.push_box_shadow(&prim_info,
|
||||
&parent.to_webrender(state.pipeline_id),
|
||||
box_bounds,
|
||||
offset,
|
||||
color,
|
||||
|
@ -2714,37 +2833,48 @@ extern "C" {
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_root_scroll_node_id() -> usize {
|
||||
pub extern "C" fn wr_root_scroll_node_id() -> WrSpatialId {
|
||||
// The PipelineId doesn't matter here, since we just want the numeric part of the id
|
||||
// produced for any given root reference frame.
|
||||
pack_clip_id(ClipId::root_scroll_node(PipelineId(0, 0)))
|
||||
WrSpatialId { id: SpatialId::root_scroll_node(PipelineId(0, 0)).0 }
|
||||
}
|
||||
|
||||
fn pack_clip_id(id: ClipId) -> usize {
|
||||
let (id, type_value) = match id {
|
||||
ClipId::Spatial(id, _) => (id, 0),
|
||||
ClipId::Clip(id, _) => (id, 1),
|
||||
ClipId::ClipChain(..) => unreachable!("Tried to pack a clip chain id"),
|
||||
};
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wr_root_clip_id() -> WrClipId {
|
||||
// The PipelineId doesn't matter here, since we just want the numeric part of the id
|
||||
// produced for any given root reference frame.
|
||||
WrClipId::from_webrender(ClipId::root(PipelineId(0, 0)))
|
||||
}
|
||||
|
||||
assert!(id <= usize::max_value() >> 1);
|
||||
return (id << 1) + type_value;
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct WrClipId {
|
||||
id: usize
|
||||
id: usize,
|
||||
}
|
||||
|
||||
fn unpack_clip_id(id: WrClipId, pipeline_id: PipelineId) -> ClipId {
|
||||
let type_value = id.id & 0b01;
|
||||
let id = id.id >> 1;
|
||||
impl WrClipId {
|
||||
fn to_webrender(&self, pipeline_id: WrPipelineId) -> ClipId {
|
||||
ClipId::Clip(self.id, pipeline_id)
|
||||
}
|
||||
|
||||
match type_value {
|
||||
0 => ClipId::Spatial(id, pipeline_id),
|
||||
1 => ClipId::Clip(id, pipeline_id),
|
||||
_ => unreachable!("Got a bizarre value for the clip type"),
|
||||
fn from_webrender(clip_id: ClipId) -> Self {
|
||||
match clip_id {
|
||||
ClipId::Clip(id, _) => WrClipId { id },
|
||||
ClipId::ClipChain(_) => panic!("Unexpected clip chain"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct WrSpatialId {
|
||||
id: usize,
|
||||
}
|
||||
|
||||
impl WrSpatialId {
|
||||
fn to_webrender(&self, pipeline_id: WrPipelineId) -> SpatialId {
|
||||
SpatialId::new(self.id, pipeline_id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -96,6 +96,8 @@ struct Transaction;
|
|||
struct WrWindowId;
|
||||
struct WrPipelineInfo;
|
||||
|
||||
const uint64_t ROOT_CLIP_CHAIN = ~0;
|
||||
|
||||
} // namespace wr
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -651,6 +651,24 @@ struct WrClipId {
|
|||
}
|
||||
};
|
||||
|
||||
struct WrSpatialId {
|
||||
uintptr_t id;
|
||||
|
||||
bool operator==(const WrSpatialId& aOther) const {
|
||||
return id == aOther.id;
|
||||
}
|
||||
};
|
||||
|
||||
struct WrSpaceAndClip {
|
||||
WrSpatialId space;
|
||||
WrClipId clip;
|
||||
|
||||
bool operator==(const WrSpaceAndClip& aOther) const {
|
||||
return space == aOther.space &&
|
||||
clip == aOther.clip;
|
||||
}
|
||||
};
|
||||
|
||||
/// A 2d Rectangle optionally tagged with a unit.
|
||||
template<typename T, typename U>
|
||||
struct TypedRect {
|
||||
|
@ -726,6 +744,16 @@ struct WrImageMask {
|
|||
}
|
||||
};
|
||||
|
||||
struct WrSpaceAndClipChain {
|
||||
WrSpatialId space;
|
||||
uint64_t clip_chain;
|
||||
|
||||
bool operator==(const WrSpaceAndClipChain& aOther) const {
|
||||
return space == aOther.space &&
|
||||
clip_chain == aOther.clip_chain;
|
||||
}
|
||||
};
|
||||
|
||||
/// The minimum and maximum allowable offset for a sticky frame in a single dimension.
|
||||
struct StickyOffsetBounds {
|
||||
/// The minimum offset for this frame, typically a negative value, which specifies how
|
||||
|
@ -1310,12 +1338,21 @@ void wr_dp_clear_save(WrState *aState)
|
|||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
uintptr_t wr_dp_define_clip(WrState *aState,
|
||||
const WrClipId *aParentId,
|
||||
LayoutRect aClipRect,
|
||||
const ComplexClipRegion *aComplex,
|
||||
uintptr_t aComplexCount,
|
||||
const WrImageMask *aMask)
|
||||
WrClipId wr_dp_define_clip_with_parent_clip(WrState *aState,
|
||||
const WrSpaceAndClip *aParent,
|
||||
LayoutRect aClipRect,
|
||||
const ComplexClipRegion *aComplex,
|
||||
uintptr_t aComplexCount,
|
||||
const WrImageMask *aMask)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
WrClipId wr_dp_define_clip_with_parent_clip_chain(WrState *aState,
|
||||
const WrSpaceAndClipChain *aParent,
|
||||
LayoutRect aClipRect,
|
||||
const ComplexClipRegion *aComplex,
|
||||
uintptr_t aComplexCount,
|
||||
const WrImageMask *aMask)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
|
@ -1326,41 +1363,30 @@ uint64_t wr_dp_define_clipchain(WrState *aState,
|
|||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
uintptr_t wr_dp_define_scroll_layer(WrState *aState,
|
||||
uint64_t aScrollId,
|
||||
const WrClipId *aParentId,
|
||||
LayoutRect aContentRect,
|
||||
LayoutRect aClipRect)
|
||||
WrSpaceAndClip wr_dp_define_scroll_layer(WrState *aState,
|
||||
uint64_t aExternalScrollId,
|
||||
const WrSpaceAndClip *aParent,
|
||||
LayoutRect aContentRect,
|
||||
LayoutRect aClipRect)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
uintptr_t wr_dp_define_sticky_frame(WrState *aState,
|
||||
LayoutRect aContentRect,
|
||||
const float *aTopMargin,
|
||||
const float *aRightMargin,
|
||||
const float *aBottomMargin,
|
||||
const float *aLeftMargin,
|
||||
StickyOffsetBounds aVerticalBounds,
|
||||
StickyOffsetBounds aHorizontalBounds,
|
||||
LayoutVector2D aAppliedOffset)
|
||||
WrSpatialId wr_dp_define_sticky_frame(WrState *aState,
|
||||
WrSpatialId aParentSpatialId,
|
||||
LayoutRect aContentRect,
|
||||
const float *aTopMargin,
|
||||
const float *aRightMargin,
|
||||
const float *aBottomMargin,
|
||||
const float *aLeftMargin,
|
||||
StickyOffsetBounds aVerticalBounds,
|
||||
StickyOffsetBounds aHorizontalBounds,
|
||||
LayoutVector2D aAppliedOffset)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
void wr_dp_pop_all_shadows(WrState *aState)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
void wr_dp_pop_clip(WrState *aState)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
void wr_dp_pop_clip_and_scroll_info(WrState *aState)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
void wr_dp_pop_scroll_layer(WrState *aState)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
void wr_dp_pop_stacking_context(WrState *aState,
|
||||
bool aIsReferenceFrame)
|
||||
|
@ -1371,6 +1397,7 @@ void wr_dp_push_border(WrState *aState,
|
|||
LayoutRect aRect,
|
||||
LayoutRect aClip,
|
||||
bool aIsBackfaceVisible,
|
||||
const WrSpaceAndClipChain *aParent,
|
||||
AntialiasBorder aDoAa,
|
||||
LayoutSideOffsets aWidths,
|
||||
BorderSide aTop,
|
||||
|
@ -1385,6 +1412,7 @@ void wr_dp_push_border_gradient(WrState *aState,
|
|||
LayoutRect aRect,
|
||||
LayoutRect aClip,
|
||||
bool aIsBackfaceVisible,
|
||||
const WrSpaceAndClipChain *aParent,
|
||||
LayoutSideOffsets aWidths,
|
||||
int32_t aWidth,
|
||||
int32_t aHeight,
|
||||
|
@ -1402,6 +1430,7 @@ void wr_dp_push_border_image(WrState *aState,
|
|||
LayoutRect aRect,
|
||||
LayoutRect aClip,
|
||||
bool aIsBackfaceVisible,
|
||||
const WrSpaceAndClipChain *aParent,
|
||||
LayoutSideOffsets aWidths,
|
||||
WrImageKey aImage,
|
||||
int32_t aWidth,
|
||||
|
@ -1417,6 +1446,7 @@ void wr_dp_push_border_radial_gradient(WrState *aState,
|
|||
LayoutRect aRect,
|
||||
LayoutRect aClip,
|
||||
bool aIsBackfaceVisible,
|
||||
const WrSpaceAndClipChain *aParent,
|
||||
LayoutSideOffsets aWidths,
|
||||
LayoutPoint aCenter,
|
||||
LayoutSize aRadius,
|
||||
|
@ -1431,6 +1461,7 @@ void wr_dp_push_box_shadow(WrState *aState,
|
|||
LayoutRect aRect,
|
||||
LayoutRect aClip,
|
||||
bool aIsBackfaceVisible,
|
||||
const WrSpaceAndClipChain *aParent,
|
||||
LayoutRect aBoxBounds,
|
||||
LayoutVector2D aOffset,
|
||||
ColorF aColor,
|
||||
|
@ -1443,18 +1474,15 @@ WR_FUNC;
|
|||
WR_INLINE
|
||||
void wr_dp_push_clear_rect(WrState *aState,
|
||||
LayoutRect aRect,
|
||||
LayoutRect aClip)
|
||||
LayoutRect aClip,
|
||||
const WrSpaceAndClipChain *aParent)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
void wr_dp_push_clip(WrState *aState,
|
||||
WrClipId aClipId)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
void wr_dp_push_clip_and_scroll_info(WrState *aState,
|
||||
WrClipId aScrollId,
|
||||
const uint64_t *aClipChainId)
|
||||
void wr_dp_push_clear_rect_with_parent_clip(WrState *aState,
|
||||
LayoutRect aRect,
|
||||
LayoutRect aClip,
|
||||
const WrSpaceAndClip *aParent)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
|
@ -1462,6 +1490,7 @@ void wr_dp_push_iframe(WrState *aState,
|
|||
LayoutRect aRect,
|
||||
LayoutRect aClip,
|
||||
bool aIsBackfaceVisible,
|
||||
const WrSpaceAndClipChain *aParent,
|
||||
WrPipelineId aPipelineId,
|
||||
bool aIgnoreMissingPipeline)
|
||||
WR_FUNC;
|
||||
|
@ -1471,6 +1500,7 @@ void wr_dp_push_image(WrState *aState,
|
|||
LayoutRect aBounds,
|
||||
LayoutRect aClip,
|
||||
bool aIsBackfaceVisible,
|
||||
const WrSpaceAndClipChain *aParent,
|
||||
LayoutSize aStretchSize,
|
||||
LayoutSize aTileSpacing,
|
||||
ImageRendering aImageRendering,
|
||||
|
@ -1483,6 +1513,7 @@ WR_INLINE
|
|||
void wr_dp_push_line(WrState *aState,
|
||||
const LayoutRect *aClip,
|
||||
bool aIsBackfaceVisible,
|
||||
const WrSpaceAndClipChain *aParent,
|
||||
const LayoutRect *aBounds,
|
||||
float aWavyLineThickness,
|
||||
LineOrientation aOrientation,
|
||||
|
@ -1495,6 +1526,7 @@ void wr_dp_push_linear_gradient(WrState *aState,
|
|||
LayoutRect aRect,
|
||||
LayoutRect aClip,
|
||||
bool aIsBackfaceVisible,
|
||||
const WrSpaceAndClipChain *aParent,
|
||||
LayoutPoint aStartPoint,
|
||||
LayoutPoint aEndPoint,
|
||||
const GradientStop *aStops,
|
||||
|
@ -1509,6 +1541,7 @@ void wr_dp_push_radial_gradient(WrState *aState,
|
|||
LayoutRect aRect,
|
||||
LayoutRect aClip,
|
||||
bool aIsBackfaceVisible,
|
||||
const WrSpaceAndClipChain *aParent,
|
||||
LayoutPoint aCenter,
|
||||
LayoutSize aRadius,
|
||||
const GradientStop *aStops,
|
||||
|
@ -1523,12 +1556,17 @@ void wr_dp_push_rect(WrState *aState,
|
|||
LayoutRect aRect,
|
||||
LayoutRect aClip,
|
||||
bool aIsBackfaceVisible,
|
||||
const WrSpaceAndClipChain *aParent,
|
||||
ColorF aColor)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
void wr_dp_push_scroll_layer(WrState *aState,
|
||||
WrClipId aScrollId)
|
||||
void wr_dp_push_rect_with_parent_clip(WrState *aState,
|
||||
LayoutRect aRect,
|
||||
LayoutRect aClip,
|
||||
bool aIsBackfaceVisible,
|
||||
const WrSpaceAndClip *aParent,
|
||||
ColorF aColor)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
|
@ -1536,25 +1574,25 @@ void wr_dp_push_shadow(WrState *aState,
|
|||
LayoutRect aBounds,
|
||||
LayoutRect aClip,
|
||||
bool aIsBackfaceVisible,
|
||||
const WrSpaceAndClipChain *aParent,
|
||||
Shadow aShadow)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
void wr_dp_push_stacking_context(WrState *aState,
|
||||
LayoutRect aBounds,
|
||||
const WrClipId *aClipNodeId,
|
||||
const WrAnimationProperty *aAnimation,
|
||||
const float *aOpacity,
|
||||
const LayoutTransform *aTransform,
|
||||
TransformStyle aTransformStyle,
|
||||
const LayoutTransform *aPerspective,
|
||||
MixBlendMode aMixBlendMode,
|
||||
const WrFilterOp *aFilters,
|
||||
uintptr_t aFilterCount,
|
||||
bool aIsBackfaceVisible,
|
||||
RasterSpace aGlyphRasterSpace,
|
||||
bool *aOutIsReferenceFrame,
|
||||
uintptr_t *aOutReferenceFrameId)
|
||||
WrSpatialId wr_dp_push_stacking_context(WrState *aState,
|
||||
LayoutRect aBounds,
|
||||
WrSpatialId aSpatialId,
|
||||
const WrClipId *aClipNodeId,
|
||||
const WrAnimationProperty *aAnimation,
|
||||
const float *aOpacity,
|
||||
const LayoutTransform *aTransform,
|
||||
TransformStyle aTransformStyle,
|
||||
const LayoutTransform *aPerspective,
|
||||
MixBlendMode aMixBlendMode,
|
||||
const WrFilterOp *aFilters,
|
||||
uintptr_t aFilterCount,
|
||||
bool aIsBackfaceVisible,
|
||||
RasterSpace aGlyphRasterSpace)
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
|
@ -1562,6 +1600,7 @@ void wr_dp_push_text(WrState *aState,
|
|||
LayoutRect aBounds,
|
||||
LayoutRect aClip,
|
||||
bool aIsBackfaceVisible,
|
||||
const WrSpaceAndClipChain *aParent,
|
||||
ColorF aColor,
|
||||
WrFontInstanceKey aFontKey,
|
||||
const GlyphInstance *aGlyphs,
|
||||
|
@ -1575,6 +1614,7 @@ void wr_dp_push_yuv_NV12_image(WrState *aState,
|
|||
LayoutRect aBounds,
|
||||
LayoutRect aClip,
|
||||
bool aIsBackfaceVisible,
|
||||
const WrSpaceAndClipChain *aParent,
|
||||
WrImageKey aImageKey0,
|
||||
WrImageKey aImageKey1,
|
||||
WrColorDepth aColorDepth,
|
||||
|
@ -1588,6 +1628,7 @@ void wr_dp_push_yuv_interleaved_image(WrState *aState,
|
|||
LayoutRect aBounds,
|
||||
LayoutRect aClip,
|
||||
bool aIsBackfaceVisible,
|
||||
const WrSpaceAndClipChain *aParent,
|
||||
WrImageKey aImageKey0,
|
||||
WrColorDepth aColorDepth,
|
||||
WrYuvColorSpace aColorSpace,
|
||||
|
@ -1600,6 +1641,7 @@ void wr_dp_push_yuv_planar_image(WrState *aState,
|
|||
LayoutRect aBounds,
|
||||
LayoutRect aClip,
|
||||
bool aIsBackfaceVisible,
|
||||
const WrSpaceAndClipChain *aParent,
|
||||
WrImageKey aImageKey0,
|
||||
WrImageKey aImageKey1,
|
||||
WrImageKey aImageKey2,
|
||||
|
@ -1823,7 +1865,11 @@ void wr_resource_updates_update_image(Transaction *aTxn,
|
|||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
uintptr_t wr_root_scroll_node_id()
|
||||
WrClipId wr_root_clip_id()
|
||||
WR_FUNC;
|
||||
|
||||
WR_INLINE
|
||||
WrSpatialId wr_root_scroll_node_id()
|
||||
WR_FUNC;
|
||||
|
||||
extern void wr_schedule_render(WrWindowId aWindowId);
|
||||
|
|
|
@ -142,12 +142,21 @@ impl Rectangle {
|
|||
api::BorderRadius::uniform(20.),
|
||||
api::ClipMode::Clip
|
||||
);
|
||||
let clip_id = builder.define_clip(rect, vec![region], None);
|
||||
builder.push_clip_id(clip_id);
|
||||
let clip_id = builder.define_clip(
|
||||
&api::SpaceAndClipInfo::root_scroll(pipeline_id),
|
||||
rect,
|
||||
vec![region],
|
||||
None,
|
||||
);
|
||||
|
||||
builder.push_rect(&api::PrimitiveInfo::new(rect), self.color);
|
||||
|
||||
builder.pop_clip_id();
|
||||
builder.push_rect(
|
||||
&api::PrimitiveInfo::new(rect),
|
||||
&api::SpaceAndClipInfo {
|
||||
spatial_id: api::SpatialId::root_scroll_node(pipeline_id),
|
||||
clip_id,
|
||||
},
|
||||
self.color,
|
||||
);
|
||||
|
||||
let mut transaction = api::Transaction::new();
|
||||
transaction.set_display_list(
|
||||
|
|
|
@ -26,14 +26,16 @@ impl Example for App {
|
|||
builder: &mut DisplayListBuilder,
|
||||
_txn: &mut Transaction,
|
||||
_framebuffer_size: DeviceIntSize,
|
||||
_pipeline_id: PipelineId,
|
||||
pipeline_id: PipelineId,
|
||||
_document_id: DocumentId,
|
||||
) {
|
||||
let bounds = (0, 0).to(1920, 1080);
|
||||
let info = LayoutPrimitiveInfo::new(bounds);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
|
||||
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
|
@ -42,7 +44,7 @@ impl Example for App {
|
|||
);
|
||||
|
||||
for _ in 0 .. self.rect_count {
|
||||
builder.push_rect(&info, ColorF::new(1.0, 1.0, 1.0, 0.05));
|
||||
builder.push_rect(&info, &space_and_clip, ColorF::new(1.0, 1.0, 1.0, 0.05));
|
||||
}
|
||||
|
||||
builder.pop_stacking_context();
|
||||
|
|
|
@ -40,6 +40,7 @@ impl App {
|
|||
bounds: LayoutRect,
|
||||
color: ColorF,
|
||||
builder: &mut DisplayListBuilder,
|
||||
pipeline_id: PipelineId,
|
||||
property_key: PropertyBindingKey<LayoutTransform>,
|
||||
opacity_key: Option<PropertyBindingKey<f32>>,
|
||||
) {
|
||||
|
@ -54,17 +55,17 @@ impl App {
|
|||
}
|
||||
};
|
||||
|
||||
let reference_frame_id = builder.push_reference_frame(
|
||||
let spatial_id = builder.push_reference_frame(
|
||||
&LayoutRect::new(bounds.origin, LayoutSize::zero()),
|
||||
SpatialId::root_scroll_node(pipeline_id),
|
||||
TransformStyle::Flat,
|
||||
Some(PropertyBinding::Binding(property_key, LayoutTransform::identity())),
|
||||
None,
|
||||
);
|
||||
|
||||
builder.push_clip_id(reference_frame_id);
|
||||
|
||||
builder.push_stacking_context(
|
||||
&LayoutPrimitiveInfo::new(LayoutRect::zero()),
|
||||
spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
|
@ -72,26 +73,29 @@ impl App {
|
|||
RasterSpace::Screen,
|
||||
);
|
||||
|
||||
let space_and_clip = SpaceAndClipInfo {
|
||||
spatial_id,
|
||||
clip_id: ClipId::root(pipeline_id),
|
||||
};
|
||||
let clip_bounds = LayoutRect::new(LayoutPoint::zero(), bounds.size);
|
||||
let complex_clip = ComplexClipRegion {
|
||||
rect: clip_bounds,
|
||||
radii: BorderRadius::uniform(30.0),
|
||||
mode: ClipMode::Clip,
|
||||
};
|
||||
let clip_id = builder.define_clip(clip_bounds, vec![complex_clip], None);
|
||||
builder.push_clip_id(clip_id);
|
||||
let clip_id = builder.define_clip(&space_and_clip, clip_bounds, vec![complex_clip], None);
|
||||
|
||||
// Fill it with a white rect
|
||||
builder.push_rect(
|
||||
&LayoutPrimitiveInfo::new(LayoutRect::new(LayoutPoint::zero(), bounds.size)),
|
||||
&SpaceAndClipInfo {
|
||||
spatial_id,
|
||||
clip_id,
|
||||
},
|
||||
color,
|
||||
);
|
||||
|
||||
builder.pop_clip_id();
|
||||
|
||||
builder.pop_stacking_context();
|
||||
|
||||
builder.pop_clip_id();
|
||||
builder.pop_reference_frame();
|
||||
}
|
||||
}
|
||||
|
@ -106,22 +110,22 @@ impl Example for App {
|
|||
builder: &mut DisplayListBuilder,
|
||||
_txn: &mut Transaction,
|
||||
_framebuffer_size: DeviceIntSize,
|
||||
_pipeline_id: PipelineId,
|
||||
pipeline_id: PipelineId,
|
||||
_document_id: DocumentId,
|
||||
) {
|
||||
let opacity_key = self.opacity_key;
|
||||
|
||||
let bounds = (150, 150).to(250, 250);
|
||||
let key0 = self.property_key0;
|
||||
self.add_rounded_rect(bounds, ColorF::new(1.0, 0.0, 0.0, 0.5), builder, key0, Some(opacity_key));
|
||||
self.add_rounded_rect(bounds, ColorF::new(1.0, 0.0, 0.0, 0.5), builder, pipeline_id, key0, Some(opacity_key));
|
||||
|
||||
let bounds = (400, 400).to(600, 600);
|
||||
let key1 = self.property_key1;
|
||||
self.add_rounded_rect(bounds, ColorF::new(0.0, 1.0, 0.0, 0.5), builder, key1, None);
|
||||
self.add_rounded_rect(bounds, ColorF::new(0.0, 1.0, 0.0, 0.5), builder, pipeline_id, key1, None);
|
||||
|
||||
let bounds = (200, 500).to(350, 580);
|
||||
let key2 = self.property_key2;
|
||||
self.add_rounded_rect(bounds, ColorF::new(0.0, 0.0, 1.0, 0.5), builder, key2, None);
|
||||
self.add_rounded_rect(bounds, ColorF::new(0.0, 0.0, 1.0, 0.5), builder, pipeline_id, key2, None);
|
||||
}
|
||||
|
||||
fn on_event(&mut self, win_event: winit::WindowEvent, api: &RenderApi, document_id: DocumentId) -> bool {
|
||||
|
|
|
@ -186,13 +186,17 @@ impl Example for App {
|
|||
builder: &mut DisplayListBuilder,
|
||||
txn: &mut Transaction,
|
||||
_: DeviceIntSize,
|
||||
_pipeline_id: PipelineId,
|
||||
pipeline_id: PipelineId,
|
||||
_document_id: DocumentId,
|
||||
) {
|
||||
let bounds = LayoutRect::new(LayoutPoint::zero(), builder.content_size());
|
||||
let info = LayoutPrimitiveInfo::new(bounds);
|
||||
let root_space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
|
||||
let spatial_id = root_space_and_clip.spatial_id;
|
||||
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
|
@ -217,14 +221,19 @@ impl Example for App {
|
|||
BorderRadius::uniform(20.0),
|
||||
ClipMode::Clip
|
||||
);
|
||||
let id = builder.define_clip(bounds, vec![complex], Some(mask));
|
||||
builder.push_clip_id(id);
|
||||
let clip_id = builder.define_clip(&root_space_and_clip, bounds, vec![complex], Some(mask));
|
||||
|
||||
let info = LayoutPrimitiveInfo::new((100, 100).to(200, 200));
|
||||
builder.push_rect(&info, ColorF::new(0.0, 1.0, 0.0, 1.0));
|
||||
builder.push_rect(
|
||||
&LayoutPrimitiveInfo::new((100, 100).to(200, 200)),
|
||||
&SpaceAndClipInfo { spatial_id, clip_id },
|
||||
ColorF::new(0.0, 1.0, 0.0, 1.0),
|
||||
);
|
||||
|
||||
let info = LayoutPrimitiveInfo::new((250, 100).to(350, 200));
|
||||
builder.push_rect(&info, ColorF::new(0.0, 1.0, 0.0, 1.0));
|
||||
builder.push_rect(
|
||||
&LayoutPrimitiveInfo::new((250, 100).to(350, 200)),
|
||||
&SpaceAndClipInfo { spatial_id, clip_id },
|
||||
ColorF::new(0.0, 1.0, 0.0, 1.0),
|
||||
);
|
||||
let border_side = BorderSide {
|
||||
color: ColorF::new(0.0, 0.0, 1.0, 1.0),
|
||||
style: BorderStyle::Groove,
|
||||
|
@ -239,9 +248,12 @@ impl Example for App {
|
|||
do_aa: true,
|
||||
});
|
||||
|
||||
let info = LayoutPrimitiveInfo::new((100, 100).to(200, 200));
|
||||
builder.push_border(&info, border_widths, border_details);
|
||||
builder.pop_clip_id();
|
||||
builder.push_border(
|
||||
&LayoutPrimitiveInfo::new((100, 100).to(200, 200)),
|
||||
&SpaceAndClipInfo { spatial_id, clip_id },
|
||||
border_widths,
|
||||
border_details,
|
||||
);
|
||||
|
||||
if false {
|
||||
// draw box shadow?
|
||||
|
@ -253,10 +265,10 @@ impl Example for App {
|
|||
let spread_radius = 0.0;
|
||||
let simple_border_radius = 8.0;
|
||||
let box_shadow_type = BoxShadowClipMode::Inset;
|
||||
let info = LayoutPrimitiveInfo::with_clip_rect(rect, bounds);
|
||||
|
||||
builder.push_box_shadow(
|
||||
&info,
|
||||
&LayoutPrimitiveInfo::with_clip_rect(rect, bounds),
|
||||
&root_space_and_clip,
|
||||
simple_box_bounds,
|
||||
offset,
|
||||
color,
|
||||
|
|
|
@ -17,7 +17,7 @@ use rayon::prelude::*;
|
|||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use webrender::api::{self, DisplayListBuilder, DocumentId, PipelineId, RenderApi, Transaction};
|
||||
use webrender::api::ColorF;
|
||||
use webrender::api::{ColorF, SpaceAndClipInfo};
|
||||
use webrender::euclid::size2;
|
||||
|
||||
// This example shows how to implement a very basic BlobImageHandler that can only render
|
||||
|
@ -200,7 +200,7 @@ impl Example for App {
|
|||
builder: &mut DisplayListBuilder,
|
||||
txn: &mut Transaction,
|
||||
_framebuffer_size: api::DeviceIntSize,
|
||||
_pipeline_id: PipelineId,
|
||||
pipeline_id: PipelineId,
|
||||
_document_id: DocumentId,
|
||||
) {
|
||||
let blob_img1 = api.generate_blob_image_key();
|
||||
|
@ -220,9 +220,11 @@ impl Example for App {
|
|||
);
|
||||
|
||||
let bounds = api::LayoutRect::new(api::LayoutPoint::zero(), builder.content_size());
|
||||
let info = api::LayoutPrimitiveInfo::new(bounds);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
|
||||
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
&api::LayoutPrimitiveInfo::new(bounds),
|
||||
space_and_clip.spatial_id,
|
||||
None,
|
||||
api::TransformStyle::Flat,
|
||||
api::MixBlendMode::Normal,
|
||||
|
@ -230,9 +232,9 @@ impl Example for App {
|
|||
api::RasterSpace::Screen,
|
||||
);
|
||||
|
||||
let info = api::LayoutPrimitiveInfo::new((30, 30).by(500, 500));
|
||||
builder.push_image(
|
||||
&info,
|
||||
&api::LayoutPrimitiveInfo::new((30, 30).by(500, 500)),
|
||||
&space_and_clip,
|
||||
api::LayoutSize::new(500.0, 500.0),
|
||||
api::LayoutSize::new(0.0, 0.0),
|
||||
api::ImageRendering::Auto,
|
||||
|
@ -241,9 +243,9 @@ impl Example for App {
|
|||
ColorF::WHITE,
|
||||
);
|
||||
|
||||
let info = api::LayoutPrimitiveInfo::new((600, 600).by(200, 200));
|
||||
builder.push_image(
|
||||
&info,
|
||||
&api::LayoutPrimitiveInfo::new((600, 600).by(200, 200)),
|
||||
&space_and_clip,
|
||||
api::LayoutSize::new(200.0, 200.0),
|
||||
api::LayoutSize::new(0.0, 0.0),
|
||||
api::ImageRendering::Auto,
|
||||
|
|
|
@ -90,7 +90,7 @@ impl Example for App {
|
|||
base_builder: &mut DisplayListBuilder,
|
||||
_txn: &mut Transaction,
|
||||
framebuffer_size: DeviceIntSize,
|
||||
_: PipelineId,
|
||||
_pipeline_id: PipelineId,
|
||||
_: DocumentId,
|
||||
) {
|
||||
if self.documents.is_empty() {
|
||||
|
@ -102,6 +102,7 @@ impl Example for App {
|
|||
}
|
||||
|
||||
for doc in &self.documents {
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(doc.pipeline_id);
|
||||
let mut builder = DisplayListBuilder::new(
|
||||
doc.pipeline_id,
|
||||
doc.content_rect.size,
|
||||
|
@ -113,6 +114,7 @@ impl Example for App {
|
|||
|
||||
builder.push_stacking_context(
|
||||
&LayoutPrimitiveInfo::new(doc.content_rect),
|
||||
space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
|
@ -121,6 +123,7 @@ impl Example for App {
|
|||
);
|
||||
builder.push_rect(
|
||||
&LayoutPrimitiveInfo::new(local_rect),
|
||||
&space_and_clip,
|
||||
doc.color,
|
||||
);
|
||||
builder.pop_stacking_context();
|
||||
|
|
|
@ -107,6 +107,7 @@ impl App {
|
|||
);
|
||||
|
||||
let info = LayoutPrimitiveInfo::new(document.content_rect);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
|
||||
let mut builder = DisplayListBuilder::new(
|
||||
document.pipeline_id,
|
||||
document.content_rect.size,
|
||||
|
@ -114,6 +115,7 @@ impl App {
|
|||
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
|
@ -121,7 +123,7 @@ impl App {
|
|||
RasterSpace::Screen,
|
||||
);
|
||||
|
||||
builder.push_rect(&info, ColorF::new(1.0, 1.0, 0.0, 1.0));
|
||||
builder.push_rect(&info, &space_and_clip, ColorF::new(1.0, 1.0, 0.0, 1.0));
|
||||
builder.pop_stacking_context();
|
||||
|
||||
txn.set_root_pipeline(pipeline_id);
|
||||
|
@ -145,7 +147,7 @@ impl Example for App {
|
|||
builder: &mut DisplayListBuilder,
|
||||
_txn: &mut Transaction,
|
||||
framebuffer_size: DeviceIntSize,
|
||||
_pipeline_id: PipelineId,
|
||||
pipeline_id: PipelineId,
|
||||
_document_id: DocumentId,
|
||||
) {
|
||||
if self.output_document.is_none() {
|
||||
|
@ -155,8 +157,11 @@ impl Example for App {
|
|||
}
|
||||
|
||||
let info = LayoutPrimitiveInfo::new((100, 100).to(200, 200));
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
|
||||
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
|
@ -166,6 +171,7 @@ impl Example for App {
|
|||
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
info.rect.size,
|
||||
LayoutSize::zero(),
|
||||
ImageRendering::Auto,
|
||||
|
|
|
@ -35,10 +35,12 @@ impl Example for App {
|
|||
|
||||
let sub_pipeline_id = PipelineId(pipeline_id.0, 42);
|
||||
let mut sub_builder = DisplayListBuilder::new(sub_pipeline_id, sub_bounds.size);
|
||||
let mut space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
|
||||
|
||||
let info = LayoutPrimitiveInfo::new(sub_bounds);
|
||||
sub_builder.push_stacking_context(
|
||||
&info,
|
||||
space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
|
@ -47,7 +49,7 @@ impl Example for App {
|
|||
);
|
||||
|
||||
// green rect visible == success
|
||||
sub_builder.push_rect(&info, ColorF::new(0.0, 1.0, 0.0, 1.0));
|
||||
sub_builder.push_rect(&info, &space_and_clip, ColorF::new(0.0, 1.0, 0.0, 1.0));
|
||||
sub_builder.pop_stacking_context();
|
||||
|
||||
let mut txn = Transaction::new();
|
||||
|
@ -60,19 +62,19 @@ impl Example for App {
|
|||
);
|
||||
api.send_transaction(document_id, txn);
|
||||
|
||||
let info = LayoutPrimitiveInfo::new(sub_bounds);
|
||||
let reference_frame_id = builder.push_reference_frame(
|
||||
space_and_clip.spatial_id = builder.push_reference_frame(
|
||||
&sub_bounds,
|
||||
space_and_clip.spatial_id,
|
||||
TransformStyle::Flat,
|
||||
Some(PropertyBinding::Binding(PropertyBindingKey::new(42), LayoutTransform::identity())),
|
||||
None,
|
||||
);
|
||||
builder.push_clip_id(reference_frame_id);
|
||||
|
||||
|
||||
// And this is for the root pipeline
|
||||
let info = LayoutPrimitiveInfo::new(sub_bounds);
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
|
@ -80,11 +82,9 @@ impl Example for App {
|
|||
RasterSpace::Screen,
|
||||
);
|
||||
// red rect under the iframe: if this is visible, things have gone wrong
|
||||
builder.push_rect(&info, ColorF::new(1.0, 0.0, 0.0, 1.0));
|
||||
builder.push_iframe(&info, sub_pipeline_id, false);
|
||||
builder.push_rect(&info, &space_and_clip, ColorF::new(1.0, 0.0, 0.0, 1.0));
|
||||
builder.push_iframe(&info, &space_and_clip, sub_pipeline_id, false);
|
||||
builder.pop_stacking_context();
|
||||
|
||||
builder.pop_clip_id();
|
||||
builder.pop_reference_frame();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ impl Example for App {
|
|||
builder: &mut DisplayListBuilder,
|
||||
txn: &mut Transaction,
|
||||
_framebuffer_size: DeviceIntSize,
|
||||
_pipeline_id: PipelineId,
|
||||
pipeline_id: PipelineId,
|
||||
_document_id: DocumentId,
|
||||
) {
|
||||
let (image_descriptor, image_data) = image_helper::make_checkerboard(32, 32);
|
||||
|
@ -39,8 +39,11 @@ impl Example for App {
|
|||
|
||||
let bounds = (0, 0).to(512, 512);
|
||||
let info = LayoutPrimitiveInfo::new(bounds);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
|
||||
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
|
@ -56,6 +59,7 @@ impl Example for App {
|
|||
);
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
image_size,
|
||||
LayoutSize::zero(),
|
||||
ImageRendering::Auto,
|
||||
|
@ -70,6 +74,7 @@ impl Example for App {
|
|||
);
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
image_size,
|
||||
LayoutSize::zero(),
|
||||
ImageRendering::Pixelated,
|
||||
|
|
|
@ -187,11 +187,13 @@ impl Window {
|
|||
let layout_size = framebuffer_size.to_f32() / euclid::TypedScale::new(device_pixel_ratio);
|
||||
let mut txn = Transaction::new();
|
||||
let mut builder = DisplayListBuilder::new(self.pipeline_id, layout_size);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(self.pipeline_id);
|
||||
|
||||
let bounds = LayoutRect::new(LayoutPoint::zero(), builder.content_size());
|
||||
let info = LayoutPrimitiveInfo::new(bounds);
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
|
@ -203,7 +205,7 @@ impl Window {
|
|||
LayoutPoint::new(100.0, 100.0),
|
||||
LayoutSize::new(100.0, 200.0)
|
||||
));
|
||||
builder.push_rect(&info, ColorF::new(0.0, 1.0, 0.0, 1.0));
|
||||
builder.push_rect(&info, &space_and_clip, ColorF::new(0.0, 1.0, 0.0, 1.0));
|
||||
|
||||
let text_bounds = LayoutRect::new(
|
||||
LayoutPoint::new(100.0, 50.0),
|
||||
|
@ -263,6 +265,7 @@ impl Window {
|
|||
let info = LayoutPrimitiveInfo::new(text_bounds);
|
||||
builder.push_text(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
&glyphs,
|
||||
self.font_instance_key,
|
||||
ColorF::new(1.0, 1.0, 0.0, 1.0),
|
||||
|
|
|
@ -27,14 +27,16 @@ impl Example for App {
|
|||
builder: &mut DisplayListBuilder,
|
||||
_txn: &mut Transaction,
|
||||
_framebuffer_size: DeviceIntSize,
|
||||
_pipeline_id: PipelineId,
|
||||
pipeline_id: PipelineId,
|
||||
_document_id: DocumentId,
|
||||
) {
|
||||
let info = LayoutPrimitiveInfo::new(
|
||||
LayoutRect::new(LayoutPoint::zero(), builder.content_size())
|
||||
);
|
||||
let root_space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
root_space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
|
@ -48,6 +50,7 @@ impl Example for App {
|
|||
let scrollbox = (0, 0).to(300, 400);
|
||||
builder.push_stacking_context(
|
||||
&LayoutPrimitiveInfo::new((10, 10).by(0, 0)),
|
||||
root_space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
|
@ -55,7 +58,8 @@ impl Example for App {
|
|||
RasterSpace::Screen,
|
||||
);
|
||||
// set the scrolling clip
|
||||
let clip_id = builder.define_scroll_frame(
|
||||
let space_and_clip1 = builder.define_scroll_frame(
|
||||
&root_space_and_clip,
|
||||
None,
|
||||
(0, 0).by(1000, 1000),
|
||||
scrollbox,
|
||||
|
@ -63,30 +67,30 @@ impl Example for App {
|
|||
None,
|
||||
ScrollSensitivity::ScriptAndInputEvents,
|
||||
);
|
||||
builder.push_clip_id(clip_id);
|
||||
|
||||
// now put some content into it.
|
||||
// start with a white background
|
||||
let mut info = LayoutPrimitiveInfo::new((0, 0).to(1000, 1000));
|
||||
info.tag = Some((0, 1));
|
||||
builder.push_rect(&info, ColorF::new(1.0, 1.0, 1.0, 1.0));
|
||||
builder.push_rect(&info, &space_and_clip1, ColorF::new(1.0, 1.0, 1.0, 1.0));
|
||||
|
||||
// let's make a 50x50 blue square as a visual reference
|
||||
let mut info = LayoutPrimitiveInfo::new((0, 0).to(50, 50));
|
||||
info.tag = Some((0, 2));
|
||||
builder.push_rect(&info, ColorF::new(0.0, 0.0, 1.0, 1.0));
|
||||
builder.push_rect(&info, &space_and_clip1, ColorF::new(0.0, 0.0, 1.0, 1.0));
|
||||
|
||||
// and a 50x50 green square next to it with an offset clip
|
||||
// to see what that looks like
|
||||
let mut info =
|
||||
LayoutPrimitiveInfo::with_clip_rect((50, 0).to(100, 50), (60, 10).to(110, 60));
|
||||
info.tag = Some((0, 3));
|
||||
builder.push_rect(&info, ColorF::new(0.0, 1.0, 0.0, 1.0));
|
||||
builder.push_rect(&info, &space_and_clip1, ColorF::new(0.0, 1.0, 0.0, 1.0));
|
||||
|
||||
// Below the above rectangles, set up a nested scrollbox. It's still in
|
||||
// the same stacking context, so note that the rects passed in need to
|
||||
// be relative to the stacking context.
|
||||
let nested_clip_id = builder.define_scroll_frame(
|
||||
let space_and_clip2 = builder.define_scroll_frame(
|
||||
&space_and_clip1,
|
||||
None,
|
||||
(0, 100).to(300, 1000),
|
||||
(0, 100).to(200, 300),
|
||||
|
@ -94,25 +98,25 @@ impl Example for App {
|
|||
None,
|
||||
ScrollSensitivity::ScriptAndInputEvents,
|
||||
);
|
||||
builder.push_clip_id(nested_clip_id);
|
||||
|
||||
// give it a giant gray background just to distinguish it and to easily
|
||||
// visually identify the nested scrollbox
|
||||
let mut info = LayoutPrimitiveInfo::new((-1000, -1000).to(5000, 5000));
|
||||
info.tag = Some((0, 4));
|
||||
builder.push_rect(&info, ColorF::new(0.5, 0.5, 0.5, 1.0));
|
||||
builder.push_rect(&info, &space_and_clip2, ColorF::new(0.5, 0.5, 0.5, 1.0));
|
||||
|
||||
// add a teal square to visualize the scrolling/clipping behaviour
|
||||
// as you scroll the nested scrollbox
|
||||
let mut info = LayoutPrimitiveInfo::new((0, 200).to(50, 250));
|
||||
info.tag = Some((0, 5));
|
||||
builder.push_rect(&info, ColorF::new(0.0, 1.0, 1.0, 1.0));
|
||||
builder.push_rect(&info, &space_and_clip2, ColorF::new(0.0, 1.0, 1.0, 1.0));
|
||||
|
||||
// Add a sticky frame. It will "stick" twice while scrolling, once
|
||||
// at a margin of 10px from the bottom, for 40 pixels of scrolling,
|
||||
// and once at a margin of 10px from the top, for 60 pixels of
|
||||
// scrolling.
|
||||
let sticky_id = builder.define_sticky_frame(
|
||||
space_and_clip2.spatial_id,
|
||||
(50, 350).by(50, 50),
|
||||
SideOffsets2D::new(Some(10.0), None, Some(10.0), None),
|
||||
StickyOffsetBounds::new(-40.0, 60.0),
|
||||
|
@ -120,21 +124,23 @@ impl Example for App {
|
|||
LayoutVector2D::new(0.0, 0.0)
|
||||
);
|
||||
|
||||
builder.push_clip_id(sticky_id);
|
||||
let mut info = LayoutPrimitiveInfo::new((50, 350).by(50, 50));
|
||||
info.tag = Some((0, 6));
|
||||
builder.push_rect(&info, ColorF::new(0.5, 0.5, 1.0, 1.0));
|
||||
builder.pop_clip_id(); // sticky_id
|
||||
builder.push_rect(
|
||||
&info,
|
||||
&SpaceAndClipInfo {
|
||||
spatial_id: sticky_id,
|
||||
clip_id: space_and_clip2.clip_id,
|
||||
},
|
||||
ColorF::new(0.5, 0.5, 1.0, 1.0),
|
||||
);
|
||||
|
||||
// just for good measure add another teal square further down and to
|
||||
// the right, which can be scrolled into view by the user
|
||||
let mut info = LayoutPrimitiveInfo::new((250, 350).to(300, 400));
|
||||
info.tag = Some((0, 7));
|
||||
builder.push_rect(&info, ColorF::new(0.0, 1.0, 1.0, 1.0));
|
||||
builder.push_rect(&info, &space_and_clip2, ColorF::new(0.0, 1.0, 1.0, 1.0));
|
||||
|
||||
builder.pop_clip_id(); // nested_clip_id
|
||||
|
||||
builder.pop_clip_id(); // clip_id
|
||||
builder.pop_stacking_context();
|
||||
}
|
||||
|
||||
|
|
|
@ -91,13 +91,16 @@ impl Example for App {
|
|||
builder: &mut DisplayListBuilder,
|
||||
txn: &mut Transaction,
|
||||
_framebuffer_size: DeviceIntSize,
|
||||
_pipeline_id: PipelineId,
|
||||
pipeline_id: PipelineId,
|
||||
_document_id: DocumentId,
|
||||
) {
|
||||
let bounds = (0, 0).to(512, 512);
|
||||
let info = LayoutPrimitiveInfo::new(bounds);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
|
||||
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
|
@ -146,6 +149,7 @@ impl Example for App {
|
|||
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
image_size,
|
||||
LayoutSize::zero(),
|
||||
ImageRendering::Auto,
|
||||
|
@ -163,6 +167,7 @@ impl Example for App {
|
|||
);
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
image_size,
|
||||
LayoutSize::zero(),
|
||||
ImageRendering::Auto,
|
||||
|
@ -180,6 +185,7 @@ impl Example for App {
|
|||
);
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
image_size,
|
||||
LayoutSize::zero(),
|
||||
ImageRendering::Auto,
|
||||
|
|
|
@ -88,13 +88,16 @@ impl Example for App {
|
|||
builder: &mut DisplayListBuilder,
|
||||
txn: &mut Transaction,
|
||||
_framebuffer_size: DeviceIntSize,
|
||||
_pipeline_id: PipelineId,
|
||||
pipeline_id: PipelineId,
|
||||
_document_id: DocumentId,
|
||||
) {
|
||||
let bounds = LayoutRect::new(LayoutPoint::zero(), builder.content_size());
|
||||
let info = LayoutPrimitiveInfo::new(bounds);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
|
||||
|
||||
builder.push_stacking_context(
|
||||
&info,
|
||||
space_and_clip.spatial_id,
|
||||
None,
|
||||
TransformStyle::Flat,
|
||||
MixBlendMode::Normal,
|
||||
|
@ -161,6 +164,7 @@ impl Example for App {
|
|||
);
|
||||
builder.push_yuv_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
YuvData::NV12(yuv_chanel1, yuv_chanel2),
|
||||
ColorDepth::Color8,
|
||||
YuvColorSpace::Rec601,
|
||||
|
@ -173,6 +177,7 @@ impl Example for App {
|
|||
);
|
||||
builder.push_yuv_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
YuvData::PlanarYCbCr(yuv_chanel1, yuv_chanel2_1, yuv_chanel3),
|
||||
ColorDepth::Color8,
|
||||
YuvColorSpace::Rec601,
|
||||
|
|
|
@ -108,7 +108,7 @@ performance impacts on WebRender.
|
|||
# Clipping and Positioning in the Display List
|
||||
|
||||
Each non-structural WebRender display list item has
|
||||
* A `ClipId` of a `SpatialNode` or `ClipNode` for positioning
|
||||
* A `SpatialId` of a `SpatialNode` for positioning
|
||||
* A `ClipId` of a `ClipNode` or a `ClipChain` for clipping
|
||||
* An item-specific rectangular clip rectangle
|
||||
|
||||
|
@ -120,28 +120,13 @@ independent of how the node is positioned and items can be clipped by any
|
|||
the item-specific clipping rectangle is applied directly to the item and should
|
||||
never result in the creation of a clip mask itself.
|
||||
|
||||
Perhaps the most inconvenient holdover from the previous single-tree
|
||||
hierarchical design is that `SpatialNodes`, `ClipNodes`, and `ClipChains` all
|
||||
share a single `ClipId` id type. This means that the client must be a bit
|
||||
careful when using the API. For instance, when specifying the parent of
|
||||
`ClipNode` one can use the `ClipId` or another `ClipNode` or a `SpatialNode`,
|
||||
but not one for a `ClipChain`.
|
||||
|
||||
WebRender's internal representation of clipping and positioning is not a perfect
|
||||
match to the display list representation of these concepts. This is due, again,
|
||||
to the evolutionary nature of the design. The general trend is that the display
|
||||
list gradually moves toward the internal representation. The most important of
|
||||
these incongruities is that while `ClipNodes`, sticky frames, and scroll frames
|
||||
are defined and simply return a `ClipId`, reference frames return a `ClipId` and
|
||||
also are pushed and popped like stacking contexts.
|
||||
|
||||
## Converting `ClipId` to global `ClipScrollTree` indices
|
||||
## Converting user-exposed `ClipId`/`SpatialId` to internal indices
|
||||
|
||||
WebRender must access `ClipNodes` and `SpatialNodes` quite a bit when building
|
||||
scenes and frames, so it tries to convert `ClipIds`, which are already
|
||||
scenes and frames, so it tries to convert `ClipId`/`SpatialId`, which are already
|
||||
per-pipeline indices, to global scene-wide indices. Internally this is a
|
||||
conversion from `ClipId` into `SpatialNodeIndex` or
|
||||
`ClipChainIndex`. In order to make this conversion cheaper, the
|
||||
conversion from `ClipId` into `ClipNodeIndex` or `ClipChainIndex`, and from
|
||||
`SpatialId` into `SpatialNodeIndex`. In order to make this conversion cheaper, the
|
||||
`DisplayListFlattner` assigns offsets for each pipeline and node type in the
|
||||
scene-wide `ClipScrollTree`.
|
||||
|
||||
|
@ -160,8 +145,7 @@ structure copies information necessary for hit testing from the
|
|||
new `ClipScrollTree` is under construction.
|
||||
|
||||
# Ideas for the Future
|
||||
1. Expose the difference between ids for `SpatialNodes`, `ClipNodes`, and
|
||||
`ClipChains` in the API.
|
||||
1. Expose the difference between `ClipId` and `ClipChainId` in the API.
|
||||
2. Prevent having to duplicate the `ClipScrollTree` for hit testing.
|
||||
3. Avoid having to create placeholder nodes in the `ClipScrollTree` while
|
||||
processing iframes.
|
||||
|
|
|
@ -204,6 +204,7 @@ pub struct ClipChainId(pub u32);
|
|||
// node, a bounds error will occur.
|
||||
impl ClipChainId {
|
||||
pub const NONE: Self = ClipChainId(u32::MAX);
|
||||
pub const INVALID: Self = ClipChainId(0xDEADBEEF);
|
||||
}
|
||||
|
||||
// A clip chain node is an id for a range of clip sources,
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{ExternalScrollId, LayoutPoint, LayoutRect, LayoutVector2D};
|
||||
use api::{PipelineId, ScrollClamping, ScrollNodeState, ScrollLocation};
|
||||
use api::{TransformStyle, LayoutSize, LayoutTransform, PropertyBinding, ScrollSensitivity, WorldPoint};
|
||||
use api::{PipelineId, ScrollClamping, ScrollNodeState, ScrollLocation, ScrollSensitivity};
|
||||
use api::{LayoutSize, LayoutTransform, PropertyBinding, TransformStyle, WorldPoint};
|
||||
use gpu_types::TransformPalette;
|
||||
use internal_types::{FastHashMap, FastHashSet};
|
||||
use print_tree::{PrintTree, PrintTreePrinter};
|
||||
|
@ -46,6 +46,7 @@ impl CoordinateSystem {
|
|||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct SpatialNodeIndex(pub u32);
|
||||
|
||||
//Note: these have to match ROOT_REFERENCE_FRAME_SPATIAL_ID and ROOT_SCROLL_NODE_SPATIAL_ID
|
||||
pub const ROOT_SPATIAL_NODE_INDEX: SpatialNodeIndex = SpatialNodeIndex(0);
|
||||
const TOPMOST_SCROLL_NODE_INDEX: SpatialNodeIndex = SpatialNodeIndex(1);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* 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/. */
|
||||
|
||||
use api::{AlphaType, BorderDetails, BorderDisplayItem, BuiltDisplayListIter, ClipAndScrollInfo};
|
||||
use api::{AlphaType, BorderDetails, BorderDisplayItem, BuiltDisplayListIter};
|
||||
use api::{ClipId, ColorF, ComplexClipRegion, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
|
||||
use api::{DisplayItemRef, ExtendMode, ExternalScrollId, AuHelpers};
|
||||
use api::{FilterOp, FontInstanceKey, GlyphInstance, GlyphOptions, RasterSpace, GradientStop};
|
||||
|
@ -10,7 +10,7 @@ use api::{IframeDisplayItem, ImageKey, ImageRendering, ItemRange, LayoutPoint, C
|
|||
use api::{LayoutPrimitiveInfo, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D};
|
||||
use api::{LineOrientation, LineStyle, NinePatchBorderSource, PipelineId};
|
||||
use api::{PropertyBinding, ReferenceFrame, ScrollFrameDisplayItem, ScrollSensitivity};
|
||||
use api::{Shadow, SpecificDisplayItem, StackingContext, StickyFrameDisplayItem, TexelRect};
|
||||
use api::{Shadow, SpaceAndClipInfo, SpatialId, SpecificDisplayItem, StackingContext, StickyFrameDisplayItem, TexelRect};
|
||||
use api::{ClipMode, TransformStyle, YuvColorSpace, YuvData};
|
||||
use app_units::Au;
|
||||
use clip::{ClipChainId, ClipRegion, ClipItemKey, ClipStore};
|
||||
|
@ -49,7 +49,7 @@ struct ClipNode {
|
|||
}
|
||||
|
||||
impl ClipNode {
|
||||
fn new(id: ClipChainId, count: usize) -> ClipNode {
|
||||
fn new(id: ClipChainId, count: usize) -> Self {
|
||||
ClipNode {
|
||||
id,
|
||||
count,
|
||||
|
@ -57,16 +57,16 @@ impl ClipNode {
|
|||
}
|
||||
}
|
||||
|
||||
/// A data structure that keeps track of mapping between API ClipIds and the indices used
|
||||
/// internally in the ClipScrollTree to avoid having to do HashMap lookups. ClipIdToIndexMapper is
|
||||
/// responsible for mapping both ClipId to ClipChainIndex and ClipId to SpatialNodeIndex.
|
||||
/// A data structure that keeps track of mapping between API Ids for clips/spatials and the indices
|
||||
/// used internally in the ClipScrollTree to avoid having to do HashMap lookups. NodeIdToIndexMapper
|
||||
/// is responsible for mapping both ClipId to ClipChainIndex and SpatialId to SpatialNodeIndex.
|
||||
#[derive(Default)]
|
||||
pub struct ClipIdToIndexMapper {
|
||||
pub struct NodeIdToIndexMapper {
|
||||
clip_node_map: FastHashMap<ClipId, ClipNode>,
|
||||
spatial_node_map: FastHashMap<ClipId, SpatialNodeIndex>,
|
||||
spatial_node_map: FastHashMap<SpatialId, SpatialNodeIndex>,
|
||||
}
|
||||
|
||||
impl ClipIdToIndexMapper {
|
||||
impl NodeIdToIndexMapper {
|
||||
pub fn add_clip_chain(
|
||||
&mut self,
|
||||
id: ClipId,
|
||||
|
@ -77,16 +77,7 @@ impl ClipIdToIndexMapper {
|
|||
debug_assert!(_old_value.is_none());
|
||||
}
|
||||
|
||||
pub fn map_to_parent_clip_chain(
|
||||
&mut self,
|
||||
id: ClipId,
|
||||
parent_id: &ClipId,
|
||||
) {
|
||||
let parent_node = self.clip_node_map[parent_id];
|
||||
self.add_clip_chain(id, parent_node.id, parent_node.count);
|
||||
}
|
||||
|
||||
pub fn map_spatial_node(&mut self, id: ClipId, index: SpatialNodeIndex) {
|
||||
pub fn map_spatial_node(&mut self, id: SpatialId, index: SpatialNodeIndex) {
|
||||
let _old_value = self.spatial_node_map.insert(id, index);
|
||||
debug_assert!(_old_value.is_none());
|
||||
}
|
||||
|
@ -95,18 +86,12 @@ impl ClipIdToIndexMapper {
|
|||
self.clip_node_map[id]
|
||||
}
|
||||
|
||||
pub fn get_clip_chain_id(&self, id: &ClipId) -> ClipChainId {
|
||||
self.clip_node_map[id].id
|
||||
pub fn get_clip_chain_id(&self, id: ClipId) -> ClipChainId {
|
||||
self.clip_node_map[&id].id
|
||||
}
|
||||
|
||||
pub fn get_spatial_node_index(&self, id: ClipId) -> SpatialNodeIndex {
|
||||
match id {
|
||||
ClipId::Clip(..) |
|
||||
ClipId::Spatial(..) => {
|
||||
self.spatial_node_map[&id]
|
||||
}
|
||||
ClipId::ClipChain(_) => panic!("Tried to use ClipChain as scroll node."),
|
||||
}
|
||||
pub fn get_spatial_node_index(&self, id: SpatialId) -> SpatialNodeIndex {
|
||||
self.spatial_node_map[&id]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,9 +112,9 @@ pub struct DisplayListFlattener<'a> {
|
|||
/// output textures.
|
||||
output_pipelines: &'a FastHashSet<PipelineId>,
|
||||
|
||||
/// The data structure that converting between ClipId and the various index
|
||||
/// types that the ClipScrollTree uses.
|
||||
id_to_index_mapper: ClipIdToIndexMapper,
|
||||
/// The data structure that converting between ClipId/SpatialId and the various
|
||||
/// index types that the ClipScrollTree uses.
|
||||
id_to_index_mapper: NodeIdToIndexMapper,
|
||||
|
||||
/// A stack of stacking context properties.
|
||||
sc_stack: Vec<FlattenedStackingContext>,
|
||||
|
@ -188,7 +173,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
font_instances,
|
||||
config: *frame_builder_config,
|
||||
output_pipelines,
|
||||
id_to_index_mapper: ClipIdToIndexMapper::default(),
|
||||
id_to_index_mapper: NodeIdToIndexMapper::default(),
|
||||
hit_testing_runs: Vec::new(),
|
||||
pending_shadow_items: VecDeque::new(),
|
||||
sc_stack: Vec::new(),
|
||||
|
@ -453,11 +438,6 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
frame_size: &LayoutSize,
|
||||
) {
|
||||
let pipeline_id = pipeline.pipeline_id;
|
||||
let reference_frame_info = self.simple_scroll_and_clip_chain(
|
||||
&ClipId::root_reference_frame(pipeline_id),
|
||||
);
|
||||
|
||||
let root_scroll_node = ClipId::root_scroll_node(pipeline_id);
|
||||
|
||||
self.push_stacking_context(
|
||||
pipeline_id,
|
||||
|
@ -465,8 +445,8 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
TransformStyle::Flat,
|
||||
true,
|
||||
true,
|
||||
root_scroll_node,
|
||||
None,
|
||||
ROOT_SPATIAL_NODE_INDEX,
|
||||
ClipChainId::NONE,
|
||||
RasterSpace::Screen,
|
||||
);
|
||||
|
||||
|
@ -477,6 +457,10 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
if self.scene.root_pipeline_id != Some(pipeline_id) {
|
||||
if let Some(pipeline) = self.scene.pipelines.get(&pipeline_id) {
|
||||
if let Some(bg_color) = pipeline.background_color {
|
||||
let reference_frame_info = ScrollNodeAndClipChain::new(
|
||||
self.id_to_index_mapper.get_spatial_node_index(SpatialId::root_reference_frame(pipeline_id)),
|
||||
ClipChainId::NONE,
|
||||
);
|
||||
let root_bounds = LayoutRect::new(LayoutPoint::zero(), *frame_size);
|
||||
let info = LayoutPrimitiveInfo::new(root_bounds);
|
||||
self.add_solid_rectangle(
|
||||
|
@ -488,7 +472,11 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
self.flatten_items(&mut pipeline.display_list.iter(), pipeline_id, LayoutVector2D::zero());
|
||||
self.flatten_items(
|
||||
&mut pipeline.display_list.iter(),
|
||||
pipeline_id,
|
||||
LayoutVector2D::zero(),
|
||||
);
|
||||
|
||||
self.pop_stacking_context();
|
||||
}
|
||||
|
@ -506,12 +494,10 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
None => break,
|
||||
};
|
||||
|
||||
if SpecificDisplayItem::PopReferenceFrame == *item.item() {
|
||||
return;
|
||||
}
|
||||
|
||||
if SpecificDisplayItem::PopStackingContext == *item.item() {
|
||||
return;
|
||||
match item.item() {
|
||||
SpecificDisplayItem::PopReferenceFrame |
|
||||
SpecificDisplayItem::PopStackingContext => return,
|
||||
_ => (),
|
||||
}
|
||||
|
||||
self.flatten_item(
|
||||
|
@ -533,8 +519,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
&mut self,
|
||||
item: &DisplayItemRef,
|
||||
info: &StickyFrameDisplayItem,
|
||||
clip_and_scroll: &ScrollNodeAndClipChain,
|
||||
parent_id: &ClipId,
|
||||
parent_node_index: SpatialNodeIndex,
|
||||
reference_frame_relative_offset: &LayoutVector2D,
|
||||
) {
|
||||
let frame_rect = item.rect().translate(reference_frame_relative_offset);
|
||||
|
@ -547,20 +532,19 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
);
|
||||
|
||||
let index = self.clip_scroll_tree.add_sticky_frame(
|
||||
clip_and_scroll.spatial_node_index, /* parent id */
|
||||
parent_node_index,
|
||||
sticky_frame_info,
|
||||
info.id.pipeline_id(),
|
||||
);
|
||||
self.id_to_index_mapper.map_spatial_node(info.id, index);
|
||||
self.id_to_index_mapper.map_to_parent_clip_chain(info.id, parent_id);
|
||||
}
|
||||
|
||||
fn flatten_scroll_frame(
|
||||
&mut self,
|
||||
item: &DisplayItemRef,
|
||||
info: &ScrollFrameDisplayItem,
|
||||
parent_node_index: SpatialNodeIndex,
|
||||
pipeline_id: PipelineId,
|
||||
clip_and_scroll_ids: &ClipAndScrollInfo,
|
||||
reference_frame_relative_offset: &LayoutVector2D,
|
||||
) {
|
||||
let complex_clips = self.get_complex_clips(pipeline_id, item.complex_clip().0);
|
||||
|
@ -574,20 +558,18 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
// This is useful when calculating scroll extents for the
|
||||
// SpatialNode::scroll(..) API as well as for properly setting sticky
|
||||
// positioning offsets.
|
||||
let frame_rect = item.clip_rect().translate(reference_frame_relative_offset);
|
||||
let content_rect = item.rect().translate(reference_frame_relative_offset);
|
||||
let frame_rect = clip_region.main.translate(reference_frame_relative_offset);
|
||||
let content_size = item.rect().size;
|
||||
|
||||
debug_assert!(info.clip_id != info.scroll_frame_id);
|
||||
|
||||
self.add_clip_node(info.clip_id, clip_and_scroll_ids, clip_region);
|
||||
self.add_clip_node(info.clip_id, item.space_and_clip_info(), clip_region);
|
||||
|
||||
self.add_scroll_frame(
|
||||
info.scroll_frame_id,
|
||||
info.clip_id,
|
||||
parent_node_index,
|
||||
info.external_id,
|
||||
pipeline_id,
|
||||
&frame_rect,
|
||||
&content_rect.size,
|
||||
&content_size,
|
||||
info.scroll_sensitivity,
|
||||
ScrollFrameKind::Explicit,
|
||||
);
|
||||
|
@ -597,33 +579,34 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
&mut self,
|
||||
traversal: &mut BuiltDisplayListIter<'a>,
|
||||
pipeline_id: PipelineId,
|
||||
item: &DisplayItemRef,
|
||||
parent_spatial_node: SpatialNodeIndex,
|
||||
origin: LayoutPoint,
|
||||
reference_frame: &ReferenceFrame,
|
||||
clip_and_scroll_ids: &ClipAndScrollInfo,
|
||||
reference_frame_relative_offset: LayoutVector2D,
|
||||
) {
|
||||
self.push_reference_frame(
|
||||
reference_frame.id,
|
||||
Some(clip_and_scroll_ids.scroll_node_id),
|
||||
clip_and_scroll_ids.clip_node_id,
|
||||
Some(parent_spatial_node),
|
||||
pipeline_id,
|
||||
reference_frame.transform_style,
|
||||
reference_frame.transform,
|
||||
reference_frame.perspective,
|
||||
reference_frame_relative_offset + item.rect().origin.to_vector(),
|
||||
reference_frame_relative_offset + origin.to_vector(),
|
||||
);
|
||||
|
||||
self.flatten_items(traversal, pipeline_id, LayoutVector2D::zero());
|
||||
}
|
||||
|
||||
|
||||
fn flatten_stacking_context(
|
||||
&mut self,
|
||||
traversal: &mut BuiltDisplayListIter<'a>,
|
||||
pipeline_id: PipelineId,
|
||||
item: &DisplayItemRef,
|
||||
stacking_context: &StackingContext,
|
||||
scroll_node_id: ClipId,
|
||||
reference_frame_relative_offset: LayoutVector2D,
|
||||
spatial_node_index: SpatialNodeIndex,
|
||||
origin: LayoutPoint,
|
||||
filters: ItemRange<FilterOp>,
|
||||
reference_frame_relative_offset: &LayoutVector2D,
|
||||
is_backface_visible: bool,
|
||||
) {
|
||||
// Avoid doing unnecessary work for empty stacking contexts.
|
||||
|
@ -636,26 +619,31 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
// TODO(optimization?): self.traversal.display_list()
|
||||
let display_list = self.scene.get_display_list_for_pipeline(pipeline_id);
|
||||
CompositeOps::new(
|
||||
stacking_context.filter_ops_for_compositing(display_list, item.filters()),
|
||||
stacking_context.filter_ops_for_compositing(display_list, filters),
|
||||
stacking_context.mix_blend_mode_for_compositing(),
|
||||
)
|
||||
};
|
||||
|
||||
let clip_chain_id = match stacking_context.clip_id {
|
||||
Some(clip_id) => self.id_to_index_mapper.get_clip_chain_id(clip_id),
|
||||
None => ClipChainId::NONE,
|
||||
};
|
||||
|
||||
self.push_stacking_context(
|
||||
pipeline_id,
|
||||
composition_operations,
|
||||
stacking_context.transform_style,
|
||||
is_backface_visible,
|
||||
false,
|
||||
scroll_node_id,
|
||||
stacking_context.clip_node_id,
|
||||
spatial_node_index,
|
||||
clip_chain_id,
|
||||
stacking_context.raster_space,
|
||||
);
|
||||
|
||||
self.flatten_items(
|
||||
traversal,
|
||||
pipeline_id,
|
||||
reference_frame_relative_offset + item.rect().origin.to_vector(),
|
||||
*reference_frame_relative_offset + origin.to_vector(),
|
||||
);
|
||||
|
||||
self.pop_stacking_context();
|
||||
|
@ -665,7 +653,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
&mut self,
|
||||
item: &DisplayItemRef,
|
||||
info: &IframeDisplayItem,
|
||||
clip_and_scroll_ids: &ClipAndScrollInfo,
|
||||
spatial_node_index: SpatialNodeIndex,
|
||||
reference_frame_relative_offset: &LayoutVector2D,
|
||||
) {
|
||||
let iframe_pipeline_id = info.pipeline_id;
|
||||
|
@ -678,21 +666,20 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
};
|
||||
|
||||
let clip_chain_index = self.add_clip_node(
|
||||
info.clip_id,
|
||||
clip_and_scroll_ids,
|
||||
ClipId::root(iframe_pipeline_id),
|
||||
item.space_and_clip_info(),
|
||||
ClipRegion::create_for_clip_node_with_local_clip(
|
||||
item.clip_rect(),
|
||||
reference_frame_relative_offset
|
||||
reference_frame_relative_offset,
|
||||
),
|
||||
);
|
||||
self.pipeline_clip_chain_stack.push(clip_chain_index);
|
||||
|
||||
let bounds = item.rect();
|
||||
let origin = *reference_frame_relative_offset + bounds.origin.to_vector();
|
||||
self.push_reference_frame(
|
||||
ClipId::root_reference_frame(iframe_pipeline_id),
|
||||
Some(info.clip_id),
|
||||
None,
|
||||
let spatial_node_index = self.push_reference_frame(
|
||||
SpatialId::root_reference_frame(iframe_pipeline_id),
|
||||
Some(spatial_node_index),
|
||||
iframe_pipeline_id,
|
||||
TransformStyle::Flat,
|
||||
None,
|
||||
|
@ -702,8 +689,8 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
|
||||
let iframe_rect = LayoutRect::new(LayoutPoint::zero(), bounds.size);
|
||||
self.add_scroll_frame(
|
||||
ClipId::root_scroll_node(iframe_pipeline_id),
|
||||
ClipId::root_reference_frame(iframe_pipeline_id),
|
||||
SpatialId::root_scroll_node(iframe_pipeline_id),
|
||||
spatial_node_index,
|
||||
Some(ExternalScrollId(0, iframe_pipeline_id)),
|
||||
iframe_pipeline_id,
|
||||
&iframe_rect,
|
||||
|
@ -726,10 +713,17 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
pipeline_id: PipelineId,
|
||||
reference_frame_relative_offset: LayoutVector2D,
|
||||
) -> Option<BuiltDisplayListIter<'a>> {
|
||||
let clip_and_scroll_ids = item.clip_and_scroll();
|
||||
let clip_and_scroll = self.map_clip_and_scroll(&clip_and_scroll_ids);
|
||||
|
||||
let space_and_clip = item.space_and_clip_info();
|
||||
let clip_and_scroll = ScrollNodeAndClipChain::new(
|
||||
self.id_to_index_mapper.get_spatial_node_index(space_and_clip.spatial_id),
|
||||
if space_and_clip.clip_id.is_valid() {
|
||||
self.id_to_index_mapper.get_clip_chain_id(space_and_clip.clip_id)
|
||||
} else {
|
||||
ClipChainId::INVALID
|
||||
},
|
||||
);
|
||||
let prim_info = item.get_layout_primitive_info(&reference_frame_relative_offset);
|
||||
|
||||
match *item.item() {
|
||||
SpecificDisplayItem::Image(ref info) => {
|
||||
self.add_image(
|
||||
|
@ -861,10 +855,11 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
self.flatten_stacking_context(
|
||||
&mut subtraversal,
|
||||
pipeline_id,
|
||||
&item,
|
||||
&info.stacking_context,
|
||||
clip_and_scroll_ids.scroll_node_id,
|
||||
reference_frame_relative_offset,
|
||||
clip_and_scroll.spatial_node_index,
|
||||
item.rect().origin,
|
||||
item.filters(),
|
||||
&reference_frame_relative_offset,
|
||||
prim_info.is_backface_visible,
|
||||
);
|
||||
return Some(subtraversal);
|
||||
|
@ -874,20 +869,19 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
self.flatten_reference_frame(
|
||||
&mut subtraversal,
|
||||
pipeline_id,
|
||||
&item,
|
||||
clip_and_scroll.spatial_node_index,
|
||||
item.rect().origin,
|
||||
&info.reference_frame,
|
||||
&clip_and_scroll_ids,
|
||||
reference_frame_relative_offset,
|
||||
);
|
||||
return Some(subtraversal);
|
||||
|
||||
}
|
||||
SpecificDisplayItem::Iframe(ref info) => {
|
||||
self.flatten_iframe(
|
||||
&item,
|
||||
info,
|
||||
&clip_and_scroll_ids,
|
||||
&reference_frame_relative_offset
|
||||
clip_and_scroll.spatial_node_index,
|
||||
&reference_frame_relative_offset,
|
||||
);
|
||||
}
|
||||
SpecificDisplayItem::Clip(ref info) => {
|
||||
|
@ -898,7 +892,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
info.image_mask,
|
||||
&reference_frame_relative_offset,
|
||||
);
|
||||
self.add_clip_node(info.id, &clip_and_scroll_ids, clip_region);
|
||||
self.add_clip_node(info.id, space_and_clip, clip_region);
|
||||
}
|
||||
SpecificDisplayItem::ClipChain(ref info) => {
|
||||
// For a user defined clip-chain the parent (if specified) must
|
||||
|
@ -907,7 +901,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
// is used to provide a root clip chain for iframes.
|
||||
let mut parent_clip_chain_id = match info.parent {
|
||||
Some(id) => {
|
||||
self.id_to_index_mapper.get_clip_chain_id(&ClipId::ClipChain(id))
|
||||
self.id_to_index_mapper.get_clip_chain_id(ClipId::ClipChain(id))
|
||||
}
|
||||
None => {
|
||||
self.pipeline_clip_chain_stack.last().cloned().unwrap()
|
||||
|
@ -923,11 +917,11 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
let mut clip_chain_id = parent_clip_chain_id;
|
||||
|
||||
// For each specified clip id
|
||||
for item in self.get_clip_chain_items(pipeline_id, item.clip_chain_items()) {
|
||||
for clip_item in self.get_clip_chain_items(pipeline_id, item.clip_chain_items()) {
|
||||
// Map the ClipId to an existing clip chain node.
|
||||
let item_clip_node = self
|
||||
.id_to_index_mapper
|
||||
.get_clip_node(&item);
|
||||
.get_clip_node(&clip_item);
|
||||
|
||||
let mut clip_node_clip_chain_id = item_clip_node.id;
|
||||
|
||||
|
@ -973,25 +967,25 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
self.flatten_scroll_frame(
|
||||
&item,
|
||||
info,
|
||||
clip_and_scroll.spatial_node_index,
|
||||
pipeline_id,
|
||||
&clip_and_scroll_ids,
|
||||
&reference_frame_relative_offset
|
||||
&reference_frame_relative_offset,
|
||||
);
|
||||
}
|
||||
SpecificDisplayItem::StickyFrame(ref info) => {
|
||||
self.flatten_sticky_frame(
|
||||
&item,
|
||||
info,
|
||||
&clip_and_scroll,
|
||||
&clip_and_scroll_ids.scroll_node_id,
|
||||
&reference_frame_relative_offset
|
||||
clip_and_scroll.spatial_node_index,
|
||||
&reference_frame_relative_offset,
|
||||
);
|
||||
}
|
||||
|
||||
// Do nothing; these are dummy items for the display list parser
|
||||
SpecificDisplayItem::SetGradientStops => {}
|
||||
|
||||
SpecificDisplayItem::PopStackingContext | SpecificDisplayItem::PopReferenceFrame => {
|
||||
SpecificDisplayItem::PopReferenceFrame |
|
||||
SpecificDisplayItem::PopStackingContext => {
|
||||
unreachable!("Should have returned in parent method.")
|
||||
}
|
||||
SpecificDisplayItem::PushShadow(shadow) => {
|
||||
|
@ -1030,13 +1024,12 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
.clip_interner
|
||||
.intern(&item, || ());
|
||||
|
||||
clip_chain_id = self.clip_store
|
||||
.add_clip_chain_node(
|
||||
handle,
|
||||
local_pos,
|
||||
spatial_node_index,
|
||||
clip_chain_id,
|
||||
);
|
||||
clip_chain_id = self.clip_store.add_clip_chain_node(
|
||||
handle,
|
||||
local_pos,
|
||||
spatial_node_index,
|
||||
clip_chain_id,
|
||||
);
|
||||
}
|
||||
|
||||
clip_chain_id
|
||||
|
@ -1218,16 +1211,10 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
transform_style: TransformStyle,
|
||||
is_backface_visible: bool,
|
||||
is_pipeline_root: bool,
|
||||
spatial_node: ClipId,
|
||||
clipping_node: Option<ClipId>,
|
||||
spatial_node_index: SpatialNodeIndex,
|
||||
clip_chain_id: ClipChainId,
|
||||
requested_raster_space: RasterSpace,
|
||||
) {
|
||||
let spatial_node_index = self.id_to_index_mapper.get_spatial_node_index(spatial_node);
|
||||
let clip_chain_id = match clipping_node {
|
||||
Some(ref clipping_node) => self.id_to_index_mapper.get_clip_chain_id(clipping_node),
|
||||
None => ClipChainId::NONE,
|
||||
};
|
||||
|
||||
// Check if this stacking context is the root of a pipeline, and the caller
|
||||
// has requested it as an output frame.
|
||||
let frame_output_pipeline_id = if is_pipeline_root && self.output_pipelines.contains(&pipeline_id) {
|
||||
|
@ -1294,7 +1281,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
// has a clip node. In the future, we may decide during
|
||||
// prepare step to skip the intermediate surface if the
|
||||
// clip node doesn't affect the stacking context rect.
|
||||
let should_isolate = clipping_node.is_some();
|
||||
let should_isolate = clip_chain_id != ClipChainId::NONE;
|
||||
|
||||
// Push the SC onto the stack, so we know how to handle things in
|
||||
// pop_stacking_context.
|
||||
|
@ -1586,16 +1573,14 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
|
||||
pub fn push_reference_frame(
|
||||
&mut self,
|
||||
reference_frame_id: ClipId,
|
||||
parent_scroll_id: Option<ClipId>,
|
||||
parent_clip_id: Option<ClipId>,
|
||||
reference_frame_id: SpatialId,
|
||||
parent_index: Option<SpatialNodeIndex>,
|
||||
pipeline_id: PipelineId,
|
||||
transform_style: TransformStyle,
|
||||
source_transform: Option<PropertyBinding<LayoutTransform>>,
|
||||
source_perspective: Option<LayoutTransform>,
|
||||
origin_in_parent_reference_frame: LayoutVector2D,
|
||||
) -> SpatialNodeIndex {
|
||||
let parent_index = parent_scroll_id.map(|id| self.id_to_index_mapper.get_spatial_node_index(id));
|
||||
let index = self.clip_scroll_tree.add_reference_frame(
|
||||
parent_index,
|
||||
transform_style,
|
||||
|
@ -1606,11 +1591,6 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
);
|
||||
self.id_to_index_mapper.map_spatial_node(reference_frame_id, index);
|
||||
|
||||
match parent_clip_id.or(parent_scroll_id) {
|
||||
Some(ref parent_id) =>
|
||||
self.id_to_index_mapper.map_to_parent_clip_chain(reference_frame_id, parent_id),
|
||||
_ => self.id_to_index_mapper.add_clip_chain(reference_frame_id, ClipChainId::NONE, 0),
|
||||
}
|
||||
index
|
||||
}
|
||||
|
||||
|
@ -1625,9 +1605,10 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
register_prim_chase_id(id);
|
||||
}
|
||||
|
||||
self.push_reference_frame(
|
||||
ClipId::root_reference_frame(pipeline_id),
|
||||
None,
|
||||
self.id_to_index_mapper.add_clip_chain(ClipId::root(pipeline_id), ClipChainId::NONE, 0);
|
||||
|
||||
let spatial_node_index = self.push_reference_frame(
|
||||
SpatialId::root_reference_frame(pipeline_id),
|
||||
None,
|
||||
pipeline_id,
|
||||
TransformStyle::Flat,
|
||||
|
@ -1637,8 +1618,8 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
);
|
||||
|
||||
self.add_scroll_frame(
|
||||
ClipId::root_scroll_node(pipeline_id),
|
||||
ClipId::root_reference_frame(pipeline_id),
|
||||
SpatialId::root_scroll_node(pipeline_id),
|
||||
spatial_node_index,
|
||||
Some(ExternalScrollId(0, pipeline_id)),
|
||||
pipeline_id,
|
||||
&LayoutRect::new(LayoutPoint::zero(), *viewport_size),
|
||||
|
@ -1651,7 +1632,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
pub fn add_clip_node<I>(
|
||||
&mut self,
|
||||
new_node_id: ClipId,
|
||||
parent: &ClipAndScrollInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
clip_region: ClipRegion<I>,
|
||||
) -> ClipChainId
|
||||
where
|
||||
|
@ -1661,15 +1642,9 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
// and the positioning node associated with those clip sources.
|
||||
|
||||
// Map from parent ClipId to existing clip-chain.
|
||||
let mut parent_clip_chain_index = self
|
||||
.id_to_index_mapper
|
||||
.get_clip_chain_id(&parent.clip_node_id());
|
||||
let mut parent_clip_chain_index = self.id_to_index_mapper.get_clip_chain_id(space_and_clip.clip_id);
|
||||
// Map the ClipId for the positioning node to a spatial node index.
|
||||
let spatial_node = self.id_to_index_mapper.get_spatial_node_index(parent.scroll_node_id);
|
||||
|
||||
// Add a mapping for this ClipId in case it's referenced as a positioning node.
|
||||
self.id_to_index_mapper
|
||||
.map_spatial_node(new_node_id, spatial_node);
|
||||
let spatial_node = self.id_to_index_mapper.get_spatial_node_index(space_and_clip.spatial_id);
|
||||
|
||||
let mut clip_count = 0;
|
||||
|
||||
|
@ -1740,8 +1715,8 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
|
||||
pub fn add_scroll_frame(
|
||||
&mut self,
|
||||
new_node_id: ClipId,
|
||||
parent_id: ClipId,
|
||||
new_node_id: SpatialId,
|
||||
parent_node_index: SpatialNodeIndex,
|
||||
external_id: Option<ExternalScrollId>,
|
||||
pipeline_id: PipelineId,
|
||||
frame_rect: &LayoutRect,
|
||||
|
@ -1749,7 +1724,6 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
scroll_sensitivity: ScrollSensitivity,
|
||||
frame_kind: ScrollFrameKind,
|
||||
) -> SpatialNodeIndex {
|
||||
let parent_node_index = self.id_to_index_mapper.get_spatial_node_index(parent_id);
|
||||
let node_index = self.clip_scroll_tree.add_scroll_frame(
|
||||
parent_node_index,
|
||||
external_id,
|
||||
|
@ -1760,7 +1734,6 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
frame_kind,
|
||||
);
|
||||
self.id_to_index_mapper.map_spatial_node(new_node_id, node_index);
|
||||
self.id_to_index_mapper.map_to_parent_clip_chain(new_node_id, &parent_id);
|
||||
node_index
|
||||
}
|
||||
|
||||
|
@ -2477,17 +2450,6 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
);
|
||||
}
|
||||
|
||||
pub fn map_clip_and_scroll(&mut self, info: &ClipAndScrollInfo) -> ScrollNodeAndClipChain {
|
||||
ScrollNodeAndClipChain::new(
|
||||
self.id_to_index_mapper.get_spatial_node_index(info.scroll_node_id),
|
||||
self.id_to_index_mapper.get_clip_chain_id(&info.clip_node_id())
|
||||
)
|
||||
}
|
||||
|
||||
pub fn simple_scroll_and_clip_chain(&mut self, id: &ClipId) -> ScrollNodeAndClipChain {
|
||||
self.map_clip_and_scroll(&ClipAndScrollInfo::simple(*id))
|
||||
}
|
||||
|
||||
pub fn add_primitive_instance_to_3d_root(&mut self, instance: PrimitiveInstance) {
|
||||
// find the 3D root and append to the children list
|
||||
for sc in self.sc_stack.iter_mut().rev() {
|
||||
|
|
|
@ -80,6 +80,7 @@ pub struct TileIndex(pub usize);
|
|||
/// size for real world pages.
|
||||
pub const TILE_SIZE_WIDTH: i32 = 1024;
|
||||
pub const TILE_SIZE_HEIGHT: i32 = 256;
|
||||
const FRAMES_BEFORE_CACHING: usize = 2;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GlobalTransformInfo {
|
||||
|
@ -127,8 +128,6 @@ pub struct Tile {
|
|||
world_rect: WorldRect,
|
||||
/// The current local rect of this tile.
|
||||
pub local_rect: LayoutRect,
|
||||
/// The valid rect within this tile.
|
||||
valid_rect: WorldRect,
|
||||
/// The currently visible rect within this tile, updated per frame.
|
||||
/// If None, this tile is not currently visible.
|
||||
visible_rect: Option<WorldRect>,
|
||||
|
@ -141,6 +140,10 @@ pub struct Tile {
|
|||
/// cache handle can be used. Tiles are invalidated during the
|
||||
/// build_dirty_regions method.
|
||||
is_valid: bool,
|
||||
/// If true, the content on this tile is the same as last frame.
|
||||
is_same_content: bool,
|
||||
/// The number of frames this tile has had the same content.
|
||||
same_frames: usize,
|
||||
/// The tile id is stable between display lists and / or frames,
|
||||
/// if the tile is retained. Useful for debugging tile evictions.
|
||||
id: TileId,
|
||||
|
@ -158,11 +161,12 @@ impl Tile {
|
|||
Tile {
|
||||
local_rect: LayoutRect::zero(),
|
||||
world_rect: WorldRect::zero(),
|
||||
valid_rect: WorldRect::zero(),
|
||||
visible_rect: None,
|
||||
handle: TextureCacheHandle::invalid(),
|
||||
descriptor: TileDescriptor::new(),
|
||||
is_same_content: false,
|
||||
is_valid: false,
|
||||
same_frames: 0,
|
||||
transforms: FastHashSet::default(),
|
||||
id,
|
||||
}
|
||||
|
@ -173,6 +177,26 @@ impl Tile {
|
|||
self.transforms.clear();
|
||||
self.descriptor.clear();
|
||||
}
|
||||
|
||||
/// Update state related to whether a tile has the same
|
||||
/// content and is valid to use.
|
||||
fn update_validity(&mut self, tile_bounding_rect: &WorldRect) {
|
||||
// Check if the contents of the primitives, clips, and
|
||||
// other dependencies are the same.
|
||||
self.is_same_content &= self.descriptor.is_same_content();
|
||||
|
||||
// The tile is only valid if:
|
||||
// - The content is the same *and*
|
||||
// - The valid part of the tile is the same wrt to world clips.
|
||||
self.is_valid &= self.is_same_content;
|
||||
self.is_valid &= self.descriptor.is_valid(&tile_bounding_rect);
|
||||
|
||||
// Update count of how many times this tile has had the same content.
|
||||
if !self.is_same_content {
|
||||
self.same_frames = 0;
|
||||
}
|
||||
self.same_frames += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines a key that uniquely identifies a primitive instance.
|
||||
|
@ -180,14 +204,23 @@ impl Tile {
|
|||
pub struct PrimitiveDescriptor {
|
||||
/// Uniquely identifies the content of the primitive template.
|
||||
prim_uid: ItemUid,
|
||||
/// The origin in local space of this primitive.
|
||||
origin: LayoutPoint,
|
||||
/// The origin in world space of this primitive.
|
||||
origin: WorldPoint,
|
||||
/// The first clip in the clip_uids array of clips that affect this tile.
|
||||
first_clip: u16,
|
||||
/// The number of clips that affect this primitive instance.
|
||||
clip_count: u16,
|
||||
}
|
||||
|
||||
/// Defines the region of a primitive that exists on a tile.
|
||||
#[derive(Debug)]
|
||||
pub struct PrimitiveRegion {
|
||||
/// The (prim relative) portion of on this tile.
|
||||
prim_region: WorldRect,
|
||||
/// Location within the tile.
|
||||
tile_offset: WorldPoint,
|
||||
}
|
||||
|
||||
/// Uniquely describes the content of this tile, in a way that can be
|
||||
/// (reasonably) efficiently hashed and compared.
|
||||
#[derive(Debug)]
|
||||
|
@ -214,10 +247,10 @@ pub struct TileDescriptor {
|
|||
opacity_bindings: ComparableVec<OpacityBinding>,
|
||||
|
||||
/// List of the required valid rectangles for each primitive.
|
||||
needed_rects: Vec<WorldRect>,
|
||||
needed_regions: Vec<PrimitiveRegion>,
|
||||
|
||||
/// List of the currently valid rectangles for each primitive.
|
||||
current_rects: Vec<WorldRect>,
|
||||
current_regions: Vec<PrimitiveRegion>,
|
||||
|
||||
/// List of the (quantized) transforms that we care about
|
||||
/// tracking for this tile.
|
||||
|
@ -232,8 +265,8 @@ impl TileDescriptor {
|
|||
clip_vertices: ComparableVec::new(),
|
||||
opacity_bindings: ComparableVec::new(),
|
||||
image_keys: ComparableVec::new(),
|
||||
needed_rects: Vec::new(),
|
||||
current_rects: Vec::new(),
|
||||
needed_regions: Vec::new(),
|
||||
current_regions: Vec::new(),
|
||||
transforms: ComparableVec::new(),
|
||||
}
|
||||
}
|
||||
|
@ -246,12 +279,24 @@ impl TileDescriptor {
|
|||
self.clip_vertices.reset();
|
||||
self.opacity_bindings.reset();
|
||||
self.image_keys.reset();
|
||||
self.needed_rects.clear();
|
||||
self.needed_regions.clear();
|
||||
self.transforms.reset();
|
||||
}
|
||||
|
||||
/// Check if the dependencies of this tile are valid.
|
||||
fn is_valid(&self) -> bool {
|
||||
/// Return true if the content of the tile is the same
|
||||
/// as last frame. This doesn't check validity of the
|
||||
/// tile based on the currently valid regions.
|
||||
fn is_same_content(&self) -> bool {
|
||||
self.image_keys.is_valid() &&
|
||||
self.opacity_bindings.is_valid() &&
|
||||
self.clip_uids.is_valid() &&
|
||||
self.clip_vertices.is_valid() &&
|
||||
self.prims.is_valid() &&
|
||||
self.transforms.is_valid()
|
||||
}
|
||||
|
||||
/// Check if the tile is valid, given that the rest of the content is the same.
|
||||
fn is_valid(&self, tile_bounding_rect: &WorldRect) -> bool {
|
||||
// For a tile to be valid, it needs to ensure that the currently valid
|
||||
// rect of each primitive encloses the required valid rect.
|
||||
// TODO(gw): This is only needed for tiles that are partially rendered
|
||||
|
@ -260,9 +305,29 @@ impl TileDescriptor {
|
|||
// TODO(gw): For partial tiles that *do* need this test, we can probably
|
||||
// make it faster again by caching and checking the relative
|
||||
// transforms of primitives on this tile.
|
||||
let rects_valid = if self.needed_rects.len() == self.current_rects.len() {
|
||||
for (needed, current) in self.needed_rects.iter().zip(self.current_rects.iter()) {
|
||||
if !current.contains_rect(needed) {
|
||||
if self.needed_regions.len() == self.current_regions.len() {
|
||||
for (needed, current) in self.needed_regions.iter().zip(self.current_regions.iter()) {
|
||||
let needed_region = needed
|
||||
.prim_region
|
||||
.translate(&needed.tile_offset.to_vector())
|
||||
.intersection(tile_bounding_rect);
|
||||
|
||||
let needed_rect = match needed_region {
|
||||
Some(rect) => rect,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
let current_region = current
|
||||
.prim_region
|
||||
.translate(¤t.tile_offset.to_vector())
|
||||
.intersection(tile_bounding_rect);
|
||||
|
||||
let current_rect = match current_region {
|
||||
Some(rect) => rect,
|
||||
None => return false,
|
||||
};
|
||||
|
||||
if needed_rect != current_rect {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -270,15 +335,7 @@ impl TileDescriptor {
|
|||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
self.image_keys.is_valid() &&
|
||||
self.opacity_bindings.is_valid() &&
|
||||
self.clip_uids.is_valid() &&
|
||||
self.clip_vertices.is_valid() &&
|
||||
self.prims.is_valid() &&
|
||||
self.transforms.is_valid() &&
|
||||
rects_valid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -612,15 +669,18 @@ impl TileCache {
|
|||
|
||||
// Do tile invalidation for any dependencies that we know now.
|
||||
for tile in &mut self.tiles {
|
||||
// Invalidate the tile if any images have changed
|
||||
// Start frame assuming that the tile has the same content.
|
||||
tile.is_same_content = true;
|
||||
|
||||
// Content has changed if any images have changed
|
||||
for image_key in tile.descriptor.image_keys.items() {
|
||||
if resource_cache.is_image_dirty(*image_key) {
|
||||
tile.is_valid = false;
|
||||
tile.is_same_content = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Invalidate the tile if any opacity bindings changed.
|
||||
// Content has changed if any opacity bindings changed.
|
||||
for binding in tile.descriptor.opacity_bindings.items() {
|
||||
if let OpacityBinding::Binding(id) = binding {
|
||||
let changed = match self.opacity_bindings.get(id) {
|
||||
|
@ -628,7 +688,7 @@ impl TileCache {
|
|||
None => true,
|
||||
};
|
||||
if changed {
|
||||
tile.is_valid = false;
|
||||
tile.is_same_content = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -870,16 +930,6 @@ impl TileCache {
|
|||
let index = (y * self.tile_count.width + x) as usize;
|
||||
let tile = &mut self.tiles[index];
|
||||
|
||||
// TODO(gw): For now, we need to always build the dependencies each
|
||||
// frame, so can't early exit here. In future, we should
|
||||
// support retaining the tile descriptor from when the
|
||||
// tile goes off-screen, which will mean we can then
|
||||
// compare against that next time it becomes visible.
|
||||
let visible_rect = match tile.visible_rect {
|
||||
Some(visible_rect) => visible_rect,
|
||||
None => WorldRect::zero(),
|
||||
};
|
||||
|
||||
// Work out the needed rect for the primitive on this tile.
|
||||
// TODO(gw): We should be able to remove this for any tile that is not
|
||||
// a partially clipped tile, which would be a significant
|
||||
|
@ -889,17 +939,15 @@ impl TileCache {
|
|||
// Ensure that even if it's currently clipped out of this tile,
|
||||
// we still insert a rect of zero size, so that the tile descriptor's
|
||||
// needed rects array matches.
|
||||
let needed_rect = world_clip_rect
|
||||
.intersection(&visible_rect)
|
||||
.map(|rect| {
|
||||
rect.translate(&-tile.world_rect.origin.to_vector())
|
||||
})
|
||||
.unwrap_or(WorldRect::zero());
|
||||
let prim_region = world_clip_rect.translate(&-world_rect.origin.to_vector());
|
||||
|
||||
tile.descriptor.needed_rects.push(needed_rect);
|
||||
tile.descriptor.needed_regions.push(PrimitiveRegion {
|
||||
prim_region,
|
||||
tile_offset: world_rect.origin - tile.world_rect.origin.to_vector(),
|
||||
});
|
||||
|
||||
// Mark if the tile is cacheable at all.
|
||||
tile.is_valid &= is_cacheable;
|
||||
tile.is_same_content &= is_cacheable;
|
||||
|
||||
// Include any image keys this tile depends on.
|
||||
tile.descriptor.image_keys.extend_from_slice(&image_keys);
|
||||
|
@ -910,7 +958,7 @@ impl TileCache {
|
|||
// Update the tile descriptor, used for tile comparison during scene swaps.
|
||||
tile.descriptor.prims.push(PrimitiveDescriptor {
|
||||
prim_uid: prim_instance.uid(),
|
||||
origin: prim_instance.prim_origin,
|
||||
origin: world_rect.origin - tile.world_rect.origin.to_vector(),
|
||||
first_clip: tile.descriptor.clip_uids.len() as u16,
|
||||
clip_count: clip_chain_uids.len() as u16,
|
||||
});
|
||||
|
@ -998,56 +1046,66 @@ impl TileCache {
|
|||
};
|
||||
|
||||
// Check the content of the tile is the same
|
||||
tile.is_valid &= tile.descriptor.is_valid();
|
||||
let tile_bounding_rect = match visible_rect.intersection(&self.world_bounding_rect) {
|
||||
Some(rect) => rect.translate(&-tile.world_rect.origin.to_vector()),
|
||||
None => continue,
|
||||
};
|
||||
|
||||
tile.update_validity(&tile_bounding_rect);
|
||||
|
||||
// If there are no primitives there is no need to draw or cache it.
|
||||
if tile.descriptor.prims.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Decide how to handle this tile when drawing this frame.
|
||||
if tile.is_valid {
|
||||
// If the tile is valid, we will generally want to draw it
|
||||
// on screen. However, if there are no primitives there is
|
||||
// no need to draw it.
|
||||
if !tile.descriptor.prims.is_empty() {
|
||||
self.tiles_to_draw.push(TileIndex(i));
|
||||
}
|
||||
self.tiles_to_draw.push(TileIndex(i));
|
||||
} else {
|
||||
// Add the tile rect to the dirty rect.
|
||||
dirty_world_rect = dirty_world_rect.union(&visible_rect);
|
||||
|
||||
// Ensure that this texture is allocated.
|
||||
resource_cache.texture_cache.update(
|
||||
&mut tile.handle,
|
||||
descriptor,
|
||||
TextureFilter::Linear,
|
||||
None,
|
||||
[0.0; 3],
|
||||
DirtyRect::All,
|
||||
gpu_cache,
|
||||
None,
|
||||
UvRectKind::Rect,
|
||||
Eviction::Eager,
|
||||
);
|
||||
// Only cache tiles that have had the same content for at least two
|
||||
// frames. This skips caching on pages / benchmarks that are changing
|
||||
// every frame, which is wasteful.
|
||||
if tile.same_frames > FRAMES_BEFORE_CACHING {
|
||||
// Ensure that this texture is allocated.
|
||||
resource_cache.texture_cache.update(
|
||||
&mut tile.handle,
|
||||
descriptor,
|
||||
TextureFilter::Linear,
|
||||
None,
|
||||
[0.0; 3],
|
||||
DirtyRect::All,
|
||||
gpu_cache,
|
||||
None,
|
||||
UvRectKind::Rect,
|
||||
Eviction::Eager,
|
||||
);
|
||||
|
||||
let cache_item = resource_cache
|
||||
.get_texture_cache_item(&tile.handle);
|
||||
let cache_item = resource_cache
|
||||
.get_texture_cache_item(&tile.handle);
|
||||
|
||||
let src_origin = (visible_rect.origin * frame_context.device_pixel_scale).round().to_i32();
|
||||
tile.valid_rect = visible_rect.translate(&-tile.world_rect.origin.to_vector());
|
||||
let src_origin = (visible_rect.origin * frame_context.device_pixel_scale).round().to_i32();
|
||||
let valid_rect = visible_rect.translate(&-tile.world_rect.origin.to_vector());
|
||||
|
||||
// Store a blit operation to be done after drawing the
|
||||
// frame in order to update the cached texture tile.
|
||||
let dest_rect = (tile.valid_rect * frame_context.device_pixel_scale).round().to_i32();
|
||||
self.pending_blits.push(TileBlit {
|
||||
target: cache_item,
|
||||
src_offset: src_origin,
|
||||
dest_offset: dest_rect.origin,
|
||||
size: dest_rect.size,
|
||||
});
|
||||
// Store a blit operation to be done after drawing the
|
||||
// frame in order to update the cached texture tile.
|
||||
let dest_rect = (valid_rect * frame_context.device_pixel_scale).round().to_i32();
|
||||
self.pending_blits.push(TileBlit {
|
||||
target: cache_item,
|
||||
src_offset: src_origin,
|
||||
dest_offset: dest_rect.origin,
|
||||
size: dest_rect.size,
|
||||
});
|
||||
|
||||
// We can consider this tile valid now.
|
||||
tile.is_valid = true;
|
||||
tile.descriptor.current_rects = mem::replace(
|
||||
&mut tile.descriptor.needed_rects,
|
||||
Vec::new(),
|
||||
);
|
||||
// We can consider this tile valid now.
|
||||
tile.is_valid = true;
|
||||
tile.descriptor.current_regions = mem::replace(
|
||||
&mut tile.descriptor.needed_regions,
|
||||
Vec::new(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1589,8 +1589,8 @@ impl ToDebugString for SpecificDisplayItem {
|
|||
SpecificDisplayItem::PopAllShadows => String::from("pop_all_shadows"),
|
||||
SpecificDisplayItem::PopReferenceFrame => String::from("pop_reference_frame"),
|
||||
SpecificDisplayItem::PopStackingContext => String::from("pop_stacking_context"),
|
||||
SpecificDisplayItem::PushReferenceFrame(..) => String::from("push_reference_frame"),
|
||||
SpecificDisplayItem::PushShadow(..) => String::from("push_shadow"),
|
||||
SpecificDisplayItem::PushReferenceFrame(..) => String::from("push_reference_frame"),
|
||||
SpecificDisplayItem::PushStackingContext(..) => String::from("push_stacking_context"),
|
||||
SpecificDisplayItem::RadialGradient(..) => String::from("radial_gradient"),
|
||||
SpecificDisplayItem::Rectangle(..) => String::from("rectangle"),
|
||||
|
|
|
@ -20,32 +20,6 @@ pub const MAX_BLUR_RADIUS: f32 = 300.;
|
|||
// a list of values nearby that this item consumes. The traversal
|
||||
// iterator should handle finding these.
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct ClipAndScrollInfo {
|
||||
pub scroll_node_id: ClipId,
|
||||
pub clip_node_id: Option<ClipId>,
|
||||
}
|
||||
|
||||
impl ClipAndScrollInfo {
|
||||
pub fn simple(node_id: ClipId) -> ClipAndScrollInfo {
|
||||
ClipAndScrollInfo {
|
||||
scroll_node_id: node_id,
|
||||
clip_node_id: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(scroll_node_id: ClipId, clip_node_id: ClipId) -> ClipAndScrollInfo {
|
||||
ClipAndScrollInfo {
|
||||
scroll_node_id,
|
||||
clip_node_id: Some(clip_node_id),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clip_node_id(&self) -> ClipId {
|
||||
self.clip_node_id.unwrap_or(self.scroll_node_id)
|
||||
}
|
||||
}
|
||||
|
||||
/// A tag that can be used to identify items during hit testing. If the tag
|
||||
/// is missing then the item doesn't take part in hit testing at all. This
|
||||
/// is composed of two numbers. In Servo, the first is an identifier while the
|
||||
|
@ -60,8 +34,8 @@ pub type ItemTag = (u64, u16);
|
|||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct GenericDisplayItem<T> {
|
||||
pub item: T,
|
||||
pub clip_and_scroll: ClipAndScrollInfo,
|
||||
pub layout: LayoutPrimitiveInfo,
|
||||
pub space_and_clip: SpaceAndClipInfo,
|
||||
}
|
||||
|
||||
pub type DisplayItem = GenericDisplayItem<SpecificDisplayItem>;
|
||||
|
@ -71,8 +45,8 @@ pub type DisplayItem = GenericDisplayItem<SpecificDisplayItem>;
|
|||
#[derive(Serialize)]
|
||||
pub struct SerializedDisplayItem<'a> {
|
||||
pub item: &'a SpecificDisplayItem,
|
||||
pub clip_and_scroll: &'a ClipAndScrollInfo,
|
||||
pub layout: &'a LayoutPrimitiveInfo,
|
||||
pub space_and_clip: &'a SpaceAndClipInfo,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
|
@ -103,6 +77,29 @@ impl LayoutPrimitiveInfo {
|
|||
|
||||
pub type LayoutPrimitiveInfo = PrimitiveInfo<LayoutPixel>;
|
||||
|
||||
/// Per-primitive information about the nodes in the clip tree and
|
||||
/// the spatial tree that the primitive belongs to.
|
||||
///
|
||||
/// Note: this is a separate struct from `PrimitiveInfo` because
|
||||
/// it needs indirectional mapping during the DL flattening phase,
|
||||
/// turning into `ScrollNodeAndClipChain`.
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct SpaceAndClipInfo {
|
||||
pub spatial_id: SpatialId,
|
||||
pub clip_id: ClipId,
|
||||
}
|
||||
|
||||
impl SpaceAndClipInfo {
|
||||
/// Create a new space/clip info associated with the root
|
||||
/// scroll frame.
|
||||
pub fn root_scroll(pipeline_id: PipelineId) -> Self {
|
||||
SpaceAndClipInfo {
|
||||
spatial_id: SpatialId::root_scroll_node(pipeline_id),
|
||||
clip_id: ClipId::root(pipeline_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(u64)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub enum SpecificDisplayItem {
|
||||
|
@ -121,10 +118,10 @@ pub enum SpecificDisplayItem {
|
|||
RadialGradient(RadialGradientDisplayItem),
|
||||
ClipChain(ClipChainItem),
|
||||
Iframe(IframeDisplayItem),
|
||||
PushReferenceFrame(ReferenceFrameDisplayListItem),
|
||||
PopReferenceFrame,
|
||||
PushStackingContext(PushStackingContextDisplayItem),
|
||||
PopStackingContext,
|
||||
PushReferenceFrame(PushReferenceFrameDisplayListItem),
|
||||
PopReferenceFrame,
|
||||
SetGradientStops,
|
||||
PushShadow(Shadow),
|
||||
PopAllShadows,
|
||||
|
@ -154,10 +151,10 @@ pub enum CompletelySpecificDisplayItem {
|
|||
Gradient(GradientDisplayItem),
|
||||
RadialGradient(RadialGradientDisplayItem),
|
||||
Iframe(IframeDisplayItem),
|
||||
PushReferenceFrame(ReferenceFrameDisplayListItem),
|
||||
PopReferenceFrame,
|
||||
PushStackingContext(PushStackingContextDisplayItem, Vec<FilterOp>),
|
||||
PopStackingContext,
|
||||
PushReferenceFrame(PushReferenceFrameDisplayListItem),
|
||||
PopReferenceFrame,
|
||||
SetGradientStops(Vec<GradientStop>),
|
||||
PushShadow(Shadow),
|
||||
PopAllShadows,
|
||||
|
@ -194,7 +191,7 @@ impl StickyOffsetBounds {
|
|||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct StickyFrameDisplayItem {
|
||||
pub id: ClipId,
|
||||
pub id: SpatialId,
|
||||
|
||||
/// The margins that should be maintained between the edge of the parent viewport and this
|
||||
/// sticky frame. A margin of None indicates that the sticky frame should not stick at all
|
||||
|
@ -230,7 +227,7 @@ pub enum ScrollSensitivity {
|
|||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ScrollFrameDisplayItem {
|
||||
pub clip_id: ClipId,
|
||||
pub scroll_frame_id: ClipId,
|
||||
pub scroll_frame_id: SpatialId,
|
||||
pub external_id: Option<ExternalScrollId>,
|
||||
pub image_mask: Option<ImageMask>,
|
||||
pub scroll_sensitivity: ScrollSensitivity,
|
||||
|
@ -517,7 +514,7 @@ pub struct RadialGradientDisplayItem {
|
|||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct PushReferenceFrameDisplayListItem {
|
||||
pub struct ReferenceFrameDisplayListItem {
|
||||
pub reference_frame: ReferenceFrame,
|
||||
}
|
||||
|
||||
|
@ -532,7 +529,7 @@ pub struct ReferenceFrame {
|
|||
pub transform_style: TransformStyle,
|
||||
pub transform: Option<PropertyBinding<LayoutTransform>>,
|
||||
pub perspective: Option<LayoutTransform>,
|
||||
pub id: ClipId,
|
||||
pub id: SpatialId,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
|
@ -544,7 +541,7 @@ pub struct PushStackingContextDisplayItem {
|
|||
pub struct StackingContext {
|
||||
pub transform_style: TransformStyle,
|
||||
pub mix_blend_mode: MixBlendMode,
|
||||
pub clip_node_id: Option<ClipId>,
|
||||
pub clip_id: Option<ClipId>,
|
||||
pub raster_space: RasterSpace,
|
||||
} // IMPLICIT: filters: Vec<FilterOp>
|
||||
|
||||
|
@ -647,7 +644,6 @@ impl FilterOp {
|
|||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct IframeDisplayItem {
|
||||
pub clip_id: ClipId,
|
||||
pub pipeline_id: PipelineId,
|
||||
pub ignore_missing_pipeline: bool,
|
||||
}
|
||||
|
@ -857,48 +853,82 @@ impl ComplexClipRegion {
|
|||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct ClipChainId(pub u64, pub PipelineId);
|
||||
|
||||
/// A reference to a clipping node defining how an item is clipped.
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub enum ClipId {
|
||||
Spatial(usize, PipelineId),
|
||||
Clip(usize, PipelineId),
|
||||
ClipChain(ClipChainId),
|
||||
}
|
||||
|
||||
const ROOT_REFERENCE_FRAME_CLIP_ID: usize = 0;
|
||||
const ROOT_SCROLL_NODE_CLIP_ID: usize = 1;
|
||||
const ROOT_CLIP_ID: usize = 0;
|
||||
|
||||
impl ClipId {
|
||||
pub fn root_scroll_node(pipeline_id: PipelineId) -> ClipId {
|
||||
ClipId::Spatial(ROOT_SCROLL_NODE_CLIP_ID, pipeline_id)
|
||||
/// Return the root clip ID - effectively doing no clipping.
|
||||
pub fn root(pipeline_id: PipelineId) -> Self {
|
||||
ClipId::Clip(ROOT_CLIP_ID, pipeline_id)
|
||||
}
|
||||
|
||||
pub fn root_reference_frame(pipeline_id: PipelineId) -> ClipId {
|
||||
ClipId::Spatial(ROOT_REFERENCE_FRAME_CLIP_ID, pipeline_id)
|
||||
/// Return an invalid clip ID - needed in places where we carry
|
||||
/// one but need to not attempt to use it.
|
||||
pub fn invalid() -> Self {
|
||||
ClipId::Clip(!0, PipelineId::dummy())
|
||||
}
|
||||
|
||||
pub fn pipeline_id(&self) -> PipelineId {
|
||||
match *self {
|
||||
ClipId::Spatial(_, pipeline_id) |
|
||||
ClipId::Clip(_, pipeline_id) |
|
||||
ClipId::ClipChain(ClipChainId(_, pipeline_id)) => pipeline_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_root_scroll_node(&self) -> bool {
|
||||
pub fn is_root(&self) -> bool {
|
||||
match *self {
|
||||
ClipId::Spatial(ROOT_SCROLL_NODE_CLIP_ID, _) => true,
|
||||
_ => false,
|
||||
ClipId::Clip(id, _) => id == ROOT_CLIP_ID,
|
||||
ClipId::ClipChain(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_root_reference_frame(&self) -> bool {
|
||||
pub fn is_valid(&self) -> bool {
|
||||
match *self {
|
||||
ClipId::Spatial(ROOT_REFERENCE_FRAME_CLIP_ID, _) => true,
|
||||
_ => false,
|
||||
ClipId::Clip(id, _) => id != !0,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A reference to a spatial node defining item positioning.
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct SpatialId(pub usize, PipelineId);
|
||||
|
||||
const ROOT_REFERENCE_FRAME_SPATIAL_ID: usize = 0;
|
||||
const ROOT_SCROLL_NODE_SPATIAL_ID: usize = 1;
|
||||
|
||||
impl SpatialId {
|
||||
pub fn new(spatial_node_index: usize, pipeline_id: PipelineId) -> Self {
|
||||
SpatialId(spatial_node_index, pipeline_id)
|
||||
}
|
||||
|
||||
pub fn root_reference_frame(pipeline_id: PipelineId) -> Self {
|
||||
SpatialId(ROOT_REFERENCE_FRAME_SPATIAL_ID, pipeline_id)
|
||||
}
|
||||
|
||||
pub fn root_scroll_node(pipeline_id: PipelineId) -> Self {
|
||||
SpatialId(ROOT_SCROLL_NODE_SPATIAL_ID, pipeline_id)
|
||||
}
|
||||
|
||||
pub fn pipeline_id(&self) -> PipelineId {
|
||||
self.1
|
||||
}
|
||||
|
||||
pub fn is_root_reference_frame(&self) -> bool {
|
||||
self.0 == ROOT_REFERENCE_FRAME_SPATIAL_ID
|
||||
}
|
||||
|
||||
pub fn is_root_scroll_node(&self) -> bool {
|
||||
self.0 == ROOT_SCROLL_NODE_SPATIAL_ID
|
||||
}
|
||||
}
|
||||
|
||||
/// An external identifier that uniquely identifies a scroll frame independent of its ClipId, which
|
||||
/// may change from frame to frame. This should be unique within a pipeline. WebRender makes no
|
||||
/// attempt to ensure uniqueness. The zero value is reserved for use by the root scroll node of
|
||||
|
|
|
@ -15,16 +15,16 @@ use std::ops::Range;
|
|||
use std::{io, mem, ptr, slice};
|
||||
use time::precise_time_ns;
|
||||
use {AlphaType, BorderDetails, BorderDisplayItem, BorderRadius, BoxShadowClipMode, CacheMarkerDisplayItem};
|
||||
use {BoxShadowDisplayItem, ClipAndScrollInfo, ClipChainId, ClipChainItem, ClipDisplayItem, ClipId};
|
||||
use {BoxShadowDisplayItem, ClipChainId, ClipChainItem, ClipDisplayItem, ClipId};
|
||||
use {ColorF, ComplexClipRegion, DisplayItem, ExtendMode, ExternalScrollId, FilterOp};
|
||||
use {FontInstanceKey, GlyphInstance, GlyphOptions, RasterSpace, Gradient, GradientBuilder};
|
||||
use {GradientDisplayItem, GradientStop, IframeDisplayItem, ImageDisplayItem, ImageKey, ImageMask};
|
||||
use {ImageRendering, LayoutPoint, LayoutPrimitiveInfo, LayoutRect, LayoutSideOffsets, LayoutSize};
|
||||
use {LayoutTransform, LayoutVector2D, LineDisplayItem, LineOrientation, LineStyle, MixBlendMode};
|
||||
use {PipelineId, PropertyBinding, PushReferenceFrameDisplayListItem};
|
||||
use {PipelineId, PropertyBinding, ReferenceFrameDisplayListItem};
|
||||
use {PushStackingContextDisplayItem, RadialGradient, RadialGradientDisplayItem};
|
||||
use {RectangleDisplayItem, ReferenceFrame, ScrollFrameDisplayItem, ScrollSensitivity};
|
||||
use {SerializedDisplayItem, Shadow, SpecificDisplayItem};
|
||||
use {SerializedDisplayItem, Shadow, SpaceAndClipInfo, SpatialId, SpecificDisplayItem};
|
||||
use {StackingContext, StickyFrameDisplayItem, StickyOffsetBounds};
|
||||
use {TextDisplayItem, TransformStyle, YuvColorSpace, YuvData, YuvImageDisplayItem, ColorDepth};
|
||||
|
||||
|
@ -32,13 +32,13 @@ use {TextDisplayItem, TransformStyle, YuvColorSpace, YuvData, YuvImageDisplayIte
|
|||
// This needs to be set to (renderer::MAX_VERTEX_TEXTURE_WIDTH - VECS_PER_TEXT_RUN) * 2
|
||||
pub const MAX_TEXT_RUN_LENGTH: usize = 2040;
|
||||
|
||||
// We start at 2, because the root reference is always 0 and the root scroll node is always 1.
|
||||
// See ROOT_REFERENCE_FRAME_SPATIAL_ID and ROOT_SCROLL_NODE_SPATIAL_ID
|
||||
// TODO(mrobinson): It would be a good idea to eliminate the root scroll frame which is only
|
||||
// used by Servo.
|
||||
const FIRST_SPATIAL_NODE_INDEX: usize = 2;
|
||||
|
||||
// There are no default clips, so we start at the 0 index for clips.
|
||||
const FIRST_CLIP_NODE_INDEX: usize = 0;
|
||||
// See ROOT_SCROLL_NODE_SPATIAL_ID
|
||||
const FIRST_CLIP_NODE_INDEX: usize = 1;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
|
@ -213,9 +213,8 @@ impl<'a> BuiltDisplayListIter<'a> {
|
|||
cur_item: DisplayItem {
|
||||
// Dummy data, will be overwritten by `next`
|
||||
item: SpecificDisplayItem::PopStackingContext,
|
||||
clip_and_scroll:
|
||||
ClipAndScrollInfo::simple(ClipId::root_scroll_node(PipelineId::dummy())),
|
||||
layout: LayoutPrimitiveInfo::new(LayoutRect::zero()),
|
||||
space_and_clip: SpaceAndClipInfo::root_scroll(PipelineId::dummy())
|
||||
},
|
||||
cur_stops: ItemRange::default(),
|
||||
cur_glyphs: ItemRange::default(),
|
||||
|
@ -370,8 +369,8 @@ impl<'a, 'b> DisplayItemRef<'a, 'b> {
|
|||
&self.iter.cur_item.layout.clip_rect
|
||||
}
|
||||
|
||||
pub fn clip_and_scroll(&self) -> ClipAndScrollInfo {
|
||||
self.iter.cur_item.clip_and_scroll
|
||||
pub fn space_and_clip_info(&self) -> &SpaceAndClipInfo {
|
||||
&self.iter.cur_item.space_and_clip
|
||||
}
|
||||
|
||||
pub fn item(&self) -> &SpecificDisplayItem {
|
||||
|
@ -490,13 +489,13 @@ impl Serialize for BuiltDisplayList {
|
|||
SpecificDisplayItem::Gradient(v) => Gradient(v),
|
||||
SpecificDisplayItem::RadialGradient(v) => RadialGradient(v),
|
||||
SpecificDisplayItem::Iframe(v) => Iframe(v),
|
||||
SpecificDisplayItem::PushReferenceFrame(v) => PushReferenceFrame(v),
|
||||
SpecificDisplayItem::PopReferenceFrame => PopReferenceFrame,
|
||||
SpecificDisplayItem::PushStackingContext(v) => PushStackingContext(
|
||||
v,
|
||||
item.iter.list.get(item.iter.cur_filters).collect()
|
||||
),
|
||||
SpecificDisplayItem::PopStackingContext => PopStackingContext,
|
||||
SpecificDisplayItem::PushReferenceFrame(v) => PushReferenceFrame(v),
|
||||
SpecificDisplayItem::PopReferenceFrame => PopReferenceFrame,
|
||||
SpecificDisplayItem::SetGradientStops => SetGradientStops(
|
||||
item.iter.list.get(item.iter.cur_stops).collect()
|
||||
),
|
||||
|
@ -505,8 +504,8 @@ impl Serialize for BuiltDisplayList {
|
|||
SpecificDisplayItem::PushCacheMarker(m) => PushCacheMarker(m),
|
||||
SpecificDisplayItem::PopCacheMarker => PopCacheMarker,
|
||||
},
|
||||
clip_and_scroll: display_item.clip_and_scroll,
|
||||
layout: display_item.layout,
|
||||
space_and_clip: display_item.space_and_clip,
|
||||
};
|
||||
seq.serialize_element(&serial_di)?
|
||||
}
|
||||
|
@ -551,7 +550,7 @@ impl<'de> Deserialize<'de> for BuiltDisplayList {
|
|||
total_clip_nodes += 1;
|
||||
DisplayListBuilder::push_iter_impl(&mut temp, complex_clips);
|
||||
SpecificDisplayItem::ScrollFrame(specific_item)
|
||||
},
|
||||
}
|
||||
StickyFrame(specific_item) => {
|
||||
total_spatial_nodes += 1;
|
||||
SpecificDisplayItem::StickyFrame(specific_item)
|
||||
|
@ -574,16 +573,16 @@ impl<'de> Deserialize<'de> for BuiltDisplayList {
|
|||
total_clip_nodes += 1;
|
||||
SpecificDisplayItem::Iframe(specific_item)
|
||||
}
|
||||
PushReferenceFrame(v) => {
|
||||
total_spatial_nodes += 1;
|
||||
SpecificDisplayItem::PushReferenceFrame(v)
|
||||
}
|
||||
PopReferenceFrame => SpecificDisplayItem::PopReferenceFrame,
|
||||
PushStackingContext(specific_item, filters) => {
|
||||
DisplayListBuilder::push_iter_impl(&mut temp, filters);
|
||||
SpecificDisplayItem::PushStackingContext(specific_item)
|
||||
},
|
||||
PopStackingContext => SpecificDisplayItem::PopStackingContext,
|
||||
PushReferenceFrame(specific_item) => {
|
||||
total_spatial_nodes += 1;
|
||||
SpecificDisplayItem::PushReferenceFrame(specific_item)
|
||||
}
|
||||
PopReferenceFrame => SpecificDisplayItem::PopReferenceFrame,
|
||||
SetGradientStops(stops) => {
|
||||
DisplayListBuilder::push_iter_impl(&mut temp, stops);
|
||||
SpecificDisplayItem::SetGradientStops
|
||||
|
@ -593,8 +592,8 @@ impl<'de> Deserialize<'de> for BuiltDisplayList {
|
|||
PushCacheMarker(marker) => SpecificDisplayItem::PushCacheMarker(marker),
|
||||
PopCacheMarker => SpecificDisplayItem::PopCacheMarker,
|
||||
},
|
||||
clip_and_scroll: complete.clip_and_scroll,
|
||||
layout: complete.layout,
|
||||
space_and_clip: complete.space_and_clip,
|
||||
};
|
||||
serialize_fast(&mut data, &item);
|
||||
// the aux data is serialized after the item, hence the temporary
|
||||
|
@ -832,7 +831,6 @@ impl<'a, 'b> Read for UnsafeReader<'a, 'b> {
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct SaveState {
|
||||
dl_len: usize,
|
||||
clip_stack_len: usize,
|
||||
next_clip_index: usize,
|
||||
next_spatial_index: usize,
|
||||
next_clip_chain_id: u64,
|
||||
|
@ -842,7 +840,6 @@ pub struct SaveState {
|
|||
pub struct DisplayListBuilder {
|
||||
pub data: Vec<u8>,
|
||||
pub pipeline_id: PipelineId,
|
||||
clip_stack: Vec<ClipAndScrollInfo>,
|
||||
next_clip_index: usize,
|
||||
next_spatial_index: usize,
|
||||
next_clip_chain_id: u64,
|
||||
|
@ -869,9 +866,6 @@ impl DisplayListBuilder {
|
|||
DisplayListBuilder {
|
||||
data: Vec::with_capacity(capacity),
|
||||
pipeline_id,
|
||||
clip_stack: vec![
|
||||
ClipAndScrollInfo::simple(ClipId::root_scroll_node(pipeline_id)),
|
||||
],
|
||||
next_clip_index: FIRST_CLIP_NODE_INDEX,
|
||||
next_spatial_index: FIRST_SPATIAL_NODE_INDEX,
|
||||
next_clip_chain_id: 0,
|
||||
|
@ -897,7 +891,6 @@ impl DisplayListBuilder {
|
|||
assert!(self.save_state.is_none(), "DisplayListBuilder doesn't support nested saves");
|
||||
|
||||
self.save_state = Some(SaveState {
|
||||
clip_stack_len: self.clip_stack.len(),
|
||||
dl_len: self.data.len(),
|
||||
next_clip_index: self.next_clip_index,
|
||||
next_spatial_index: self.next_spatial_index,
|
||||
|
@ -909,7 +902,6 @@ impl DisplayListBuilder {
|
|||
pub fn restore(&mut self) {
|
||||
let state = self.save_state.take().expect("No save to restore DisplayListBuilder from");
|
||||
|
||||
self.clip_stack.truncate(state.clip_stack_len);
|
||||
self.data.truncate(state.dl_len);
|
||||
self.next_clip_index = state.next_clip_index;
|
||||
self.next_spatial_index = state.next_spatial_index;
|
||||
|
@ -969,36 +961,31 @@ impl DisplayListBuilder {
|
|||
/// NOTE: It is usually preferable to use the specialized methods to push
|
||||
/// display items. Pushing unexpected or invalid items here may
|
||||
/// result in WebRender panicking or behaving in unexpected ways.
|
||||
pub fn push_item(&mut self, item: &SpecificDisplayItem, layout: &LayoutPrimitiveInfo) {
|
||||
serialize_fast(
|
||||
&mut self.data,
|
||||
SerializedDisplayItem {
|
||||
item,
|
||||
clip_and_scroll: self.clip_stack.last().unwrap(),
|
||||
layout,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn push_item_with_clip_scroll_info(
|
||||
#[inline]
|
||||
pub fn push_item(
|
||||
&mut self,
|
||||
item: &SpecificDisplayItem,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
clip_and_scroll: &ClipAndScrollInfo
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
) {
|
||||
serialize_fast(
|
||||
&mut self.data,
|
||||
SerializedDisplayItem {
|
||||
item,
|
||||
clip_and_scroll,
|
||||
layout,
|
||||
space_and_clip,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn push_new_empty_item(&mut self, item: &SpecificDisplayItem) {
|
||||
let layout = &LayoutPrimitiveInfo::new(LayoutRect::zero());
|
||||
self.push_item(item, layout)
|
||||
let pipeline_id = self.pipeline_id;
|
||||
self.push_item(
|
||||
item,
|
||||
&LayoutPrimitiveInfo::new(LayoutRect::zero()),
|
||||
&SpaceAndClipInfo::root_scroll(pipeline_id),
|
||||
)
|
||||
}
|
||||
|
||||
fn push_iter_impl<I>(data: &mut Vec<u8>, iter_source: I)
|
||||
|
@ -1046,18 +1033,28 @@ impl DisplayListBuilder {
|
|||
Self::push_iter_impl(&mut self.data, iter);
|
||||
}
|
||||
|
||||
pub fn push_rect(&mut self, layout: &LayoutPrimitiveInfo, color: ColorF) {
|
||||
pub fn push_rect(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
color: ColorF,
|
||||
) {
|
||||
let item = SpecificDisplayItem::Rectangle(RectangleDisplayItem { color });
|
||||
self.push_item(&item, layout);
|
||||
self.push_item(&item, layout, space_and_clip);
|
||||
}
|
||||
|
||||
pub fn push_clear_rect(&mut self, layout: &LayoutPrimitiveInfo) {
|
||||
self.push_item(&SpecificDisplayItem::ClearRectangle, layout);
|
||||
pub fn push_clear_rect(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
) {
|
||||
self.push_item(&SpecificDisplayItem::ClearRectangle, layout, space_and_clip);
|
||||
}
|
||||
|
||||
pub fn push_line(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
wavy_line_thickness: f32,
|
||||
orientation: LineOrientation,
|
||||
color: &ColorF,
|
||||
|
@ -1070,12 +1067,13 @@ impl DisplayListBuilder {
|
|||
style,
|
||||
});
|
||||
|
||||
self.push_item(&item, layout);
|
||||
self.push_item(&item, layout, space_and_clip);
|
||||
}
|
||||
|
||||
pub fn push_image(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
stretch_size: LayoutSize,
|
||||
tile_spacing: LayoutSize,
|
||||
image_rendering: ImageRendering,
|
||||
|
@ -1092,13 +1090,14 @@ impl DisplayListBuilder {
|
|||
color,
|
||||
});
|
||||
|
||||
self.push_item(&item, layout);
|
||||
self.push_item(&item, layout, space_and_clip);
|
||||
}
|
||||
|
||||
/// Push a yuv image. All planar data in yuv image should use the same buffer type.
|
||||
pub fn push_yuv_image(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
yuv_data: YuvData,
|
||||
color_depth: ColorDepth,
|
||||
color_space: YuvColorSpace,
|
||||
|
@ -1110,12 +1109,13 @@ impl DisplayListBuilder {
|
|||
color_space,
|
||||
image_rendering,
|
||||
});
|
||||
self.push_item(&item, layout);
|
||||
self.push_item(&item, layout, space_and_clip);
|
||||
}
|
||||
|
||||
pub fn push_text(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
glyphs: &[GlyphInstance],
|
||||
font_key: FontInstanceKey,
|
||||
color: ColorF,
|
||||
|
@ -1128,7 +1128,7 @@ impl DisplayListBuilder {
|
|||
});
|
||||
|
||||
for split_glyphs in glyphs.chunks(MAX_TEXT_RUN_LENGTH) {
|
||||
self.push_item(&item, layout);
|
||||
self.push_item(&item, layout, space_and_clip);
|
||||
self.push_iter(split_glyphs);
|
||||
}
|
||||
}
|
||||
|
@ -1166,17 +1166,19 @@ impl DisplayListBuilder {
|
|||
pub fn push_border(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
widths: LayoutSideOffsets,
|
||||
details: BorderDetails,
|
||||
) {
|
||||
let item = SpecificDisplayItem::Border(BorderDisplayItem { details, widths });
|
||||
|
||||
self.push_item(&item, layout);
|
||||
self.push_item(&item, layout, space_and_clip);
|
||||
}
|
||||
|
||||
pub fn push_box_shadow(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
box_bounds: LayoutRect,
|
||||
offset: LayoutVector2D,
|
||||
color: ColorF,
|
||||
|
@ -1195,7 +1197,7 @@ impl DisplayListBuilder {
|
|||
clip_mode,
|
||||
});
|
||||
|
||||
self.push_item(&item, layout);
|
||||
self.push_item(&item, layout, space_and_clip);
|
||||
}
|
||||
|
||||
/// Pushes a linear gradient to be displayed.
|
||||
|
@ -1215,6 +1217,7 @@ impl DisplayListBuilder {
|
|||
pub fn push_gradient(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
gradient: Gradient,
|
||||
tile_size: LayoutSize,
|
||||
tile_spacing: LayoutSize,
|
||||
|
@ -1225,7 +1228,7 @@ impl DisplayListBuilder {
|
|||
tile_spacing,
|
||||
});
|
||||
|
||||
self.push_item(&item, layout);
|
||||
self.push_item(&item, layout, space_and_clip);
|
||||
}
|
||||
|
||||
/// Pushes a radial gradient to be displayed.
|
||||
|
@ -1234,6 +1237,7 @@ impl DisplayListBuilder {
|
|||
pub fn push_radial_gradient(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
gradient: RadialGradient,
|
||||
tile_size: LayoutSize,
|
||||
tile_spacing: LayoutSize,
|
||||
|
@ -1244,18 +1248,20 @@ impl DisplayListBuilder {
|
|||
tile_spacing,
|
||||
});
|
||||
|
||||
self.push_item(&item, layout);
|
||||
self.push_item(&item, layout, space_and_clip);
|
||||
}
|
||||
|
||||
pub fn push_reference_frame(
|
||||
&mut self,
|
||||
rect: &LayoutRect,
|
||||
parent: SpatialId,
|
||||
transform_style: TransformStyle,
|
||||
transform: Option<PropertyBinding<LayoutTransform>>,
|
||||
perspective: Option<LayoutTransform>,
|
||||
) -> ClipId {
|
||||
) -> SpatialId {
|
||||
let id = self.generate_spatial_index();
|
||||
let item = SpecificDisplayItem::PushReferenceFrame(PushReferenceFrameDisplayListItem {
|
||||
|
||||
let item = SpecificDisplayItem::PushReferenceFrame(ReferenceFrameDisplayListItem {
|
||||
reference_frame: ReferenceFrame {
|
||||
transform_style,
|
||||
transform,
|
||||
|
@ -1263,7 +1269,12 @@ impl DisplayListBuilder {
|
|||
id,
|
||||
},
|
||||
});
|
||||
self.push_item(&item, &LayoutPrimitiveInfo::new(*rect));
|
||||
|
||||
let layout = LayoutPrimitiveInfo::new(*rect);
|
||||
self.push_item(&item, &layout, &SpaceAndClipInfo {
|
||||
spatial_id: parent,
|
||||
clip_id: ClipId::invalid(),
|
||||
});
|
||||
id
|
||||
}
|
||||
|
||||
|
@ -1287,7 +1298,8 @@ impl DisplayListBuilder {
|
|||
pub fn push_stacking_context(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
clip_node_id: Option<ClipId>,
|
||||
spatial_id: SpatialId,
|
||||
clip_id: Option<ClipId>,
|
||||
transform_style: TransformStyle,
|
||||
mix_blend_mode: MixBlendMode,
|
||||
filters: &[FilterOp],
|
||||
|
@ -1297,12 +1309,15 @@ impl DisplayListBuilder {
|
|||
stacking_context: StackingContext {
|
||||
transform_style,
|
||||
mix_blend_mode,
|
||||
clip_node_id,
|
||||
clip_id,
|
||||
raster_space,
|
||||
},
|
||||
});
|
||||
|
||||
self.push_item(&item, layout);
|
||||
self.push_item(&item, layout, &SpaceAndClipInfo {
|
||||
spatial_id,
|
||||
clip_id: ClipId::invalid(),
|
||||
});
|
||||
self.push_iter(filters);
|
||||
}
|
||||
|
||||
|
@ -1323,9 +1338,9 @@ impl DisplayListBuilder {
|
|||
ClipId::Clip(self.next_clip_index - 1, self.pipeline_id)
|
||||
}
|
||||
|
||||
fn generate_spatial_index(&mut self) -> ClipId {
|
||||
fn generate_spatial_index(&mut self) -> SpatialId {
|
||||
self.next_spatial_index += 1;
|
||||
ClipId::Spatial(self.next_spatial_index - 1, self.pipeline_id)
|
||||
SpatialId::new(self.next_spatial_index - 1, self.pipeline_id)
|
||||
}
|
||||
|
||||
fn generate_clip_chain_id(&mut self) -> ClipChainId {
|
||||
|
@ -1335,38 +1350,14 @@ impl DisplayListBuilder {
|
|||
|
||||
pub fn define_scroll_frame<I>(
|
||||
&mut self,
|
||||
parent_space_and_clip: &SpaceAndClipInfo,
|
||||
external_id: Option<ExternalScrollId>,
|
||||
content_rect: LayoutRect,
|
||||
clip_rect: LayoutRect,
|
||||
complex_clips: I,
|
||||
image_mask: Option<ImageMask>,
|
||||
scroll_sensitivity: ScrollSensitivity,
|
||||
) -> ClipId
|
||||
where
|
||||
I: IntoIterator<Item = ComplexClipRegion>,
|
||||
I::IntoIter: ExactSizeIterator + Clone,
|
||||
{
|
||||
let parent = self.clip_stack.last().unwrap().scroll_node_id;
|
||||
self.define_scroll_frame_with_parent(
|
||||
parent,
|
||||
external_id,
|
||||
content_rect,
|
||||
clip_rect,
|
||||
complex_clips,
|
||||
image_mask,
|
||||
scroll_sensitivity)
|
||||
}
|
||||
|
||||
pub fn define_scroll_frame_with_parent<I>(
|
||||
&mut self,
|
||||
parent: ClipId,
|
||||
external_id: Option<ExternalScrollId>,
|
||||
content_rect: LayoutRect,
|
||||
clip_rect: LayoutRect,
|
||||
complex_clips: I,
|
||||
image_mask: Option<ImageMask>,
|
||||
scroll_sensitivity: ScrollSensitivity,
|
||||
) -> ClipId
|
||||
) -> SpaceAndClipInfo
|
||||
where
|
||||
I: IntoIterator<Item = ComplexClipRegion>,
|
||||
I::IntoIter: ExactSizeIterator + Clone,
|
||||
|
@ -1381,14 +1372,17 @@ impl DisplayListBuilder {
|
|||
scroll_sensitivity,
|
||||
});
|
||||
|
||||
self.push_item_with_clip_scroll_info(
|
||||
self.push_item(
|
||||
&item,
|
||||
&LayoutPrimitiveInfo::with_clip_rect(content_rect, clip_rect),
|
||||
&ClipAndScrollInfo::simple(parent),
|
||||
parent_space_and_clip,
|
||||
);
|
||||
self.push_iter(complex_clips);
|
||||
|
||||
scroll_frame_id
|
||||
SpaceAndClipInfo {
|
||||
spatial_id: scroll_frame_id,
|
||||
clip_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn define_clip_chain<I>(
|
||||
|
@ -1408,45 +1402,7 @@ impl DisplayListBuilder {
|
|||
|
||||
pub fn define_clip<I>(
|
||||
&mut self,
|
||||
clip_rect: LayoutRect,
|
||||
complex_clips: I,
|
||||
image_mask: Option<ImageMask>,
|
||||
) -> ClipId
|
||||
where
|
||||
I: IntoIterator<Item = ComplexClipRegion>,
|
||||
I::IntoIter: ExactSizeIterator + Clone,
|
||||
{
|
||||
let clip_and_scroll = self.clip_stack.last().unwrap().clone();
|
||||
self.define_clip_impl(
|
||||
clip_and_scroll,
|
||||
clip_rect,
|
||||
complex_clips,
|
||||
image_mask,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn define_clip_with_parent<I>(
|
||||
&mut self,
|
||||
parent: ClipId,
|
||||
clip_rect: LayoutRect,
|
||||
complex_clips: I,
|
||||
image_mask: Option<ImageMask>,
|
||||
) -> ClipId
|
||||
where
|
||||
I: IntoIterator<Item = ComplexClipRegion>,
|
||||
I::IntoIter: ExactSizeIterator + Clone,
|
||||
{
|
||||
self.define_clip_impl(
|
||||
ClipAndScrollInfo::simple(parent),
|
||||
clip_rect,
|
||||
complex_clips,
|
||||
image_mask,
|
||||
)
|
||||
}
|
||||
|
||||
fn define_clip_impl<I>(
|
||||
&mut self,
|
||||
scrollinfo: ClipAndScrollInfo,
|
||||
parent_space_and_clip: &SpaceAndClipInfo,
|
||||
clip_rect: LayoutRect,
|
||||
complex_clips: I,
|
||||
image_mask: Option<ImageMask>,
|
||||
|
@ -1461,21 +1417,24 @@ impl DisplayListBuilder {
|
|||
image_mask,
|
||||
});
|
||||
|
||||
let layout = LayoutPrimitiveInfo::new(clip_rect);
|
||||
|
||||
self.push_item_with_clip_scroll_info(&item, &layout, &scrollinfo);
|
||||
self.push_item(
|
||||
&item,
|
||||
&LayoutPrimitiveInfo::new(clip_rect),
|
||||
parent_space_and_clip,
|
||||
);
|
||||
self.push_iter(complex_clips);
|
||||
id
|
||||
}
|
||||
|
||||
pub fn define_sticky_frame(
|
||||
&mut self,
|
||||
parent_spatial_id: SpatialId,
|
||||
frame_rect: LayoutRect,
|
||||
margins: SideOffsets2D<Option<f32>>,
|
||||
vertical_offset_bounds: StickyOffsetBounds,
|
||||
horizontal_offset_bounds: StickyOffsetBounds,
|
||||
previously_applied_offset: LayoutVector2D,
|
||||
) -> ClipId {
|
||||
) -> SpatialId {
|
||||
let id = self.generate_spatial_index();
|
||||
let item = SpecificDisplayItem::StickyFrame(StickyFrameDisplayItem {
|
||||
id,
|
||||
|
@ -1485,44 +1444,38 @@ impl DisplayListBuilder {
|
|||
previously_applied_offset,
|
||||
});
|
||||
|
||||
let layout = LayoutPrimitiveInfo::new(frame_rect);
|
||||
self.push_item(&item, &layout);
|
||||
self.push_item(
|
||||
&item,
|
||||
&LayoutPrimitiveInfo::new(frame_rect),
|
||||
&SpaceAndClipInfo {
|
||||
spatial_id: parent_spatial_id,
|
||||
clip_id: ClipId::invalid(),
|
||||
},
|
||||
);
|
||||
id
|
||||
}
|
||||
|
||||
pub fn push_clip_id(&mut self, id: ClipId) {
|
||||
self.clip_stack.push(ClipAndScrollInfo::simple(id));
|
||||
}
|
||||
|
||||
pub fn push_clip_and_scroll_info(&mut self, layout: ClipAndScrollInfo) {
|
||||
self.clip_stack.push(layout);
|
||||
}
|
||||
|
||||
pub fn pop_clip_id(&mut self) {
|
||||
self.clip_stack.pop();
|
||||
if let Some(save_state) = self.save_state.as_ref() {
|
||||
assert!(self.clip_stack.len() >= save_state.clip_stack_len,
|
||||
"Cannot pop clips that were pushed before the DisplayListBuilder save.");
|
||||
}
|
||||
assert!(!self.clip_stack.is_empty());
|
||||
}
|
||||
|
||||
pub fn push_iframe(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
pipeline_id: PipelineId,
|
||||
ignore_missing_pipeline: bool
|
||||
) {
|
||||
let item = SpecificDisplayItem::Iframe(IframeDisplayItem {
|
||||
clip_id: self.generate_clip_index(),
|
||||
pipeline_id,
|
||||
ignore_missing_pipeline,
|
||||
});
|
||||
self.push_item(&item, layout);
|
||||
self.push_item(&item, layout, space_and_clip);
|
||||
}
|
||||
|
||||
pub fn push_shadow(&mut self, layout: &LayoutPrimitiveInfo, shadow: Shadow) {
|
||||
self.push_item(&SpecificDisplayItem::PushShadow(shadow), layout);
|
||||
pub fn push_shadow(
|
||||
&mut self,
|
||||
layout: &LayoutPrimitiveInfo,
|
||||
space_and_clip: &SpaceAndClipInfo,
|
||||
shadow: Shadow,
|
||||
) {
|
||||
self.push_item(&SpecificDisplayItem::PushShadow(shadow), layout, space_and_clip);
|
||||
}
|
||||
|
||||
pub fn pop_all_shadows(&mut self) {
|
||||
|
@ -1533,6 +1486,7 @@ impl DisplayListBuilder {
|
|||
assert!(self.save_state.is_none(), "Finalized DisplayListBuilder with a pending save");
|
||||
|
||||
let end_time = precise_time_ns();
|
||||
|
||||
(
|
||||
self.pipeline_id,
|
||||
self.content_size,
|
||||
|
|
|
@ -7,22 +7,22 @@ root:
|
|||
scroll-offset: [0, 50]
|
||||
items:
|
||||
# The rectangles below should stay in place even when the parent scroll area scrolls,
|
||||
# because they are use the root reference frame as their scroll node (fixed position).
|
||||
# because they use the root reference frame as their scroll node (fixed position).
|
||||
# On the other hand, the clip item here will scroll with its parent scroll area. Normally
|
||||
# fixed position items would only be clipped by their reference frame (in this case the
|
||||
# root), but ince these items specify an auxiliary clip, they will be clipped by their
|
||||
# root), but since these items specify an auxiliary clip, they will be clipped by their
|
||||
# sibling clip (42).
|
||||
- type: clip
|
||||
bounds: [10, 60, 50, 50]
|
||||
id: 42
|
||||
- type: stacking-context
|
||||
bounds: [10, 10, 100, 100]
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [0, 0, 100, 50]
|
||||
color: green
|
||||
clip-and-scroll: [root-reference-frame, 42]
|
||||
- type: rect
|
||||
bounds: [0, 50, 100, 50]
|
||||
color: red
|
||||
clip-and-scroll: [root-reference-frame, 42]
|
||||
- type: clip
|
||||
bounds: [10, 60, 50, 50]
|
||||
id: 42
|
||||
- type: stacking-context
|
||||
bounds: [10, 10, 100, 100]
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [0, 0, 100, 50]
|
||||
color: green
|
||||
clip-and-scroll: [root-reference-frame, 42]
|
||||
- type: rect
|
||||
bounds: [0, 50, 100, 50]
|
||||
color: red
|
||||
clip-and-scroll: [root-reference-frame, 42]
|
||||
|
|
|
@ -2,18 +2,14 @@ root:
|
|||
bounds: [0, 0, 1024, 10000]
|
||||
scroll-offset: [0, 100]
|
||||
items:
|
||||
# This stacking context should not scroll out of view because it is fixed position.
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 50, 50]
|
||||
items:
|
||||
# This item should not scroll out of view because it is fixed position.
|
||||
- type: rect
|
||||
bounds: [0, 0, 50, 50]
|
||||
color: green
|
||||
clip-and-scroll: root-reference-frame
|
||||
# Even though there is a fixed position stacking context, it should scroll,
|
||||
# because it is fixed relative to its reference frame. The reference frame
|
||||
# of this stacking context is the stacking context parent because it has
|
||||
# a transformation.
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 50, 50]
|
||||
transform: translate(60, 100)
|
||||
|
@ -22,17 +18,21 @@ root:
|
|||
- type: stacking-context
|
||||
bounds: [0, 0, 50, 50]
|
||||
items:
|
||||
# Even though there is a custom clip-scroll ID, it should scroll,
|
||||
# because it is fixed relative to its reference frame. The reference frame
|
||||
# of this stacking context is the stacking context parent because it has
|
||||
# a transformation.
|
||||
- type: rect
|
||||
bounds: [0, 0, 50, 50]
|
||||
color: green
|
||||
clip-and-scroll: 100
|
||||
# This is similar to the previous case, but ensures that this still works
|
||||
# even with an identity transform.
|
||||
- type: stacking-context
|
||||
bounds: [120, 0, 50, 200]
|
||||
transform: translate(0, 0)
|
||||
id: 101
|
||||
items:
|
||||
# This is similar to the previous case, but ensures that this still works
|
||||
# even with an identity transform.
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 50, 200]
|
||||
items:
|
||||
|
@ -40,12 +40,12 @@ root:
|
|||
bounds: [0, 100, 50, 50]
|
||||
color: green
|
||||
clip-and-scroll: 101
|
||||
# This is similar to the previous case, but for perspective.
|
||||
- type: stacking-context
|
||||
bounds: [180, 0, 50, 200]
|
||||
perspective: 1
|
||||
id: 102
|
||||
items:
|
||||
# This is similar to the previous case, but for perspective.
|
||||
- type: stacking-context
|
||||
bounds: [0, 0, 50, 200]
|
||||
items:
|
||||
|
|
|
@ -6,7 +6,6 @@ root:
|
|||
# ensure that offsets within reference frames are handled
|
||||
# properly when drawing the mask.
|
||||
bounds: [10, 10, 100, 100]
|
||||
scroll-policy: scrollable
|
||||
items:
|
||||
- type: scroll-frame
|
||||
bounds: [0, 0, 100, 100]
|
||||
|
@ -15,15 +14,14 @@ root:
|
|||
rect: [0, 0, 100, 100]
|
||||
repeat: false
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [0, 0, 100, 100]
|
||||
color: green
|
||||
- type: rect
|
||||
bounds: [0, 0, 100, 100]
|
||||
color: green
|
||||
|
||||
# The same test, but this time ensure that scroll offsets don't affect the masking.
|
||||
-
|
||||
type: stacking-context
|
||||
bounds: [100, 0, 100, 100]
|
||||
scroll-policy: scrollable
|
||||
items:
|
||||
- type: scroll-frame
|
||||
bounds: [10, 10, 100, 300]
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
---
|
||||
root:
|
||||
items:
|
||||
-
|
||||
root:
|
||||
items:
|
||||
-
|
||||
bounds: [8, 8, 500, 500]
|
||||
type: "stacking-context"
|
||||
items:
|
||||
-
|
||||
items:
|
||||
-
|
||||
bounds: [0, 0, 200, 200]
|
||||
type: clip
|
||||
id: 2
|
||||
items:
|
||||
-
|
||||
bounds: [0, 0, 200, 200]
|
||||
type: rect
|
||||
color: red
|
||||
-
|
||||
bounds: [0, 0, 200, 200]
|
||||
type: "stacking-context"
|
||||
transform: translate(100, 0)
|
||||
items:
|
||||
-
|
||||
bounds: [-100, 0, 200, 200]
|
||||
clip-rect: [-300, -300, 900, 900]
|
||||
type: rect
|
||||
color: green
|
||||
-
|
||||
bounds: [0, 0, 200, 200]
|
||||
type: rect
|
||||
color: red
|
||||
-
|
||||
bounds: [0, 0, 200, 200]
|
||||
type: "stacking-context"
|
||||
transform: translate(100, 0)
|
||||
items:
|
||||
-
|
||||
bounds: [-100, 0, 200, 200]
|
||||
clip-rect: [-300, -300, 900, 900]
|
||||
type: rect
|
||||
color: green
|
||||
id: [0, 0]
|
||||
pipelines: []
|
||||
|
|
|
@ -49,27 +49,6 @@ def is_linux():
|
|||
return sys.platform.startswith('linux')
|
||||
|
||||
|
||||
def debugger():
|
||||
if "DEBUGGER" in os.environ:
|
||||
return os.environ["DEBUGGER"]
|
||||
return None
|
||||
|
||||
|
||||
def use_gdb():
|
||||
return debugger() in ['gdb', 'cgdb', 'rust-gdb']
|
||||
|
||||
|
||||
def use_rr():
|
||||
return debugger() == 'rr'
|
||||
|
||||
|
||||
def optimized_build():
|
||||
if "OPTIMIZED" in os.environ:
|
||||
opt = os.environ["OPTIMIZED"]
|
||||
return opt not in ["0", "false"]
|
||||
return True
|
||||
|
||||
|
||||
def set_osmesa_env(bin_path):
|
||||
"""Set proper LD_LIBRARY_PATH and DRIVE for software rendering on Linux and OSX"""
|
||||
if is_linux():
|
||||
|
@ -88,34 +67,11 @@ def set_osmesa_env(bin_path):
|
|||
|
||||
extra_flags = os.getenv('CARGOFLAGS', None)
|
||||
extra_flags = extra_flags.split(' ') if extra_flags else []
|
||||
build_cmd = ['cargo', 'build'] + extra_flags + ['--verbose', '--features', 'headless']
|
||||
if optimized_build():
|
||||
build_cmd += ['--release']
|
||||
|
||||
objdir = ''
|
||||
if optimized_build():
|
||||
objdir = '../target/release/'
|
||||
else:
|
||||
objdir = '../target/debug/'
|
||||
|
||||
subprocess.check_call(build_cmd)
|
||||
|
||||
set_osmesa_env(objdir)
|
||||
|
||||
dbg_cmd = []
|
||||
if use_rr():
|
||||
dbg_cmd = ['rr', 'record']
|
||||
elif use_gdb():
|
||||
dbg_cmd = [debugger(), '--args']
|
||||
elif debugger():
|
||||
print("Unknown debugger: " + debugger())
|
||||
sys.exit(1)
|
||||
|
||||
subprocess.check_call(['cargo', 'build'] + extra_flags + ['--release', '--verbose', '--features', 'headless'])
|
||||
set_osmesa_env('../target/release/')
|
||||
# TODO(gw): We have an occasional accuracy issue or bug (could be WR or OSMesa)
|
||||
# where the output of a previous test that uses intermediate targets can
|
||||
# cause 1.0 / 255.0 pixel differences in a subsequent test. For now, we
|
||||
# run tests with no-scissor mode, which ensures a complete target clear
|
||||
# between test runs. But we should investigate this further...
|
||||
cmd = dbg_cmd + [objdir + '/wrench', '--no-scissor', '-h'] + sys.argv[1:]
|
||||
print('Running: `' + ' '.join(cmd) + '`')
|
||||
subprocess.check_call(cmd)
|
||||
subprocess.check_call(['../target/release/wrench', '--no-scissor', '-h'] + sys.argv[1:])
|
||||
|
|
|
@ -109,6 +109,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
// setup some malicious image size parameters
|
||||
builder.push_image(
|
||||
&info,
|
||||
&SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id),
|
||||
size(151., 56.0),
|
||||
size(151.0, 56.0),
|
||||
ImageRendering::Auto,
|
||||
|
@ -170,12 +171,18 @@ impl<'a> RawtestHarness<'a> {
|
|||
|
||||
let image_size = size(1510., 111256.);
|
||||
|
||||
let clip_id = builder.define_clip(rect(40., 41., 200., 201.), vec![], None);
|
||||
let root_space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id);
|
||||
let clip_id = builder.define_clip(
|
||||
&root_space_and_clip,
|
||||
rect(40., 41., 200., 201.),
|
||||
vec![],
|
||||
None,
|
||||
);
|
||||
|
||||
builder.push_clip_id(clip_id);
|
||||
// setup some malicious image size parameters
|
||||
builder.push_image(
|
||||
&info,
|
||||
&SpaceAndClipInfo { clip_id, spatial_id: root_space_and_clip.spatial_id },
|
||||
image_size * 2.,
|
||||
image_size,
|
||||
ImageRendering::Auto,
|
||||
|
@ -191,8 +198,6 @@ impl<'a> RawtestHarness<'a> {
|
|||
}
|
||||
);
|
||||
|
||||
builder.pop_clip_id();
|
||||
|
||||
let mut epoch = Epoch(0);
|
||||
|
||||
self.submit_dl(&mut epoch, layout_size, builder, &txn.resource_updates);
|
||||
|
@ -242,7 +247,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
}
|
||||
|
||||
fn test_insufficient_blob_visible_area(&mut self) {
|
||||
println!("\tinsufficient blob visible area.");
|
||||
println!("\tinsufficient blob visible area...");
|
||||
|
||||
// This test compares two almost identical display lists containing the a blob
|
||||
// image. The only difference is that one of the display lists specifies a visible
|
||||
|
@ -261,6 +266,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
let layout_size = LayoutSize::new(800.0, 800.0);
|
||||
let image_size = size(800.0, 800.0);
|
||||
let info = LayoutPrimitiveInfo::new(rect(0.0, 0.0, 800.0, 800.0));
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id);
|
||||
|
||||
let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size);
|
||||
let mut txn = Transaction::new();
|
||||
|
@ -281,6 +287,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
image_size,
|
||||
image_size,
|
||||
ImageRendering::Auto,
|
||||
|
@ -317,6 +324,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
image_size,
|
||||
image_size,
|
||||
ImageRendering::Auto,
|
||||
|
@ -349,6 +357,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
DeviceIntPoint::new(0, window_size.height - test_size.height),
|
||||
test_size,
|
||||
);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id);
|
||||
|
||||
// This exposes a crash in tile decomposition
|
||||
let mut txn = Transaction::new();
|
||||
|
@ -371,6 +380,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
// setup some malicious image size parameters
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
image_size,
|
||||
image_size,
|
||||
ImageRendering::Auto,
|
||||
|
@ -396,6 +406,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
// setup some malicious image size parameters
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
image_size,
|
||||
image_size,
|
||||
ImageRendering::Auto,
|
||||
|
@ -426,6 +437,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
// setup some malicious image size parameters
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
image_size,
|
||||
image_size,
|
||||
ImageRendering::Auto,
|
||||
|
@ -461,6 +473,8 @@ impl<'a> RawtestHarness<'a> {
|
|||
test_size,
|
||||
);
|
||||
let layout_size = LayoutSize::new(400., 400.);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id);
|
||||
|
||||
let mut txn = Transaction::new();
|
||||
{
|
||||
let api = &self.wrench.api;
|
||||
|
@ -487,6 +501,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
size(200.0, 200.0),
|
||||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
|
@ -510,6 +525,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
let info = LayoutPrimitiveInfo::new(rect(1.0, 60.0, 200.0, 200.0));
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
size(200.0, 200.0),
|
||||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
|
@ -534,10 +550,6 @@ impl<'a> RawtestHarness<'a> {
|
|||
assert!(pixels_first != pixels_second);
|
||||
|
||||
// cleanup
|
||||
txn = Transaction::new();
|
||||
txn.delete_blob_image(blob_img);
|
||||
self.wrench.api.update_resources(txn.resource_updates);
|
||||
|
||||
*self.wrench.callbacks.lock().unwrap() = blob::BlobCallbacks::new();
|
||||
}
|
||||
|
||||
|
@ -553,6 +565,8 @@ impl<'a> RawtestHarness<'a> {
|
|||
test_size,
|
||||
);
|
||||
let layout_size = LayoutSize::new(400., 400.);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id);
|
||||
|
||||
let mut txn = Transaction::new();
|
||||
let (blob_img, blob_img2) = {
|
||||
let api = &self.wrench.api;
|
||||
|
@ -599,6 +613,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
let push_images = |builder: &mut DisplayListBuilder| {
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
size(200.0, 200.0),
|
||||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
|
@ -608,6 +623,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
);
|
||||
builder.push_image(
|
||||
&info2,
|
||||
&space_and_clip,
|
||||
size(200.0, 200.0),
|
||||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
|
@ -666,11 +682,6 @@ impl<'a> RawtestHarness<'a> {
|
|||
assert_eq!(img2_requested.load(Ordering::SeqCst), 2);
|
||||
|
||||
// cleanup
|
||||
txn = Transaction::new();
|
||||
txn.delete_blob_image(blob_img);
|
||||
txn.delete_blob_image(blob_img2);
|
||||
self.wrench.api.update_resources(txn.resource_updates);
|
||||
|
||||
*self.wrench.callbacks.lock().unwrap() = blob::BlobCallbacks::new();
|
||||
}
|
||||
|
||||
|
@ -685,6 +696,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
test_size,
|
||||
);
|
||||
let layout_size = LayoutSize::new(400., 400.);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id);
|
||||
let mut txn = Transaction::new();
|
||||
|
||||
let blob_img = {
|
||||
|
@ -704,6 +716,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
size(200.0, 200.0),
|
||||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
|
@ -731,6 +744,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
let info = LayoutPrimitiveInfo::new(rect(0.0, 60.0, 200.0, 200.0));
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
size(200.0, 200.0),
|
||||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
|
@ -756,6 +770,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
let info = LayoutPrimitiveInfo::new(rect(0.0, 60.0, 200.0, 200.0));
|
||||
builder.push_image(
|
||||
&info,
|
||||
&space_and_clip,
|
||||
size(200.0, 200.0),
|
||||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
|
@ -769,11 +784,6 @@ impl<'a> RawtestHarness<'a> {
|
|||
|
||||
assert!(pixels_first == pixels_second);
|
||||
assert!(pixels_first != pixels_third);
|
||||
|
||||
// cleanup
|
||||
txn = Transaction::new();
|
||||
txn.delete_blob_image(blob_img);
|
||||
self.wrench.api.update_resources(txn.resource_updates);
|
||||
}
|
||||
|
||||
// Ensures that content doing a save-restore produces the same results as not
|
||||
|
@ -792,54 +802,71 @@ impl<'a> RawtestHarness<'a> {
|
|||
let mut do_test = |should_try_and_fail| {
|
||||
let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size);
|
||||
|
||||
let clip = builder.define_clip(
|
||||
let spatial_id = SpatialId::root_scroll_node(self.wrench.root_pipeline_id);
|
||||
let clip_id = builder.define_clip(
|
||||
&SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id),
|
||||
rect(110., 120., 200., 200.),
|
||||
None::<ComplexClipRegion>,
|
||||
None
|
||||
);
|
||||
builder.push_clip_id(clip);
|
||||
builder.push_rect(&PrimitiveInfo::new(rect(100., 100., 100., 100.)),
|
||||
ColorF::new(0.0, 0.0, 1.0, 1.0));
|
||||
builder.push_rect(
|
||||
&PrimitiveInfo::new(rect(100., 100., 100., 100.)),
|
||||
&SpaceAndClipInfo { spatial_id, clip_id },
|
||||
ColorF::new(0.0, 0.0, 1.0, 1.0),
|
||||
);
|
||||
|
||||
if should_try_and_fail {
|
||||
builder.save();
|
||||
let clip = builder.define_clip(
|
||||
let clip_id = builder.define_clip(
|
||||
&SpaceAndClipInfo { spatial_id, clip_id },
|
||||
rect(80., 80., 90., 90.),
|
||||
None::<ComplexClipRegion>,
|
||||
None
|
||||
);
|
||||
builder.push_clip_id(clip);
|
||||
builder.push_rect(&PrimitiveInfo::new(rect(110., 110., 50., 50.)),
|
||||
ColorF::new(0.0, 1.0, 0.0, 1.0));
|
||||
builder.push_shadow(&PrimitiveInfo::new(rect(100., 100., 100., 100.)),
|
||||
Shadow {
|
||||
offset: LayoutVector2D::new(1.0, 1.0),
|
||||
blur_radius: 1.0,
|
||||
color: ColorF::new(0.0, 0.0, 0.0, 1.0),
|
||||
});
|
||||
builder.push_line(&PrimitiveInfo::new(rect(110., 110., 50., 2.)),
|
||||
0.0, LineOrientation::Horizontal,
|
||||
&ColorF::new(0.0, 0.0, 0.0, 1.0), LineStyle::Solid);
|
||||
let space_and_clip = SpaceAndClipInfo {
|
||||
spatial_id,
|
||||
clip_id
|
||||
};
|
||||
builder.push_rect(
|
||||
&PrimitiveInfo::new(rect(110., 110., 50., 50.)),
|
||||
&space_and_clip,
|
||||
ColorF::new(0.0, 1.0, 0.0, 1.0),
|
||||
);
|
||||
builder.push_shadow(
|
||||
&PrimitiveInfo::new(rect(100., 100., 100., 100.)),
|
||||
&space_and_clip,
|
||||
Shadow {
|
||||
offset: LayoutVector2D::new(1.0, 1.0),
|
||||
blur_radius: 1.0,
|
||||
color: ColorF::new(0.0, 0.0, 0.0, 1.0),
|
||||
},
|
||||
);
|
||||
builder.push_line(
|
||||
&PrimitiveInfo::new(rect(110., 110., 50., 2.)),
|
||||
&space_and_clip,
|
||||
0.0, LineOrientation::Horizontal,
|
||||
&ColorF::new(0.0, 0.0, 0.0, 1.0),
|
||||
LineStyle::Solid,
|
||||
);
|
||||
builder.restore();
|
||||
}
|
||||
|
||||
{
|
||||
builder.save();
|
||||
let clip = builder.define_clip(
|
||||
let clip_id = builder.define_clip(
|
||||
&SpaceAndClipInfo { spatial_id, clip_id },
|
||||
rect(80., 80., 100., 100.),
|
||||
None::<ComplexClipRegion>,
|
||||
None
|
||||
);
|
||||
builder.push_clip_id(clip);
|
||||
builder.push_rect(&PrimitiveInfo::new(rect(150., 150., 100., 100.)),
|
||||
ColorF::new(0.0, 0.0, 1.0, 1.0));
|
||||
|
||||
builder.pop_clip_id();
|
||||
builder.push_rect(
|
||||
&PrimitiveInfo::new(rect(150., 150., 100., 100.)),
|
||||
&SpaceAndClipInfo { spatial_id, clip_id },
|
||||
ColorF::new(0.0, 0.0, 1.0, 1.0),
|
||||
);
|
||||
builder.clear_save();
|
||||
}
|
||||
|
||||
builder.pop_clip_id();
|
||||
|
||||
let txn = Transaction::new();
|
||||
|
||||
self.submit_dl(&mut Epoch(0), layout_size, builder, &txn.resource_updates);
|
||||
|
@ -866,6 +893,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
test_size,
|
||||
);
|
||||
let layout_size = LayoutSize::new(400., 400.);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id);
|
||||
|
||||
let mut do_test = |shadow_is_red| {
|
||||
let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size);
|
||||
|
@ -875,15 +903,22 @@ impl<'a> RawtestHarness<'a> {
|
|||
ColorF::new(0.0, 1.0, 0.0, 1.0)
|
||||
};
|
||||
|
||||
builder.push_shadow(&PrimitiveInfo::new(rect(100., 100., 100., 100.)),
|
||||
builder.push_shadow(
|
||||
&PrimitiveInfo::new(rect(100., 100., 100., 100.)),
|
||||
&space_and_clip,
|
||||
Shadow {
|
||||
offset: LayoutVector2D::new(1.0, 1.0),
|
||||
blur_radius: 1.0,
|
||||
color: shadow_color,
|
||||
});
|
||||
builder.push_line(&PrimitiveInfo::new(rect(110., 110., 50., 2.)),
|
||||
0.0, LineOrientation::Horizontal,
|
||||
&ColorF::new(0.0, 0.0, 0.0, 1.0), LineStyle::Solid);
|
||||
},
|
||||
);
|
||||
builder.push_line(
|
||||
&PrimitiveInfo::new(rect(110., 110., 50., 2.)),
|
||||
&space_and_clip,
|
||||
0.0, LineOrientation::Horizontal,
|
||||
&ColorF::new(0.0, 0.0, 0.0, 1.0),
|
||||
LineStyle::Solid,
|
||||
);
|
||||
builder.pop_all_shadows();
|
||||
|
||||
let txn = Transaction::new();
|
||||
|
@ -923,6 +958,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
|
||||
builder.push_image(
|
||||
&LayoutPrimitiveInfo::new(rect(300.0, 70.0, 150.0, 50.0)),
|
||||
&SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id),
|
||||
size(150.0, 50.0),
|
||||
size(0.0, 0.0),
|
||||
ImageRendering::Auto,
|
||||
|
@ -991,7 +1027,11 @@ impl<'a> RawtestHarness<'a> {
|
|||
let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size);
|
||||
let info = LayoutPrimitiveInfo::new(LayoutRect::new(LayoutPoint::zero(),
|
||||
LayoutSize::new(100.0, 100.0)));
|
||||
builder.push_rect(&info, ColorF::new(0.0, 1.0, 0.0, 1.0));
|
||||
builder.push_rect(
|
||||
&info,
|
||||
&SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id),
|
||||
ColorF::new(0.0, 1.0, 0.0, 1.0),
|
||||
);
|
||||
|
||||
let mut txn = Transaction::new();
|
||||
txn.set_root_pipeline(self.wrench.root_pipeline_id);
|
||||
|
@ -1017,11 +1057,12 @@ impl<'a> RawtestHarness<'a> {
|
|||
let layout_size = LayoutSize::new(400., 400.);
|
||||
let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id, layout_size);
|
||||
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(self.wrench.root_pipeline_id);
|
||||
|
||||
// Add a rectangle that covers the entire scene.
|
||||
let mut info = LayoutPrimitiveInfo::new(LayoutRect::new(LayoutPoint::zero(), layout_size));
|
||||
info.tag = Some((0, 1));
|
||||
builder.push_rect(&info, ColorF::new(1.0, 1.0, 1.0, 1.0));
|
||||
|
||||
builder.push_rect(&info, &space_and_clip, ColorF::new(1.0, 1.0, 1.0, 1.0));
|
||||
|
||||
// Add a simple 100x100 rectangle at 100,0.
|
||||
let mut info = LayoutPrimitiveInfo::new(LayoutRect::new(
|
||||
|
@ -1029,7 +1070,7 @@ impl<'a> RawtestHarness<'a> {
|
|||
LayoutSize::new(100., 100.)
|
||||
));
|
||||
info.tag = Some((0, 2));
|
||||
builder.push_rect(&info, ColorF::new(1.0, 1.0, 1.0, 1.0));
|
||||
builder.push_rect(&info, &space_and_clip, ColorF::new(1.0, 1.0, 1.0, 1.0));
|
||||
|
||||
let make_rounded_complex_clip = |rect: &LayoutRect, radius: f32| -> ComplexClipRegion {
|
||||
ComplexClipRegion::new(
|
||||
|
@ -1039,30 +1080,46 @@ impl<'a> RawtestHarness<'a> {
|
|||
)
|
||||
};
|
||||
|
||||
|
||||
// Add a rectangle that is clipped by a rounded rect clip item.
|
||||
let rect = LayoutRect::new(LayoutPoint::new(100., 100.), LayoutSize::new(100., 100.));
|
||||
let clip_id = builder.define_clip(rect, vec![make_rounded_complex_clip(&rect, 20.)], None);
|
||||
builder.push_clip_id(clip_id);
|
||||
let mut info = LayoutPrimitiveInfo::new(rect);
|
||||
info.tag = Some((0, 4));
|
||||
builder.push_rect(&info, ColorF::new(1.0, 1.0, 1.0, 1.0));
|
||||
builder.pop_clip_id();
|
||||
|
||||
let temp_clip_id = builder.define_clip(
|
||||
&space_and_clip,
|
||||
rect,
|
||||
vec![make_rounded_complex_clip(&rect, 20.)],
|
||||
None,
|
||||
);
|
||||
builder.push_rect(
|
||||
&LayoutPrimitiveInfo {
|
||||
tag: Some((0, 4)),
|
||||
.. LayoutPrimitiveInfo::new(rect)
|
||||
},
|
||||
&SpaceAndClipInfo {
|
||||
clip_id: temp_clip_id,
|
||||
spatial_id: space_and_clip.spatial_id,
|
||||
},
|
||||
ColorF::new(1.0, 1.0, 1.0, 1.0),
|
||||
);
|
||||
|
||||
// Add a rectangle that is clipped by a ClipChain containing a rounded rect.
|
||||
let rect = LayoutRect::new(LayoutPoint::new(200., 100.), LayoutSize::new(100., 100.));
|
||||
let clip_id = builder.define_clip(rect, vec![make_rounded_complex_clip(&rect, 20.)], None);
|
||||
let clip_id = builder.define_clip(
|
||||
&space_and_clip,
|
||||
rect,
|
||||
vec![make_rounded_complex_clip(&rect, 20.)],
|
||||
None,
|
||||
);
|
||||
let clip_chain_id = builder.define_clip_chain(None, vec![clip_id]);
|
||||
builder.push_clip_and_scroll_info(ClipAndScrollInfo::new(
|
||||
ClipId::root_scroll_node(self.wrench.root_pipeline_id),
|
||||
ClipId::ClipChain(clip_chain_id),
|
||||
));
|
||||
let mut info = LayoutPrimitiveInfo::new(rect);
|
||||
info.tag = Some((0, 5));
|
||||
builder.push_rect(&info, ColorF::new(1.0, 1.0, 1.0, 1.0));
|
||||
builder.pop_clip_id();
|
||||
|
||||
builder.push_rect(
|
||||
&LayoutPrimitiveInfo {
|
||||
tag: Some((0, 5)),
|
||||
.. LayoutPrimitiveInfo::new(rect)
|
||||
},
|
||||
&SpaceAndClipInfo {
|
||||
clip_id: ClipId::ClipChain(clip_chain_id),
|
||||
spatial_id: space_and_clip.spatial_id,
|
||||
},
|
||||
ColorF::new(1.0, 1.0, 1.0, 1.0),
|
||||
);
|
||||
|
||||
let mut epoch = Epoch(0);
|
||||
let txn = Transaction::new();
|
||||
|
|
|
@ -224,7 +224,11 @@ pub struct YamlFrameReader {
|
|||
|
||||
/// A HashMap that allows specifying a numeric id for clip and clip chains in YAML
|
||||
/// and having each of those ids correspond to a unique ClipId.
|
||||
clip_id_map: HashMap<u64, ClipId>,
|
||||
user_clip_id_map: HashMap<u64, ClipId>,
|
||||
user_spatial_id_map: HashMap<u64, SpatialId>,
|
||||
|
||||
clip_id_stack: Vec<ClipId>,
|
||||
spatial_id_stack: Vec<SpatialId>,
|
||||
}
|
||||
|
||||
impl YamlFrameReader {
|
||||
|
@ -243,9 +247,12 @@ impl YamlFrameReader {
|
|||
fonts: HashMap::new(),
|
||||
font_instances: HashMap::new(),
|
||||
font_render_mode: None,
|
||||
image_map: HashMap::new(),
|
||||
clip_id_map: HashMap::new(),
|
||||
allow_mipmaps: false,
|
||||
image_map: HashMap::new(),
|
||||
user_clip_id_map: HashMap::new(),
|
||||
user_spatial_id_map: HashMap::new(),
|
||||
clip_id_stack: Vec::new(),
|
||||
spatial_id_stack: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -263,6 +270,13 @@ impl YamlFrameReader {
|
|||
wrench.api.update_resources(txn.resource_updates);
|
||||
}
|
||||
|
||||
fn top_space_and_clip(&self) -> SpaceAndClipInfo {
|
||||
SpaceAndClipInfo {
|
||||
spatial_id: *self.spatial_id_stack.last().unwrap(),
|
||||
clip_id: *self.clip_id_stack.last().unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn yaml_path(&self) -> &PathBuf {
|
||||
&self.yaml_path
|
||||
}
|
||||
|
@ -316,13 +330,21 @@ impl YamlFrameReader {
|
|||
yaml: &Yaml
|
||||
) {
|
||||
// Don't allow referencing clips between pipelines for now.
|
||||
self.clip_id_map.clear();
|
||||
self.user_clip_id_map.clear();
|
||||
self.user_spatial_id_map.clear();
|
||||
self.clip_id_stack.clear();
|
||||
self.clip_id_stack.push(ClipId::root(pipeline_id));
|
||||
self.spatial_id_stack.clear();
|
||||
self.spatial_id_stack.push(SpatialId::root_scroll_node(pipeline_id));
|
||||
|
||||
let content_size = self.get_root_size_from_yaml(wrench, yaml);
|
||||
let mut builder = DisplayListBuilder::new(pipeline_id, content_size);
|
||||
let mut info = LayoutPrimitiveInfo::new(LayoutRect::zero());
|
||||
self.add_stacking_context_from_yaml(&mut builder, wrench, yaml, true, &mut info);
|
||||
self.display_lists.push(builder.finalize());
|
||||
|
||||
assert_eq!(self.clip_id_stack.len(), 1);
|
||||
assert_eq!(self.spatial_id_stack.len(), 1);
|
||||
}
|
||||
|
||||
fn to_complex_clip_region(&mut self, item: &Yaml) -> ComplexClipRegion {
|
||||
|
@ -362,50 +384,84 @@ impl YamlFrameReader {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn u64_to_clip_id(&self, number: u64, pipeline_id: PipelineId) -> ClipId {
|
||||
match number {
|
||||
0 => ClipId::root_reference_frame(pipeline_id),
|
||||
1 => ClipId::root_scroll_node(pipeline_id),
|
||||
_ => self.clip_id_map[&number],
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn to_clip_id(&self, item: &Yaml, pipeline_id: PipelineId) -> Option<ClipId> {
|
||||
match *item {
|
||||
Yaml::Integer(value) => Some(self.u64_to_clip_id(value as u64, pipeline_id)),
|
||||
Yaml::String(ref id_string) if id_string == "root-reference-frame" =>
|
||||
Some(ClipId::root_reference_frame(pipeline_id)),
|
||||
Yaml::String(ref id_string) if id_string == "root-scroll-node" =>
|
||||
Some(ClipId::root_scroll_node(pipeline_id)),
|
||||
Yaml::Integer(value) => Some(self.user_clip_id_map[&(value as u64)]),
|
||||
Yaml::String(ref id_string) if id_string == "root_clip" =>
|
||||
Some(ClipId::root(pipeline_id)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_spatial_id(&self, item: &Yaml, pipeline_id: PipelineId) -> SpatialId {
|
||||
match *item {
|
||||
Yaml::Integer(value) => self.user_spatial_id_map[&(value as u64)],
|
||||
Yaml::String(ref id_string) if id_string == "root-reference-frame" =>
|
||||
SpatialId::root_reference_frame(pipeline_id),
|
||||
Yaml::String(ref id_string) if id_string == "root-scroll-node" =>
|
||||
SpatialId::root_scroll_node(pipeline_id),
|
||||
_ => {
|
||||
println!("Unable to parse SpatialId {:?}", item);
|
||||
SpatialId::root_reference_frame(pipeline_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_clip_id_mapping(&mut self, numeric_id: u64, real_id: ClipId) {
|
||||
assert!(numeric_id != 0, "id=0 is reserved for the root reference frame");
|
||||
assert!(numeric_id != 1, "id=1 is reserved for the root scroll node");
|
||||
self.clip_id_map.insert(numeric_id, real_id);
|
||||
assert_ne!(numeric_id, 0, "id=0 is reserved for the root clip");
|
||||
self.user_clip_id_map.insert(numeric_id, real_id);
|
||||
}
|
||||
|
||||
pub fn add_spatial_id_mapping(&mut self, numeric_id: u64, real_id: SpatialId) {
|
||||
assert_ne!(numeric_id, 0, "id=0 is reserved for the root reference frame");
|
||||
assert_ne!(numeric_id, 1, "id=1 is reserved for the root scroll node");
|
||||
self.user_spatial_id_map.insert(numeric_id, real_id);
|
||||
}
|
||||
|
||||
fn to_clip_and_scroll_info(
|
||||
&self,
|
||||
item: &Yaml,
|
||||
pipeline_id: PipelineId
|
||||
) -> Option<ClipAndScrollInfo> {
|
||||
) -> (Option<ClipId>, Option<SpatialId>) {
|
||||
// Note: this is tricky. In the old code the single ID could be used either way
|
||||
// for clip/scroll. In the new code we are trying to reflect that and not break
|
||||
// all the reftests. Ultimately we'd want the clip and scroll nodes to be
|
||||
// provided separately in YAML.
|
||||
match *item {
|
||||
Yaml::BadValue => (None, None),
|
||||
Yaml::Array(ref array) if array.len() == 2 => {
|
||||
let scroll_id = match self.to_clip_id(&array[0], pipeline_id) {
|
||||
Some(id) => id,
|
||||
None => return None,
|
||||
};
|
||||
let clip_id = match self.to_clip_id(&array[1], pipeline_id) {
|
||||
Some(id) => id,
|
||||
None => return None,
|
||||
};
|
||||
Some(ClipAndScrollInfo::new(scroll_id, clip_id))
|
||||
let scroll_id = self.to_spatial_id(&array[0], pipeline_id);
|
||||
let clip_id = self.to_clip_id(&array[1], pipeline_id);
|
||||
(clip_id, Some(scroll_id))
|
||||
}
|
||||
Yaml::String(ref id_string) if id_string == "root-reference-frame" => {
|
||||
let scroll_id = SpatialId::root_reference_frame(pipeline_id);
|
||||
let clip_id = ClipId::root(pipeline_id);
|
||||
(Some(clip_id), Some(scroll_id))
|
||||
}
|
||||
Yaml::String(ref id_string) if id_string == "root-scroll-node" => {
|
||||
let scroll_id = SpatialId::root_scroll_node(pipeline_id);
|
||||
(None, Some(scroll_id))
|
||||
}
|
||||
Yaml::String(ref id_string) if id_string == "root_clip" => {
|
||||
let clip_id = ClipId::root(pipeline_id);
|
||||
(Some(clip_id), None)
|
||||
}
|
||||
Yaml::Integer(value) => {
|
||||
let scroll_id = self.user_spatial_id_map
|
||||
.get(&(value as u64))
|
||||
.cloned();
|
||||
let clip_id = self.user_clip_id_map
|
||||
.get(&(value as u64))
|
||||
.cloned();
|
||||
assert!(scroll_id.is_some() || clip_id.is_some(),
|
||||
"clip-and-scroll index not found: {}", value);
|
||||
(clip_id, scroll_id)
|
||||
}
|
||||
_ => {
|
||||
println!("Unable to parse clip/scroll {:?}", item);
|
||||
(None, None)
|
||||
}
|
||||
_ => self.to_clip_id(item, pipeline_id).map(|id| ClipAndScrollInfo::simple(id)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -709,7 +765,7 @@ impl YamlFrameReader {
|
|||
.as_rect()
|
||||
.expect("rect type must have bounds");
|
||||
let color = item["color"].as_colorf().unwrap_or(ColorF::WHITE);
|
||||
dl.push_rect(&info, color);
|
||||
dl.push_rect(&info, &self.top_space_and_clip(), color);
|
||||
}
|
||||
|
||||
fn handle_clear_rect(
|
||||
|
@ -721,7 +777,7 @@ impl YamlFrameReader {
|
|||
info.rect = item["bounds"]
|
||||
.as_rect()
|
||||
.expect("clear-rect type must have bounds");
|
||||
dl.push_clear_rect(&info);
|
||||
dl.push_clear_rect(&info, &self.top_space_and_clip());
|
||||
}
|
||||
|
||||
fn handle_line(
|
||||
|
@ -777,6 +833,7 @@ impl YamlFrameReader {
|
|||
|
||||
dl.push_line(
|
||||
&info,
|
||||
&self.top_space_and_clip(),
|
||||
wavy_line_thickness,
|
||||
orientation,
|
||||
&color,
|
||||
|
@ -803,7 +860,7 @@ impl YamlFrameReader {
|
|||
let tile_size = item["tile-size"].as_size().unwrap_or(bounds.size);
|
||||
let tile_spacing = item["tile-spacing"].as_size().unwrap_or(LayoutSize::zero());
|
||||
|
||||
dl.push_gradient(&info, gradient, tile_size, tile_spacing);
|
||||
dl.push_gradient(&info, &self.top_space_and_clip(), gradient, tile_size, tile_spacing);
|
||||
}
|
||||
|
||||
fn handle_radial_gradient(
|
||||
|
@ -825,7 +882,13 @@ impl YamlFrameReader {
|
|||
let tile_size = item["tile-size"].as_size().unwrap_or(bounds.size);
|
||||
let tile_spacing = item["tile-spacing"].as_size().unwrap_or(LayoutSize::zero());
|
||||
|
||||
dl.push_radial_gradient(&info, gradient, tile_size, tile_spacing);
|
||||
dl.push_radial_gradient(
|
||||
&info,
|
||||
&self.top_space_and_clip(),
|
||||
gradient,
|
||||
tile_size,
|
||||
tile_spacing,
|
||||
);
|
||||
}
|
||||
|
||||
fn handle_border(
|
||||
|
@ -987,7 +1050,7 @@ impl YamlFrameReader {
|
|||
None
|
||||
};
|
||||
if let Some(details) = border_details {
|
||||
dl.push_border(&info, widths, details);
|
||||
dl.push_border(&info, &self.top_space_and_clip(), widths, details);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1028,6 +1091,7 @@ impl YamlFrameReader {
|
|||
|
||||
dl.push_box_shadow(
|
||||
&info,
|
||||
&self.top_space_and_clip(),
|
||||
box_bounds,
|
||||
offset,
|
||||
color,
|
||||
|
@ -1090,6 +1154,7 @@ impl YamlFrameReader {
|
|||
|
||||
dl.push_yuv_image(
|
||||
&info,
|
||||
&self.top_space_and_clip(),
|
||||
yuv_data,
|
||||
color_depth,
|
||||
color_space,
|
||||
|
@ -1150,7 +1215,16 @@ impl YamlFrameReader {
|
|||
item
|
||||
),
|
||||
};
|
||||
dl.push_image(&info, stretch_size, tile_spacing, rendering, alpha_type, image_key, ColorF::WHITE);
|
||||
dl.push_image(
|
||||
&info,
|
||||
&self.top_space_and_clip(),
|
||||
stretch_size,
|
||||
tile_spacing,
|
||||
rendering,
|
||||
alpha_type,
|
||||
image_key,
|
||||
ColorF::WHITE,
|
||||
);
|
||||
}
|
||||
|
||||
fn handle_text(
|
||||
|
@ -1265,7 +1339,14 @@ impl YamlFrameReader {
|
|||
};
|
||||
info.rect = rect;
|
||||
|
||||
dl.push_text(&info, &glyphs, font_instance_key, color, None);
|
||||
dl.push_text(
|
||||
&info,
|
||||
&self.top_space_and_clip(),
|
||||
&glyphs,
|
||||
font_instance_key,
|
||||
color,
|
||||
None,
|
||||
);
|
||||
}
|
||||
|
||||
fn handle_iframe(
|
||||
|
@ -1277,7 +1358,7 @@ impl YamlFrameReader {
|
|||
info.rect = item["bounds"].as_rect().expect("iframe must have bounds");
|
||||
let pipeline_id = item["id"].as_pipeline_id().unwrap();
|
||||
let ignore = item["ignore_missing_pipeline"].as_bool().unwrap_or(true);
|
||||
dl.push_iframe(&info, pipeline_id, ignore);
|
||||
dl.push_iframe(&info, &self.top_space_and_clip(), pipeline_id, ignore);
|
||||
}
|
||||
|
||||
pub fn get_complex_clip_for_item(&mut self, yaml: &Yaml) -> Option<ComplexClipRegion> {
|
||||
|
@ -1332,12 +1413,15 @@ impl YamlFrameReader {
|
|||
continue;
|
||||
}
|
||||
|
||||
let clip_scroll_info = self.to_clip_and_scroll_info(
|
||||
let (set_clip_id, set_scroll_id) = self.to_clip_and_scroll_info(
|
||||
&item["clip-and-scroll"],
|
||||
dl.pipeline_id
|
||||
);
|
||||
if let Some(clip_scroll_info) = clip_scroll_info {
|
||||
dl.push_clip_and_scroll_info(clip_scroll_info);
|
||||
if let Some(clip_id) = set_clip_id {
|
||||
self.clip_id_stack.push(clip_id);
|
||||
}
|
||||
if let Some(scroll_id) = set_scroll_id {
|
||||
self.spatial_id_stack.push(scroll_id);
|
||||
}
|
||||
|
||||
let complex_clip = self.get_complex_clip_for_item(item);
|
||||
|
@ -1348,8 +1432,13 @@ impl YamlFrameReader {
|
|||
match item_type {
|
||||
"clip" | "clip-chain" | "scroll-frame" => {},
|
||||
_ => {
|
||||
let id = dl.define_clip(clip_rect, vec![complex_clip], None);
|
||||
dl.push_clip_id(id);
|
||||
let id = dl.define_clip(
|
||||
&self.top_space_and_clip(),
|
||||
clip_rect,
|
||||
vec![complex_clip],
|
||||
None,
|
||||
);
|
||||
self.clip_id_stack.push(id);
|
||||
pushed_clip = true;
|
||||
}
|
||||
}
|
||||
|
@ -1385,14 +1474,14 @@ impl YamlFrameReader {
|
|||
}
|
||||
|
||||
if pushed_clip {
|
||||
dl.pop_clip_id();
|
||||
|
||||
self.clip_id_stack.pop().unwrap();
|
||||
}
|
||||
|
||||
if clip_scroll_info.is_some() {
|
||||
dl.pop_clip_id();
|
||||
if set_clip_id.is_some() {
|
||||
self.clip_id_stack.pop().unwrap();
|
||||
}
|
||||
if set_scroll_id.is_some() {
|
||||
self.spatial_id_stack.pop().unwrap();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1419,7 +1508,8 @@ impl YamlFrameReader {
|
|||
id
|
||||
});
|
||||
|
||||
let real_id = dl.define_scroll_frame(
|
||||
let space_and_clip = dl.define_scroll_frame(
|
||||
&self.top_space_and_clip(),
|
||||
external_id,
|
||||
content_rect,
|
||||
clip_rect,
|
||||
|
@ -1428,13 +1518,16 @@ impl YamlFrameReader {
|
|||
ScrollSensitivity::ScriptAndInputEvents,
|
||||
);
|
||||
if let Some(numeric_id) = numeric_id {
|
||||
self.add_clip_id_mapping(numeric_id, real_id);
|
||||
self.add_spatial_id_mapping(numeric_id, space_and_clip.spatial_id);
|
||||
self.add_clip_id_mapping(numeric_id, space_and_clip.clip_id);
|
||||
}
|
||||
|
||||
if !yaml["items"].is_badvalue() {
|
||||
dl.push_clip_id(real_id);
|
||||
self.spatial_id_stack.push(space_and_clip.spatial_id);
|
||||
self.clip_id_stack.push(space_and_clip.clip_id);
|
||||
self.add_display_list_items_from_yaml(dl, wrench, &yaml["items"]);
|
||||
dl.pop_clip_id();
|
||||
self.clip_id_stack.pop().unwrap();
|
||||
self.spatial_id_stack.pop().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1448,6 +1541,7 @@ impl YamlFrameReader {
|
|||
let numeric_id = yaml["id"].as_i64().map(|id| id as u64);
|
||||
|
||||
let real_id = dl.define_sticky_frame(
|
||||
*self.spatial_id_stack.last().unwrap(),
|
||||
bounds,
|
||||
SideOffsets2D::new(
|
||||
yaml["margin-top"].as_f32(),
|
||||
|
@ -1461,13 +1555,13 @@ impl YamlFrameReader {
|
|||
);
|
||||
|
||||
if let Some(numeric_id) = numeric_id {
|
||||
self.add_clip_id_mapping(numeric_id, real_id);
|
||||
self.add_spatial_id_mapping(numeric_id, real_id);
|
||||
}
|
||||
|
||||
if !yaml["items"].is_badvalue() {
|
||||
dl.push_clip_id(real_id);
|
||||
self.spatial_id_stack.push(real_id);
|
||||
self.add_display_list_items_from_yaml(dl, wrench, &yaml["items"]);
|
||||
dl.pop_clip_id();
|
||||
self.spatial_id_stack.pop().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1483,6 +1577,7 @@ impl YamlFrameReader {
|
|||
|
||||
dl.push_shadow(
|
||||
&info,
|
||||
&self.top_space_and_clip(),
|
||||
Shadow {
|
||||
blur_radius,
|
||||
offset,
|
||||
|
@ -1499,8 +1594,9 @@ impl YamlFrameReader {
|
|||
let numeric_id = yaml["id"].as_i64().expect("clip chains must have an id");
|
||||
let clip_ids: Vec<ClipId> = yaml["clips"]
|
||||
.as_vec_u64()
|
||||
.unwrap_or_else(Vec::new)
|
||||
.iter().map(|id| self.u64_to_clip_id(*id, builder.pipeline_id))
|
||||
.unwrap_or_default()
|
||||
.iter()
|
||||
.map(|id| self.user_clip_id_map[id])
|
||||
.collect();
|
||||
|
||||
let parent = self.to_clip_id(&yaml["parent"], builder.pipeline_id);
|
||||
|
@ -1520,15 +1616,22 @@ impl YamlFrameReader {
|
|||
let complex_clips = self.to_complex_clip_regions(&yaml["complex"]);
|
||||
let image_mask = self.to_image_mask(&yaml["image-mask"], wrench);
|
||||
|
||||
let real_id = dl.define_clip(clip_rect, complex_clips, image_mask);
|
||||
let space_and_clip = self.top_space_and_clip();
|
||||
let real_id = dl.define_clip(
|
||||
&space_and_clip,
|
||||
clip_rect,
|
||||
complex_clips,
|
||||
image_mask,
|
||||
);
|
||||
if let Some(numeric_id) = numeric_id {
|
||||
self.add_clip_id_mapping(numeric_id as u64, real_id);
|
||||
self.add_spatial_id_mapping(numeric_id as u64, space_and_clip.spatial_id);
|
||||
}
|
||||
|
||||
if !yaml["items"].is_badvalue() {
|
||||
dl.push_clip_id(real_id);
|
||||
self.clip_id_stack.push(real_id);
|
||||
self.add_display_list_items_from_yaml(dl, wrench, &yaml["items"]);
|
||||
dl.pop_clip_id();
|
||||
self.clip_id_stack.pop().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1544,7 +1647,7 @@ impl YamlFrameReader {
|
|||
dl: &mut DisplayListBuilder,
|
||||
wrench: &mut Wrench,
|
||||
yaml: &Yaml,
|
||||
) -> ClipId {
|
||||
) -> SpatialId {
|
||||
let default_bounds = LayoutRect::new(LayoutPoint::zero(), wrench.window_size_f32());
|
||||
let bounds = yaml["bounds"].as_rect().unwrap_or(default_bounds);
|
||||
let default_transform_origin = LayoutPoint::new(
|
||||
|
@ -1578,6 +1681,7 @@ impl YamlFrameReader {
|
|||
|
||||
let reference_frame_id = dl.push_reference_frame(
|
||||
&bounds,
|
||||
*self.spatial_id_stack.last().unwrap(),
|
||||
transform_style,
|
||||
transform.into(),
|
||||
perspective,
|
||||
|
@ -1585,7 +1689,7 @@ impl YamlFrameReader {
|
|||
|
||||
let numeric_id = yaml["id"].as_i64();
|
||||
if let Some(numeric_id) = numeric_id {
|
||||
self.add_clip_id_mapping(numeric_id as u64, reference_frame_id);
|
||||
self.add_spatial_id_mapping(numeric_id as u64, reference_frame_id);
|
||||
}
|
||||
|
||||
reference_frame_id
|
||||
|
@ -1597,14 +1701,14 @@ impl YamlFrameReader {
|
|||
wrench: &mut Wrench,
|
||||
yaml: &Yaml,
|
||||
) {
|
||||
let reference_frame_id = self.push_reference_frame(dl, wrench, yaml);
|
||||
let real_id = self.push_reference_frame(dl, wrench, yaml);
|
||||
self.spatial_id_stack.push(real_id);
|
||||
|
||||
if !yaml["items"].is_badvalue() {
|
||||
dl.push_clip_id(reference_frame_id);
|
||||
self.add_display_list_items_from_yaml(dl, wrench, &yaml["items"]);
|
||||
dl.pop_clip_id();
|
||||
}
|
||||
|
||||
self.spatial_id_stack.pop().unwrap();
|
||||
dl.pop_reference_frame();
|
||||
}
|
||||
|
||||
|
@ -1617,21 +1721,21 @@ impl YamlFrameReader {
|
|||
info: &mut LayoutPrimitiveInfo,
|
||||
) {
|
||||
let default_bounds = LayoutRect::new(LayoutPoint::zero(), wrench.window_size_f32());
|
||||
let bounds = yaml["bounds"].as_rect().unwrap_or(default_bounds);
|
||||
info.rect = bounds;
|
||||
info.clip_rect = bounds;
|
||||
let mut bounds = yaml["bounds"].as_rect().unwrap_or(default_bounds);
|
||||
|
||||
let reference_frame_id = if !yaml["transform"].is_badvalue() ||
|
||||
!yaml["perspective"].is_badvalue() {
|
||||
let reference_frame_id = self.push_reference_frame(dl, wrench, yaml);
|
||||
info.rect.origin = LayoutPoint::zero();
|
||||
info.clip_rect.origin = LayoutPoint::zero();
|
||||
self.spatial_id_stack.push(reference_frame_id);
|
||||
bounds.origin = LayoutPoint::zero();
|
||||
Some(reference_frame_id)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// note: this API is deprecated, use the standard clip-and-scroll field instead
|
||||
let clip_node_id = self.to_clip_id(&yaml["clip-node"], dl.pipeline_id);
|
||||
|
||||
let transform_style = yaml["transform-style"]
|
||||
.as_transform_style()
|
||||
.unwrap_or(TransformStyle::Flat);
|
||||
|
@ -1651,12 +1755,12 @@ impl YamlFrameReader {
|
|||
|
||||
let filters = yaml["filters"].as_vec_filter_op().unwrap_or(vec![]);
|
||||
|
||||
if let Some(reference_frame_id) = reference_frame_id {
|
||||
dl.push_clip_id(reference_frame_id);
|
||||
}
|
||||
info.rect = bounds;
|
||||
info.clip_rect = bounds;
|
||||
|
||||
dl.push_stacking_context(
|
||||
&info,
|
||||
*self.spatial_id_stack.last().unwrap(),
|
||||
clip_node_id,
|
||||
transform_style,
|
||||
mix_blend_mode,
|
||||
|
@ -1671,10 +1775,7 @@ impl YamlFrameReader {
|
|||
dl.pop_stacking_context();
|
||||
|
||||
if reference_frame_id.is_some() {
|
||||
dl.pop_clip_id();
|
||||
}
|
||||
|
||||
if reference_frame_id.is_some() {
|
||||
self.spatial_id_stack.pop().unwrap();
|
||||
dl.pop_reference_frame();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ use super::CURRENT_FRAME_NUMBER;
|
|||
use time;
|
||||
use webrender;
|
||||
use webrender::api::*;
|
||||
use webrender::api::SpecificDisplayItem::*;
|
||||
use webrender::api::SpecificDisplayItem as Sdi;
|
||||
use webrender::api::channel::Payload;
|
||||
use yaml_helper::StringEnum;
|
||||
use yaml_rust::{Yaml, YamlEmitter};
|
||||
|
@ -206,7 +206,7 @@ fn write_reference_frame(
|
|||
matrix4d_node(parent, "perspective", &perspective);
|
||||
}
|
||||
|
||||
usize_node(parent, "id", clip_id_mapper.add_id(reference_frame.id));
|
||||
usize_node(parent, "id", clip_id_mapper.add_spatial_id(reference_frame.id));
|
||||
}
|
||||
|
||||
fn write_stacking_context(
|
||||
|
@ -214,7 +214,6 @@ fn write_stacking_context(
|
|||
sc: &StackingContext,
|
||||
properties: &SceneProperties,
|
||||
filter_iter: AuxIter<FilterOp>,
|
||||
clip_id_mapper: &ClipIdMapper,
|
||||
) {
|
||||
enum_node(parent, "transform-style", sc.transform_style);
|
||||
|
||||
|
@ -228,10 +227,6 @@ fn write_stacking_context(
|
|||
};
|
||||
str_node(parent, "raster-space", &raster_space);
|
||||
|
||||
if let Some(clip_node_id) = sc.clip_node_id {
|
||||
yaml_node(parent, "clip-node", clip_id_mapper.map_id(&clip_node_id));
|
||||
}
|
||||
|
||||
// mix_blend_mode
|
||||
if sc.mix_blend_mode != MixBlendMode::Normal {
|
||||
enum_node(parent, "mix-blend-mode", sc.mix_blend_mode)
|
||||
|
@ -767,18 +762,22 @@ impl YamlFrameWriter {
|
|||
);
|
||||
}
|
||||
|
||||
yaml_node(&mut v, "clip-and-scroll", clip_id_mapper.map_info(&base.clip_and_scroll()));
|
||||
let space_and_clip = base.space_and_clip_info();
|
||||
let clip_id = if space_and_clip.clip_id.is_root() { None } else { Some(space_and_clip.clip_id) };
|
||||
yaml_node(&mut v, "clip-and-scroll",
|
||||
clip_id_mapper.map_clip_and_scroll_ids(clip_id, space_and_clip.spatial_id)
|
||||
);
|
||||
bool_node(&mut v, "backface-visible", base.is_backface_visible());
|
||||
|
||||
match *base.item() {
|
||||
Rectangle(item) => {
|
||||
Sdi::Rectangle(item) => {
|
||||
str_node(&mut v, "type", "rect");
|
||||
color_node(&mut v, "color", item.color);
|
||||
}
|
||||
ClearRectangle => {
|
||||
Sdi::ClearRectangle => {
|
||||
str_node(&mut v, "type", "clear-rect");;
|
||||
}
|
||||
Line(item) => {
|
||||
Sdi::Line(item) => {
|
||||
str_node(&mut v, "type", "line");
|
||||
if let LineStyle::Wavy = item.style {
|
||||
f32_node(&mut v, "thickness", item.wavy_line_thickness);
|
||||
|
@ -787,7 +786,7 @@ impl YamlFrameWriter {
|
|||
color_node(&mut v, "color", item.color);
|
||||
str_node(&mut v, "style", item.style.as_str());
|
||||
}
|
||||
Text(item) => {
|
||||
Sdi::Text(item) => {
|
||||
let gi = display_list.get(base.glyphs());
|
||||
let mut indices: Vec<u32> = vec![];
|
||||
let mut offsets: Vec<f32> = vec![];
|
||||
|
@ -841,7 +840,7 @@ impl YamlFrameWriter {
|
|||
}
|
||||
}
|
||||
}
|
||||
Image(item) => {
|
||||
Sdi::Image(item) => {
|
||||
if let Some(path) = self.path_for_image(item.image_key) {
|
||||
path_node(&mut v, "image", &path);
|
||||
}
|
||||
|
@ -864,12 +863,12 @@ impl YamlFrameWriter {
|
|||
AlphaType::Alpha => str_node(&mut v, "alpha-type", "alpha"),
|
||||
};
|
||||
}
|
||||
YuvImage(_) => {
|
||||
Sdi::YuvImage(_) => {
|
||||
str_node(&mut v, "type", "yuv-image");
|
||||
// TODO
|
||||
println!("TODO YAML YuvImage");
|
||||
}
|
||||
Border(item) => {
|
||||
Sdi::Border(item) => {
|
||||
str_node(&mut v, "type", "border");
|
||||
match item.details {
|
||||
BorderDetails::Normal(ref details) => {
|
||||
|
@ -984,7 +983,7 @@ impl YamlFrameWriter {
|
|||
}
|
||||
}
|
||||
}
|
||||
BoxShadow(item) => {
|
||||
Sdi::BoxShadow(item) => {
|
||||
str_node(&mut v, "type", "box-shadow");
|
||||
rect_node(&mut v, "box-bounds", &item.box_bounds);
|
||||
vector_node(&mut v, "offset", &item.offset);
|
||||
|
@ -1000,7 +999,7 @@ impl YamlFrameWriter {
|
|||
};
|
||||
str_node(&mut v, "clip-mode", clip_mode);
|
||||
}
|
||||
Gradient(item) => {
|
||||
Sdi::Gradient(item) => {
|
||||
str_node(&mut v, "type", "gradient");
|
||||
point_node(&mut v, "start", &item.gradient.start_point);
|
||||
point_node(&mut v, "end", &item.gradient.end_point);
|
||||
|
@ -1018,7 +1017,7 @@ impl YamlFrameWriter {
|
|||
item.gradient.extend_mode == ExtendMode::Repeat,
|
||||
);
|
||||
}
|
||||
RadialGradient(item) => {
|
||||
Sdi::RadialGradient(item) => {
|
||||
str_node(&mut v, "type", "radial-gradient");
|
||||
size_node(&mut v, "tile-size", &item.tile_size);
|
||||
size_node(&mut v, "tile-spacing", &item.tile_spacing);
|
||||
|
@ -1029,12 +1028,12 @@ impl YamlFrameWriter {
|
|||
display_list
|
||||
);
|
||||
}
|
||||
Iframe(item) => {
|
||||
Sdi::Iframe(item) => {
|
||||
str_node(&mut v, "type", "iframe");
|
||||
u32_vec_node(&mut v, "id", &[item.pipeline_id.0, item.pipeline_id.1]);
|
||||
bool_node(&mut v, "ignore_missing_pipeline", item.ignore_missing_pipeline);
|
||||
}
|
||||
PushStackingContext(item) => {
|
||||
Sdi::PushStackingContext(item) => {
|
||||
str_node(&mut v, "type", "stacking-context");
|
||||
let filters = display_list.get(base.filters());
|
||||
write_stacking_context(
|
||||
|
@ -1042,6 +1041,18 @@ impl YamlFrameWriter {
|
|||
&item.stacking_context,
|
||||
&scene.properties,
|
||||
filters,
|
||||
);
|
||||
|
||||
let mut sub_iter = base.sub_iter();
|
||||
self.write_display_list(&mut v, display_list, scene, &mut sub_iter, clip_id_mapper);
|
||||
continue_traversal = Some(sub_iter);
|
||||
}
|
||||
Sdi::PushReferenceFrame(item) => {
|
||||
str_node(&mut v, "type", "reference-frame");
|
||||
write_reference_frame(
|
||||
&mut v,
|
||||
&item.reference_frame,
|
||||
&scene.properties,
|
||||
clip_id_mapper,
|
||||
);
|
||||
|
||||
|
@ -1049,22 +1060,9 @@ impl YamlFrameWriter {
|
|||
self.write_display_list(&mut v, display_list, scene, &mut sub_iter, clip_id_mapper);
|
||||
continue_traversal = Some(sub_iter);
|
||||
}
|
||||
PushReferenceFrame(item) => {
|
||||
str_node(&mut v, "type", "reference-frame");
|
||||
write_reference_frame(
|
||||
&mut v,
|
||||
&item.reference_frame,
|
||||
&scene.properties,
|
||||
clip_id_mapper
|
||||
);
|
||||
|
||||
let mut sub_iter = base.sub_iter();
|
||||
self.write_display_list(&mut v, display_list, scene, &mut sub_iter, clip_id_mapper);
|
||||
continue_traversal = Some(sub_iter);
|
||||
}
|
||||
Clip(item) => {
|
||||
Sdi::Clip(item) => {
|
||||
str_node(&mut v, "type", "clip");
|
||||
usize_node(&mut v, "id", clip_id_mapper.add_id(item.id));
|
||||
usize_node(&mut v, "id", clip_id_mapper.add_clip_id(item.id));
|
||||
|
||||
let (complex_clips, complex_clip_count) = base.complex_clip();
|
||||
if let Some(complex) = self.make_complex_clips_node(
|
||||
|
@ -1079,25 +1077,25 @@ impl YamlFrameWriter {
|
|||
yaml_node(&mut v, "image-mask", mask_yaml);
|
||||
}
|
||||
}
|
||||
ClipChain(item) => {
|
||||
Sdi::ClipChain(item) => {
|
||||
str_node(&mut v, "type", "clip-chain");
|
||||
|
||||
let id = ClipId::ClipChain(item.id);
|
||||
u32_node(&mut v, "id", clip_id_mapper.add_id(id) as u32);
|
||||
u32_node(&mut v, "id", clip_id_mapper.add_clip_id(id) as u32);
|
||||
|
||||
let clip_ids = display_list.get(base.clip_chain_items()).map(|clip_id| {
|
||||
clip_id_mapper.map_id(&clip_id)
|
||||
clip_id_mapper.map_clip_id(&clip_id)
|
||||
}).collect();
|
||||
yaml_node(&mut v, "clips", Yaml::Array(clip_ids));
|
||||
|
||||
if let Some(parent) = item.parent {
|
||||
let parent = ClipId::ClipChain(parent);
|
||||
yaml_node(&mut v, "parent", clip_id_mapper.map_id(&parent));
|
||||
yaml_node(&mut v, "parent", clip_id_mapper.map_clip_id(&parent));
|
||||
}
|
||||
}
|
||||
ScrollFrame(item) => {
|
||||
Sdi::ScrollFrame(item) => {
|
||||
str_node(&mut v, "type", "scroll-frame");
|
||||
usize_node(&mut v, "id", clip_id_mapper.add_id(item.scroll_frame_id));
|
||||
usize_node(&mut v, "id", clip_id_mapper.add_spatial_id(item.scroll_frame_id));
|
||||
size_node(&mut v, "content-size", &base.rect().size);
|
||||
rect_node(&mut v, "bounds", &base.clip_rect());
|
||||
|
||||
|
@ -1114,9 +1112,9 @@ impl YamlFrameWriter {
|
|||
yaml_node(&mut v, "image-mask", mask_yaml);
|
||||
}
|
||||
}
|
||||
StickyFrame(item) => {
|
||||
Sdi::StickyFrame(item) => {
|
||||
str_node(&mut v, "type", "sticky-frame");
|
||||
usize_node(&mut v, "id", clip_id_mapper.add_id(item.id));
|
||||
usize_node(&mut v, "id", clip_id_mapper.add_spatial_id(item.id));
|
||||
rect_node(&mut v, "bounds", &base.clip_rect());
|
||||
|
||||
if let Some(margin) = item.margins.top {
|
||||
|
@ -1151,21 +1149,22 @@ impl YamlFrameWriter {
|
|||
yaml_node(&mut v, "previously-applied-offset", Yaml::Array(applied));
|
||||
}
|
||||
|
||||
PopCacheMarker => return,
|
||||
PushCacheMarker(_) => {
|
||||
Sdi::PopReferenceFrame |
|
||||
Sdi::PopStackingContext => return,
|
||||
|
||||
Sdi::PopCacheMarker => return,
|
||||
Sdi::PushCacheMarker(_) => {
|
||||
str_node(&mut v, "type", "cache-marker");
|
||||
}
|
||||
|
||||
PopStackingContext => return,
|
||||
PopReferenceFrame => return,
|
||||
SetGradientStops => panic!("dummy item yielded?"),
|
||||
PushShadow(shadow) => {
|
||||
Sdi::SetGradientStops => panic!("dummy item yielded?"),
|
||||
Sdi::PushShadow(shadow) => {
|
||||
str_node(&mut v, "type", "shadow");
|
||||
vector_node(&mut v, "offset", &shadow.offset);
|
||||
color_node(&mut v, "color", shadow.color);
|
||||
f32_node(&mut v, "blur-radius", shadow.blur_radius);
|
||||
}
|
||||
PopAllShadows => {
|
||||
Sdi::PopAllShadows => {
|
||||
str_node(&mut v, "type", "pop-all-shadows");
|
||||
}
|
||||
}
|
||||
|
@ -1247,43 +1246,62 @@ impl webrender::ApiRecordingReceiver for YamlFrameWriterReceiver {
|
|||
}
|
||||
|
||||
/// This structure allows mapping both `Clip` and `ClipExternalId`
|
||||
/// `ClipIds` onto one set of numeric ids. This prevents ids
|
||||
/// from clashing in the yaml output.
|
||||
/// `ClipIds` onto one set of numeric ids. It also handles `SpatialId`
|
||||
/// in a separate map. This prevents ids from clashing in the yaml output.
|
||||
struct ClipIdMapper {
|
||||
hash_map: HashMap<ClipId, usize>,
|
||||
clip_map: HashMap<ClipId, usize>,
|
||||
spatial_map: HashMap<SpatialId, usize>,
|
||||
current_clip_id: usize,
|
||||
current_spatial_id: usize,
|
||||
}
|
||||
|
||||
impl ClipIdMapper {
|
||||
fn new() -> ClipIdMapper {
|
||||
fn new() -> Self {
|
||||
ClipIdMapper {
|
||||
hash_map: HashMap::new(),
|
||||
current_clip_id: 2,
|
||||
clip_map: HashMap::new(),
|
||||
spatial_map: HashMap::new(),
|
||||
current_clip_id: 1, // see FIRST_CLIP_NODE_INDEX
|
||||
current_spatial_id: 2, // see FIRST_SPATIAL_NODE_INDEX
|
||||
}
|
||||
}
|
||||
|
||||
fn add_id(&mut self, id: ClipId) -> usize {
|
||||
self.hash_map.insert(id, self.current_clip_id);
|
||||
fn add_clip_id(&mut self, id: ClipId) -> usize {
|
||||
self.clip_map.insert(id, self.current_clip_id);
|
||||
self.current_clip_id += 1;
|
||||
self.current_clip_id - 1
|
||||
}
|
||||
|
||||
fn map_id(&self, id: &ClipId) -> Yaml {
|
||||
fn add_spatial_id(&mut self, id: SpatialId) -> usize {
|
||||
self.spatial_map.insert(id, self.current_spatial_id);
|
||||
self.current_spatial_id += 1;
|
||||
self.current_spatial_id - 1
|
||||
}
|
||||
|
||||
fn map_spatial_id(&self, id: &SpatialId) -> Yaml {
|
||||
if id.is_root_reference_frame() {
|
||||
Yaml::String("root-reference-frame".to_owned())
|
||||
} else if id.is_root_scroll_node() {
|
||||
Yaml::String("root-scroll-node".to_owned())
|
||||
} else {
|
||||
Yaml::Integer(*self.hash_map.get(id).unwrap() as i64)
|
||||
Yaml::Integer(self.spatial_map[id] as i64)
|
||||
}
|
||||
}
|
||||
|
||||
fn map_info(&self, info: &ClipAndScrollInfo) -> Yaml {
|
||||
let scroll_node_yaml = self.map_id(&info.scroll_node_id);
|
||||
match info.clip_node_id {
|
||||
fn map_clip_id(&self, id: &ClipId) -> Yaml {
|
||||
assert!(id.is_valid());
|
||||
if id.is_root() {
|
||||
Yaml::String("root_clip".to_owned())
|
||||
} else {
|
||||
Yaml::Integer(self.clip_map[id] as i64)
|
||||
}
|
||||
}
|
||||
|
||||
fn map_clip_and_scroll_ids(&self, clip_id: Option<ClipId>, spatial_id: SpatialId) -> Yaml {
|
||||
let scroll_node_yaml = self.map_spatial_id(&spatial_id);
|
||||
match clip_id {
|
||||
Some(ref clip_node_id) => Yaml::Array(vec![
|
||||
scroll_node_yaml,
|
||||
self.map_id(&clip_node_id)
|
||||
self.map_clip_id(&clip_node_id)
|
||||
]),
|
||||
None => scroll_node_yaml,
|
||||
}
|
||||
|
|
|
@ -485,12 +485,7 @@ bool BulletRenderer::CreateWebRenderCommandsForPath(
|
|||
return true;
|
||||
}
|
||||
case NS_STYLE_LIST_STYLE_DISC: {
|
||||
AutoTArray<wr::ComplexClipRegion, 1> clips;
|
||||
clips.AppendElement(wr::SimpleRadii(dest, dest.size.width / 2));
|
||||
auto clipId = aBuilder.DefineClip(Nothing(), dest, &clips, nullptr);
|
||||
aBuilder.PushClip(clipId);
|
||||
aBuilder.PushRect(dest, dest, isBackfaceVisible, color);
|
||||
aBuilder.PopClip();
|
||||
aBuilder.PushRoundedRect(dest, dest, isBackfaceVisible, color);
|
||||
return true;
|
||||
}
|
||||
case NS_STYLE_LIST_STYLE_SQUARE: {
|
||||
|
|
|
@ -1666,12 +1666,7 @@ ImgDrawResult nsImageFrame::DisplayAltFeedbackWithoutLayer(
|
|||
rect, PresContext()->AppUnitsPerDevPixel());
|
||||
dest = wr::ToRoundedLayoutRect(devPxRect);
|
||||
|
||||
AutoTArray<wr::ComplexClipRegion, 1> clips;
|
||||
clips.AppendElement(wr::SimpleRadii(dest, dest.size.width / 2));
|
||||
auto clipId = aBuilder.DefineClip(Nothing(), dest, &clips, nullptr);
|
||||
aBuilder.PushClip(clipId);
|
||||
aBuilder.PushRect(dest, wrBounds, isBackfaceVisible, color);
|
||||
aBuilder.PopClip();
|
||||
aBuilder.PushRoundedRect(dest, wrBounds, isBackfaceVisible, color);
|
||||
}
|
||||
|
||||
// Reduce the inner rect by the width of the icon, and leave an
|
||||
|
|
|
@ -3302,6 +3302,7 @@ void nsCSSBorderRenderer::CreateWebRenderCommands(
|
|||
const layers::StackingContextHelper& aSc) {
|
||||
LayoutDeviceRect outerRect = LayoutDeviceRect::FromUnknownRect(mOuterRect);
|
||||
wr::LayoutRect roundedRect = wr::ToRoundedLayoutRect(outerRect);
|
||||
wr::LayoutRect clipRect = roundedRect;
|
||||
wr::BorderSide side[4];
|
||||
NS_FOR_CSS_SIDES(i) {
|
||||
side[i] =
|
||||
|
@ -3315,22 +3316,16 @@ void nsCSSBorderRenderer::CreateWebRenderCommands(
|
|||
LayoutDeviceSize::FromUnknownSize(mBorderRadii[2]));
|
||||
|
||||
if (mLocalClip) {
|
||||
LayoutDeviceRect clip =
|
||||
LayoutDeviceRect localClip =
|
||||
LayoutDeviceRect::FromUnknownRect(mLocalClip.value());
|
||||
wr::LayoutRect clipRect = wr::ToRoundedLayoutRect(clip);
|
||||
wr::WrClipId clipId = aBuilder.DefineClip(Nothing(), clipRect);
|
||||
aBuilder.PushClip(clipId);
|
||||
clipRect = wr::ToRoundedLayoutRect(localClip.Intersect(outerRect));
|
||||
}
|
||||
|
||||
Range<const wr::BorderSide> wrsides(side, 4);
|
||||
aBuilder.PushBorder(roundedRect, roundedRect, mBackfaceIsVisible,
|
||||
aBuilder.PushBorder(roundedRect, clipRect, mBackfaceIsVisible,
|
||||
wr::ToBorderWidths(mBorderWidths[0], mBorderWidths[1],
|
||||
mBorderWidths[2], mBorderWidths[3]),
|
||||
wrsides, borderRadius);
|
||||
|
||||
if (mLocalClip) {
|
||||
aBuilder.PopClip();
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ Maybe<nsCSSBorderImageRenderer>
|
||||
|
|
|
@ -6880,6 +6880,8 @@ bool nsDisplayStickyPosition::CreateWebRenderCommands(
|
|||
}
|
||||
}
|
||||
|
||||
Maybe<wr::SpaceAndClipChainHelper> saccHelper;
|
||||
|
||||
if (stickyScrollContainer) {
|
||||
float auPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
|
||||
|
@ -6997,13 +6999,13 @@ bool nsDisplayStickyPosition::CreateWebRenderCommands(
|
|||
wr::LayoutVector2D applied = {
|
||||
NSAppUnitsToFloatPixels(appliedOffset.x, auPerDevPixel),
|
||||
NSAppUnitsToFloatPixels(appliedOffset.y, auPerDevPixel)};
|
||||
wr::WrClipId id = aBuilder.DefineStickyFrame(
|
||||
wr::WrSpatialId spatialId = aBuilder.DefineStickyFrame(
|
||||
wr::ToRoundedLayoutRect(bounds), topMargin.ptrOr(nullptr),
|
||||
rightMargin.ptrOr(nullptr), bottomMargin.ptrOr(nullptr),
|
||||
leftMargin.ptrOr(nullptr), vBounds, hBounds, applied);
|
||||
|
||||
aBuilder.PushClip(id);
|
||||
aManager->CommandBuilder().PushOverrideForASR(mContainerASR, id);
|
||||
saccHelper.emplace(aBuilder, spatialId);
|
||||
aManager->CommandBuilder().PushOverrideForASR(mContainerASR, spatialId);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -7015,7 +7017,6 @@ bool nsDisplayStickyPosition::CreateWebRenderCommands(
|
|||
|
||||
if (stickyScrollContainer) {
|
||||
aManager->CommandBuilder().PopOverrideForASR(mContainerASR);
|
||||
aBuilder.PopClip();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -67,6 +67,9 @@ relativesrcdir dom/locales:
|
|||
# Note: All rules must be wildcards, as localized files are optional
|
||||
# Only run this if we're not en-US, as en-US is already built
|
||||
# by toolkit/locales/jar.mn.
|
||||
# If you're including files from a subdirectory, ensure that you're
|
||||
# putting them into the corresponding subdirectory in the target.
|
||||
# The wildcard ** does that for us in toolkit.
|
||||
|
||||
#define EN_US en-US
|
||||
#if AB_CD != EN_US
|
||||
|
@ -74,8 +77,10 @@ relativesrcdir dom/locales:
|
|||
relativesrcdir toolkit/locales:
|
||||
#about:crashes
|
||||
crashreporter (%crashreporter/**/*.ftl)
|
||||
#endif
|
||||
#about:about
|
||||
toolkit (%toolkit/about/*About.ftl)
|
||||
toolkit/about (%toolkit/about/*About.ftl)
|
||||
#about:support
|
||||
toolkit (%toolkit/about/*Support.ftl)
|
||||
toolkit/about (%toolkit/about/*Support.ftl)
|
||||
#endif
|
||||
# Do not add files below the endif. Reviewers, expand more context above
|
||||
# for comments.
|
||||
|
|
|
@ -66,7 +66,7 @@ async function jexlFilterFunc(entry, environment) {
|
|||
let result;
|
||||
try {
|
||||
const context = {
|
||||
environment,
|
||||
env: environment,
|
||||
};
|
||||
result = await FilterExpressions.eval(filter_expression, context);
|
||||
} catch (e) {
|
||||
|
|
|
@ -56,13 +56,13 @@ add_task(async function test_returns_entries_where_jexl_is_true() {
|
|||
filter_expression: "1 == 2 || 1 == 1",
|
||||
}, {
|
||||
willMatch: true,
|
||||
filter_expression: 'environment.appID == "xpcshell@tests.mozilla.org"',
|
||||
filter_expression: 'env.appID == "xpcshell@tests.mozilla.org"',
|
||||
}, {
|
||||
willMatch: false,
|
||||
filter_expression: "environment.version == undefined",
|
||||
filter_expression: "env.version == undefined",
|
||||
}, {
|
||||
willMatch: true,
|
||||
filter_expression: "environment.unknown == undefined",
|
||||
filter_expression: "env.unknown == undefined",
|
||||
}, {
|
||||
willMatch: false,
|
||||
filter_expression: "1 == 2",
|
||||
|
|
|
@ -284,7 +284,7 @@ var RecipeRunner = {
|
|||
arguments: recipe.arguments,
|
||||
};
|
||||
return {
|
||||
environment,
|
||||
env: environment,
|
||||
// Backwards compatibility -- see bug 1477255.
|
||||
normandy: environment,
|
||||
};
|
||||
|
|
|
@ -37,29 +37,29 @@ add_task(async function getFilterContext() {
|
|||
"version",
|
||||
];
|
||||
for (const key of expectedNormandyKeys) {
|
||||
ok(key in context.environment, `environment.${key} is available`);
|
||||
ok(key in context.env, `env.${key} is available`);
|
||||
ok(key in context.normandy, `normandy.${key} is available`);
|
||||
}
|
||||
Assert.deepEqual(context.normandy, context.environment,
|
||||
Assert.deepEqual(context.normandy, context.env,
|
||||
"context offers normandy as backwards-compatible alias for context.environment");
|
||||
|
||||
is(
|
||||
context.environment.recipe.id,
|
||||
context.env.recipe.id,
|
||||
recipe.id,
|
||||
"environment.recipe is the recipe passed to getFilterContext",
|
||||
);
|
||||
delete recipe.unrelated;
|
||||
Assert.deepEqual(
|
||||
context.environment.recipe,
|
||||
context.env.recipe,
|
||||
recipe,
|
||||
"environment.recipe drops unrecognized attributes from the recipe",
|
||||
);
|
||||
|
||||
// Filter context attributes are cached.
|
||||
await SpecialPowers.pushPrefEnv({set: [["app.normandy.user_id", "some id"]]});
|
||||
is(context.environment.userId, "some id", "User id is read from prefs when accessed");
|
||||
is(context.env.userId, "some id", "User id is read from prefs when accessed");
|
||||
await SpecialPowers.pushPrefEnv({set: [["app.normandy.user_id", "real id"]]});
|
||||
is(context.environment.userId, "some id", "userId was cached");
|
||||
is(context.env.userId, "some id", "userId was cached");
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -3891,14 +3891,10 @@ void nsWindow::AddWindowOverlayWebRenderCommands(
|
|||
wr::IpcResourceUpdateQueue& aResources) {
|
||||
if (mWindowButtonsRect) {
|
||||
wr::LayoutRect rect = wr::ToLayoutRect(*mWindowButtonsRect);
|
||||
nsTArray<wr::ComplexClipRegion> roundedClip;
|
||||
roundedClip.AppendElement(wr::ToComplexClipRegion(
|
||||
auto complexRegion = wr::ToComplexClipRegion(
|
||||
RoundedRect(IntRectToRect(mWindowButtonsRect->ToUnknownRect()),
|
||||
RectCornerRadii(0, 0, 3, 3))));
|
||||
wr::WrClipId clipId = aBuilder.DefineClip(Nothing(), rect, &roundedClip);
|
||||
aBuilder.PushClip(clipId);
|
||||
aBuilder.PushClearRect(rect);
|
||||
aBuilder.PopClip();
|
||||
RectCornerRadii(0, 0, 3, 3)));
|
||||
aBuilder.PushClearRectWithComplexRegion(rect, complexRegion);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче