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

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

Issue 2739973002: Revert of WebVR compositor bypass via BrowserMain context + mailbox (Closed)
Patch Set: Created 3 years, 9 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/css/StylePropertySet.h" 7 #include "core/css/StylePropertySet.h"
8 #include "core/dom/DOMException.h" 8 #include "core/dom/DOMException.h"
9 #include "core/dom/DocumentUserGestureToken.h" 9 #include "core/dom/DocumentUserGestureToken.h"
10 #include "core/dom/FrameRequestCallback.h" 10 #include "core/dom/FrameRequestCallback.h"
11 #include "core/dom/Fullscreen.h"
11 #include "core/dom/ScriptedAnimationController.h" 12 #include "core/dom/ScriptedAnimationController.h"
12 #include "core/dom/TaskRunnerHelper.h" 13 #include "core/dom/TaskRunnerHelper.h"
13 #include "core/frame/FrameView.h"
14 #include "core/frame/ImageBitmap.h"
15 #include "core/frame/UseCounter.h" 14 #include "core/frame/UseCounter.h"
16 #include "core/inspector/ConsoleMessage.h" 15 #include "core/inspector/ConsoleMessage.h"
17 #include "core/layout/LayoutView.h"
18 #include "core/layout/compositing/PaintLayerCompositor.h"
19 #include "core/loader/DocumentLoader.h" 16 #include "core/loader/DocumentLoader.h"
20 #include "gpu/command_buffer/client/gles2_interface.h" 17 #include "gpu/command_buffer/client/gles2_interface.h"
21 #include "gpu/command_buffer/common/mailbox_holder.h"
22 #include "modules/EventTargetModules.h" 18 #include "modules/EventTargetModules.h"
23 #include "modules/vr/NavigatorVR.h" 19 #include "modules/vr/NavigatorVR.h"
24 #include "modules/vr/VRController.h" 20 #include "modules/vr/VRController.h"
25 #include "modules/vr/VRDisplayCapabilities.h" 21 #include "modules/vr/VRDisplayCapabilities.h"
26 #include "modules/vr/VREyeParameters.h" 22 #include "modules/vr/VREyeParameters.h"
27 #include "modules/vr/VRFrameData.h" 23 #include "modules/vr/VRFrameData.h"
28 #include "modules/vr/VRLayer.h" 24 #include "modules/vr/VRLayer.h"
29 #include "modules/vr/VRPose.h" 25 #include "modules/vr/VRPose.h"
30 #include "modules/vr/VRStageParameters.h" 26 #include "modules/vr/VRStageParameters.h"
31 #include "modules/webgl/WebGLRenderingContextBase.h" 27 #include "modules/webgl/WebGLRenderingContextBase.h"
32 #include "platform/Histogram.h" 28 #include "platform/Histogram.h"
33 #include "platform/UserGestureIndicator.h" 29 #include "platform/UserGestureIndicator.h"
34 #include "platform/instrumentation/tracing/TraceEvent.h"
35 #include "public/platform/Platform.h" 30 #include "public/platform/Platform.h"
36 #include "wtf/AutoReset.h" 31 #include "wtf/AutoReset.h"
37 #include "wtf/Time.h" 32 #include "wtf/Time.h"
38 33
39 #include <array> 34 #include <array>
40 35
41 namespace blink { 36 namespace blink {
42 37
43 namespace { 38 namespace {
44 39
40 // Magic numbers used to mark valid pose index values encoded in frame
41 // data. Must match the magic numbers used in vr_shell.cc.
42 static constexpr std::array<uint8_t, 2> kWebVrPosePixelMagicNumbers{{42, 142}};
43
45 VREye stringToVREye(const String& whichEye) { 44 VREye stringToVREye(const String& whichEye) {
46 if (whichEye == "left") 45 if (whichEye == "left")
47 return VREyeLeft; 46 return VREyeLeft;
48 if (whichEye == "right") 47 if (whichEye == "right")
49 return VREyeRight; 48 return VREyeRight;
50 return VREyeNone; 49 return VREyeNone;
51 } 50 }
52 51
53 } // namespace 52 } // namespace
54 53
55 VRDisplay::VRDisplay(NavigatorVR* navigatorVR, 54 VRDisplay::VRDisplay(NavigatorVR* navigatorVR,
56 device::mojom::blink::VRDisplayPtr display, 55 device::mojom::blink::VRDisplayPtr display,
57 device::mojom::blink::VRDisplayClientRequest request) 56 device::mojom::blink::VRDisplayClientRequest request)
58 : ContextLifecycleObserver(navigatorVR->document()), 57 : ContextLifecycleObserver(navigatorVR->document()),
59 m_navigatorVR(navigatorVR), 58 m_navigatorVR(navigatorVR),
60 m_capabilities(new VRDisplayCapabilities()), 59 m_capabilities(new VRDisplayCapabilities()),
61 m_eyeParametersLeft(new VREyeParameters()), 60 m_eyeParametersLeft(new VREyeParameters()),
62 m_eyeParametersRight(new VREyeParameters()), 61 m_eyeParametersRight(new VREyeParameters()),
62 m_fullscreenCheckTimer(
63 TaskRunnerHelper::get(TaskType::UnspecedTimer,
64 navigatorVR->document()->frame()),
65 this,
66 &VRDisplay::onFullscreenCheck),
63 m_display(std::move(display)), 67 m_display(std::move(display)),
64 m_submit_frame_client_binding(this),
65 m_displayClientBinding(this, std::move(request)) {} 68 m_displayClientBinding(this, std::move(request)) {}
66 69
67 VRDisplay::~VRDisplay() {} 70 VRDisplay::~VRDisplay() {}
68 71
69 VRController* VRDisplay::controller() { 72 VRController* VRDisplay::controller() {
70 return m_navigatorVR->controller(); 73 return m_navigatorVR->controller();
71 } 74 }
72 75
73 void VRDisplay::update(const device::mojom::blink::VRDisplayInfoPtr& display) { 76 void VRDisplay::update(const device::mojom::blink::VRDisplayInfoPtr& display) {
74 m_displayId = display->index; 77 m_displayId = display->index;
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 // allowed outside a user gesture so that the presented content may be 232 // allowed outside a user gesture so that the presented content may be
230 // updated. 233 // updated.
231 if (firstPresent && !UserGestureIndicator::utilizeUserGesture()) { 234 if (firstPresent && !UserGestureIndicator::utilizeUserGesture()) {
232 DOMException* exception = DOMException::create( 235 DOMException* exception = DOMException::create(
233 InvalidStateError, "API can only be initiated by a user gesture."); 236 InvalidStateError, "API can only be initiated by a user gesture.");
234 resolver->reject(exception); 237 resolver->reject(exception);
235 ReportPresentationResult(PresentationResult::NotInitiatedByUserGesture); 238 ReportPresentationResult(PresentationResult::NotInitiatedByUserGesture);
236 return promise; 239 return promise;
237 } 240 }
238 241
242 // TODO(mthiesse): Remove fullscreen requirement for presentation. See
243 // crbug.com/687369
244 Document* doc = this->document();
245 if (!doc || !Fullscreen::fullscreenEnabled(*doc)) {
246 DOMException* exception =
247 DOMException::create(InvalidStateError, "Fullscreen is not enabled.");
248 resolver->reject(exception);
249 ReportPresentationResult(PresentationResult::FullscreenNotEnabled);
250 return promise;
251 }
252
239 // A valid number of layers must be provided in order to present. 253 // A valid number of layers must be provided in order to present.
240 if (layers.size() == 0 || layers.size() > m_capabilities->maxLayers()) { 254 if (layers.size() == 0 || layers.size() > m_capabilities->maxLayers()) {
241 forceExitPresent(); 255 forceExitPresent();
242 DOMException* exception = 256 DOMException* exception =
243 DOMException::create(InvalidStateError, "Invalid number of layers."); 257 DOMException::create(InvalidStateError, "Invalid number of layers.");
244 resolver->reject(exception); 258 resolver->reject(exception);
245 ReportPresentationResult(PresentationResult::InvalidNumberOfLayers); 259 ReportPresentationResult(PresentationResult::InvalidNumberOfLayers);
246 return promise; 260 return promise;
247 } 261 }
248 262
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 bool secureContext = scriptState->getExecutionContext()->isSecureContext(); 317 bool secureContext = scriptState->getExecutionContext()->isSecureContext();
304 if (!m_display) { 318 if (!m_display) {
305 forceExitPresent(); 319 forceExitPresent();
306 DOMException* exception = DOMException::create( 320 DOMException* exception = DOMException::create(
307 InvalidStateError, "The service is no longer active."); 321 InvalidStateError, "The service is no longer active.");
308 resolver->reject(exception); 322 resolver->reject(exception);
309 return promise; 323 return promise;
310 } 324 }
311 325
312 m_pendingPresentResolvers.append(resolver); 326 m_pendingPresentResolvers.append(resolver);
313 m_submit_frame_client_binding.Close(); 327 m_display->RequestPresent(secureContext, convertToBaseCallback(WTF::bind(
314 m_display->RequestPresent( 328 &VRDisplay::onPresentComplete,
315 secureContext, 329 wrapPersistent(this))));
316 m_submit_frame_client_binding.CreateInterfacePtrAndBind(),
317 convertToBaseCallback(
318 WTF::bind(&VRDisplay::onPresentComplete, wrapPersistent(this))));
319 } else { 330 } else {
320 updateLayerBounds(); 331 updateLayerBounds();
321 resolver->resolve(); 332 resolver->resolve();
322 ReportPresentationResult(PresentationResult::SuccessAlreadyPresenting); 333 ReportPresentationResult(PresentationResult::SuccessAlreadyPresenting);
323 } 334 }
324 335
325 return promise; 336 return promise;
326 } 337 }
327 338
328 void VRDisplay::onPresentComplete(bool success) { 339 void VRDisplay::onPresentComplete(bool success) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 "VR Presentation not implemented for this VRDisplay."); 388 "VR Presentation not implemented for this VRDisplay.");
378 while (!m_pendingPresentResolvers.isEmpty()) { 389 while (!m_pendingPresentResolvers.isEmpty()) {
379 ScriptPromiseResolver* resolver = m_pendingPresentResolvers.takeFirst(); 390 ScriptPromiseResolver* resolver = m_pendingPresentResolvers.takeFirst();
380 resolver->reject(exception); 391 resolver->reject(exception);
381 } 392 }
382 ReportPresentationResult( 393 ReportPresentationResult(
383 PresentationResult::PresentationNotSupportedByDisplay); 394 PresentationResult::PresentationNotSupportedByDisplay);
384 return; 395 return;
385 } else { 396 } else {
386 if (m_layer.source().isHTMLCanvasElement()) { 397 if (m_layer.source().isHTMLCanvasElement()) {
387 // TODO(klausw,crbug.com/698923): suppress compositor updates 398 HTMLCanvasElement* canvas = m_layer.source().getAsHTMLCanvasElement();
388 // since they aren't needed, they do a fair amount of extra 399 // TODO(klausw,crbug.com/655722): Need a proper VR compositor, but
389 // work. 400 // for the moment on mobile we'll just make the canvas fullscreen
401 // so that VrShell can pick it up through the standard (high
402 // latency) compositing path. auto canvas =
403 // m_layer.source().getAsHTMLCanvasElement();
404 auto inlineStyle = canvas->inlineStyle();
405 if (inlineStyle) {
406 // THREE.js's VREffect sets explicit style.width/height on its rendering
407 // canvas based on the non-fullscreen window dimensions, and it keeps
408 // those unchanged when presenting. Unfortunately it appears that a
409 // fullscreened canvas just gets centered if it has explicitly set a
410 // size smaller than the fullscreen dimensions. Manually set size to
411 // 100% in this case and restore it when exiting fullscreen. This is a
412 // stopgap measure since THREE.js's usage appears legal according to the
413 // WebVR API spec. This will no longer be necessary once we can get rid
414 // of this fullscreen hack.
415 m_fullscreenOrigWidth = inlineStyle->getPropertyValue(CSSPropertyWidth);
416 if (!m_fullscreenOrigWidth.isNull()) {
417 canvas->setInlineStyleProperty(CSSPropertyWidth, "100%");
418 }
419 m_fullscreenOrigHeight =
420 inlineStyle->getPropertyValue(CSSPropertyHeight);
421 if (!m_fullscreenOrigHeight.isNull()) {
422 canvas->setInlineStyleProperty(CSSPropertyHeight, "100%");
423 }
424 } else {
425 m_fullscreenOrigWidth = String();
426 m_fullscreenOrigHeight = String();
427 }
428
429 if (doc) {
430 // Since the callback for requestPresent is asynchronous, we've lost our
431 // UserGestureToken, and need to create a new one to enter fullscreen.
432 gestureIndicator = WTF::wrapUnique(
433 new UserGestureIndicator(DocumentUserGestureToken::create(
434 doc, UserGestureToken::Status::PossiblyExistingGesture)));
435 }
436 Fullscreen::requestFullscreen(*canvas);
437
438 // Check to see if the canvas is still the current fullscreen
439 // element once every 2 seconds.
440 m_fullscreenCheckTimer.startRepeating(2.0, BLINK_FROM_HERE);
441 m_reenteredFullscreen = false;
390 } else { 442 } else {
391 DCHECK(m_layer.source().isOffscreenCanvas()); 443 DCHECK(m_layer.source().isOffscreenCanvas());
392 // TODO(junov, crbug.com/695497): Implement OffscreenCanvas presentation 444 // TODO(junov, crbug.com/695497): Implement OffscreenCanvas presentation
393 forceExitPresent(); 445 forceExitPresent();
394 DOMException* exception = DOMException::create( 446 DOMException* exception = DOMException::create(
395 InvalidStateError, "OffscreenCanvas presentation not implemented."); 447 InvalidStateError, "OffscreenCanvas presentation not implemented.");
396 while (!m_pendingPresentResolvers.isEmpty()) { 448 while (!m_pendingPresentResolvers.isEmpty()) {
397 ScriptPromiseResolver* resolver = m_pendingPresentResolvers.takeFirst(); 449 ScriptPromiseResolver* resolver = m_pendingPresentResolvers.takeFirst();
398 resolver->reject(exception); 450 resolver->reject(exception);
399 } 451 }
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 } else { 512 } else {
461 // Right eye defaults 513 // Right eye defaults
462 rightBounds->left = 0.5f; 514 rightBounds->left = 0.5f;
463 rightBounds->top = 0.0f; 515 rightBounds->top = 0.0f;
464 rightBounds->width = 0.5f; 516 rightBounds->width = 0.5f;
465 rightBounds->height = 1.0f; 517 rightBounds->height = 1.0f;
466 m_layer.setRightBounds({0.5f, 0.0f, 0.5f, 1.0f}); 518 m_layer.setRightBounds({0.5f, 0.0f, 0.5f, 1.0f});
467 } 519 }
468 520
469 m_display->UpdateLayerBounds(m_vrFrameId, std::move(leftBounds), 521 m_display->UpdateLayerBounds(m_vrFrameId, std::move(leftBounds),
470 std::move(rightBounds), m_sourceWidth, 522 std::move(rightBounds));
471 m_sourceHeight);
472 } 523 }
473 524
474 HeapVector<VRLayer> VRDisplay::getLayers() { 525 HeapVector<VRLayer> VRDisplay::getLayers() {
475 HeapVector<VRLayer> layers; 526 HeapVector<VRLayer> layers;
476 527
477 if (m_isPresenting) { 528 if (m_isPresenting) {
478 layers.push_back(m_layer); 529 layers.push_back(m_layer);
479 } 530 }
480 531
481 return layers; 532 return layers;
482 } 533 }
483 534
484 void VRDisplay::submitFrame() { 535 void VRDisplay::submitFrame() {
485 if (!m_display) 536 if (!m_display)
486 return; 537 return;
487 TRACE_EVENT1("gpu", "submitFrame", "frame", m_vrFrameId);
488 538
489 Document* doc = this->document(); 539 Document* doc = this->document();
490 if (!m_isPresenting) { 540 if (!m_isPresenting) {
491 if (doc) { 541 if (doc) {
492 doc->addConsoleMessage(ConsoleMessage::create( 542 doc->addConsoleMessage(ConsoleMessage::create(
493 RenderingMessageSource, WarningMessageLevel, 543 RenderingMessageSource, WarningMessageLevel,
494 "submitFrame has no effect when the VRDisplay is not presenting.")); 544 "submitFrame has no effect when the VRDisplay is not presenting."));
495 } 545 }
496 return; 546 return;
497 } 547 }
498 548
499 if (!m_inAnimationFrame) { 549 if (!m_inAnimationFrame) {
500 if (doc) { 550 if (doc) {
501 doc->addConsoleMessage( 551 doc->addConsoleMessage(
502 ConsoleMessage::create(RenderingMessageSource, WarningMessageLevel, 552 ConsoleMessage::create(RenderingMessageSource, WarningMessageLevel,
503 "submitFrame must be called within a " 553 "submitFrame must be called within a "
504 "VRDisplay.requestAnimationFrame callback.")); 554 "VRDisplay.requestAnimationFrame callback."));
505 } 555 }
506 return; 556 return;
507 } 557 }
508 558
509 if (!m_contextGL) { 559 if (!m_contextGL) {
510 // Something got confused, we can't submit frames without a GL context. 560 // Something got confused, we can't submit frames without a GL context.
511 return; 561 return;
512 } 562 }
513 563
514 // No frame Id to write before submitting the frame. 564 // No frame Id to write before submitting the frame.
515 if (m_vrFrameId < 0) { 565 if (m_vrFrameId < 0) {
516 // TODO(klausw): There used to be a submitFrame here, but we can't 566 m_display->SubmitFrame(m_framePose.Clone());
517 // submit without a frameId and associated pose data. Just drop it.
518 return; 567 return;
519 } 568 }
520 569
521 m_contextGL->Flush(); 570 // Write the frame number for the pose used into a bottom left pixel block.
522 auto elem = m_layer.source(); 571 // It is read by chrome/browser/android/vr_shell/vr_shell.cc to associate
572 // the correct corresponding pose for submission.
573 auto gl = m_contextGL;
523 574
524 // Check if the canvas got resized, if yes send a bounds update. 575 // We must ensure that the WebGL app's GL state is preserved. We do this by
525 int currentWidth = m_renderingContext->drawingBufferWidth(); 576 // calling low-level GL commands directly so that the rendering context's
526 int currentHeight = m_renderingContext->drawingBufferHeight(); 577 // saved parameters don't get overwritten.
527 if ((currentWidth != m_sourceWidth || currentHeight != m_sourceHeight) &&
528 currentWidth != 0 && currentHeight != 0) {
529 m_sourceWidth = currentWidth;
530 m_sourceHeight = currentHeight;
531 updateLayerBounds();
532 }
533 578
534 // There's two types of synchronization needed for submitting frames: 579 gl->Enable(GL_SCISSOR_TEST);
535 // 580 // Use a few pixels to ensure we get a clean color. The resolution for the
536 // - Before submitting, need to wait for the previous frame to be 581 // WebGL buffer may not match the final rendered destination size, and
537 // pulled off the transfer surface to avoid lost frames. This 582 // texture filtering could interfere for single pixels. This isn't visible
538 // is currently a compile-time option, normally we always want 583 // since the final rendering hides the edges via a vignette effect.
539 // to defer this wait to increase parallelism. 584 gl->Scissor(0, 0, 4, 4);
540 // 585 gl->ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
541 // - After submitting, need to wait for the mailbox to be consumed, 586 // Careful with the arithmetic here. Float color 1.f is equivalent to int 255.
542 // and must remain inside the execution context while waiting. 587 // Use the low byte of the index as the red component, and store an arbitrary
543 // The waitForPreviousTransferToFinish option defers this wait 588 // magic number in green/blue. This number must match the reading code in
544 // until the next frame. That's more efficient, but seems to 589 // vr_shell.cc. Avoid all-black/all-white.
545 // cause wobbly framerates. 590 gl->ClearColor((m_vrFrameId & 255) / 255.0f,
546 bool waitForPreviousTransferToFinish = 591 kWebVrPosePixelMagicNumbers[0] / 255.0f,
547 RuntimeEnabledFeatures::webVRExperimentalRenderingEnabled(); 592 kWebVrPosePixelMagicNumbers[1] / 255.0f, 1.0f);
593 gl->Clear(GL_COLOR_BUFFER_BIT);
548 594
549 if (waitForPreviousTransferToFinish) { 595 // Set the GL state back to what was set by the WebVR application.
550 TRACE_EVENT0("gpu", "VRDisplay::waitForPreviousTransferToFinish"); 596 m_renderingContext->restoreScissorEnabled();
551 while (m_pendingSubmitFrame) { 597 m_renderingContext->restoreScissorBox();
552 if (!m_submit_frame_client_binding.WaitForIncomingMethodCall()) { 598 m_renderingContext->restoreColorMask();
553 DLOG(ERROR) << "Failed to receive SubmitFrame response"; 599 m_renderingContext->restoreClearColor();
554 break;
555 }
556 }
557 }
558 600
559 RefPtr<Image> imageRef = m_renderingContext->getImage( 601 m_display->SubmitFrame(m_framePose.Clone());
560 PreferAcceleration, SnapshotReasonCreateImageBitmap);
561
562 // Hardware-accelerated rendering should always be texture backed.
563 // I hope nobody is trying to do WebVR with software rendering.
564 DCHECK(imageRef->isTextureBacked());
565
566 // The AcceleratedStaticBitmapImage must be kept alive until the
567 // mailbox is used via createAndConsumeTextureCHROMIUM, the mailbox
568 // itself does not keep it alive. We must keep a reference to the
569 // image until the mailbox was consumed.
570 StaticBitmapImage* staticImage =
571 static_cast<StaticBitmapImage*>(imageRef.get());
572 staticImage->ensureMailbox();
573
574 if (waitForPreviousTransferToFinish) {
575 // Save a reference to the image to keep it alive until next frame,
576 // where we'll wait for the transfer to finish before overwriting
577 // it.
578 m_previousImage = std::move(imageRef);
579 }
580
581 // Wait for the previous render to finish, to avoid losing frames in the
582 // Android Surface / GLConsumer pair. TODO(klausw): make this tunable?
583 // Other devices may have different preferences.
584 {
585 TRACE_EVENT0("gpu", "waitForPreviousRenderToFinish");
586 while (m_pendingPreviousFrameRender) {
587 if (!m_submit_frame_client_binding.WaitForIncomingMethodCall()) {
588 DLOG(ERROR) << "Failed to receive SubmitFrame response";
589 break;
590 }
591 }
592 }
593
594 m_pendingPreviousFrameRender = true;
595 m_pendingSubmitFrame = true;
596 m_display->SubmitFrame(
597 m_vrFrameId, gpu::MailboxHolder(staticImage->mailbox(),
598 staticImage->syncToken(), GL_TEXTURE_2D));
599
600 // If we're not deferring the wait for transferring the mailbox,
601 // we need to wait for it now to prevent the image going out of
602 // scope before its mailbox is retrieved.
603 if (!waitForPreviousTransferToFinish) {
604 TRACE_EVENT0("gpu", "waitForCurrentTransferToFinish");
605 while (m_pendingSubmitFrame) {
606 if (!m_submit_frame_client_binding.WaitForIncomingMethodCall()) {
607 DLOG(ERROR) << "Failed to receive SubmitFrame response";
608 break;
609 }
610 }
611 }
612 }
613
614 void VRDisplay::OnSubmitFrameTransferred() {
615 m_pendingSubmitFrame = false;
616 }
617
618 void VRDisplay::OnSubmitFrameRendered() {
619 m_pendingPreviousFrameRender = false;
620 } 602 }
621 603
622 Document* VRDisplay::document() { 604 Document* VRDisplay::document() {
623 return m_navigatorVR->document(); 605 return m_navigatorVR->document();
624 } 606 }
625 607
626 void VRDisplay::OnPresentChange() { 608 void VRDisplay::OnPresentChange() {
627 if (m_isPresenting && !m_isValidDeviceForPresenting) { 609 if (m_isPresenting && !m_isValidDeviceForPresenting) {
628 DVLOG(1) << __FUNCTION__ << ": device not valid, not sending event"; 610 VLOG(1) << __FUNCTION__ << ": device not valid, not sending event";
629 return; 611 return;
630 } 612 }
631 m_navigatorVR->enqueueVREvent(VRDisplayEvent::create( 613 m_navigatorVR->enqueueVREvent(VRDisplayEvent::create(
632 EventTypeNames::vrdisplaypresentchange, true, false, this, "")); 614 EventTypeNames::vrdisplaypresentchange, true, false, this, ""));
633 } 615 }
634 616
635 void VRDisplay::OnChanged(device::mojom::blink::VRDisplayInfoPtr display) { 617 void VRDisplay::OnChanged(device::mojom::blink::VRDisplayInfoPtr display) {
636 update(display); 618 update(display);
637 } 619 }
638 620
639 void VRDisplay::OnExitPresent() { 621 void VRDisplay::OnExitPresent() {
640 stopPresenting(); 622 stopPresenting();
641 } 623 }
642 624
643 void VRDisplay::onConnected() { 625 void VRDisplay::onConnected() {
644 m_navigatorVR->enqueueVREvent(VRDisplayEvent::create( 626 m_navigatorVR->enqueueVREvent(VRDisplayEvent::create(
645 EventTypeNames::vrdisplayconnect, true, false, this, "connect")); 627 EventTypeNames::vrdisplayconnect, true, false, this, "connect"));
646 } 628 }
647 629
648 void VRDisplay::onDisconnected() { 630 void VRDisplay::onDisconnected() {
649 m_navigatorVR->enqueueVREvent(VRDisplayEvent::create( 631 m_navigatorVR->enqueueVREvent(VRDisplayEvent::create(
650 EventTypeNames::vrdisplaydisconnect, true, false, this, "disconnect")); 632 EventTypeNames::vrdisplaydisconnect, true, false, this, "disconnect"));
651 } 633 }
652 634
653 void VRDisplay::stopPresenting() { 635 void VRDisplay::stopPresenting() {
654 if (m_isPresenting) { 636 if (m_isPresenting) {
655 if (!m_capabilities->hasExternalDisplay()) { 637 if (!m_capabilities->hasExternalDisplay()) {
656 if (m_layer.source().isHTMLCanvasElement()) { 638 if (m_layer.source().isHTMLCanvasElement()) {
657 // TODO(klausw,crbug.com/698923): If compositor updates are 639 auto canvas = m_layer.source().getAsHTMLCanvasElement();
658 // suppressed, restore them here. 640 Fullscreen::fullyExitFullscreen(canvas->document());
641 m_fullscreenCheckTimer.stop();
642 if (!m_fullscreenOrigWidth.isNull()) {
643 canvas->setInlineStyleProperty(CSSPropertyWidth,
644 m_fullscreenOrigWidth);
645 m_fullscreenOrigWidth = String();
646 }
647 if (!m_fullscreenOrigHeight.isNull()) {
648 canvas->setInlineStyleProperty(CSSPropertyWidth,
649 m_fullscreenOrigHeight);
650 m_fullscreenOrigHeight = String();
651 }
659 } else { 652 } else {
660 // TODO(junov, crbug.com/695497): Implement for OffscreenCanvas 653 // TODO(junov, crbug.com/695497): Implement for OffscreenCanvas
661 } 654 }
662 } else { 655 } else {
663 // Can't get into this presentation mode, so nothing to do here. 656 // Can't get into this presentation mode, so nothing to do here.
664 } 657 }
665 m_isPresenting = false; 658 m_isPresenting = false;
666 OnPresentChange(); 659 OnPresentChange();
667 } 660 }
668 661
669 m_renderingContext = nullptr; 662 m_renderingContext = nullptr;
670 m_contextGL = nullptr; 663 m_contextGL = nullptr;
671 m_pendingSubmitFrame = false;
672 m_pendingPreviousFrameRender = false;
673 } 664 }
674 665
675 void VRDisplay::OnActivate(device::mojom::blink::VRDisplayEventReason reason) { 666 void VRDisplay::OnActivate(device::mojom::blink::VRDisplayEventReason reason) {
676 if (!m_navigatorVR->isFocused() || m_displayBlurred) 667 if (!m_navigatorVR->isFocused() || m_displayBlurred)
677 return; 668 return;
678 m_navigatorVR->dispatchVRGestureEvent(VRDisplayEvent::create( 669 m_navigatorVR->dispatchVRGestureEvent(VRDisplayEvent::create(
679 EventTypeNames::vrdisplayactivate, true, false, this, reason)); 670 EventTypeNames::vrdisplayactivate, true, false, this, reason));
680 } 671 }
681 672
682 void VRDisplay::OnDeactivate( 673 void VRDisplay::OnDeactivate(
683 device::mojom::blink::VRDisplayEventReason reason) { 674 device::mojom::blink::VRDisplayEventReason reason) {
684 m_navigatorVR->enqueueVREvent(VRDisplayEvent::create( 675 m_navigatorVR->enqueueVREvent(VRDisplayEvent::create(
685 EventTypeNames::vrdisplaydeactivate, true, false, this, reason)); 676 EventTypeNames::vrdisplaydeactivate, true, false, this, reason));
686 } 677 }
687 678
688 void VRDisplay::OnVSync(device::mojom::blink::VRPosePtr pose, 679 void VRDisplay::OnVSync(device::mojom::blink::VRPosePtr pose,
689 mojo::common::mojom::blink::TimeDeltaPtr time, 680 mojo::common::mojom::blink::TimeDeltaPtr time,
690 int16_t frameId, 681 int16_t frameId,
691 device::mojom::blink::VRVSyncProvider::Status error) { 682 device::mojom::blink::VRVSyncProvider::Status error) {
692 switch (error) { 683 switch (error) {
693 case device::mojom::blink::VRVSyncProvider::Status::SUCCESS: 684 case device::mojom::blink::VRVSyncProvider::Status::SUCCESS:
694 break; 685 break;
695 case device::mojom::blink::VRVSyncProvider::Status::CLOSING: 686 case device::mojom::blink::VRVSyncProvider::Status::RETRY:
687 m_vrVSyncProvider->GetVSync(convertToBaseCallback(
688 WTF::bind(&VRDisplay::OnVSync, wrapWeakPersistent(this))));
696 return; 689 return;
697 } 690 }
698 m_pendingVsync = false; 691 m_pendingVsync = false;
692 if (m_displayBlurred)
693 return;
694 if (!m_scriptedAnimationController)
695 return;
699 Document* doc = this->document(); 696 Document* doc = this->document();
700 if (!doc || m_displayBlurred || !m_scriptedAnimationController) 697 if (!doc)
701 return; 698 return;
702 699
703 WTF::TimeDelta timeDelta = 700 WTF::TimeDelta timeDelta =
704 WTF::TimeDelta::FromMicroseconds(time->microseconds); 701 WTF::TimeDelta::FromMicroseconds(time->microseconds);
705 // Ensure a consistent timebase with document rAF. 702 // Ensure a consistent timebase with document rAF.
706 if (m_timebase < 0) { 703 if (m_timebase < 0) {
707 m_timebase = WTF::monotonicallyIncreasingTime() - timeDelta.InSecondsF(); 704 m_timebase = WTF::monotonicallyIncreasingTime() - timeDelta.InSecondsF();
708 } 705 }
709 706
710 AutoReset<bool> animating(&m_inAnimationFrame, true); 707 AutoReset<bool> animating(&m_inAnimationFrame, true);
711 m_framePose = std::move(pose); 708 m_framePose = std::move(pose);
712 m_vrFrameId = frameId; 709 m_vrFrameId = frameId;
713 m_pendingRaf = false; 710 m_pendingRaf = false;
714 m_scriptedAnimationController->serviceScriptedAnimations( 711 m_scriptedAnimationController->serviceScriptedAnimations(
715 m_timebase + timeDelta.InSecondsF()); 712 m_timebase + timeDelta.InSecondsF());
716 } 713 }
717 714
718 void VRDisplay::ConnectVSyncProvider() { 715 void VRDisplay::ConnectVSyncProvider() {
719 if (!m_navigatorVR->isFocused() || m_vrVSyncProvider.is_bound()) 716 if (!m_navigatorVR->isFocused() || m_vrVSyncProvider.is_bound())
720 return; 717 return;
721 m_display->GetVRVSyncProvider(mojo::MakeRequest(&m_vrVSyncProvider)); 718 m_display->GetVRVSyncProvider(mojo::MakeRequest(&m_vrVSyncProvider));
722 m_vrVSyncProvider.set_connection_error_handler(convertToBaseCallback(
723 WTF::bind(&VRDisplay::OnVSyncConnectionError, wrapWeakPersistent(this))));
724 if (m_pendingRaf && !m_displayBlurred) { 719 if (m_pendingRaf && !m_displayBlurred) {
725 m_pendingVsync = true; 720 m_pendingVsync = true;
726 m_vrVSyncProvider->GetVSync(convertToBaseCallback( 721 m_vrVSyncProvider->GetVSync(convertToBaseCallback(
727 WTF::bind(&VRDisplay::OnVSync, wrapWeakPersistent(this)))); 722 WTF::bind(&VRDisplay::OnVSync, wrapWeakPersistent(this))));
728 } 723 }
729 } 724 }
730 725
731 void VRDisplay::OnVSyncConnectionError() { 726 void VRDisplay::onFullscreenCheck(TimerBase*) {
732 m_vrVSyncProvider.reset(); 727 DCHECK(m_layer.source().isHTMLCanvasElement());
733 ConnectVSyncProvider(); 728 if (!m_isPresenting) {
729 m_fullscreenCheckTimer.stop();
730 return;
731 }
732 // TODO: This is a temporary measure to track if fullscreen mode has been
733 // exited by the UA. If so we need to end VR presentation. Soon we won't
734 // depend on the Fullscreen API to fake VR presentation, so this will
735 // become unnessecary. Until that point, though, this seems preferable to
736 // adding a bunch of notification plumbing to Fullscreen.
737 if (!Fullscreen::isCurrentFullScreenElement(
738 *m_layer.source().getAsHTMLCanvasElement())) {
739 // TODO(mthiesse): Due to asynchronous resizing, we might get kicked out of
740 // fullscreen when changing display parameters upon entering WebVR. So one
741 // time only, we reenter fullscreen after having left it; otherwise we exit
742 // presentation.
743 if (m_reenteredFullscreen) {
744 m_isPresenting = false;
745 OnPresentChange();
746 m_fullscreenCheckTimer.stop();
747 if (m_display)
748 m_display->ExitPresent();
749 return;
750 }
751 m_reenteredFullscreen = true;
752 auto canvas = m_layer.source().getAsHTMLCanvasElement();
753 Document* doc = this->document();
754 std::unique_ptr<UserGestureIndicator> gestureIndicator;
755 if (doc) {
756 gestureIndicator = WTF::wrapUnique(
757 new UserGestureIndicator(DocumentUserGestureToken::create(
758 doc, UserGestureToken::Status::PossiblyExistingGesture)));
759 }
760 Fullscreen::requestFullscreen(*canvas);
761 }
734 } 762 }
735 763
736 ScriptedAnimationController& VRDisplay::ensureScriptedAnimationController( 764 ScriptedAnimationController& VRDisplay::ensureScriptedAnimationController(
737 Document* doc) { 765 Document* doc) {
738 if (!m_scriptedAnimationController) 766 if (!m_scriptedAnimationController)
739 m_scriptedAnimationController = ScriptedAnimationController::create(doc); 767 m_scriptedAnimationController = ScriptedAnimationController::create(doc);
740 768
741 return *m_scriptedAnimationController; 769 return *m_scriptedAnimationController;
742 } 770 }
743 771
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
779 visitor->trace(m_stageParameters); 807 visitor->trace(m_stageParameters);
780 visitor->trace(m_eyeParametersLeft); 808 visitor->trace(m_eyeParametersLeft);
781 visitor->trace(m_eyeParametersRight); 809 visitor->trace(m_eyeParametersRight);
782 visitor->trace(m_layer); 810 visitor->trace(m_layer);
783 visitor->trace(m_renderingContext); 811 visitor->trace(m_renderingContext);
784 visitor->trace(m_scriptedAnimationController); 812 visitor->trace(m_scriptedAnimationController);
785 visitor->trace(m_pendingPresentResolvers); 813 visitor->trace(m_pendingPresentResolvers);
786 } 814 }
787 815
788 } // namespace blink 816 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/modules/vr/VRDisplay.h ('k') | third_party/WebKit/public/blink_typemaps.gni » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698