From be34abff1962d096d19a9b2b7b548838daf3fa18 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Wed, 9 Jul 2014 12:25:31 -0700 Subject: [PATCH] Bug 1036604 - add VR display item and VR frame state bit; r=roc --- layout/base/nsDisplayList.cpp | 25 +++++++++++++++++++++++++ layout/base/nsDisplayList.h | 26 ++++++++++++++++++++++++++ layout/generic/nsFrame.cpp | 26 +++++++++++++++++++++++++- layout/generic/nsFrameStateBits.h | 3 +++ 4 files changed, 79 insertions(+), 1 deletion(-) diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index ca7dd683fbd..faffde866ee 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -5660,6 +5660,31 @@ nsDisplaySVGEffects::~nsDisplaySVGEffects() } #endif +nsDisplayVR::nsDisplayVR(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, + nsDisplayList* aList, mozilla::gfx::VRHMDInfo* aHMD) + : nsDisplayOwnLayer(aBuilder, aFrame, aList) + , mHMD(aHMD) +{ +} + +already_AddRefed +nsDisplayVR::BuildLayer(nsDisplayListBuilder* aBuilder, + LayerManager* aManager, + const ContainerLayerParameters& aContainerParameters) +{ + ContainerLayerParameters newContainerParameters = aContainerParameters; + uint32_t flags = FrameLayerBuilder::CONTAINER_NOT_CLIPPED_BY_ANCESTORS; + nsRefPtr container = aManager->GetLayerBuilder()-> + BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList, + newContainerParameters, nullptr, flags); + + // This gets uncommented when it's implemented by the layers functionality patch + //container->SetVRHMDInfo(mHMD); + container->SetUserData(nsIFrame::LayerIsPrerenderedDataKey(), + /*the value is irrelevant*/nullptr); + + return container.forget(); +} nsRegion nsDisplaySVGEffects::GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap) { diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index a51318b4c8b..a97798d09de 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -28,6 +28,7 @@ #include "FrameMetrics.h" #include "mozilla/UniquePtr.h" #include "mozilla/gfx/UserData.h" +#include "gfxVR.h" #include #include "nsTHashtable.h" @@ -3616,4 +3617,29 @@ public: nscoord mRightEdge; // length from the right side }; +/** + * A wrapper layer that wraps its children in a container, then renders + * everything with an appropriate VR effect based on the HMDInfo. + */ + +class nsDisplayVR : public nsDisplayOwnLayer { +public: + nsDisplayVR(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, + nsDisplayList* aList, mozilla::gfx::VRHMDInfo* aHMD); + + virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, + LayerManager* aManager, + const ContainerLayerParameters& aParameters) MOZ_OVERRIDE + { + return mozilla::LAYER_ACTIVE; + } + + virtual already_AddRefed BuildLayer(nsDisplayListBuilder* aBuilder, + LayerManager* aManager, + const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE; + +protected: + nsRefPtr mHMD; +}; + #endif /*NSDISPLAYLIST_H_*/ diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index f0ce0a5f0e8..7a13d7e17fa 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -102,6 +102,12 @@ using namespace mozilla::gfx; using namespace mozilla::layers; using namespace mozilla::layout; +namespace mozilla { +namespace gfx { +class VRHMDInfo; +} +} + // Struct containing cached metrics for box-wrapped frames. struct nsBoxLayoutMetrics { @@ -590,6 +596,10 @@ nsFrame::Init(nsIContent* aContent, "root frame should always be a container"); } + if (aContent && aContent->GetProperty(nsGkAtoms::vr_state) != nullptr) { + AddStateBits(NS_FRAME_HAS_VR_CONTENT); + } + DidSetStyleContext(nullptr); if (::IsBoxWrapped(this)) @@ -1995,6 +2005,12 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, nsDisplayListBuilder::AutoBuildingDisplayList buildingDisplayList(aBuilder, this, dirtyRect, true); + + mozilla::gfx::VRHMDInfo* vrHMDInfo = nullptr; + if ((GetStateBits() & NS_FRAME_HAS_VR_CONTENT)) { + vrHMDInfo = static_cast(mContent->GetProperty(nsGkAtoms::vr_state)); + } + DisplayListClipState::AutoSaveRestore clipState(aBuilder); if (isTransformed || useOpacity || useBlendMode || usingSVGEffects || useStickyPosition) { @@ -2155,6 +2171,13 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, } } + /* If we're doing VR rendering, then we need to wrap everything in a nsDisplayVR + */ + if (vrHMDInfo && !resultList.IsEmpty()) { + resultList.AppendNewToTop( + new (aBuilder) nsDisplayVR(aBuilder, this, &resultList, vrHMDInfo)); + } + /* If adding both a nsDisplayBlendContainer and a nsDisplayMixBlendMode to the * same list, the nsDisplayBlendContainer should be added first. This only * happens when the element creating this stacking context has mix-blend-mode @@ -2325,7 +2348,8 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, // but the spec says it acts like the rest of these || disp->mChildPerspective.GetUnit() == eStyleUnit_Coord || disp->mMixBlendMode != NS_STYLE_BLEND_NORMAL - || nsSVGIntegrationUtils::UsingEffectsForFrame(child); + || nsSVGIntegrationUtils::UsingEffectsForFrame(child) + || (child->GetStateBits() & NS_FRAME_HAS_VR_CONTENT); bool isPositioned = disp->IsPositioned(child); bool isStackingContext = diff --git a/layout/generic/nsFrameStateBits.h b/layout/generic/nsFrameStateBits.h index 2d04f97c23e..e2c647c833e 100644 --- a/layout/generic/nsFrameStateBits.h +++ b/layout/generic/nsFrameStateBits.h @@ -249,6 +249,9 @@ FRAME_STATE_BIT(Generic, 53, NS_FRAME_IS_NONDISPLAY) // Frame has a LayerActivityProperty property FRAME_STATE_BIT(Generic, 54, NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY) +// Frame has VR content, and needs VR display items created +FRAME_STATE_BIT(Generic, 57, NS_FRAME_HAS_VR_CONTENT) + // Set for all descendants of MathML sub/supscript elements (other than the // base frame) to indicate that the SSTY font feature should be used. FRAME_STATE_BIT(Generic, 58, NS_FRAME_MATHML_SCRIPT_DESCENDANT)