void
VRDisplayClient::NotifyVRVsync()
{
  VRManagerChild *vm = VRManagerChild::Get();
  vm->RunFrameRequestCallbacks();
  mLastVSyncTime = TimeStamp::Now();
}
VRHMDSensorState
VRDisplayClient::GetSensorState()
{
  VRHMDSensorState sensorState;
  VRManagerChild *vm = VRManagerChild::Get();
  Unused << vm->SendGetSensorState(mDisplayInfo.mDisplayID, &sensorState);
  return sensorState;
}
void
VRDisplayClient::NotifyVsync()
{
  VRManagerChild *vm = VRManagerChild::Get();

  bool isPresenting = GetIsPresenting();

  bool bShouldCallback = !isPresenting;
  if (mLastVSyncTime.IsNull()) {
    bShouldCallback = true;
  } else {
    TimeDuration duration = TimeStamp::Now() - mLastVSyncTime;
    if (duration.ToMilliseconds() > kVRDisplayRAFMaxDuration) {
      bShouldCallback = true;
    }
  }

  if (bShouldCallback) {
    vm->RunFrameRequestCallbacks();
    mLastVSyncTime = TimeStamp::Now();
  }

  // Check if we need to trigger onVRDisplayPresentChange event
  if (bLastEventWasPresenting != isPresenting) {
    bLastEventWasPresenting = isPresenting;
    vm->FireDOMVRDisplayPresentChangeEvent(mDisplayInfo.mDisplayID);
  }

  // Check if we need to trigger onvrdisplayactivate event
  if (!bLastEventWasMounted && mDisplayInfo.mIsMounted) {
    bLastEventWasMounted = true;
    if (gfxPrefs::VRAutoActivateEnabled()) {
      vm->FireDOMVRDisplayMountedEvent(mDisplayInfo.mDisplayID);
    }
  }

  // Check if we need to trigger onvrdisplaydeactivate event
  if (bLastEventWasMounted && !mDisplayInfo.mIsMounted) {
    bLastEventWasMounted = false;
    if (gfxPrefs::VRAutoActivateEnabled()) {
      vm->FireDOMVRDisplayUnmountedEvent(mDisplayInfo.mDisplayID);
    }
  }
}
void
VRDisplayClient::ZeroSensor()
{
  VRManagerChild *vm = VRManagerChild::Get();
  vm->SendResetSensor(mDisplayInfo.mDisplayID);
}
void
VRDisplayPresentation::CreateLayers()
{
  if (mLayers.Length()) {
    return;
  }

  for (dom::VRLayer& layer : mDOMLayers) {
    dom::HTMLCanvasElement* canvasElement = layer.mSource;
    if (!canvasElement) {
      /// XXX In the future we will support WebVR in WebWorkers here
      continue;
    }

    Rect leftBounds(0.0, 0.0, 0.5, 1.0);
    if (layer.mLeftBounds.Length() == 4) {
      leftBounds.x = layer.mLeftBounds[0];
      leftBounds.y = layer.mLeftBounds[1];
      leftBounds.width = layer.mLeftBounds[2];
      leftBounds.height = layer.mLeftBounds[3];
    } else if (layer.mLeftBounds.Length() != 0) {
      /**
       * We ignore layers with an incorrect number of values.
       * In the future, VRDisplay.requestPresent may throw in
       * this case.  See https://github.com/w3c/webvr/issues/71
       */
      continue;
    }

    Rect rightBounds(0.5, 0.0, 0.5, 1.0);
    if (layer.mRightBounds.Length() == 4) {
      rightBounds.x = layer.mRightBounds[0];
      rightBounds.y = layer.mRightBounds[1];
      rightBounds.width = layer.mRightBounds[2];
      rightBounds.height = layer.mRightBounds[3];
    } else if (layer.mRightBounds.Length() != 0) {
      /**
       * We ignore layers with an incorrect number of values.
       * In the future, VRDisplay.requestPresent may throw in
       * this case.  See https://github.com/w3c/webvr/issues/71
       */
      continue;
    }

    VRManagerChild *manager = VRManagerChild::Get();
    if (!manager) {
      NS_WARNING("VRManagerChild::Get returned null!");
      continue;
    }

    nsCOMPtr<nsIEventTarget> target;
    nsIDocument* doc;
    doc = canvasElement->OwnerDoc();
    if (doc) {
      target = doc->EventTargetFor(TaskCategory::Other);
    }

    RefPtr<VRLayerChild> vrLayer =
      static_cast<VRLayerChild*>(manager->CreateVRLayer(mDisplayClient->GetDisplayInfo().GetDisplayID(),
                                                        leftBounds, rightBounds, target));
    if (!vrLayer) {
      NS_WARNING("CreateVRLayer returned null!");
      continue;
    }

    vrLayer->Initialize(canvasElement);

    mLayers.AppendElement(vrLayer);
  }
}
void
VRDisplayPresentation::CreateLayers()
{
  VRManagerChild *manager = VRManagerChild::Get();
  if (!manager) {
    // This should not happen, but let's log it and avoid a crash in case
    // of regression.
    NS_WARNING("VRManagerChild::Get returned null!");
    return;
  }

  unsigned int iLayer=0;
  for (dom::VRLayer& layer : mDOMLayers) {
    dom::HTMLCanvasElement* canvasElement = layer.mSource;
    if (!canvasElement) {
      /// XXX In the future we will support WebVR in WebWorkers here
      continue;
    }

    Rect leftBounds(0.0, 0.0, 0.5, 1.0);
    if (layer.mLeftBounds.Length() == 4) {
      leftBounds.SetRect(layer.mLeftBounds[0],
                         layer.mLeftBounds[1],
                         layer.mLeftBounds[2],
                         layer.mLeftBounds[3]);
    } else if (layer.mLeftBounds.Length() != 0) {
      /**
       * We ignore layers with an incorrect number of values.
       * In the future, VRDisplay.requestPresent may throw in
       * this case.  See https://github.com/w3c/webvr/issues/71
       */
      continue;
    }

    Rect rightBounds(0.5, 0.0, 0.5, 1.0);
    if (layer.mRightBounds.Length() == 4) {
      rightBounds.SetRect(layer.mRightBounds[0], 
                          layer.mRightBounds[1],
                          layer.mRightBounds[2],
                          layer.mRightBounds[3]);
    } else if (layer.mRightBounds.Length() != 0) {
      /**
       * We ignore layers with an incorrect number of values.
       * In the future, VRDisplay.requestPresent may throw in
       * this case.  See https://github.com/w3c/webvr/issues/71
       */
      continue;
    }

    nsCOMPtr<nsIEventTarget> target;
    nsIDocument* doc;
    doc = canvasElement->OwnerDoc();
    if (doc) {
      target = doc->EventTargetFor(TaskCategory::Other);
    }

    if (mLayers.Length() <= iLayer) {
      // Not enough layers, let's add one
      RefPtr<VRLayerChild> vrLayer =
        static_cast<VRLayerChild*>(manager->CreateVRLayer(mDisplayClient->GetDisplayInfo().GetDisplayID(),
                                                          target, mGroup));
      if (!vrLayer) {
        NS_WARNING("CreateVRLayer returned null!");
        continue;
      }
      vrLayer->Initialize(canvasElement, leftBounds, rightBounds);
      mLayers.AppendElement(vrLayer);
    } else {
      // We already have a layer, let's update it
      mLayers[iLayer]->Initialize(canvasElement, leftBounds, rightBounds);
    }
    iLayer++;
  }

  // Truncate any excess layers that weren't included in the updated list
  mLayers.SetLength(iLayer);
}