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

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: Rebase and added further page isolation logic 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
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 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
OLDNEW
« device/vr/vr_device_manager.cc ('K') | « 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