LCOV - code coverage report
Current view: top level - dom/vr - VRDisplay.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 473 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 120 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
       5             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "nsWrapperCache.h"
       8             : 
       9             : #include "mozilla/dom/Element.h"
      10             : #include "mozilla/dom/ElementBinding.h"
      11             : #include "mozilla/dom/Promise.h"
      12             : #include "mozilla/dom/VRDisplay.h"
      13             : #include "mozilla/HoldDropJSObjects.h"
      14             : #include "mozilla/dom/VRDisplayBinding.h"
      15             : #include "mozilla/Base64.h"
      16             : #include "mozilla/EventStateManager.h"
      17             : #include "mozilla/gfx/DataSurfaceHelpers.h"
      18             : #include "Navigator.h"
      19             : #include "gfxPrefs.h"
      20             : #include "gfxUtils.h"
      21             : #include "gfxVR.h"
      22             : #include "VRDisplayClient.h"
      23             : #include "VRManagerChild.h"
      24             : #include "VRDisplayPresentation.h"
      25             : #include "nsIObserverService.h"
      26             : #include "nsIFrame.h"
      27             : #include "nsISupportsPrimitives.h"
      28             : 
      29             : using namespace mozilla::gfx;
      30             : 
      31             : namespace mozilla {
      32             : namespace dom {
      33             : 
      34           0 : VRFieldOfView::VRFieldOfView(nsISupports* aParent,
      35             :                              double aUpDegrees, double aRightDegrees,
      36           0 :                              double aDownDegrees, double aLeftDegrees)
      37             :   : mParent(aParent)
      38             :   , mUpDegrees(aUpDegrees)
      39             :   , mRightDegrees(aRightDegrees)
      40             :   , mDownDegrees(aDownDegrees)
      41           0 :   , mLeftDegrees(aLeftDegrees)
      42             : {
      43           0 : }
      44             : 
      45           0 : VRFieldOfView::VRFieldOfView(nsISupports* aParent, const gfx::VRFieldOfView& aSrc)
      46             :   : mParent(aParent)
      47           0 :   , mUpDegrees(aSrc.upDegrees)
      48           0 :   , mRightDegrees(aSrc.rightDegrees)
      49           0 :   , mDownDegrees(aSrc.downDegrees)
      50           0 :   , mLeftDegrees(aSrc.leftDegrees)
      51             : {
      52           0 : }
      53             : 
      54             : bool
      55           0 : VRDisplayCapabilities::HasPosition() const
      56             : {
      57           0 :   return bool(mFlags & gfx::VRDisplayCapabilityFlags::Cap_Position);
      58             : }
      59             : 
      60             : bool
      61           0 : VRDisplayCapabilities::HasOrientation() const
      62             : {
      63           0 :   return bool(mFlags & gfx::VRDisplayCapabilityFlags::Cap_Orientation);
      64             : }
      65             : 
      66             : bool
      67           0 : VRDisplayCapabilities::HasExternalDisplay() const
      68             : {
      69           0 :   return bool(mFlags & gfx::VRDisplayCapabilityFlags::Cap_External);
      70             : }
      71             : 
      72             : bool
      73           0 : VRDisplayCapabilities::CanPresent() const
      74             : {
      75           0 :   return bool(mFlags & gfx::VRDisplayCapabilityFlags::Cap_Present);
      76             : }
      77             : 
      78             : uint32_t
      79           0 : VRDisplayCapabilities::MaxLayers() const
      80             : {
      81           0 :   return CanPresent() ? 1 : 0;
      82             : }
      83             : 
      84             : /*static*/ bool
      85           0 : VRDisplay::RefreshVRDisplays(uint64_t aWindowId)
      86             : {
      87           0 :   gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
      88           0 :   return vm && vm->RefreshVRDisplaysWithCallback(aWindowId);
      89             : }
      90             : 
      91             : /*static*/ void
      92           0 : VRDisplay::UpdateVRDisplays(nsTArray<RefPtr<VRDisplay>>& aDisplays, nsPIDOMWindowInner* aWindow)
      93             : {
      94           0 :   nsTArray<RefPtr<VRDisplay>> displays;
      95             : 
      96           0 :   gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
      97           0 :   nsTArray<RefPtr<gfx::VRDisplayClient>> updatedDisplays;
      98           0 :   if (vm && vm->GetVRDisplays(updatedDisplays)) {
      99           0 :     for (size_t i = 0; i < updatedDisplays.Length(); i++) {
     100           0 :       RefPtr<gfx::VRDisplayClient> display = updatedDisplays[i];
     101           0 :       bool isNewDisplay = true;
     102           0 :       for (size_t j = 0; j < aDisplays.Length(); j++) {
     103           0 :         if (aDisplays[j]->GetClient()->GetDisplayInfo() == display->GetDisplayInfo()) {
     104           0 :           displays.AppendElement(aDisplays[j]);
     105           0 :           isNewDisplay = false;
     106             :         }
     107             :       }
     108             : 
     109           0 :       if (isNewDisplay) {
     110           0 :         displays.AppendElement(new VRDisplay(aWindow, display));
     111             :       }
     112             :     }
     113             :   }
     114             : 
     115           0 :   aDisplays = displays;
     116           0 : }
     117             : 
     118           0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRFieldOfView, mParent)
     119           0 : NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRFieldOfView, AddRef)
     120           0 : NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRFieldOfView, Release)
     121             : 
     122             : 
     123             : JSObject*
     124           0 : VRFieldOfView::WrapObject(JSContext* aCx,
     125             :                           JS::Handle<JSObject*> aGivenProto)
     126             : {
     127           0 :   return VRFieldOfViewBinding::Wrap(aCx, this, aGivenProto);
     128             : }
     129             : 
     130             : NS_IMPL_CYCLE_COLLECTION_CLASS(VREyeParameters)
     131             : 
     132           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(VREyeParameters)
     133           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent, mFOV)
     134           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
     135           0 :   tmp->mOffset = nullptr;
     136           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     137             : 
     138           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(VREyeParameters)
     139           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent, mFOV)
     140           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     141             : 
     142           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(VREyeParameters)
     143           0 :   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
     144           0 :   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mOffset)
     145           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
     146             : 
     147           0 : NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VREyeParameters, AddRef)
     148           0 : NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VREyeParameters, Release)
     149             : 
     150           0 : VREyeParameters::VREyeParameters(nsISupports* aParent,
     151             :                                  const gfx::Point3D& aEyeTranslation,
     152             :                                  const gfx::VRFieldOfView& aFOV,
     153           0 :                                  const gfx::IntSize& aRenderSize)
     154             :   : mParent(aParent)
     155             :   , mEyeTranslation(aEyeTranslation)
     156           0 :   , mRenderSize(aRenderSize)
     157             : {
     158           0 :   mFOV = new VRFieldOfView(aParent, aFOV);
     159           0 :   mozilla::HoldJSObjects(this);
     160           0 : }
     161             : 
     162           0 : VREyeParameters::~VREyeParameters()
     163             : {
     164           0 :   mozilla::DropJSObjects(this);
     165           0 : }
     166             : 
     167             : VRFieldOfView*
     168           0 : VREyeParameters::FieldOfView()
     169             : {
     170           0 :   return mFOV;
     171             : }
     172             : 
     173             : void
     174           0 : VREyeParameters::GetOffset(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval, ErrorResult& aRv)
     175             : {
     176           0 :   if (!mOffset) {
     177             :     // Lazily create the Float32Array
     178           0 :     mOffset = dom::Float32Array::Create(aCx, this, 3, mEyeTranslation.components);
     179           0 :     if (!mOffset) {
     180           0 :       aRv.NoteJSContextException(aCx);
     181           0 :       return;
     182             :     }
     183             :   }
     184           0 :   aRetval.set(mOffset);
     185             : }
     186             : 
     187             : JSObject*
     188           0 : VREyeParameters::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     189             : {
     190           0 :   return VREyeParametersBinding::Wrap(aCx, this, aGivenProto);
     191             : }
     192             : 
     193           0 : VRStageParameters::VRStageParameters(nsISupports* aParent,
     194             :                                      const gfx::Matrix4x4& aSittingToStandingTransform,
     195           0 :                                      const gfx::Size& aSize)
     196             :   : mParent(aParent)
     197             :   , mSittingToStandingTransform(aSittingToStandingTransform)
     198             :   , mSittingToStandingTransformArray(nullptr)
     199           0 :   , mSize(aSize)
     200             : {
     201           0 :   mozilla::HoldJSObjects(this);
     202           0 : }
     203             : 
     204           0 : VRStageParameters::~VRStageParameters()
     205             : {
     206           0 :   mozilla::DropJSObjects(this);
     207           0 : }
     208             : 
     209             : JSObject*
     210           0 : VRStageParameters::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     211             : {
     212           0 :   return VRStageParametersBinding::Wrap(aCx, this, aGivenProto);
     213             : }
     214             : 
     215             : NS_IMPL_CYCLE_COLLECTION_CLASS(VRStageParameters)
     216             : 
     217           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(VRStageParameters)
     218           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
     219           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
     220           0 :   tmp->mSittingToStandingTransformArray = nullptr;
     221           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     222             : 
     223           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(VRStageParameters)
     224           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
     225           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     226             : 
     227           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(VRStageParameters)
     228           0 :   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
     229           0 :   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mSittingToStandingTransformArray)
     230           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
     231             : 
     232           0 : NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRStageParameters, AddRef)
     233           0 : NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRStageParameters, Release)
     234             : 
     235             : void
     236           0 : VRStageParameters::GetSittingToStandingTransform(JSContext* aCx,
     237             :                                                  JS::MutableHandle<JSObject*> aRetval,
     238             :                                                  ErrorResult& aRv)
     239             : {
     240           0 :   if (!mSittingToStandingTransformArray) {
     241             :     // Lazily create the Float32Array
     242           0 :     mSittingToStandingTransformArray = dom::Float32Array::Create(aCx, this, 16,
     243           0 :       mSittingToStandingTransform.components);
     244           0 :     if (!mSittingToStandingTransformArray) {
     245           0 :       aRv.NoteJSContextException(aCx);
     246           0 :       return;
     247             :     }
     248             :   }
     249           0 :   aRetval.set(mSittingToStandingTransformArray);
     250             : }
     251             : 
     252           0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRDisplayCapabilities, mParent)
     253           0 : NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRDisplayCapabilities, AddRef)
     254           0 : NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRDisplayCapabilities, Release)
     255             : 
     256             : JSObject*
     257           0 : VRDisplayCapabilities::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     258             : {
     259           0 :   return VRDisplayCapabilitiesBinding::Wrap(aCx, this, aGivenProto);
     260             : }
     261             : 
     262           0 : VRPose::VRPose(nsISupports* aParent, const gfx::VRHMDSensorState& aState)
     263             :   : Pose(aParent)
     264           0 :   , mVRState(aState)
     265             : {
     266           0 :   mFrameId = aState.inputFrameID;
     267           0 :   mozilla::HoldJSObjects(this);
     268           0 : }
     269             : 
     270           0 : VRPose::VRPose(nsISupports* aParent)
     271           0 :   : Pose(aParent)
     272             : {
     273           0 :   mFrameId = 0;
     274           0 :   mozilla::HoldJSObjects(this);
     275           0 : }
     276             : 
     277           0 : VRPose::~VRPose()
     278             : {
     279           0 :   mozilla::DropJSObjects(this);
     280           0 : }
     281             : 
     282             : void
     283           0 : VRPose::GetPosition(JSContext* aCx,
     284             :                     JS::MutableHandle<JSObject*> aRetval,
     285             :                     ErrorResult& aRv)
     286             : {
     287           0 :   SetFloat32Array(aCx, aRetval, mPosition, mVRState.position, 3,
     288           0 :     !mPosition && bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Position),
     289           0 :     aRv);
     290           0 : }
     291             : 
     292             : void
     293           0 : VRPose::GetLinearVelocity(JSContext* aCx,
     294             :                           JS::MutableHandle<JSObject*> aRetval,
     295             :                           ErrorResult& aRv)
     296             : {
     297           0 :   SetFloat32Array(aCx, aRetval, mLinearVelocity, mVRState.linearVelocity, 3,
     298           0 :     !mLinearVelocity && bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Position),
     299           0 :     aRv);
     300           0 : }
     301             : 
     302             : void
     303           0 : VRPose::GetLinearAcceleration(JSContext* aCx,
     304             :                               JS::MutableHandle<JSObject*> aRetval,
     305             :                               ErrorResult& aRv)
     306             : {
     307           0 :   SetFloat32Array(aCx, aRetval, mLinearAcceleration, mVRState.linearAcceleration, 3,
     308           0 :     !mLinearAcceleration && bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_LinearAcceleration),
     309           0 :     aRv);
     310             : 
     311           0 : }
     312             : 
     313             : void
     314           0 : VRPose::GetOrientation(JSContext* aCx,
     315             :                        JS::MutableHandle<JSObject*> aRetval,
     316             :                        ErrorResult& aRv)
     317             : {
     318           0 :   SetFloat32Array(aCx, aRetval, mOrientation, mVRState.orientation, 4,
     319           0 :     !mOrientation && bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Orientation),
     320           0 :     aRv);
     321           0 : }
     322             : 
     323             : void
     324           0 : VRPose::GetAngularVelocity(JSContext* aCx,
     325             :                            JS::MutableHandle<JSObject*> aRetval,
     326             :                            ErrorResult& aRv)
     327             : {
     328           0 :   SetFloat32Array(aCx, aRetval, mAngularVelocity, mVRState.angularVelocity, 3,
     329           0 :     !mAngularVelocity && bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Orientation),
     330           0 :     aRv);
     331           0 : }
     332             : 
     333             : void
     334           0 : VRPose::GetAngularAcceleration(JSContext* aCx,
     335             :                                JS::MutableHandle<JSObject*> aRetval,
     336             :                                ErrorResult& aRv)
     337             : {
     338           0 :   SetFloat32Array(aCx, aRetval, mAngularAcceleration, mVRState.angularAcceleration, 3,
     339           0 :     !mAngularAcceleration && bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_AngularAcceleration),
     340           0 :     aRv);
     341           0 : }
     342             : 
     343             : JSObject*
     344           0 : VRPose::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     345             : {
     346           0 :   return VRPoseBinding::Wrap(aCx, this, aGivenProto);
     347             : }
     348             : 
     349             : /* virtual */ JSObject*
     350           0 : VRDisplay::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     351             : {
     352           0 :   return VRDisplayBinding::Wrap(aCx, this, aGivenProto);
     353             : }
     354             : 
     355           0 : VRDisplay::VRDisplay(nsPIDOMWindowInner* aWindow, gfx::VRDisplayClient* aClient)
     356             :   : DOMEventTargetHelper(aWindow)
     357             :   , mClient(aClient)
     358             :   , mDepthNear(0.01f) // Default value from WebVR Spec
     359             :   , mDepthFar(10000.0f) // Default value from WebVR Spec
     360             :   , mVRNavigationEventDepth(0)
     361           0 :   , mShutdown(false)
     362             : {
     363           0 :   const gfx::VRDisplayInfo& info = aClient->GetDisplayInfo();
     364           0 :   mDisplayId = info.GetDisplayID();
     365           0 :   mDisplayName = NS_ConvertASCIItoUTF16(info.GetDisplayName());
     366           0 :   mCapabilities = new VRDisplayCapabilities(aWindow, info.GetCapabilities());
     367           0 :   if (info.GetCapabilities() & gfx::VRDisplayCapabilityFlags::Cap_StageParameters) {
     368             :     mStageParameters = new VRStageParameters(aWindow,
     369             :                                              info.GetSittingToStandingTransform(),
     370           0 :                                              info.GetStageSize());
     371             :   }
     372           0 :   mozilla::HoldJSObjects(this);
     373           0 :   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
     374           0 :   if (MOZ_LIKELY(obs)) {
     375           0 :     obs->AddObserver(this, "inner-window-destroyed", false);
     376             :   }
     377           0 : }
     378             : 
     379           0 : VRDisplay::~VRDisplay()
     380             : {
     381           0 :   MOZ_ASSERT(mShutdown);
     382           0 :   mozilla::DropJSObjects(this);
     383           0 : }
     384             : 
     385             : void
     386           0 : VRDisplay::LastRelease()
     387             : {
     388             :   // We don't want to wait for the CC to free up the presentation
     389             :   // for use in other documents, so we do this in LastRelease().
     390           0 :   Shutdown();
     391           0 : }
     392             : 
     393             : already_AddRefed<VREyeParameters>
     394           0 : VRDisplay::GetEyeParameters(VREye aEye)
     395             : {
     396           0 :   gfx::VRDisplayInfo::Eye eye = aEye == VREye::Left ? gfx::VRDisplayInfo::Eye_Left : gfx::VRDisplayInfo::Eye_Right;
     397             :   RefPtr<VREyeParameters> params =
     398           0 :     new VREyeParameters(GetParentObject(),
     399           0 :                         mClient->GetDisplayInfo().GetEyeTranslation(eye),
     400           0 :                         mClient->GetDisplayInfo().GetEyeFOV(eye),
     401           0 :                         mClient->GetDisplayInfo().SuggestedEyeResolution());
     402           0 :   return params.forget();
     403             : }
     404             : 
     405             : VRDisplayCapabilities*
     406           0 : VRDisplay::Capabilities()
     407             : {
     408           0 :   return mCapabilities;
     409             : }
     410             : 
     411             : VRStageParameters*
     412           0 : VRDisplay::GetStageParameters()
     413             : {
     414           0 :   return mStageParameters;
     415             : }
     416             : 
     417             : void
     418           0 : VRDisplay::UpdateFrameInfo()
     419             : {
     420             :   /**
     421             :    * The WebVR 1.1 spec Requires that VRDisplay.getPose and VRDisplay.getFrameData
     422             :    * must return the same values until the next VRDisplay.submitFrame.
     423             :    *
     424             :    * mFrameInfo is marked dirty at the end of the frame or start of a new
     425             :    * composition and lazily created here in order to receive mid-frame
     426             :    * pose-prediction updates while still ensuring conformance to the WebVR spec
     427             :    * requirements.
     428             :    *
     429             :    * If we are not presenting WebVR content, the frame will never end and we should
     430             :    * return the latest frame data always.
     431             :    */
     432           0 :   if (mFrameInfo.IsDirty() || !mPresentation) {
     433           0 :     gfx::VRHMDSensorState state = mClient->GetSensorState();
     434           0 :     const gfx::VRDisplayInfo& info = mClient->GetDisplayInfo();
     435           0 :     mFrameInfo.Update(info, state, mDepthNear, mDepthFar);
     436             :   }
     437           0 : }
     438             : 
     439             : bool
     440           0 : VRDisplay::GetFrameData(VRFrameData& aFrameData)
     441             : {
     442           0 :   UpdateFrameInfo();
     443           0 :   aFrameData.Update(mFrameInfo);
     444           0 :   return true;
     445             : }
     446             : 
     447             : bool
     448           0 : VRDisplay::GetSubmitFrameResult(VRSubmitFrameResult& aResult)
     449             : {
     450           0 :   if (!mPresentation) {
     451           0 :     return false;
     452             :   }
     453             : 
     454           0 :   VRSubmitFrameResultInfo resultInfo;
     455           0 :   mClient->GetSubmitFrameResult(resultInfo);
     456           0 :   if (!resultInfo.mBase64Image.Length()) {
     457           0 :     return false;  // The submit frame result is not ready.
     458             :   }
     459             : 
     460           0 :   nsAutoCString decodedImg;
     461           0 :   if (Base64Decode(resultInfo.mBase64Image, decodedImg) != NS_OK) {
     462           0 :     MOZ_ASSERT(false, "Failed to do decode base64 images.");
     463             :     return false;
     464             :   }
     465             : 
     466           0 :   const char* srcData = decodedImg.get();
     467           0 :   const gfx::IntSize size(resultInfo.mWidth, resultInfo.mHeight);
     468           0 :   RefPtr<DataSourceSurface> dataSurface = gfx::CreateDataSourceSurfaceFromData(
     469             :                                             size, resultInfo.mFormat, (uint8_t*)srcData,
     470           0 :                                             StrideForFormatAndWidth(resultInfo.mFormat, resultInfo.mWidth));
     471           0 :   if (!dataSurface || !dataSurface->IsValid()) {
     472           0 :     MOZ_ASSERT(false, "dataSurface is null.");
     473             :     return false;
     474             :   }
     475             : 
     476           0 :   nsAutoCString encodedImg(gfxUtils::GetAsDataURI(dataSurface));
     477           0 :   aResult.Update(resultInfo.mFrameNum, encodedImg);
     478           0 :   return true;
     479             : }
     480             : 
     481             : already_AddRefed<VRPose>
     482           0 : VRDisplay::GetPose()
     483             : {
     484           0 :   UpdateFrameInfo();
     485           0 :   RefPtr<VRPose> obj = new VRPose(GetParentObject(), mFrameInfo.mVRState);
     486             : 
     487           0 :   return obj.forget();
     488             : }
     489             : 
     490             : void
     491           0 : VRDisplay::ResetPose()
     492             : {
     493           0 :   mClient->ZeroSensor();
     494           0 : }
     495             : 
     496             : void
     497           0 : VRDisplay::StartHandlingVRNavigationEvent()
     498             : {
     499           0 :   mHandlingVRNavigationEventStart = TimeStamp::Now();
     500           0 :   ++mVRNavigationEventDepth;
     501           0 : }
     502             : 
     503             : void
     504           0 : VRDisplay::StopHandlingVRNavigationEvent()
     505             : {
     506           0 :   MOZ_ASSERT(mVRNavigationEventDepth > 0);
     507           0 :   --mVRNavigationEventDepth;
     508           0 : }
     509             : 
     510             : bool
     511           0 : VRDisplay::IsHandlingVRNavigationEvent()
     512             : {
     513           0 :   if (mVRNavigationEventDepth == 0) {
     514           0 :     return false;
     515             :   }
     516           0 :   if (mHandlingVRNavigationEventStart.IsNull()) {
     517           0 :     return false;
     518             :   }
     519           0 :   TimeDuration timeout = TimeDuration::FromMilliseconds(gfxPrefs::VRNavigationTimeout());
     520           0 :   return timeout <= TimeDuration(0) ||
     521           0 :     (TimeStamp::Now() - mHandlingVRNavigationEventStart) <= timeout;
     522             : }
     523             : 
     524             : already_AddRefed<Promise>
     525           0 : VRDisplay::RequestPresent(const nsTArray<VRLayer>& aLayers,
     526             :                           CallerType aCallerType,
     527             :                           ErrorResult& aRv)
     528             : {
     529           0 :   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
     530           0 :   if (!global) {
     531           0 :     aRv.Throw(NS_ERROR_FAILURE);
     532           0 :     return nullptr;
     533             :   }
     534             : 
     535           0 :   RefPtr<Promise> promise = Promise::Create(global, aRv);
     536           0 :   NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
     537             : 
     538           0 :   bool isChromePresentation = aCallerType == CallerType::System;
     539           0 :   uint32_t presentationGroup = isChromePresentation ? gfx::kVRGroupChrome : gfx::kVRGroupContent;
     540             : 
     541           0 :   if (!EventStateManager::IsHandlingUserInput() &&
     542           0 :       !isChromePresentation &&
     543           0 :       !IsHandlingVRNavigationEvent() &&
     544           0 :       gfxPrefs::VRRequireGesture()) {
     545             :     // The WebVR API states that if called outside of a user gesture, the
     546             :     // promise must be rejected.  We allow VR presentations to start within
     547             :     // trusted events such as vrdisplayactivate, which triggers in response to
     548             :     // HMD proximity sensors and when navigating within a VR presentation.
     549             :     // This user gesture requirement is not enforced for chrome/system code.
     550           0 :     promise->MaybeRejectWithUndefined();
     551           0 :   } else if (!IsPresenting() && IsAnyPresenting(presentationGroup)) {
     552             :     // Only one presentation allowed per VRDisplay on a
     553             :     // first-come-first-serve basis.
     554             :     // If this Javascript context is presenting, then we can replace our
     555             :     // presentation with a new one containing new layers but we should never
     556             :     // replace the presentation of another context.
     557             :     // Simultaneous presentations in other groups are allowed in separate
     558             :     // Javascript contexts to enable browser UI from chrome/system contexts.
     559             :     // Eventually, this restriction will be loosened to enable multitasking
     560             :     // use cases.
     561           0 :     promise->MaybeRejectWithUndefined();
     562             :   } else {
     563           0 :     mPresentation = mClient->BeginPresentation(aLayers, presentationGroup);
     564           0 :     mFrameInfo.Clear();
     565           0 :     promise->MaybeResolve(JS::UndefinedHandleValue);
     566             :   }
     567           0 :   return promise.forget();
     568             : }
     569             : 
     570             : NS_IMETHODIMP
     571           0 : VRDisplay::Observe(nsISupports* aSubject, const char* aTopic,
     572             :   const char16_t* aData)
     573             : {
     574           0 :   MOZ_ASSERT(NS_IsMainThread());
     575             : 
     576           0 :   if (strcmp(aTopic, "inner-window-destroyed") == 0) {
     577           0 :     nsCOMPtr<nsISupportsPRUint64> wrapper = do_QueryInterface(aSubject);
     578           0 :     NS_ENSURE_TRUE(wrapper, NS_ERROR_FAILURE);
     579             : 
     580             :     uint64_t innerID;
     581           0 :     nsresult rv = wrapper->GetData(&innerID);
     582           0 :     NS_ENSURE_SUCCESS(rv, rv);
     583             : 
     584           0 :     if (!GetOwner() || GetOwner()->WindowID() == innerID) {
     585           0 :       Shutdown();
     586             :     }
     587             : 
     588           0 :     return NS_OK;
     589             :   }
     590             : 
     591             :   // This should not happen.
     592           0 :   return NS_ERROR_FAILURE;
     593             : }
     594             : 
     595             : already_AddRefed<Promise>
     596           0 : VRDisplay::ExitPresent(ErrorResult& aRv)
     597             : {
     598           0 :   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
     599           0 :   if (!global) {
     600           0 :     aRv.Throw(NS_ERROR_FAILURE);
     601           0 :     return nullptr;
     602             :   }
     603             : 
     604             : 
     605           0 :   RefPtr<Promise> promise = Promise::Create(global, aRv);
     606           0 :   NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
     607             : 
     608           0 :   if (!IsPresenting()) {
     609             :     // We can not exit a presentation outside of the context that
     610             :     // started the presentation.
     611           0 :     promise->MaybeRejectWithUndefined();
     612             :   } else {
     613           0 :     promise->MaybeResolve(JS::UndefinedHandleValue);
     614           0 :     ExitPresentInternal();
     615             :   }
     616             : 
     617           0 :   return promise.forget();
     618             : }
     619             : 
     620             : void
     621           0 : VRDisplay::ExitPresentInternal()
     622             : {
     623           0 :   mPresentation = nullptr;
     624           0 : }
     625             : 
     626             : void
     627           0 : VRDisplay::Shutdown()
     628             : {
     629           0 :   mShutdown = true;
     630           0 :   ExitPresentInternal();
     631           0 :   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
     632           0 :   if (MOZ_LIKELY(obs)) {
     633           0 :     obs->RemoveObserver(this, "inner-window-destroyed");
     634             :   }
     635           0 : }
     636             : 
     637             : void
     638           0 : VRDisplay::GetLayers(nsTArray<VRLayer>& result)
     639             : {
     640           0 :   if (mPresentation) {
     641           0 :     mPresentation->GetDOMLayers(result);
     642             :   } else {
     643           0 :     result = nsTArray<VRLayer>();
     644             :   }
     645           0 : }
     646             : 
     647             : void
     648           0 : VRDisplay::SubmitFrame()
     649             : {
     650           0 :   if (mPresentation) {
     651           0 :     mPresentation->SubmitFrame();
     652             :   }
     653           0 :   mFrameInfo.Clear();
     654           0 : }
     655             : 
     656             : int32_t
     657           0 : VRDisplay::RequestAnimationFrame(FrameRequestCallback& aCallback,
     658             : ErrorResult& aError)
     659             : {
     660           0 :   if (mShutdown) {
     661           0 :     return 0;
     662             :   }
     663             : 
     664           0 :   gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
     665             : 
     666             :   int32_t handle;
     667           0 :   aError = vm->ScheduleFrameRequestCallback(aCallback, &handle);
     668           0 :   return handle;
     669             : }
     670             : 
     671             : void
     672           0 : VRDisplay::CancelAnimationFrame(int32_t aHandle, ErrorResult& aError)
     673             : {
     674           0 :   gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
     675           0 :   vm->CancelFrameRequestCallback(aHandle);
     676           0 : }
     677             : 
     678             : 
     679             : bool
     680           0 : VRDisplay::IsPresenting() const
     681             : {
     682             :   // IsPresenting returns true only if this Javascript context is presenting
     683             :   // and will return false if another context is presenting.
     684           0 :   return mPresentation != nullptr;
     685             : }
     686             : 
     687             : bool
     688           0 : VRDisplay::IsAnyPresenting(uint32_t aGroupMask) const
     689             : {
     690             :   // IsAnyPresenting returns true if either this VRDisplay object or any other
     691             :   // from anther Javascript context is presenting with a group matching
     692             :   // aGroupMask.
     693           0 :   if (mPresentation && (mPresentation->GetGroup() & aGroupMask)) {
     694           0 :     return true;
     695             :   }
     696           0 :   if (mClient->GetDisplayInfo().GetPresentingGroups() & aGroupMask) {
     697           0 :     return true;
     698             :   }
     699           0 :   return false;
     700             : }
     701             : 
     702             : bool
     703           0 : VRDisplay::IsConnected() const
     704             : {
     705           0 :   return mClient->GetIsConnected();
     706             : }
     707             : 
     708             : uint32_t
     709           0 : VRDisplay::PresentingGroups() const
     710             : {
     711           0 :   return mClient->GetDisplayInfo().GetPresentingGroups();
     712             : }
     713             : 
     714             : uint32_t
     715           0 : VRDisplay::GroupMask() const
     716             : {
     717           0 :   return mClient->GetDisplayInfo().GetGroupMask();
     718             : }
     719             : 
     720             : void
     721           0 : VRDisplay::SetGroupMask(const uint32_t& aGroupMask)
     722             : {
     723           0 :   mClient->SetGroupMask(aGroupMask);
     724           0 : }
     725             : 
     726           0 : NS_IMPL_CYCLE_COLLECTION_INHERITED(VRDisplay, DOMEventTargetHelper, mCapabilities, mStageParameters)
     727             : 
     728           0 : NS_IMPL_ADDREF_INHERITED(VRDisplay, DOMEventTargetHelper)
     729           0 : NS_IMPL_RELEASE_INHERITED(VRDisplay, DOMEventTargetHelper)
     730             : 
     731           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(VRDisplay)
     732           0 : NS_INTERFACE_MAP_ENTRY(nsIObserver)
     733           0 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, DOMEventTargetHelper)
     734           0 : NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
     735             : 
     736             : NS_IMPL_CYCLE_COLLECTION_CLASS(VRFrameData)
     737             : 
     738           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(VRFrameData)
     739           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent, mPose)
     740           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
     741           0 :   tmp->mLeftProjectionMatrix = nullptr;
     742           0 :   tmp->mLeftViewMatrix = nullptr;
     743           0 :   tmp->mRightProjectionMatrix = nullptr;
     744           0 :   tmp->mRightViewMatrix = nullptr;
     745           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     746             : 
     747           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(VRFrameData)
     748           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent, mPose)
     749           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     750             : 
     751           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(VRFrameData)
     752           0 :   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
     753           0 :   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mLeftProjectionMatrix)
     754           0 :   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mLeftViewMatrix)
     755           0 :   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mRightProjectionMatrix)
     756           0 :   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mRightViewMatrix)
     757           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
     758             : 
     759           0 : NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRFrameData, AddRef)
     760           0 : NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRFrameData, Release)
     761             : 
     762           0 : VRFrameData::VRFrameData(nsISupports* aParent)
     763             :   : mParent(aParent)
     764             :   , mLeftProjectionMatrix(nullptr)
     765             :   , mLeftViewMatrix(nullptr)
     766             :   , mRightProjectionMatrix(nullptr)
     767           0 :   , mRightViewMatrix(nullptr)
     768             : {
     769           0 :   mozilla::HoldJSObjects(this);
     770           0 :   mPose = new VRPose(aParent);
     771           0 : }
     772             : 
     773           0 : VRFrameData::~VRFrameData()
     774             : {
     775           0 :   mozilla::DropJSObjects(this);
     776           0 : }
     777             : 
     778             : /* static */ already_AddRefed<VRFrameData>
     779           0 : VRFrameData::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
     780             : {
     781           0 :   RefPtr<VRFrameData> obj = new VRFrameData(aGlobal.GetAsSupports());
     782           0 :   return obj.forget();
     783             : }
     784             : 
     785             : JSObject*
     786           0 : VRFrameData::WrapObject(JSContext* aCx,
     787             :                         JS::Handle<JSObject*> aGivenProto)
     788             : {
     789           0 :   return VRFrameDataBinding::Wrap(aCx, this, aGivenProto);
     790             : }
     791             : 
     792             : VRPose*
     793           0 : VRFrameData::Pose()
     794             : {
     795           0 :   return mPose;
     796             : }
     797             : 
     798             : void
     799           0 : VRFrameData::LazyCreateMatrix(JS::Heap<JSObject*>& aArray, gfx::Matrix4x4& aMat, JSContext* aCx,
     800             :                               JS::MutableHandle<JSObject*> aRetval, ErrorResult& aRv)
     801             : {
     802           0 :   if (!aArray) {
     803             :     // Lazily create the Float32Array
     804           0 :     aArray = dom::Float32Array::Create(aCx, this, 16, aMat.components);
     805           0 :     if (!aArray) {
     806           0 :       aRv.NoteJSContextException(aCx);
     807           0 :       return;
     808             :     }
     809             :   }
     810           0 :   if (aArray) {
     811           0 :     JS::ExposeObjectToActiveJS(aArray);
     812             :   }
     813           0 :   aRetval.set(aArray);
     814             : }
     815             : 
     816             : double
     817           0 : VRFrameData::Timestamp() const
     818             : {
     819             :   // Converting from seconds to milliseconds
     820           0 :   return mFrameInfo.mVRState.timestamp * 1000.0f;
     821             : }
     822             : 
     823             : void
     824           0 : VRFrameData::GetLeftProjectionMatrix(JSContext* aCx,
     825             :                                      JS::MutableHandle<JSObject*> aRetval,
     826             :                                      ErrorResult& aRv)
     827             : {
     828           0 :   LazyCreateMatrix(mLeftProjectionMatrix, mFrameInfo.mLeftProjection, aCx,
     829           0 :                    aRetval, aRv);
     830           0 : }
     831             : 
     832             : void
     833           0 : VRFrameData::GetLeftViewMatrix(JSContext* aCx,
     834             :                                JS::MutableHandle<JSObject*> aRetval,
     835             :                                ErrorResult& aRv)
     836             : {
     837           0 :   LazyCreateMatrix(mLeftViewMatrix, mFrameInfo.mLeftView, aCx, aRetval, aRv);
     838           0 : }
     839             : 
     840             : void
     841           0 : VRFrameData::GetRightProjectionMatrix(JSContext* aCx,
     842             :                                       JS::MutableHandle<JSObject*> aRetval,
     843             :                                       ErrorResult& aRv)
     844             : {
     845           0 :   LazyCreateMatrix(mRightProjectionMatrix, mFrameInfo.mRightProjection, aCx,
     846           0 :                    aRetval, aRv);
     847           0 : }
     848             : 
     849             : void
     850           0 : VRFrameData::GetRightViewMatrix(JSContext* aCx,
     851             :                                 JS::MutableHandle<JSObject*> aRetval,
     852             :                                 ErrorResult& aRv)
     853             : {
     854           0 :   LazyCreateMatrix(mRightViewMatrix, mFrameInfo.mRightView, aCx, aRetval, aRv);
     855           0 : }
     856             : 
     857             : void
     858           0 : VRFrameData::Update(const VRFrameInfo& aFrameInfo)
     859             : {
     860           0 :   mFrameInfo = aFrameInfo;
     861             : 
     862           0 :   mLeftProjectionMatrix = nullptr;
     863           0 :   mLeftViewMatrix = nullptr;
     864           0 :   mRightProjectionMatrix = nullptr;
     865           0 :   mRightViewMatrix = nullptr;
     866             : 
     867           0 :   mPose = new VRPose(GetParentObject(), mFrameInfo.mVRState);
     868           0 : }
     869             : 
     870             : void
     871           0 : VRFrameInfo::Update(const gfx::VRDisplayInfo& aInfo,
     872             :                     const gfx::VRHMDSensorState& aState,
     873             :                     float aDepthNear,
     874             :                     float aDepthFar)
     875             : {
     876           0 :   mVRState = aState;
     877           0 :   if (mTimeStampOffset == 0.0f) {
     878             :     /**
     879             :      * A mTimeStampOffset value of 0.0f indicates that this is the first iteration
     880             :      * and an offset has not yet been set.
     881             :      *
     882             :      * Generate a value for mTimeStampOffset such that if aState.timestamp is
     883             :      * monotonically increasing, aState.timestamp + mTimeStampOffset will never
     884             :      * be a negative number and will start at a pseudo-random offset
     885             :      * between 1000.0f and 11000.0f seconds.
     886             :      *
     887             :      * We use a pseudo random offset rather than 0.0f just to discourage users
     888             :      * from making the assumption that the timestamp returned in the WebVR API
     889             :      * has a base of 0, which is not necessarily true in all UA's.
     890             :      */
     891           0 :     mTimeStampOffset = float(rand()) / RAND_MAX * 10000.0f + 1000.0f - aState.timestamp;
     892             :   }
     893           0 :   mVRState.timestamp = aState.timestamp + mTimeStampOffset;
     894             : 
     895           0 :   gfx::Quaternion qt;
     896           0 :   if (mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Orientation) {
     897           0 :     qt.x = mVRState.orientation[0];
     898           0 :     qt.y = mVRState.orientation[1];
     899           0 :     qt.z = mVRState.orientation[2];
     900           0 :     qt.w = mVRState.orientation[3];
     901             :   }
     902           0 :   gfx::Point3D pos;
     903           0 :   if (mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Position) {
     904           0 :     pos.x = -mVRState.position[0];
     905           0 :     pos.y = -mVRState.position[1];
     906           0 :     pos.z = -mVRState.position[2];
     907             :   }
     908           0 :   gfx::Matrix4x4 matHead;
     909           0 :   matHead.SetRotationFromQuaternion(qt);
     910           0 :   matHead.PreTranslate(pos);
     911             : 
     912           0 :   mLeftView = matHead;
     913           0 :   mLeftView.PostTranslate(-aInfo.mEyeTranslation[gfx::VRDisplayInfo::Eye_Left]);
     914             : 
     915           0 :   mRightView = matHead;
     916           0 :   mRightView.PostTranslate(-aInfo.mEyeTranslation[gfx::VRDisplayInfo::Eye_Right]);
     917             : 
     918             :   // Avoid division by zero within ConstructProjectionMatrix
     919           0 :   const float kEpsilon = 0.00001f;
     920           0 :   if (fabs(aDepthFar - aDepthNear) < kEpsilon) {
     921           0 :     aDepthFar = aDepthNear + kEpsilon;
     922             :   }
     923             : 
     924           0 :   const gfx::VRFieldOfView leftFOV = aInfo.mEyeFOV[gfx::VRDisplayInfo::Eye_Left];
     925           0 :   mLeftProjection = leftFOV.ConstructProjectionMatrix(aDepthNear, aDepthFar, true);
     926           0 :   const gfx::VRFieldOfView rightFOV = aInfo.mEyeFOV[gfx::VRDisplayInfo::Eye_Right];
     927           0 :   mRightProjection = rightFOV.ConstructProjectionMatrix(aDepthNear, aDepthFar, true);
     928           0 : }
     929             : 
     930           0 : VRFrameInfo::VRFrameInfo()
     931           0 :  : mTimeStampOffset(0.0f)
     932             : {
     933           0 : }
     934             : 
     935             : bool
     936           0 : VRFrameInfo::IsDirty()
     937             : {
     938           0 :   return mVRState.timestamp == 0;
     939             : }
     940             : 
     941             : void
     942           0 : VRFrameInfo::Clear()
     943             : {
     944           0 :   mVRState.Clear();
     945           0 : }
     946             : 
     947           0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRSubmitFrameResult, mParent)
     948           0 : NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRSubmitFrameResult, AddRef)
     949           0 : NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRSubmitFrameResult, Release)
     950             : 
     951           0 : VRSubmitFrameResult::VRSubmitFrameResult(nsISupports* aParent)
     952             :   : mParent(aParent)
     953           0 :   , mFrameNum(0)
     954             : {
     955           0 :   mozilla::HoldJSObjects(this);
     956           0 : }
     957             : 
     958           0 : VRSubmitFrameResult::~VRSubmitFrameResult()
     959             : {
     960           0 :   mozilla::DropJSObjects(this);
     961           0 : }
     962             : 
     963             : /* static */ already_AddRefed<VRSubmitFrameResult>
     964           0 : VRSubmitFrameResult::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
     965             : {
     966           0 :   RefPtr<VRSubmitFrameResult> obj = new VRSubmitFrameResult(aGlobal.GetAsSupports());
     967           0 :   return obj.forget();
     968             : }
     969             : 
     970             : JSObject*
     971           0 : VRSubmitFrameResult::WrapObject(JSContext* aCx,
     972             :                                 JS::Handle<JSObject*> aGivenProto)
     973             : {
     974           0 :   return VRSubmitFrameResultBinding::Wrap(aCx, this, aGivenProto);
     975             : }
     976             : 
     977             : void
     978           0 : VRSubmitFrameResult::Update(uint32_t aFrameNum, const nsACString& aBase64Image)
     979             : {
     980           0 :   mFrameNum = aFrameNum;
     981           0 :   mBase64Image = NS_ConvertASCIItoUTF16(aBase64Image);
     982           0 : }
     983             : 
     984             : double
     985           0 : VRSubmitFrameResult::FrameNum() const
     986             : {
     987           0 :   return mFrameNum;
     988             : }
     989             : 
     990             : void
     991           0 : VRSubmitFrameResult::GetBase64Image(nsAString& aImage) const
     992             : {
     993           0 :   aImage = mBase64Image;
     994           0 : }
     995             : 
     996             : } // namespace dom
     997             : } // namespace mozilla

Generated by: LCOV version 1.13