 Chromium Code Reviews
 Chromium Code Reviews Issue 2413903002:
  Allow VRDisplay to manage it's own rAF callbacks  (Closed)
    
  
    Issue 2413903002:
  Allow VRDisplay to manage it's own rAF callbacks  (Closed) 
  | Index: third_party/WebKit/Source/modules/vr/VRDisplay.cpp | 
| diff --git a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp | 
| index b7c149764abad85e4d1c99449b0fc3429db8e67b..e39fce2330b64dbca57992deddb339bd7d81d04f 100644 | 
| --- a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp | 
| +++ b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp | 
| @@ -5,7 +5,9 @@ | 
| #include "modules/vr/VRDisplay.h" | 
| #include "core/dom/DOMException.h" | 
| +#include "core/dom/FrameRequestCallback.h" | 
| #include "core/dom/Fullscreen.h" | 
| +#include "core/dom/ScriptedAnimationController.h" | 
| #include "core/frame/UseCounter.h" | 
| #include "core/inspector/ConsoleMessage.h" | 
| #include "gpu/command_buffer/client/gles2_interface.h" | 
| @@ -34,6 +36,24 @@ VREye stringToVREye(const String& whichEye) { | 
| return VREyeNone; | 
| } | 
| +class VRDisplayFrameRequestCallback : public FrameRequestCallback { | 
| + public: | 
| + VRDisplayFrameRequestCallback(VRDisplay* vrDisplay) | 
| + : m_vrDisplay(vrDisplay) {} | 
| + ~VRDisplayFrameRequestCallback() override {} | 
| + void handleEvent(double highResTimeMs) override { | 
| + m_vrDisplay->serviceScriptedAnimations(highResTimeMs); | 
| + } | 
| + | 
| + DEFINE_INLINE_VIRTUAL_TRACE() { | 
| + visitor->trace(m_vrDisplay); | 
| + | 
| + FrameRequestCallback::trace(visitor); | 
| + } | 
| + | 
| + Member<VRDisplay> m_vrDisplay; | 
| +}; | 
| + | 
| } // namespace | 
| VRDisplay::VRDisplay(NavigatorVR* navigatorVR) | 
| @@ -47,7 +67,9 @@ VRDisplay::VRDisplay(NavigatorVR* navigatorVR) | 
| m_eyeParametersRight(new VREyeParameters()), | 
| m_depthNear(0.01), | 
| m_depthFar(10000.0), | 
| - m_fullscreenCheckTimer(this, &VRDisplay::onFullscreenCheck) {} | 
| + m_fullscreenCheckTimer(this, &VRDisplay::onFullscreenCheck), | 
| + m_animationCallbackRequested(false), | 
| + m_inAnimationFrame(false) {} | 
| VRDisplay::~VRDisplay() {} | 
| @@ -132,16 +154,33 @@ VREyeParameters* VRDisplay::getEyeParameters(const String& whichEye) { | 
| } | 
| int VRDisplay::requestAnimationFrame(FrameRequestCallback* callback) { | 
| - // TODO: Use HMD-specific rAF when an external display is present. | 
| + Document* doc = m_navigatorVR->document(); | 
| + if (!doc) | 
| + return 0; | 
| + | 
| + if (!m_animationCallbackRequested) { | 
| + doc->requestAnimationFrame(new VRDisplayFrameRequestCallback(this)); | 
| + m_animationCallbackRequested = true; | 
| + } | 
| + | 
| callback->m_useLegacyTimeBase = false; | 
| - if (Document* doc = m_navigatorVR->document()) | 
| - return doc->requestAnimationFrame(callback); | 
| - return 0; | 
| + return ensureScriptedAnimationController(doc).registerCallback(callback); | 
| 
Sami
2016/10/24 10:12:23
Does it ever make sense to register more than one
 | 
| } | 
| void VRDisplay::cancelAnimationFrame(int id) { | 
| - if (Document* document = m_navigatorVR->document()) | 
| - document->cancelAnimationFrame(id); | 
| + if (!m_scriptedAnimationController) | 
| + return; | 
| + m_scriptedAnimationController->cancelCallback(id); | 
| +} | 
| + | 
| +void VRDisplay::serviceScriptedAnimations(double monotonicAnimationStartTime) { | 
| + if (!m_scriptedAnimationController) | 
| + return; | 
| + m_animationCallbackRequested = false; | 
| + m_inAnimationFrame = true; | 
| 
Sami
2016/10/24 10:12:23
nit: Could use AutoReset here.
 | 
| + m_scriptedAnimationController->serviceScriptedAnimations( | 
| + monotonicAnimationStartTime); | 
| + m_inAnimationFrame = false; | 
| } | 
| void ReportPresentationResult(PresentationResult result) { | 
| @@ -376,8 +415,28 @@ HeapVector<VRLayer> VRDisplay::getLayers() { | 
| } | 
| void VRDisplay::submitFrame() { | 
| - if (!m_isPresenting || !m_contextGL) { | 
| - // Something got confused, we can't submit frames if we're not presenting. | 
| + Document* doc = m_navigatorVR->document(); | 
| + if (!m_isPresenting) { | 
| + if (doc) { | 
| + doc->addConsoleMessage(ConsoleMessage::create( | 
| + RenderingMessageSource, WarningMessageLevel, | 
| + "submitFrame has no effect when the VRDisplay is not presenting.")); | 
| + } | 
| + return; | 
| + } | 
| + | 
| + if (!m_inAnimationFrame) { | 
| + if (doc) { | 
| + doc->addConsoleMessage( | 
| + ConsoleMessage::create(RenderingMessageSource, WarningMessageLevel, | 
| + "submitFrame must be called within a " | 
| + "VRDisplay.requestAnimationFrame callback.")); | 
| + } | 
| + return; | 
| + } | 
| + | 
| + if (!m_contextGL) { | 
| + // Something got confused, we can't submit frames without a GL context. | 
| return; | 
| } | 
| @@ -427,6 +486,20 @@ void VRDisplay::onFullscreenCheck(TimerBase*) { | 
| } | 
| } | 
| +ScriptedAnimationController& VRDisplay::ensureScriptedAnimationController( | 
| + Document* doc) { | 
| + if (!m_scriptedAnimationController) { | 
| + m_scriptedAnimationController = ScriptedAnimationController::create(doc); | 
| + // We need to make sure that we don't start up the animation controller on a | 
| 
Sami
2016/10/24 10:12:23
Should this be a TODO since we're not resuming the
 | 
| + // background tab, for example. | 
| + | 
| + if (!doc->page()) | 
| + m_scriptedAnimationController->suspend(); | 
| + } | 
| + | 
| + return *m_scriptedAnimationController; | 
| +} | 
| + | 
| DEFINE_TRACE(VRDisplay) { | 
| visitor->trace(m_navigatorVR); | 
| visitor->trace(m_capabilities); | 
| @@ -435,6 +508,7 @@ DEFINE_TRACE(VRDisplay) { | 
| visitor->trace(m_eyeParametersRight); | 
| visitor->trace(m_layer); | 
| visitor->trace(m_renderingContext); | 
| + visitor->trace(m_scriptedAnimationController); | 
| } | 
| } // namespace blink |