VRDisplayPresentation.cpp (4894B)
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 #include "mozilla/dom/DocGroup.h" 9 #include "mozilla/dom/Document.h" 10 #include "mozilla/dom/XRWebGLLayer.h" 11 #include "VRDisplayClient.h" 12 #include "VRLayerChild.h" 13 14 using namespace mozilla; 15 using namespace mozilla::gfx; 16 17 VRDisplayPresentation::VRDisplayPresentation( 18 VRDisplayClient* aDisplayClient, 19 const nsTArray<mozilla::dom::VRLayer>& aLayers, uint32_t aGroup) 20 : mDisplayClient(aDisplayClient), 21 mDOMLayers(aLayers.Clone()), 22 mGroup(aGroup) { 23 CreateLayers(); 24 } 25 26 void VRDisplayPresentation::UpdateLayers( 27 const nsTArray<mozilla::dom::VRLayer>& aLayers) { 28 mDOMLayers = aLayers.Clone(); 29 CreateLayers(); 30 } 31 32 void VRDisplayPresentation::UpdateXRWebGLLayer(dom::XRWebGLLayer* aLayer) { 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 dom::HTMLCanvasElement* canvasElement = aLayer->GetCanvas(); 42 43 if (mLayers.Length() == 0) { 44 // WebXR uses a single layer for now. 45 RefPtr<VRLayerChild> vrLayer = 46 static_cast<VRLayerChild*>(manager->CreateVRLayer( 47 mDisplayClient->GetDisplayInfo().GetDisplayID(), mGroup)); 48 mLayers.AppendElement(vrLayer); 49 } 50 RefPtr<VRLayerChild> vrLayer = mLayers[0]; 51 52 Rect leftBounds(0.0, 0.0, 0.5, 1.0); 53 Rect rightBounds(0.5, 0.0, 0.5, 1.0); 54 55 vrLayer->Initialize(canvasElement, leftBounds, rightBounds); 56 vrLayer->SetXRFramebuffer(aLayer->GetFramebuffer()); 57 } 58 59 uint32_t VRDisplayPresentation::GetGroup() const { return mGroup; } 60 61 void VRDisplayPresentation::CreateLayers() { 62 VRManagerChild* manager = VRManagerChild::Get(); 63 if (!manager) { 64 // This should not happen, but let's log it and avoid a crash in case 65 // of regression. 66 NS_WARNING("VRManagerChild::Get returned null!"); 67 return; 68 } 69 70 unsigned int iLayer = 0; 71 for (dom::VRLayer& layer : mDOMLayers) { 72 dom::HTMLCanvasElement* canvasElement = layer.mSource; 73 if (!canvasElement) { 74 /// XXX In the future we will support WebVR in WebWorkers here 75 continue; 76 } 77 78 Rect leftBounds(0.0, 0.0, 0.5, 1.0); 79 if (layer.mLeftBounds.Length() == 4) { 80 leftBounds.SetRect(layer.mLeftBounds[0], layer.mLeftBounds[1], 81 layer.mLeftBounds[2], layer.mLeftBounds[3]); 82 } else if (layer.mLeftBounds.Length() != 0) { 83 /** 84 * We ignore layers with an incorrect number of values. 85 * In the future, VRDisplay.requestPresent may throw in 86 * this case. See https://github.com/w3c/webvr/issues/71 87 */ 88 continue; 89 } 90 91 Rect rightBounds(0.5, 0.0, 0.5, 1.0); 92 if (layer.mRightBounds.Length() == 4) { 93 rightBounds.SetRect(layer.mRightBounds[0], layer.mRightBounds[1], 94 layer.mRightBounds[2], layer.mRightBounds[3]); 95 } else if (layer.mRightBounds.Length() != 0) { 96 /** 97 * We ignore layers with an incorrect number of values. 98 * In the future, VRDisplay.requestPresent may throw in 99 * this case. See https://github.com/w3c/webvr/issues/71 100 */ 101 continue; 102 } 103 104 if (mLayers.Length() <= iLayer) { 105 // Not enough layers, let's add one 106 RefPtr<VRLayerChild> vrLayer = 107 static_cast<VRLayerChild*>(manager->CreateVRLayer( 108 mDisplayClient->GetDisplayInfo().GetDisplayID(), mGroup)); 109 if (!vrLayer) { 110 NS_WARNING("CreateVRLayer returned null!"); 111 continue; 112 } 113 vrLayer->Initialize(canvasElement, leftBounds, rightBounds); 114 mLayers.AppendElement(vrLayer); 115 } else { 116 // We already have a layer, let's update it 117 mLayers[iLayer]->Initialize(canvasElement, leftBounds, rightBounds); 118 } 119 iLayer++; 120 } 121 122 // Truncate any excess layers that weren't included in the updated list 123 mLayers.SetLength(iLayer); 124 } 125 126 void VRDisplayPresentation::DestroyLayers() { 127 for (VRLayerChild* layer : mLayers) { 128 if (layer->IsIPCOpen()) { 129 (void)layer->SendDestroy(); 130 } 131 } 132 mLayers.Clear(); 133 } 134 135 void VRDisplayPresentation::GetDOMLayers(nsTArray<dom::VRLayer>& result) { 136 result = mDOMLayers.Clone(); 137 } 138 139 VRDisplayPresentation::~VRDisplayPresentation() { 140 DestroyLayers(); 141 mDisplayClient->PresentationDestroyed(); 142 } 143 144 void VRDisplayPresentation::SubmitFrame() { 145 // Currently only one layer supported, submit only the first 146 if (mLayers.Length() >= 1) { 147 VRLayerChild* layer = mLayers.ElementAt(0); 148 layer->SubmitFrame(mDisplayClient->GetDisplayInfo()); 149 } 150 }