summaryrefslogtreecommitdiffstats
path: root/gfx/vr/VRDisplayPresentation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/vr/VRDisplayPresentation.cpp')
-rw-r--r--gfx/vr/VRDisplayPresentation.cpp155
1 files changed, 155 insertions, 0 deletions
diff --git a/gfx/vr/VRDisplayPresentation.cpp b/gfx/vr/VRDisplayPresentation.cpp
new file mode 100644
index 0000000000..127225105b
--- /dev/null
+++ b/gfx/vr/VRDisplayPresentation.cpp
@@ -0,0 +1,155 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "VRDisplayPresentation.h"
+#include "mozilla/dom/DocGroup.h"
+#include "mozilla/dom/Document.h"
+#include "mozilla/dom/XRWebGLLayer.h"
+#include "mozilla/Unused.h"
+#include "VRDisplayClient.h"
+#include "VRLayerChild.h"
+
+using namespace mozilla;
+using namespace mozilla::gfx;
+
+VRDisplayPresentation::VRDisplayPresentation(
+ VRDisplayClient* aDisplayClient,
+ const nsTArray<mozilla::dom::VRLayer>& aLayers, uint32_t aGroup)
+ : mDisplayClient(aDisplayClient),
+ mDOMLayers(aLayers.Clone()),
+ mGroup(aGroup) {
+ CreateLayers();
+}
+
+void VRDisplayPresentation::UpdateLayers(
+ const nsTArray<mozilla::dom::VRLayer>& aLayers) {
+ mDOMLayers = aLayers.Clone();
+ CreateLayers();
+}
+
+void VRDisplayPresentation::UpdateXRWebGLLayer(dom::XRWebGLLayer* aLayer) {
+ 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;
+ }
+
+ dom::HTMLCanvasElement* canvasElement = aLayer->GetCanvas();
+ nsCOMPtr<nsISerialEventTarget> target =
+ canvasElement->OwnerDoc()->EventTargetFor(TaskCategory::Other);
+
+ if (mLayers.Length() == 0) {
+ // WebXR uses a single layer for now.
+ RefPtr<VRLayerChild> vrLayer =
+ static_cast<VRLayerChild*>(manager->CreateVRLayer(
+ mDisplayClient->GetDisplayInfo().GetDisplayID(), target, mGroup));
+ mLayers.AppendElement(vrLayer);
+ }
+ RefPtr<VRLayerChild> vrLayer = mLayers[0];
+
+ Rect leftBounds(0.0, 0.0, 0.5, 1.0);
+ Rect rightBounds(0.5, 0.0, 0.5, 1.0);
+
+ vrLayer->Initialize(canvasElement, leftBounds, rightBounds);
+ vrLayer->SetXRFramebuffer(aLayer->GetFramebuffer());
+}
+
+uint32_t VRDisplayPresentation::GetGroup() const { return mGroup; }
+
+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<nsISerialEventTarget> target =
+ canvasElement->OwnerDoc()->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);
+}
+
+void VRDisplayPresentation::DestroyLayers() {
+ for (VRLayerChild* layer : mLayers) {
+ if (layer->IsIPCOpen()) {
+ Unused << layer->SendDestroy();
+ }
+ }
+ mLayers.Clear();
+}
+
+void VRDisplayPresentation::GetDOMLayers(nsTArray<dom::VRLayer>& result) {
+ result = mDOMLayers.Clone();
+}
+
+VRDisplayPresentation::~VRDisplayPresentation() {
+ DestroyLayers();
+ mDisplayClient->PresentationDestroyed();
+}
+
+void VRDisplayPresentation::SubmitFrame() {
+ for (VRLayerChild* layer : mLayers) {
+ layer->SubmitFrame(mDisplayClient->GetDisplayInfo());
+ break; // Currently only one layer supported, submit only the first
+ }
+}