| 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 88ae98b7eea2d69815d12cd4d3b301cc5cac4c43..0e5f5abd06ad0e28605ee1b4dd45c475140adf71 100644
|
| --- a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
|
| +++ b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
|
| @@ -160,11 +160,13 @@ ScriptPromise VRDisplay::requestPresent(ScriptState* scriptState, const HeapVect
|
| return promise;
|
| }
|
|
|
| + bool firstPresent = !m_isPresenting;
|
| +
|
| // Initiating VR presentation is only allowed in response to a user gesture.
|
| // If the VRDisplay is already presenting, however, repeated calls are
|
| // allowed outside a user gesture so that the presented content may be
|
| // updated.
|
| - if (!m_isPresenting && !UserGestureIndicator::utilizeUserGesture()) {
|
| + if (firstPresent && !UserGestureIndicator::utilizeUserGesture()) {
|
| DOMException* exception = DOMException::create(InvalidStateError, "API can only be initiated by a user gesture.");
|
| resolver->reject(exception);
|
| return promise;
|
| @@ -174,73 +176,46 @@ ScriptPromise VRDisplay::requestPresent(ScriptState* scriptState, const HeapVect
|
|
|
| // A valid number of layers must be provided in order to present.
|
| if (layers.size() == 0 || layers.size() > m_capabilities->maxLayers()) {
|
| + forceExitPresent();
|
| DOMException* exception = DOMException::create(InvalidStateError, "Invalid number of layers.");
|
| - if (m_isPresenting) {
|
| - exitPresent(scriptState);
|
| - }
|
| resolver->reject(exception);
|
| return promise;
|
| }
|
|
|
| m_layer = layers[0];
|
|
|
| - if (m_layer.source()) {
|
| - if (!m_capabilities->hasExternalDisplay()) {
|
| - // TODO: Need a proper VR compositor, but for the moment on mobile
|
| - // we'll just make the canvas fullscreen so that VrShell can pick it
|
| - // up through the standard (high latency) compositing path.
|
| - Fullscreen::requestFullscreen(*m_layer.source(), Fullscreen::UnprefixedRequest);
|
| -
|
| - m_isPresenting = true;
|
| -
|
| - resolver->resolve();
|
| -
|
| - m_navigatorVR->fireVRDisplayPresentChange(this);
|
| -
|
| - // Check to see if the canvas is still the current fullscreen
|
| - // element once per second.
|
| - m_fullscreenCheckTimer.startRepeating(1.0, BLINK_FROM_HERE);
|
| -
|
| - controller()->requestPresent(m_displayId);
|
| - } else {
|
| - DOMException* exception = DOMException::create(InvalidStateError, "VR Presentation not implemented for this VRDisplay.");
|
| - resolver->reject(exception);
|
| - }
|
| + if (!m_layer.source()) {
|
| + forceExitPresent();
|
| + DOMException* exception = DOMException::create(InvalidStateError, "Invalid layer source.");
|
| + resolver->reject(exception);
|
| + return promise;
|
| + }
|
|
|
| - // Set up the texture bounds for the provided layer
|
| - device::blink::VRLayerBoundsPtr leftBounds = device::blink::VRLayerBounds::New();
|
| - device::blink::VRLayerBoundsPtr rightBounds = device::blink::VRLayerBounds::New();
|
| + CanvasRenderingContext* renderingContext = m_layer.source()->renderingContext();
|
|
|
| - if (m_layer.hasLeftBounds()) {
|
| - leftBounds->left = m_layer.leftBounds()[0];
|
| - leftBounds->top = m_layer.leftBounds()[1];
|
| - leftBounds->width = m_layer.leftBounds()[2];
|
| - leftBounds->height = m_layer.leftBounds()[3];
|
| - } else {
|
| - // Left eye defaults
|
| - leftBounds->left = 0.0f;
|
| - leftBounds->top = 0.0f;
|
| - leftBounds->width = 0.5f;
|
| - leftBounds->height = 1.0f;
|
| - }
|
| + if (!renderingContext || !renderingContext->is3d()) {
|
| + forceExitPresent();
|
| + DOMException* exception = DOMException::create(InvalidStateError, "Layer source must have a WebGLRenderingContext");
|
| + resolver->reject(exception);
|
| + return promise;
|
| + }
|
|
|
| - if (m_layer.hasRightBounds()) {
|
| - rightBounds->left = m_layer.rightBounds()[0];
|
| - rightBounds->top = m_layer.rightBounds()[1];
|
| - rightBounds->width = m_layer.rightBounds()[2];
|
| - rightBounds->height = m_layer.rightBounds()[3];
|
| - } else {
|
| - // Right eye defaults
|
| - rightBounds->left = 0.5f;
|
| - rightBounds->top = 0.0f;
|
| - rightBounds->width = 0.5f;
|
| - rightBounds->height = 1.0f;
|
| - }
|
| + if (!m_capabilities->hasExternalDisplay()) {
|
| + // TODO: Need a proper VR compositor, but for the moment on mobile
|
| + // we'll just make the canvas fullscreen so that VrShell can pick it
|
| + // up through the standard (high latency) compositing path.
|
| + Fullscreen::requestFullscreen(*m_layer.source(), Fullscreen::UnprefixedRequest);
|
| +
|
| + // Check to see if the canvas is still the current fullscreen
|
| + // element once per second.
|
| + m_fullscreenCheckTimer.startRepeating(1.0, BLINK_FROM_HERE);
|
| + }
|
|
|
| - controller()->updateLayerBounds(m_displayId, std::move(leftBounds), std::move(rightBounds));
|
| + if (firstPresent) {
|
| + controller()->requestPresent(resolver, m_displayId);
|
| } else {
|
| - DOMException* exception = DOMException::create(InvalidStateError, "Invalid layer source.");
|
| - resolver->reject(exception);
|
| + updateLayerBounds();
|
| + resolver->resolve();
|
| }
|
|
|
| return promise;
|
| @@ -258,22 +233,80 @@ ScriptPromise VRDisplay::exitPresent(ScriptState* scriptState)
|
| return promise;
|
| }
|
|
|
| - if (!m_capabilities->hasExternalDisplay()) {
|
| - Fullscreen::fullyExitFullscreen(m_layer.source()->document());
|
| - m_fullscreenCheckTimer.stop();
|
| - controller()->exitPresent(m_displayId);
|
| - } else {
|
| - // Can't get into this presentation mode, so nothing to do here.
|
| + controller()->exitPresent(m_displayId);
|
| +
|
| + resolver->resolve();
|
| +
|
| + forceExitPresent();
|
| +
|
| + return promise;
|
| +}
|
| +
|
| +void VRDisplay::beginPresent(ScriptPromiseResolver* resolver)
|
| +{
|
| + if (m_capabilities->hasExternalDisplay()) {
|
| + forceExitPresent();
|
| + DOMException* exception = DOMException::create(InvalidStateError, "VR Presentation not implemented for this VRDisplay.");
|
| + resolver->reject(exception);
|
| + return;
|
| }
|
|
|
| - m_isPresenting = false;
|
| + m_isPresenting = true;
|
|
|
| - // TODO: Resolve when exit is confirmed
|
| - resolver->resolve();
|
| + updateLayerBounds();
|
|
|
| + resolver->resolve();
|
| m_navigatorVR->fireVRDisplayPresentChange(this);
|
| +}
|
|
|
| - return promise;
|
| +void VRDisplay::forceExitPresent()
|
| +{
|
| + if (m_isPresenting) {
|
| + if (!m_capabilities->hasExternalDisplay()) {
|
| + Fullscreen::fullyExitFullscreen(m_layer.source()->document());
|
| + m_fullscreenCheckTimer.stop();
|
| + } else {
|
| + // Can't get into this presentation mode, so nothing to do here.
|
| + }
|
| + m_navigatorVR->fireVRDisplayPresentChange(this);
|
| + }
|
| +
|
| + m_isPresenting = false;
|
| +}
|
| +
|
| +void VRDisplay::updateLayerBounds()
|
| +{
|
| + // Set up the texture bounds for the provided layer
|
| + device::blink::VRLayerBoundsPtr leftBounds = device::blink::VRLayerBounds::New();
|
| + device::blink::VRLayerBoundsPtr rightBounds = device::blink::VRLayerBounds::New();
|
| +
|
| + if (m_layer.hasLeftBounds()) {
|
| + leftBounds->left = m_layer.leftBounds()[0];
|
| + leftBounds->top = m_layer.leftBounds()[1];
|
| + leftBounds->width = m_layer.leftBounds()[2];
|
| + leftBounds->height = m_layer.leftBounds()[3];
|
| + } else {
|
| + // Left eye defaults
|
| + leftBounds->left = 0.0f;
|
| + leftBounds->top = 0.0f;
|
| + leftBounds->width = 0.5f;
|
| + leftBounds->height = 1.0f;
|
| + }
|
| +
|
| + if (m_layer.hasRightBounds()) {
|
| + rightBounds->left = m_layer.rightBounds()[0];
|
| + rightBounds->top = m_layer.rightBounds()[1];
|
| + rightBounds->width = m_layer.rightBounds()[2];
|
| + rightBounds->height = m_layer.rightBounds()[3];
|
| + } else {
|
| + // Right eye defaults
|
| + rightBounds->left = 0.5f;
|
| + rightBounds->top = 0.0f;
|
| + rightBounds->width = 0.5f;
|
| + rightBounds->height = 1.0f;
|
| + }
|
| +
|
| + controller()->updateLayerBounds(m_displayId, std::move(leftBounds), std::move(rightBounds));
|
| }
|
|
|
| HeapVector<VRLayer> VRDisplay::getLayers()
|
| @@ -289,7 +322,7 @@ HeapVector<VRLayer> VRDisplay::getLayers()
|
|
|
| void VRDisplay::submitFrame()
|
| {
|
| - controller()->submitFrame(m_displayId);
|
| + controller()->submitFrame(m_displayId, m_framePose.Clone());
|
| m_canUpdateFramePose = true;
|
| }
|
|
|
|
|