OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "modules/vr/VRDisplay.h" | 5 #include "modules/vr/VRDisplay.h" |
6 | 6 |
7 #include "core/dom/DOMException.h" | 7 #include "core/dom/DOMException.h" |
| 8 #include "core/dom/Fullscreen.h" |
8 #include "core/inspector/ConsoleMessage.h" | 9 #include "core/inspector/ConsoleMessage.h" |
9 #include "modules/vr/NavigatorVR.h" | 10 #include "modules/vr/NavigatorVR.h" |
10 #include "modules/vr/VRController.h" | 11 #include "modules/vr/VRController.h" |
11 #include "modules/vr/VRDisplayCapabilities.h" | 12 #include "modules/vr/VRDisplayCapabilities.h" |
12 #include "modules/vr/VREyeParameters.h" | 13 #include "modules/vr/VREyeParameters.h" |
13 #include "modules/vr/VRLayer.h" | 14 #include "modules/vr/VRLayer.h" |
14 #include "modules/vr/VRPose.h" | 15 #include "modules/vr/VRPose.h" |
15 #include "modules/vr/VRStageParameters.h" | 16 #include "modules/vr/VRStageParameters.h" |
16 #include "modules/webgl/WebGLRenderingContextBase.h" | 17 #include "modules/webgl/WebGLRenderingContextBase.h" |
17 #include "public/platform/Platform.h" | 18 #include "public/platform/Platform.h" |
(...skipping 15 matching lines...) Expand all Loading... |
33 | 34 |
34 VRDisplay::VRDisplay(NavigatorVR* navigatorVR) | 35 VRDisplay::VRDisplay(NavigatorVR* navigatorVR) |
35 : m_navigatorVR(navigatorVR) | 36 : m_navigatorVR(navigatorVR) |
36 , m_displayId(0) | 37 , m_displayId(0) |
37 , m_isConnected(false) | 38 , m_isConnected(false) |
38 , m_isPresenting(false) | 39 , m_isPresenting(false) |
39 , m_canUpdateFramePose(true) | 40 , m_canUpdateFramePose(true) |
40 , m_capabilities(new VRDisplayCapabilities()) | 41 , m_capabilities(new VRDisplayCapabilities()) |
41 , m_eyeParametersLeft(new VREyeParameters()) | 42 , m_eyeParametersLeft(new VREyeParameters()) |
42 , m_eyeParametersRight(new VREyeParameters()) | 43 , m_eyeParametersRight(new VREyeParameters()) |
| 44 , m_fullscreenCheckTimer(this, &VRDisplay::onFullscreenCheck) |
43 { | 45 { |
44 } | 46 } |
45 | 47 |
46 VRDisplay::~VRDisplay() | 48 VRDisplay::~VRDisplay() |
47 { | 49 { |
48 } | 50 } |
49 | 51 |
50 VRController* VRDisplay::controller() | 52 VRController* VRDisplay::controller() |
51 { | 53 { |
52 return m_navigatorVR->controller(); | 54 return m_navigatorVR->controller(); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 { | 126 { |
125 if (Document* document = m_navigatorVR->document()) | 127 if (Document* document = m_navigatorVR->document()) |
126 document->cancelAnimationFrame(id); | 128 document->cancelAnimationFrame(id); |
127 } | 129 } |
128 | 130 |
129 ScriptPromise VRDisplay::requestPresent(ScriptState* scriptState, const HeapVect
or<VRLayer>& layers) | 131 ScriptPromise VRDisplay::requestPresent(ScriptState* scriptState, const HeapVect
or<VRLayer>& layers) |
130 { | 132 { |
131 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 133 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
132 ScriptPromise promise = resolver->promise(); | 134 ScriptPromise promise = resolver->promise(); |
133 | 135 |
| 136 m_isPresenting = false; |
| 137 |
134 if (!m_capabilities->canPresent()) { | 138 if (!m_capabilities->canPresent()) { |
135 DOMException* exception = DOMException::create(InvalidStateError, "VRDis
play cannot present"); | 139 DOMException* exception = DOMException::create(InvalidStateError, "VRDis
play cannot present"); |
136 resolver->reject(exception); | 140 resolver->reject(exception); |
137 return promise; | 141 return promise; |
138 } | 142 } |
139 | 143 |
140 if (layers.size() == 0 || layers.size() > m_capabilities->maxLayers()) { | 144 if (layers.size() == 0 || layers.size() > m_capabilities->maxLayers()) { |
141 DOMException* exception = DOMException::create(InvalidStateError, "Inval
id number of layers."); | 145 DOMException* exception = DOMException::create(InvalidStateError, "Inval
id number of layers."); |
142 if (m_isPresenting) { | 146 if (m_isPresenting) { |
143 exitPresent(scriptState); | 147 exitPresent(scriptState); |
144 } | 148 } |
145 resolver->reject(exception); | 149 resolver->reject(exception); |
146 return promise; | 150 return promise; |
147 } | 151 } |
148 | 152 |
149 // TODO: Implement VR presentation | 153 m_layer = layers[0]; |
150 NOTIMPLEMENTED(); | |
151 | 154 |
152 DOMException* exception = DOMException::create(InvalidStateError, "VR Presen
tation not implemented"); | 155 if (m_layer.source()) { |
153 resolver->reject(exception); | 156 if (!m_capabilities->hasExternalDisplay()) { |
| 157 // TODO: Need a proper VR compositor, but for the moment on mobile |
| 158 // we'll just make the canvas fullscreen so that VrShell can pick it |
| 159 // up through the standard (high latency) compositing path. |
| 160 Fullscreen::from(m_layer.source()->document()).requestFullscreen(*m_
layer.source(), Fullscreen::UnprefixedRequest); |
| 161 |
| 162 m_isPresenting = true; |
| 163 |
| 164 resolver->resolve(); |
| 165 |
| 166 m_navigatorVR->fireVRDisplayPresentChange(this); |
| 167 |
| 168 // Check to see if the canvas is still the current fullscreen |
| 169 // element once per second. |
| 170 m_fullscreenCheckTimer.startRepeating(1.0, BLINK_FROM_HERE); |
| 171 } else { |
| 172 DOMException* exception = DOMException::create(InvalidStateError, "V
R Presentation not implemented for this VRDisplay"); |
| 173 resolver->reject(exception); |
| 174 } |
| 175 } else { |
| 176 DOMException* exception = DOMException::create(InvalidStateError, "Inval
id layer source"); |
| 177 resolver->reject(exception); |
| 178 } |
154 | 179 |
155 return promise; | 180 return promise; |
156 } | 181 } |
157 | 182 |
158 ScriptPromise VRDisplay::exitPresent(ScriptState* scriptState) | 183 ScriptPromise VRDisplay::exitPresent(ScriptState* scriptState) |
159 { | 184 { |
160 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 185 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
161 ScriptPromise promise = resolver->promise(); | 186 ScriptPromise promise = resolver->promise(); |
162 | 187 |
163 // Can't stop presenting if we're not presenting. | 188 if (!m_isPresenting) { |
164 DOMException* exception = DOMException::create(InvalidStateError, "VRDisplay
is not presenting"); | 189 // Can't stop presenting if we're not presenting. |
165 resolver->reject(exception); | 190 DOMException* exception = DOMException::create(InvalidStateError, "VRDis
play is not presenting"); |
| 191 resolver->reject(exception); |
| 192 return promise; |
| 193 } |
| 194 |
| 195 if (!m_capabilities->hasExternalDisplay()) { |
| 196 Fullscreen::fullyExitFullscreen(m_layer.source()->document()); |
| 197 m_fullscreenCheckTimer.stop(); |
| 198 } else { |
| 199 // Can't get into this presentation mode, so nothing to do here. |
| 200 } |
| 201 |
| 202 m_isPresenting = false; |
| 203 |
| 204 // TODO: Resolve when exit is confirmed |
| 205 resolver->resolve(); |
| 206 |
| 207 m_navigatorVR->fireVRDisplayPresentChange(this); |
| 208 |
166 return promise; | 209 return promise; |
167 } | 210 } |
168 | 211 |
169 HeapVector<VRLayer> VRDisplay::getLayers() | 212 HeapVector<VRLayer> VRDisplay::getLayers() |
170 { | 213 { |
171 HeapVector<VRLayer> layers; | 214 HeapVector<VRLayer> layers; |
| 215 |
| 216 if (m_isPresenting) { |
| 217 layers.append(m_layer); |
| 218 } |
| 219 |
172 return layers; | 220 return layers; |
173 } | 221 } |
174 | 222 |
175 void VRDisplay::submitFrame(VRPose* pose) | 223 void VRDisplay::submitFrame(VRPose* pose) |
176 { | 224 { |
177 NOTIMPLEMENTED(); | |
178 } | 225 } |
179 | 226 |
180 void VRDisplay::didProcessTask() | 227 void VRDisplay::didProcessTask() |
181 { | 228 { |
182 // Pose should be stable until control is returned to the user agent. | 229 // Pose should be stable until control is returned to the user agent. |
183 if (!m_canUpdateFramePose) { | 230 if (!m_canUpdateFramePose) { |
184 Platform::current()->currentThread()->removeTaskObserver(this); | 231 Platform::current()->currentThread()->removeTaskObserver(this); |
185 m_canUpdateFramePose = true; | 232 m_canUpdateFramePose = true; |
186 } | 233 } |
187 } | 234 } |
188 | 235 |
| 236 void VRDisplay::onFullscreenCheck(TimerBase*) |
| 237 { |
| 238 // TODO: This is a temporary measure to track if fullscreen mode has been |
| 239 // exited by the UA. If so we need to end VR presentation. Soon we won't |
| 240 // depend on the Fullscreen API to fake VR presentation, so this will |
| 241 // become unnessecary. Until that point, though, this seems preferable to |
| 242 // adding a bunch of notification plumbing to Fullscreen. |
| 243 if (!Fullscreen::isCurrentFullScreenElement(*m_layer.source())) { |
| 244 m_isPresenting = false; |
| 245 m_navigatorVR->fireVRDisplayPresentChange(this); |
| 246 m_fullscreenCheckTimer.stop(); |
| 247 } |
| 248 } |
| 249 |
189 DEFINE_TRACE(VRDisplay) | 250 DEFINE_TRACE(VRDisplay) |
190 { | 251 { |
191 visitor->trace(m_navigatorVR); | 252 visitor->trace(m_navigatorVR); |
192 visitor->trace(m_capabilities); | 253 visitor->trace(m_capabilities); |
193 visitor->trace(m_stageParameters); | 254 visitor->trace(m_stageParameters); |
194 visitor->trace(m_eyeParametersLeft); | 255 visitor->trace(m_eyeParametersLeft); |
195 visitor->trace(m_eyeParametersRight); | 256 visitor->trace(m_eyeParametersRight); |
196 visitor->trace(m_framePose); | 257 visitor->trace(m_framePose); |
| 258 visitor->trace(m_layer); |
197 } | 259 } |
198 | 260 |
199 } // namespace blink | 261 } // namespace blink |
OLD | NEW |