Skip to content

Commit

Permalink
Bug 1306415 - Part 1: Implement VRFrameData and VRDisplay.getFrameDat…
Browse files Browse the repository at this point in the history
…a,r=smaug,r=dmu

MozReview-Commit-ID: HlZUtZ7iZb5

--HG--
extra : rebase_source : 2d5de1522c0b06aa49d5a0ad3fe2170fff78ec37
  • Loading branch information
Kearwood (Kip) Gilbert committed Sep 30, 2016
1 parent 43c76f1 commit 423a243
Show file tree
Hide file tree
Showing 5 changed files with 275 additions and 2 deletions.
192 changes: 192 additions & 0 deletions dom/vr/VRDisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,20 @@ VRPose::VRPose(nsISupports* aParent, const gfx::VRHMDSensorState& aState)
mozilla::HoldJSObjects(this);
}

VRPose::VRPose(nsISupports* aParent)
: mParent(aParent)
, mPosition(nullptr)
, mLinearVelocity(nullptr)
, mLinearAcceleration(nullptr)
, mOrientation(nullptr)
, mAngularVelocity(nullptr)
, mAngularAcceleration(nullptr)
{
mFrameId = 0;
mVRState.Clear();
mozilla::HoldJSObjects(this);
}

VRPose::~VRPose()
{
mozilla::DropJSObjects(this);
Expand Down Expand Up @@ -490,6 +504,15 @@ VRDisplay::GetStageParameters()
return mStageParameters;
}

bool
VRDisplay::GetFrameData(VRFrameData& aFrameData)
{
gfx::VRHMDSensorState state = mClient->GetSensorState();
const gfx::VRDisplayInfo& info = mClient->GetDisplayInfo();
aFrameData.Update(info, state, mDepthNear, mDepthFar);
return true;
}

already_AddRefed<VRPose>
VRDisplay::GetPose()
{
Expand Down Expand Up @@ -658,5 +681,174 @@ NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, DOMEventTargetHelper)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)

NS_IMPL_CYCLE_COLLECTION_CLASS(VRFrameData)

NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(VRFrameData)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent, mPose)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
tmp->mLeftProjectionMatrix = nullptr;
tmp->mLeftViewMatrix = nullptr;
tmp->mRightProjectionMatrix = nullptr;
tmp->mRightViewMatrix = nullptr;
NS_IMPL_CYCLE_COLLECTION_UNLINK_END

NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(VRFrameData)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent, mPose)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END

NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(VRFrameData)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mLeftProjectionMatrix)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mLeftViewMatrix)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mRightProjectionMatrix)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mRightViewMatrix)
NS_IMPL_CYCLE_COLLECTION_TRACE_END

NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRFrameData, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRFrameData, Release)

VRFrameData::VRFrameData(nsISupports* aParent)
: mParent(aParent)
, mLeftProjectionMatrix(nullptr)
, mLeftViewMatrix(nullptr)
, mRightProjectionMatrix(nullptr)
, mRightViewMatrix(nullptr)
{
mPose = new VRPose(aParent);
}

VRFrameData::~VRFrameData()
{
mozilla::DropJSObjects(this);
}

/* static */ already_AddRefed<VRFrameData>
VRFrameData::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
{
RefPtr<VRFrameData> obj = new VRFrameData(aGlobal.GetAsSupports());
return obj.forget();
}

JSObject*
VRFrameData::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
return VRFrameDataBinding::Wrap(aCx, this, aGivenProto);
}

VRPose*
VRFrameData::Pose()
{
return mPose;
}

void
VRFrameData::LazyCreateMatrix(JS::Heap<JSObject*>& aArray, gfx::Matrix4x4& aMat, JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval, ErrorResult& aRv)
{
if (!aArray) {
// Lazily create the Float32Array
aArray = dom::Float32Array::Create(aCx, this, 16, aMat.components);
if (!aArray) {
aRv.NoteJSContextException(aCx);
return;
}
}
if (aArray) {
JS::ExposeObjectToActiveJS(aArray);
}
aRetval.set(aArray);
}

double
VRFrameData::Timestamp() const
{
return mVRState.timestamp * 1000.0f; // Converting from seconds to milliseconds
}

void
VRFrameData::GetLeftProjectionMatrix(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv)
{
LazyCreateMatrix(mLeftProjectionMatrix, mLeftProjection, aCx, aRetval, aRv);
}

void
VRFrameData::GetLeftViewMatrix(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv)
{
LazyCreateMatrix(mLeftViewMatrix, mLeftView, aCx, aRetval, aRv);
}

void
VRFrameData::GetRightProjectionMatrix(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv)
{
LazyCreateMatrix(mRightProjectionMatrix, mRightProjection, aCx, aRetval, aRv);
}

void
VRFrameData::GetRightViewMatrix(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv)
{
LazyCreateMatrix(mRightViewMatrix, mRightView, aCx, aRetval, aRv);
}

void
VRFrameData::Update(const gfx::VRDisplayInfo& aInfo,
const gfx::VRHMDSensorState& aState,
float aDepthNear,
float aDepthFar)
{
mVRState = aState;

mLeftProjectionMatrix = nullptr;
mLeftViewMatrix = nullptr;
mRightProjectionMatrix = nullptr;
mRightViewMatrix = nullptr;

mPose = new VRPose(GetParentObject(), aState);

gfx::Quaternion qt;
if (mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Orientation) {
qt.x = mVRState.orientation[0];
qt.y = mVRState.orientation[1];
qt.z = mVRState.orientation[2];
qt.w = mVRState.orientation[3];
}
gfx::Point3D pos;
if (mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Position) {
pos.x = -mVRState.position[0];
pos.y = -mVRState.position[1];
pos.z = -mVRState.position[2];
}
gfx::Matrix4x4 matHead;
matHead.SetRotationFromQuaternion(qt);
matHead.PreTranslate(pos);

mLeftView = matHead;
mLeftView.PostTranslate(-aInfo.mEyeTranslation[gfx::VRDisplayInfo::Eye_Left]);

mRightView = matHead;
mRightView.PostTranslate(-aInfo.mEyeTranslation[gfx::VRDisplayInfo::Eye_Right]);

// Avoid division by zero within ConstructProjectionMatrix
const float kEpsilon = 0.00001f;
if (fabs(aDepthFar - aDepthNear) < kEpsilon) {
aDepthFar = aDepthNear + kEpsilon;
}

const gfx::VRFieldOfView leftFOV = aInfo.mEyeFOV[gfx::VRDisplayInfo::Eye_Left];
mLeftProjection = leftFOV.ConstructProjectionMatrix(aDepthNear, aDepthFar, true);
const gfx::VRFieldOfView rightFOV = aInfo.mEyeFOV[gfx::VRDisplayInfo::Eye_Right];
mRightProjection = rightFOV.ConstructProjectionMatrix(aDepthNear, aDepthFar, true);

}

} // namespace dom
} // namespace mozilla
59 changes: 59 additions & 0 deletions dom/vr/VRDisplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ class VRPose final : public nsWrapperCache

public:
VRPose(nsISupports* aParent, const gfx::VRHMDSensorState& aState);
explicit VRPose(nsISupports* aParent);

NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRPose)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRPose)
Expand Down Expand Up @@ -144,6 +145,63 @@ class VRPose final : public nsWrapperCache

};

class VRFrameData final : public nsWrapperCache
{
public:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRFrameData)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRFrameData)

explicit VRFrameData(nsISupports* aParent);
static already_AddRefed<VRFrameData> Constructor(const GlobalObject& aGlobal,
ErrorResult& aRv);

void Update(const gfx::VRDisplayInfo& aInfo,
const gfx::VRHMDSensorState& aState,
float aDepthNear,
float aDepthFar);

// WebIDL Members
double Timestamp() const;
void GetLeftProjectionMatrix(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv);
void GetLeftViewMatrix(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv);
void GetRightProjectionMatrix(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv);
void GetRightViewMatrix(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv);

VRPose* Pose();

// WebIDL Boilerplate
nsISupports* GetParentObject() const { return mParent; }
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;

protected:
~VRFrameData();
nsCOMPtr<nsISupports> mParent;

gfx::VRHMDSensorState mVRState;
RefPtr<VRPose> mPose;
JS::Heap<JSObject*> mLeftProjectionMatrix;
JS::Heap<JSObject*> mLeftViewMatrix;
JS::Heap<JSObject*> mRightProjectionMatrix;
JS::Heap<JSObject*> mRightViewMatrix;

gfx::Matrix4x4 mLeftProjection;
gfx::Matrix4x4 mLeftView;
gfx::Matrix4x4 mRightProjection;
gfx::Matrix4x4 mRightView;

void LazyCreateMatrix(JS::Heap<JSObject*>& aArray, gfx::Matrix4x4& aMat,
JSContext* aCx, JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv);
};

class VRStageParameters final : public nsWrapperCache
{
public:
Expand Down Expand Up @@ -235,6 +293,7 @@ class VRDisplay final : public DOMEventTargetHelper

virtual already_AddRefed<VREyeParameters> GetEyeParameters(VREye aEye);

bool GetFrameData(VRFrameData& aFrameData);
already_AddRefed<VRPose> GetPose();
already_AddRefed<VRPose> GetImmediatePose();
void ResetPose();
Expand Down
21 changes: 21 additions & 0 deletions dom/webidl/VRDisplay.webidl
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,21 @@ interface VRPose {
[Constant, Throws] readonly attribute Float32Array? angularAcceleration;
};

[Constructor,
Pref="dom.vr.enabled",
HeaderFile="mozilla/dom/VRDisplay.h"]
interface VRFrameData {
readonly attribute DOMHighResTimeStamp timestamp;

[Throws, Pure] readonly attribute Float32Array leftProjectionMatrix;
[Throws, Pure] readonly attribute Float32Array leftViewMatrix;

[Throws, Pure] readonly attribute Float32Array rightProjectionMatrix;
[Throws, Pure] readonly attribute Float32Array rightViewMatrix;

[Pure] readonly attribute VRPose pose;
};

[Pref="dom.vr.enabled",
HeaderFile="mozilla/dom/VRDisplay.h"]
interface VREyeParameters {
Expand Down Expand Up @@ -187,6 +202,12 @@ interface VRDisplay : EventTarget {
*/
[Constant] readonly attribute DOMString displayName;

/**
* Populates the passed VRFrameData with the information required to render
* the current frame.
*/
boolean getFrameData(VRFrameData frameData);

/**
* Return a VRPose containing the future predicted pose of the VRDisplay
* when the current frame will be presented. Subsequent calls to getPose()
Expand Down
3 changes: 2 additions & 1 deletion gfx/vr/gfxVR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ VRDisplayManager::AllocateDisplayID()
}

Matrix4x4
VRFieldOfView::ConstructProjectionMatrix(float zNear, float zFar, bool rightHanded)
VRFieldOfView::ConstructProjectionMatrix(float zNear, float zFar,
bool rightHanded) const
{
float upTan = tan(upDegrees * M_PI / 180.0);
float downTan = tan(downDegrees * M_PI / 180.0);
Expand Down
2 changes: 1 addition & 1 deletion gfx/vr/gfxVR.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ struct VRFieldOfView {
leftDegrees == 0.0;
}

Matrix4x4 ConstructProjectionMatrix(float zNear, float zFar, bool rightHanded);
Matrix4x4 ConstructProjectionMatrix(float zNear, float zFar, bool rightHanded) const;

double upDegrees;
double rightDegrees;
Expand Down

0 comments on commit 423a243

Please sign in to comment.