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
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "VRDisplayPresentation.h"
8
9 #include "mozilla/dom/DocGroup.h"
10 #include "mozilla/Unused.h"
11 #include "VRDisplayClient.h"
12 #include "VRLayerChild.h"
13
14 using namespace mozilla;
15 using namespace mozilla::gfx;
16
VRDisplayPresentation(VRDisplayClient * aDisplayClient,const nsTArray<mozilla::dom::VRLayer> & aLayers,uint32_t aGroup)17 VRDisplayPresentation::VRDisplayPresentation(
18 VRDisplayClient* aDisplayClient,
19 const nsTArray<mozilla::dom::VRLayer>& aLayers, uint32_t aGroup)
20 : mDisplayClient(aDisplayClient), mDOMLayers(aLayers), mGroup(aGroup) {
21 CreateLayers();
22 }
23
UpdateLayers(const nsTArray<mozilla::dom::VRLayer> & aLayers)24 void VRDisplayPresentation::UpdateLayers(
25 const nsTArray<mozilla::dom::VRLayer>& aLayers) {
26 mDOMLayers = aLayers;
27 CreateLayers();
28 }
29
GetGroup() const30 uint32_t VRDisplayPresentation::GetGroup() const { return mGroup; }
31
CreateLayers()32 void VRDisplayPresentation::CreateLayers() {
33 VRManagerChild* manager = VRManagerChild::Get();
34 if (!manager) {
35 // This should not happen, but let's log it and avoid a crash in case
36 // of regression.
37 NS_WARNING("VRManagerChild::Get returned null!");
38 return;
39 }
40
41 unsigned int iLayer = 0;
42 for (dom::VRLayer& layer : mDOMLayers) {
43 dom::HTMLCanvasElement* canvasElement = layer.mSource;
44 if (!canvasElement) {
45 /// XXX In the future we will support WebVR in WebWorkers here
46 continue;
47 }
48
49 Rect leftBounds(0.0, 0.0, 0.5, 1.0);
50 if (layer.mLeftBounds.Length() == 4) {
51 leftBounds.SetRect(layer.mLeftBounds[0], layer.mLeftBounds[1],
52 layer.mLeftBounds[2], layer.mLeftBounds[3]);
53 } else if (layer.mLeftBounds.Length() != 0) {
54 /**
55 * We ignore layers with an incorrect number of values.
56 * In the future, VRDisplay.requestPresent may throw in
57 * this case. See https://github.com/w3c/webvr/issues/71
58 */
59 continue;
60 }
61
62 Rect rightBounds(0.5, 0.0, 0.5, 1.0);
63 if (layer.mRightBounds.Length() == 4) {
64 rightBounds.SetRect(layer.mRightBounds[0], layer.mRightBounds[1],
65 layer.mRightBounds[2], layer.mRightBounds[3]);
66 } else if (layer.mRightBounds.Length() != 0) {
67 /**
68 * We ignore layers with an incorrect number of values.
69 * In the future, VRDisplay.requestPresent may throw in
70 * this case. See https://github.com/w3c/webvr/issues/71
71 */
72 continue;
73 }
74
75 nsCOMPtr<nsIEventTarget> target;
76 nsIDocument* doc;
77 doc = canvasElement->OwnerDoc();
78 if (doc) {
79 target = doc->EventTargetFor(TaskCategory::Other);
80 }
81
82 if (mLayers.Length() <= iLayer) {
83 // Not enough layers, let's add one
84 RefPtr<VRLayerChild> vrLayer =
85 static_cast<VRLayerChild*>(manager->CreateVRLayer(
86 mDisplayClient->GetDisplayInfo().GetDisplayID(), target, mGroup));
87 if (!vrLayer) {
88 NS_WARNING("CreateVRLayer returned null!");
89 continue;
90 }
91 vrLayer->Initialize(canvasElement, leftBounds, rightBounds);
92 mLayers.AppendElement(vrLayer);
93 } else {
94 // We already have a layer, let's update it
95 mLayers[iLayer]->Initialize(canvasElement, leftBounds, rightBounds);
96 }
97 iLayer++;
98 }
99
100 // Truncate any excess layers that weren't included in the updated list
101 mLayers.SetLength(iLayer);
102 }
103
DestroyLayers()104 void VRDisplayPresentation::DestroyLayers() {
105 for (VRLayerChild* layer : mLayers) {
106 if (layer->IsIPCOpen()) {
107 Unused << layer->SendDestroy();
108 }
109 }
110 mLayers.Clear();
111 }
112
GetDOMLayers(nsTArray<dom::VRLayer> & result)113 void VRDisplayPresentation::GetDOMLayers(nsTArray<dom::VRLayer>& result) {
114 result = mDOMLayers;
115 }
116
~VRDisplayPresentation()117 VRDisplayPresentation::~VRDisplayPresentation() {
118 DestroyLayers();
119 mDisplayClient->PresentationDestroyed();
120 }
121
SubmitFrame()122 void VRDisplayPresentation::SubmitFrame() {
123 for (VRLayerChild* layer : mLayers) {
124 layer->SubmitFrame(mDisplayClient->GetDisplayInfo().GetFrameId());
125 break; // Currently only one layer supported, submit only the first
126 }
127 }
128