Merge mozilla-central to inbound. a=merge CLOSED TREE

This commit is contained in:
Margareta Eliza Balazs 2019-01-09 11:54:44 +02:00
Родитель f10ced4f9d 5053031ba7
Коммит 1981ff9293
57 изменённых файлов: 1847 добавлений и 1394 удалений

Просмотреть файл

@ -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(&current.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);
}
}