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/dom/Fullscreen.h" |
9 #include "core/inspector/ConsoleMessage.h" | 9 #include "core/inspector/ConsoleMessage.h" |
10 #include "modules/vr/NavigatorVR.h" | 10 #include "modules/vr/NavigatorVR.h" |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
167 if (!m_isPresenting && !UserGestureIndicator::utilizeUserGesture()) { | 167 if (!m_isPresenting && !UserGestureIndicator::utilizeUserGesture()) { |
168 DOMException* exception = DOMException::create(InvalidStateError, "API c an only be initiated by a user gesture."); | 168 DOMException* exception = DOMException::create(InvalidStateError, "API c an only be initiated by a user gesture."); |
169 resolver->reject(exception); | 169 resolver->reject(exception); |
170 return promise; | 170 return promise; |
171 } | 171 } |
172 | 172 |
173 m_isPresenting = false; | 173 m_isPresenting = false; |
174 | 174 |
175 // A valid number of layers must be provided in order to present. | 175 // A valid number of layers must be provided in order to present. |
176 if (layers.size() == 0 || layers.size() > m_capabilities->maxLayers()) { | 176 if (layers.size() == 0 || layers.size() > m_capabilities->maxLayers()) { |
177 forceExitPresent(); | |
177 DOMException* exception = DOMException::create(InvalidStateError, "Inval id number of layers."); | 178 DOMException* exception = DOMException::create(InvalidStateError, "Inval id number of layers."); |
178 if (m_isPresenting) { | |
179 exitPresent(scriptState); | |
180 } | |
181 resolver->reject(exception); | 179 resolver->reject(exception); |
182 return promise; | 180 return promise; |
183 } | 181 } |
184 | 182 |
185 m_layer = layers[0]; | 183 m_layer = layers[0]; |
186 | 184 |
187 if (m_layer.source()) { | 185 if (!m_layer.source()) { |
188 if (!m_capabilities->hasExternalDisplay()) { | 186 forceExitPresent(); |
189 // TODO: Need a proper VR compositor, but for the moment on mobile | |
190 // we'll just make the canvas fullscreen so that VrShell can pick it | |
191 // up through the standard (high latency) compositing path. | |
192 Fullscreen::requestFullscreen(*m_layer.source(), Fullscreen::Unprefi xedRequest); | |
193 | |
194 m_isPresenting = true; | |
195 | |
196 resolver->resolve(); | |
197 | |
198 m_navigatorVR->fireVRDisplayPresentChange(this); | |
199 | |
200 // Check to see if the canvas is still the current fullscreen | |
201 // element once per second. | |
202 m_fullscreenCheckTimer.startRepeating(1.0, BLINK_FROM_HERE); | |
203 | |
204 controller()->requestPresent(m_displayId); | |
205 } else { | |
206 DOMException* exception = DOMException::create(InvalidStateError, "V R Presentation not implemented for this VRDisplay."); | |
207 resolver->reject(exception); | |
208 } | |
209 | |
210 // Set up the texture bounds for the provided layer | |
211 device::blink::VRLayerBoundsPtr leftBounds = device::blink::VRLayerBound s::New(); | |
212 device::blink::VRLayerBoundsPtr rightBounds = device::blink::VRLayerBoun ds::New(); | |
213 | |
214 if (m_layer.hasLeftBounds()) { | |
215 leftBounds->left = m_layer.leftBounds()[0]; | |
216 leftBounds->top = m_layer.leftBounds()[1]; | |
217 leftBounds->width = m_layer.leftBounds()[2]; | |
218 leftBounds->height = m_layer.leftBounds()[3]; | |
219 } else { | |
220 // Left eye defaults | |
221 leftBounds->left = 0.0f; | |
222 leftBounds->top = 0.0f; | |
223 leftBounds->width = 0.5f; | |
224 leftBounds->height = 1.0f; | |
225 } | |
226 | |
227 if (m_layer.hasRightBounds()) { | |
228 rightBounds->left = m_layer.rightBounds()[0]; | |
229 rightBounds->top = m_layer.rightBounds()[1]; | |
230 rightBounds->width = m_layer.rightBounds()[2]; | |
231 rightBounds->height = m_layer.rightBounds()[3]; | |
232 } else { | |
233 // Right eye defaults | |
234 rightBounds->left = 0.5f; | |
235 rightBounds->top = 0.0f; | |
236 rightBounds->width = 0.5f; | |
237 rightBounds->height = 1.0f; | |
238 } | |
239 | |
240 controller()->updateLayerBounds(m_displayId, std::move(leftBounds), std: :move(rightBounds)); | |
241 } else { | |
242 DOMException* exception = DOMException::create(InvalidStateError, "Inval id layer source."); | 187 DOMException* exception = DOMException::create(InvalidStateError, "Inval id layer source."); |
243 resolver->reject(exception); | 188 resolver->reject(exception); |
189 return promise; | |
190 } | |
191 | |
192 CanvasRenderingContext* renderingContext = m_layer.source()->renderingContex t(); | |
193 | |
194 if (!renderingContext || !renderingContext->is3d()) { | |
195 forceExitPresent(); | |
196 DOMException* exception = DOMException::create(InvalidStateError, "Layer source must have a WebGLRenderingContext"); | |
197 resolver->reject(exception); | |
198 return promise; | |
199 } | |
200 | |
201 if (!m_capabilities->hasExternalDisplay()) { | |
202 // TODO: Need a proper VR compositor, but for the moment on mobile | |
203 // we'll just make the canvas fullscreen so that VrShell can pick it | |
204 // up through the standard (high latency) compositing path. | |
205 Fullscreen::requestFullscreen(*m_layer.source(), Fullscreen::UnprefixedR equest); | |
206 | |
207 // Check to see if the canvas is still the current fullscreen | |
208 // element once per second. | |
209 m_fullscreenCheckTimer.startRepeating(1.0, BLINK_FROM_HERE); | |
mthiesse
2016/09/13 18:46:15
ew. I know this is already landed, so don't let my
bajones
2016/09/13 19:42:57
NO! It's not anywhere close to the best way to do
| |
210 } | |
211 | |
212 if (firstPresent) { | |
213 controller()->requestPresent(resolver, m_displayId); | |
214 } else { | |
215 updateLayerBounds(); | |
216 resolver->resolve(); | |
244 } | 217 } |
245 | 218 |
246 return promise; | 219 return promise; |
247 } | 220 } |
248 | 221 |
249 ScriptPromise VRDisplay::exitPresent(ScriptState* scriptState) | 222 ScriptPromise VRDisplay::exitPresent(ScriptState* scriptState) |
250 { | 223 { |
251 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; | 224 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; |
252 ScriptPromise promise = resolver->promise(); | 225 ScriptPromise promise = resolver->promise(); |
253 | 226 |
254 if (!m_isPresenting) { | 227 if (!m_isPresenting) { |
255 // Can't stop presenting if we're not presenting. | 228 // Can't stop presenting if we're not presenting. |
256 DOMException* exception = DOMException::create(InvalidStateError, "VRDis play is not presenting."); | 229 DOMException* exception = DOMException::create(InvalidStateError, "VRDis play is not presenting."); |
257 resolver->reject(exception); | 230 resolver->reject(exception); |
258 return promise; | 231 return promise; |
259 } | 232 } |
260 | 233 |
261 if (!m_capabilities->hasExternalDisplay()) { | 234 controller()->exitPresent(m_displayId); |
262 Fullscreen::fullyExitFullscreen(m_layer.source()->document()); | |
263 m_fullscreenCheckTimer.stop(); | |
264 controller()->exitPresent(m_displayId); | |
265 } else { | |
266 // Can't get into this presentation mode, so nothing to do here. | |
267 } | |
268 | 235 |
269 m_isPresenting = false; | |
270 | |
271 // TODO: Resolve when exit is confirmed | |
272 resolver->resolve(); | 236 resolver->resolve(); |
273 | 237 |
274 m_navigatorVR->fireVRDisplayPresentChange(this); | 238 forceExitPresent(); |
275 | 239 |
276 return promise; | 240 return promise; |
277 } | 241 } |
278 | 242 |
243 void VRDisplay::beginPresent(ScriptPromiseResolver* resolver) | |
244 { | |
245 if (m_capabilities->hasExternalDisplay()) { | |
246 forceExitPresent(); | |
247 DOMException* exception = DOMException::create(InvalidStateError, "VR Pr esentation not implemented for this VRDisplay."); | |
248 resolver->reject(exception); | |
249 return; | |
250 } | |
251 | |
252 m_isPresenting = true; | |
253 | |
254 resolver->resolve(); | |
255 m_navigatorVR->fireVRDisplayPresentChange(this); | |
256 | |
257 updateLayerBounds(); | |
mthiesse
2016/09/13 18:46:15
This feels like it should go before the PresentCha
bajones
2016/09/13 19:42:57
Done.
| |
258 } | |
259 | |
260 void VRDisplay::forceExitPresent() | |
261 { | |
262 if (m_isPresenting) { | |
263 if (!m_capabilities->hasExternalDisplay()) { | |
264 Fullscreen::fullyExitFullscreen(m_layer.source()->document()); | |
265 m_fullscreenCheckTimer.stop(); | |
266 } else { | |
267 // Can't get into this presentation mode, so nothing to do here. | |
268 } | |
269 m_navigatorVR->fireVRDisplayPresentChange(this); | |
270 } | |
271 | |
272 m_isPresenting = false; | |
273 } | |
274 | |
275 void VRDisplay::updateLayerBounds() | |
276 { | |
277 // Set up the texture bounds for the provided layer | |
278 device::blink::VRLayerBoundsPtr leftBounds = device::blink::VRLayerBounds::N ew(); | |
279 device::blink::VRLayerBoundsPtr rightBounds = device::blink::VRLayerBounds:: New(); | |
280 | |
281 if (m_layer.hasLeftBounds()) { | |
282 leftBounds->left = m_layer.leftBounds()[0]; | |
283 leftBounds->top = m_layer.leftBounds()[1]; | |
284 leftBounds->width = m_layer.leftBounds()[2]; | |
285 leftBounds->height = m_layer.leftBounds()[3]; | |
286 } else { | |
287 // Left eye defaults | |
288 leftBounds->left = 0.0f; | |
289 leftBounds->top = 0.0f; | |
290 leftBounds->width = 0.5f; | |
291 leftBounds->height = 1.0f; | |
292 } | |
293 | |
294 if (m_layer.hasRightBounds()) { | |
295 rightBounds->left = m_layer.rightBounds()[0]; | |
296 rightBounds->top = m_layer.rightBounds()[1]; | |
297 rightBounds->width = m_layer.rightBounds()[2]; | |
298 rightBounds->height = m_layer.rightBounds()[3]; | |
299 } else { | |
300 // Right eye defaults | |
301 rightBounds->left = 0.5f; | |
302 rightBounds->top = 0.0f; | |
303 rightBounds->width = 0.5f; | |
304 rightBounds->height = 1.0f; | |
305 } | |
306 | |
307 controller()->updateLayerBounds(m_displayId, std::move(leftBounds), std::mov e(rightBounds)); | |
308 } | |
309 | |
279 HeapVector<VRLayer> VRDisplay::getLayers() | 310 HeapVector<VRLayer> VRDisplay::getLayers() |
280 { | 311 { |
281 HeapVector<VRLayer> layers; | 312 HeapVector<VRLayer> layers; |
282 | 313 |
283 if (m_isPresenting) { | 314 if (m_isPresenting) { |
284 layers.append(m_layer); | 315 layers.append(m_layer); |
285 } | 316 } |
286 | 317 |
287 return layers; | 318 return layers; |
288 } | 319 } |
289 | 320 |
290 void VRDisplay::submitFrame() | 321 void VRDisplay::submitFrame() |
291 { | 322 { |
292 controller()->submitFrame(m_displayId); | 323 controller()->submitFrame(m_displayId, m_framePose.Clone()); |
293 m_canUpdateFramePose = true; | 324 m_canUpdateFramePose = true; |
294 } | 325 } |
295 | 326 |
296 void VRDisplay::onFullscreenCheck(TimerBase*) | 327 void VRDisplay::onFullscreenCheck(TimerBase*) |
297 { | 328 { |
298 // TODO: This is a temporary measure to track if fullscreen mode has been | 329 // TODO: This is a temporary measure to track if fullscreen mode has been |
299 // exited by the UA. If so we need to end VR presentation. Soon we won't | 330 // exited by the UA. If so we need to end VR presentation. Soon we won't |
300 // depend on the Fullscreen API to fake VR presentation, so this will | 331 // depend on the Fullscreen API to fake VR presentation, so this will |
301 // become unnessecary. Until that point, though, this seems preferable to | 332 // become unnessecary. Until that point, though, this seems preferable to |
302 // adding a bunch of notification plumbing to Fullscreen. | 333 // adding a bunch of notification plumbing to Fullscreen. |
303 if (!Fullscreen::isCurrentFullScreenElement(*m_layer.source())) { | 334 if (!Fullscreen::isCurrentFullScreenElement(*m_layer.source())) { |
304 m_isPresenting = false; | 335 m_isPresenting = false; |
305 m_navigatorVR->fireVRDisplayPresentChange(this); | 336 m_navigatorVR->fireVRDisplayPresentChange(this); |
306 m_fullscreenCheckTimer.stop(); | 337 m_fullscreenCheckTimer.stop(); |
307 controller()->exitPresent(m_displayId); | 338 controller()->exitPresent(m_displayId); |
308 } | 339 } |
309 } | 340 } |
310 | 341 |
311 DEFINE_TRACE(VRDisplay) | 342 DEFINE_TRACE(VRDisplay) |
312 { | 343 { |
313 visitor->trace(m_navigatorVR); | 344 visitor->trace(m_navigatorVR); |
314 visitor->trace(m_capabilities); | 345 visitor->trace(m_capabilities); |
315 visitor->trace(m_stageParameters); | 346 visitor->trace(m_stageParameters); |
316 visitor->trace(m_eyeParametersLeft); | 347 visitor->trace(m_eyeParametersLeft); |
317 visitor->trace(m_eyeParametersRight); | 348 visitor->trace(m_eyeParametersRight); |
318 visitor->trace(m_layer); | 349 visitor->trace(m_layer); |
319 } | 350 } |
320 | 351 |
321 } // namespace blink | 352 } // namespace blink |
OLD | NEW |