Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(152)

Side by Side Diff: third_party/WebKit/Source/modules/vr/VRDisplay.cpp

Issue 2329893002: Isolate a presenting VR device from pages other than the one presenting. (Closed)
Patch Set: Unit tests Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/modules/vr/VRDisplay.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; 153 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ;
154 ScriptPromise promise = resolver->promise(); 154 ScriptPromise promise = resolver->promise();
155 155
156 // If the VRDisplay does not advertise the ability to present reject the req uest. 156 // If the VRDisplay does not advertise the ability to present reject the req uest.
157 if (!m_capabilities->canPresent()) { 157 if (!m_capabilities->canPresent()) {
158 DOMException* exception = DOMException::create(InvalidStateError, "VRDis play cannot present."); 158 DOMException* exception = DOMException::create(InvalidStateError, "VRDis play cannot present.");
159 resolver->reject(exception); 159 resolver->reject(exception);
160 return promise; 160 return promise;
161 } 161 }
162 162
163 bool firstPresent = !m_isPresenting;
164
163 // Initiating VR presentation is only allowed in response to a user gesture. 165 // Initiating VR presentation is only allowed in response to a user gesture.
164 // If the VRDisplay is already presenting, however, repeated calls are 166 // If the VRDisplay is already presenting, however, repeated calls are
165 // allowed outside a user gesture so that the presented content may be 167 // allowed outside a user gesture so that the presented content may be
166 // updated. 168 // updated.
167 if (!m_isPresenting && !UserGestureIndicator::utilizeUserGesture()) { 169 if (firstPresent && !UserGestureIndicator::utilizeUserGesture()) {
168 DOMException* exception = DOMException::create(InvalidStateError, "API c an only be initiated by a user gesture."); 170 DOMException* exception = DOMException::create(InvalidStateError, "API c an only be initiated by a user gesture.");
169 resolver->reject(exception); 171 resolver->reject(exception);
170 return promise; 172 return promise;
171 } 173 }
172 174
173 m_isPresenting = false; 175 m_isPresenting = false;
174 176
175 // A valid number of layers must be provided in order to present. 177 // A valid number of layers must be provided in order to present.
176 if (layers.size() == 0 || layers.size() > m_capabilities->maxLayers()) { 178 if (layers.size() == 0 || layers.size() > m_capabilities->maxLayers()) {
179 forceExitPresent();
177 DOMException* exception = DOMException::create(InvalidStateError, "Inval id number of layers."); 180 DOMException* exception = DOMException::create(InvalidStateError, "Inval id number of layers.");
178 if (m_isPresenting) {
179 exitPresent(scriptState);
180 }
181 resolver->reject(exception); 181 resolver->reject(exception);
182 return promise; 182 return promise;
183 } 183 }
184 184
185 m_layer = layers[0]; 185 m_layer = layers[0];
186 186
187 if (m_layer.source()) { 187 if (!m_layer.source()) {
188 if (!m_capabilities->hasExternalDisplay()) { 188 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."); 189 DOMException* exception = DOMException::create(InvalidStateError, "Inval id layer source.");
243 resolver->reject(exception); 190 resolver->reject(exception);
191 return promise;
192 }
193
194 CanvasRenderingContext* renderingContext = m_layer.source()->renderingContex t();
195
196 if (!renderingContext || !renderingContext->is3d()) {
197 forceExitPresent();
198 DOMException* exception = DOMException::create(InvalidStateError, "Layer source must have a WebGLRenderingContext");
199 resolver->reject(exception);
200 return promise;
201 }
202
203 if (!m_capabilities->hasExternalDisplay()) {
204 // TODO: Need a proper VR compositor, but for the moment on mobile
205 // we'll just make the canvas fullscreen so that VrShell can pick it
206 // up through the standard (high latency) compositing path.
207 Fullscreen::requestFullscreen(*m_layer.source(), Fullscreen::UnprefixedR equest);
208
209 // Check to see if the canvas is still the current fullscreen
210 // element once per second.
211 m_fullscreenCheckTimer.startRepeating(1.0, BLINK_FROM_HERE);
212 }
213
214 if (firstPresent) {
215 controller()->requestPresent(resolver, m_displayId);
216 } else {
217 updateLayerBounds();
218 resolver->resolve();
244 } 219 }
245 220
246 return promise; 221 return promise;
247 } 222 }
248 223
249 ScriptPromise VRDisplay::exitPresent(ScriptState* scriptState) 224 ScriptPromise VRDisplay::exitPresent(ScriptState* scriptState)
250 { 225 {
251 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; 226 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ;
252 ScriptPromise promise = resolver->promise(); 227 ScriptPromise promise = resolver->promise();
253 228
254 if (!m_isPresenting) { 229 if (!m_isPresenting) {
255 // Can't stop presenting if we're not presenting. 230 // Can't stop presenting if we're not presenting.
256 DOMException* exception = DOMException::create(InvalidStateError, "VRDis play is not presenting."); 231 DOMException* exception = DOMException::create(InvalidStateError, "VRDis play is not presenting.");
257 resolver->reject(exception); 232 resolver->reject(exception);
258 return promise; 233 return promise;
259 } 234 }
260 235
261 if (!m_capabilities->hasExternalDisplay()) { 236 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 237
269 m_isPresenting = false;
270
271 // TODO: Resolve when exit is confirmed
272 resolver->resolve(); 238 resolver->resolve();
273 239
274 m_navigatorVR->fireVRDisplayPresentChange(this); 240 forceExitPresent();
275 241
276 return promise; 242 return promise;
277 } 243 }
278 244
245 void VRDisplay::beginPresent(ScriptPromiseResolver* resolver)
246 {
247 if (m_capabilities->hasExternalDisplay()) {
248 forceExitPresent();
249 DOMException* exception = DOMException::create(InvalidStateError, "VR Pr esentation not implemented for this VRDisplay.");
250 resolver->reject(exception);
251 return;
252 }
253
254 m_isPresenting = true;
255
256 updateLayerBounds();
257
258 resolver->resolve();
259 m_navigatorVR->fireVRDisplayPresentChange(this);
260 }
261
262 void VRDisplay::forceExitPresent()
263 {
264 if (m_isPresenting) {
265 if (!m_capabilities->hasExternalDisplay()) {
266 Fullscreen::fullyExitFullscreen(m_layer.source()->document());
267 m_fullscreenCheckTimer.stop();
268 } else {
269 // Can't get into this presentation mode, so nothing to do here.
270 }
271 m_navigatorVR->fireVRDisplayPresentChange(this);
272 }
273
274 m_isPresenting = false;
275 }
276
277 void VRDisplay::updateLayerBounds()
278 {
279 // Set up the texture bounds for the provided layer
280 device::blink::VRLayerBoundsPtr leftBounds = device::blink::VRLayerBounds::N ew();
281 device::blink::VRLayerBoundsPtr rightBounds = device::blink::VRLayerBounds:: New();
282
283 if (m_layer.hasLeftBounds()) {
284 leftBounds->left = m_layer.leftBounds()[0];
285 leftBounds->top = m_layer.leftBounds()[1];
286 leftBounds->width = m_layer.leftBounds()[2];
287 leftBounds->height = m_layer.leftBounds()[3];
288 } else {
289 // Left eye defaults
290 leftBounds->left = 0.0f;
291 leftBounds->top = 0.0f;
292 leftBounds->width = 0.5f;
293 leftBounds->height = 1.0f;
294 }
295
296 if (m_layer.hasRightBounds()) {
297 rightBounds->left = m_layer.rightBounds()[0];
298 rightBounds->top = m_layer.rightBounds()[1];
299 rightBounds->width = m_layer.rightBounds()[2];
300 rightBounds->height = m_layer.rightBounds()[3];
301 } else {
302 // Right eye defaults
303 rightBounds->left = 0.5f;
304 rightBounds->top = 0.0f;
305 rightBounds->width = 0.5f;
306 rightBounds->height = 1.0f;
307 }
308
309 controller()->updateLayerBounds(m_displayId, std::move(leftBounds), std::mov e(rightBounds));
310 }
311
279 HeapVector<VRLayer> VRDisplay::getLayers() 312 HeapVector<VRLayer> VRDisplay::getLayers()
280 { 313 {
281 HeapVector<VRLayer> layers; 314 HeapVector<VRLayer> layers;
282 315
283 if (m_isPresenting) { 316 if (m_isPresenting) {
284 layers.append(m_layer); 317 layers.append(m_layer);
285 } 318 }
286 319
287 return layers; 320 return layers;
288 } 321 }
289 322
290 void VRDisplay::submitFrame() 323 void VRDisplay::submitFrame()
291 { 324 {
292 controller()->submitFrame(m_displayId); 325 controller()->submitFrame(m_displayId, m_framePose.Clone());
293 m_canUpdateFramePose = true; 326 m_canUpdateFramePose = true;
294 } 327 }
295 328
296 void VRDisplay::onFullscreenCheck(TimerBase*) 329 void VRDisplay::onFullscreenCheck(TimerBase*)
297 { 330 {
298 // TODO: This is a temporary measure to track if fullscreen mode has been 331 // 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 332 // 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 333 // depend on the Fullscreen API to fake VR presentation, so this will
301 // become unnessecary. Until that point, though, this seems preferable to 334 // become unnessecary. Until that point, though, this seems preferable to
302 // adding a bunch of notification plumbing to Fullscreen. 335 // adding a bunch of notification plumbing to Fullscreen.
303 if (!Fullscreen::isCurrentFullScreenElement(*m_layer.source())) { 336 if (!Fullscreen::isCurrentFullScreenElement(*m_layer.source())) {
304 m_isPresenting = false; 337 m_isPresenting = false;
305 m_navigatorVR->fireVRDisplayPresentChange(this); 338 m_navigatorVR->fireVRDisplayPresentChange(this);
306 m_fullscreenCheckTimer.stop(); 339 m_fullscreenCheckTimer.stop();
307 controller()->exitPresent(m_displayId); 340 controller()->exitPresent(m_displayId);
308 } 341 }
309 } 342 }
310 343
311 DEFINE_TRACE(VRDisplay) 344 DEFINE_TRACE(VRDisplay)
312 { 345 {
313 visitor->trace(m_navigatorVR); 346 visitor->trace(m_navigatorVR);
314 visitor->trace(m_capabilities); 347 visitor->trace(m_capabilities);
315 visitor->trace(m_stageParameters); 348 visitor->trace(m_stageParameters);
316 visitor->trace(m_eyeParametersLeft); 349 visitor->trace(m_eyeParametersLeft);
317 visitor->trace(m_eyeParametersRight); 350 visitor->trace(m_eyeParametersRight);
318 visitor->trace(m_layer); 351 visitor->trace(m_layer);
319 } 352 }
320 353
321 } // namespace blink 354 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/modules/vr/VRDisplay.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698