author | Chris Lord <chrislord.net@gmail.com> |
Tue, 26 Jun 2012 14:43:11 +0100 | |
changeset 102977 | 9b952d9249536576a90b41b95bc60ab367607b97 |
parent 102976 | 03efce5856692f8b2573ed134d775d49db3d75fe |
child 102978 | ddd519d0767ed613df103591e62d5412aee02aa0 |
push id | 191 |
push user | lsblakk@mozilla.com |
push date | Fri, 05 Oct 2012 17:12:53 +0000 |
treeherder | mozilla-release@ddb22ac6c03b [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | roc |
bugs | 758620 |
milestone | 16.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -726,28 +726,38 @@ public: /** * CONSTRUCTION PHASE ONLY * A layer is "fixed position" when it draws content from a content * (not chrome) document, the topmost content document has a root scrollframe * with a displayport, but the layer does not move when that displayport scrolls. */ void SetIsFixedPosition(bool aFixedPosition) { mIsFixedPosition = aFixedPosition; } + /** + * CONSTRUCTION PHASE ONLY + * If a layer is "fixed position", this determines which point on the layer + * is considered the "anchor" point, that is, the point which remains in the + * same position when compositing the layer tree with a transformation + * (such as when asynchronously scrolling and zooming). + */ + void SetFixedPositionAnchor(const gfxPoint& aAnchor) { mAnchor = aAnchor; } + // These getters can be used anytime. float GetOpacity() { return mOpacity; } const nsIntRect* GetClipRect() { return mUseClipRect ? &mClipRect : nsnull; } PRUint32 GetContentFlags() { return mContentFlags; } const nsIntRegion& GetVisibleRegion() { return mVisibleRegion; } ContainerLayer* GetParent() { return mParent; } Layer* GetNextSibling() { return mNextSibling; } Layer* GetPrevSibling() { return mPrevSibling; } virtual Layer* GetFirstChild() { return nsnull; } virtual Layer* GetLastChild() { return nsnull; } const gfx3DMatrix& GetTransform() { return mTransform; } bool GetIsFixedPosition() { return mIsFixedPosition; } + gfxPoint GetFixedPositionAnchor() { return mAnchor; } Layer* GetMaskLayer() { return mMaskLayer; } /** * DRAWING PHASE ONLY * * Write layer-subtype-specific attributes into aAttrs. Used to * synchronize layer attributes to their shadows'. */ @@ -987,16 +997,17 @@ protected: gfx3DMatrix mEffectiveTransform; float mOpacity; nsIntRect mClipRect; nsIntRect mTileSourceRect; PRUint32 mContentFlags; bool mUseClipRect; bool mUseTileSourceRect; bool mIsFixedPosition; + gfxPoint mAnchor; DebugOnly<PRUint32> mDebugColorIndex; }; /** * A Layer which we can draw into using Thebes. It is a conceptually * infinite surface, but each ThebesLayer has an associated "valid region" * of contents that it is currently storing, which is finite. ThebesLayer * implementations can store content between paints.
--- a/gfx/layers/ipc/PLayers.ipdl +++ b/gfx/layers/ipc/PLayers.ipdl @@ -7,16 +7,17 @@ include protocol PCompositor; include protocol PLayer; include protocol PRenderFrame; include "gfxipc/ShadowLayerUtils.h"; using gfx3DMatrix; +using gfxPoint; using gfxRGBA; using nsIntPoint; using nsIntRect; using nsIntRegion; using nsIntSize; using mozilla::GraphicsFilterType; using mozilla::layers::FrameMetrics; using mozilla::layers::SurfaceDescriptorX11; @@ -80,16 +81,17 @@ union CanvasSurface { struct CommonLayerAttributes { nsIntRegion visibleRegion; gfx3DMatrix transform; PRUint32 contentFlags; float opacity; bool useClipRect; nsIntRect clipRect; bool isFixedPosition; + gfxPoint fixedPositionAnchor; nullable PLayer maskLayer; }; struct ThebesLayerAttributes { nsIntRegion validRegion; }; struct ContainerLayerAttributes{ FrameMetrics metrics; }; struct ColorLayerAttributes { gfxRGBA color; };
--- a/gfx/layers/ipc/ShadowLayers.cpp +++ b/gfx/layers/ipc/ShadowLayers.cpp @@ -286,16 +286,17 @@ ShadowLayerForwarder::EndTransaction(Inf common.visibleRegion() = mutant->GetVisibleRegion(); common.transform() = mutant->GetTransform(); common.contentFlags() = mutant->GetContentFlags(); common.opacity() = mutant->GetOpacity(); common.useClipRect() = !!mutant->GetClipRect(); common.clipRect() = (common.useClipRect() ? *mutant->GetClipRect() : nsIntRect()); common.isFixedPosition() = mutant->GetIsFixedPosition(); + common.fixedPositionAnchor() = mutant->GetFixedPositionAnchor(); if (Layer* maskLayer = mutant->GetMaskLayer()) { common.maskLayerChild() = Shadow(maskLayer->AsShadowableLayer()); } else { common.maskLayerChild() = NULL; } common.maskLayerParent() = NULL; attrs.specific() = null_t(); mutant->FillSpecificAttributes(attrs.specific());
--- a/gfx/layers/ipc/ShadowLayersParent.cpp +++ b/gfx/layers/ipc/ShadowLayersParent.cpp @@ -202,16 +202,17 @@ ShadowLayersParent::RecvUpdate(const Inf layer->SetVisibleRegion(common.visibleRegion()); layer->SetContentFlags(common.contentFlags()); layer->SetOpacity(common.opacity()); layer->SetClipRect(common.useClipRect() ? &common.clipRect() : NULL); layer->SetTransform(common.transform()); static bool fixedPositionLayersEnabled = getenv("MOZ_ENABLE_FIXED_POSITION_LAYERS") != 0; if (fixedPositionLayersEnabled) { layer->SetIsFixedPosition(common.isFixedPosition()); + layer->SetFixedPositionAnchor(common.fixedPositionAnchor()); } if (PLayerParent* maskLayer = common.maskLayerParent()) { layer->SetMaskLayer(cast(maskLayer)->AsLayer()); } else { layer->SetMaskLayer(NULL); } typedef SpecificLayerAttributes Specific;
--- a/ipc/glue/IPCMessageUtils.h +++ b/ipc/glue/IPCMessageUtils.h @@ -423,16 +423,37 @@ struct ParamTraits<gfxMatrix> static void Log(const paramType& aParam, std::wstring* aLog) { aLog->append(StringPrintf(L"[[%g %g] [%g %g] [%g %g]]", aParam.xx, aParam.xy, aParam.yx, aParam.yy, aParam.x0, aParam.y0)); } }; template<> +struct ParamTraits<gfxPoint> +{ + typedef gfxPoint paramType; + + static void Write(Message* aMsg, const paramType& aParam) + { + WriteParam(aMsg, aParam.x); + WriteParam(aMsg, aParam.y); + } + + static bool Read(const Message* aMsg, void** aIter, paramType* aResult) + { + if (ReadParam(aMsg, aIter, &aResult->x) && + ReadParam(aMsg, aIter, &aResult->y)) + return true; + + return false; + } +}; + +template<> struct ParamTraits<gfxSize> { typedef gfxSize paramType; static void Write(Message* aMsg, const paramType& aParam) { WriteParam(aMsg, aParam.width); WriteParam(aMsg, aParam.height);
--- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -1997,16 +1997,78 @@ nsDisplayOwnLayer::BuildLayer(nsDisplayL LayerManager* aManager, const ContainerParameters& aContainerParameters) { nsRefPtr<Layer> layer = aBuilder->LayerBuilder()-> BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList, aContainerParameters, nsnull); return layer.forget(); } +nsDisplayFixedPosition::nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder, + nsIFrame* aFrame, + nsDisplayList* aList) + : nsDisplayOwnLayer(aBuilder, aFrame, aList) { + MOZ_COUNT_CTOR(nsDisplayFixedPosition); +} + +#ifdef NS_BUILD_REFCNT_LOGGING +nsDisplayFixedPosition::~nsDisplayFixedPosition() { + MOZ_COUNT_DTOR(nsDisplayFixedPosition); +} +#endif + +already_AddRefed<Layer> +nsDisplayFixedPosition::BuildLayer(nsDisplayListBuilder* aBuilder, + LayerManager* aManager, + const ContainerParameters& aContainerParameters) { + nsRefPtr<Layer> layer = + nsDisplayOwnLayer::BuildLayer(aBuilder, aManager, aContainerParameters); + + // Work out the anchor point for this fixed position layer. We assume that + // any positioning set (left/top/right/bottom) indicates that the + // corresponding side of its container should be the anchor point, + // defaulting to top-left. + nsIFrame* viewportFrame = mFrame->GetParent(); + nsPresContext *presContext = viewportFrame->PresContext(); + + // Fixed position frames are reflowed into the scroll-port size if one has + // been set. + nsSize containingBlockSize = viewportFrame->GetSize(); + if (presContext->PresShell()->IsScrollPositionClampingScrollPortSizeSet()) { + containingBlockSize = presContext->PresShell()-> + GetScrollPositionClampingScrollPortSize(); + } + + // Find out the rect of the viewport frame relative to the reference frame. + // This, in conjunction with the container scale, will correspond to the + // coordinate-space of the built layer. + float factor = presContext->AppUnitsPerDevPixel(); + nsPoint origin = aBuilder->ToReferenceFrame(viewportFrame); + gfxRect anchorRect(NSAppUnitsToFloatPixels(origin.x, factor) * + aContainerParameters.mXScale, + NSAppUnitsToFloatPixels(origin.y, factor) * + aContainerParameters.mYScale, + NSAppUnitsToFloatPixels(containingBlockSize.width, factor) * + aContainerParameters.mXScale, + NSAppUnitsToFloatPixels(containingBlockSize.height, factor) * + aContainerParameters.mYScale); + + gfxPoint anchor(anchorRect.x, anchorRect.y); + + const nsStylePosition* position = mFrame->GetStylePosition(); + if (position->mOffset.GetRightUnit() != eStyleUnit_Auto) + anchor.x = anchorRect.XMost(); + if (position->mOffset.GetBottomUnit() != eStyleUnit_Auto) + anchor.y = anchorRect.YMost(); + + layer->SetFixedPositionAnchor(anchor); + + return layer.forget(); +} + nsDisplayScrollLayer::nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder, nsDisplayList* aList, nsIFrame* aForFrame, nsIFrame* aScrolledFrame, nsIFrame* aScrollFrame) : nsDisplayWrapList(aBuilder, aForFrame, aList) , mScrollFrame(aScrollFrame) , mScrolledFrame(aScrolledFrame)
--- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -1905,16 +1905,35 @@ public: { // Don't allow merging, each sublist must have its own layer return false; } NS_DISPLAY_DECL_NAME("OwnLayer", TYPE_OWN_LAYER) }; /** + * A display item used to represent fixed position elements. This will ensure + * the contents gets its own layer, and that the built layer will have + * position-related metadata set on it. + */ +class nsDisplayFixedPosition : public nsDisplayOwnLayer { +public: + nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, + nsDisplayList* aList); +#ifdef NS_BUILD_REFCNT_LOGGING + virtual ~nsDisplayFixedPosition(); +#endif + + virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder, + LayerManager* aManager, + const ContainerParameters& aContainerParameters); + NS_DISPLAY_DECL_NAME("FixedPosition", TYPE_OWN_LAYER) +}; + +/** * This potentially creates a layer for the given list of items, whose * visibility is determined by the displayport for the given frame instead of * what is passed in to ComputeVisibility. * * Here in content, we can use this to render more content than is actually * visible. Then, the compositing process can manipulate the generated layer * through transformations so that asynchronous scrolling can be implemented. *
--- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -2163,18 +2163,26 @@ nsIFrame::BuildDisplayListForChild(nsDis } NS_ENSURE_SUCCESS(rv, rv); if (isPositioned || isVisuallyAtomic || (aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT)) { // Genuine stacking contexts, and positioned pseudo-stacking-contexts, // go in this level. if (!list.IsEmpty()) { - rv = aLists.PositionedDescendants()->AppendNewToTop(new (aBuilder) - nsDisplayWrapList(aBuilder, child, &list)); + // Make sure the root of a fixed position frame sub-tree gets the + // correct displaylist item type. + nsDisplayItem* item; + if (!child->GetParent()->GetParent() && + disp->mPosition == NS_STYLE_POSITION_FIXED) { + item = new (aBuilder) nsDisplayFixedPosition(aBuilder, child, &list); + } else { + item = new (aBuilder) nsDisplayWrapList(aBuilder, child, &list); + } + rv = aLists.PositionedDescendants()->AppendNewToTop(item); NS_ENSURE_SUCCESS(rv, rv); } } else if (disp->IsFloating()) { if (!list.IsEmpty()) { rv = aLists.Floats()->AppendNewToTop(new (aBuilder) nsDisplayWrapList(aBuilder, child, &list)); NS_ENSURE_SUCCESS(rv, rv); }