Source/WebCore/ChangeLog

 12018-04-12 Sergio Villar Senin <svillar@igalia.com>
 2
 3 [WebVR][OpenVR] Implement requestPresent()/exitPresent() and getLayers()
 4 https://bugs.webkit.org/show_bug.cgi?id=184530
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 WebVR apps should invoke requestPresent() to start presenting contents of a VRLayerInit
 9 (right now a HTML canvas with a WebGL context) on the VRDisplay. This request might fail for
 10 a variety of reasons and can be eventually cancelled with exitPresent(). Once we are
 11 presenting we could access the presenting layers (right now just one) with getLayers().
 12
 13 I took the chance to correct a mistak in the VRDisplayCapabilities object which has a method
 14 that should be called maxLayers instead of maxLayer.
 15
 16 * Modules/webvr/VRDisplay.cpp:
 17 (WebCore::VRDisplay::VRDisplay):
 18 (WebCore::VRDisplay::rejectRequestAndStopPresenting):
 19 (WebCore::VRDisplay::requestPresent):
 20 (WebCore::VRDisplay::stopPresenting):
 21 (WebCore::VRDisplay::exitPresent):
 22 (WebCore::VRDisplay::getLayers const):
 23 (WebCore::VRDisplay::isPresenting const): Deleted. Implemented in the header file.
 24 * Modules/webvr/VRDisplay.h:
 25 (WebCore::VRDisplay::isPresenting const):
 26 * Modules/webvr/VRDisplayCapabilities.h:
 27 (WebCore::VRDisplayCapabilities::maxLayers const): Renamed from maxLayer.
 28 (WebCore::VRDisplayCapabilities::maxLayer const): Deleted.
 29 * Modules/webvr/VRDisplayCapabilities.idl:
 30
1312018-04-12 Xabier Rodriguez Calvar <calvaris@igalia.com>
232
333 Unreviewed, fix GStreamer builds

Source/WebCore/Modules/webvr/VRDisplay.cpp

2626#include "config.h"
2727#include "VRDisplay.h"
2828
 29#include "CanvasRenderingContext.h"
2930#include "Chrome.h"
 31#include "DOMException.h"
3032#include "Page.h"
3133#include "ScriptedAnimationController.h"
 34#include "UserGestureIndicator.h"
3235#include "VRDisplayCapabilities.h"
3336#include "VREyeParameters.h"
3437#include "VRFrameData.h"

@@bool VRDisplay::isConnected() const
6871 return m_display->getDisplayInfo().isConnected();
6972}
7073
71 bool VRDisplay::isPresenting() const
72 {
73  return false;
74 }
75 
7674const VRDisplayCapabilities& VRDisplay::capabilities() const
7775{
7876 return *m_capabilities;

@@void VRDisplay::cancelAnimationFrame(uint32_t id)
132130 m_scriptedAnimationController->cancelCallback(id);
133131}
134132
135 void VRDisplay::requestPresent(const Vector<VRLayerInit>&, Ref<DeferredPromise>&&)
 133void VRDisplay::rejectRequestAndStopPresenting(Ref<DeferredPromise>& promise, ExceptionCode exceptionCode, const String& message)
 134{
 135 promise->reject(Exception { exceptionCode, message });
 136 if (m_presentingLayer)
 137 stopPresenting();
 138}
 139
 140void VRDisplay::requestPresent(const Vector<VRLayerInit>& layers, Ref<DeferredPromise>&& promise)
 141{
 142 if (!m_capabilities->canPresent()) {
 143 rejectRequestAndStopPresenting(promise, NotSupportedError, ASCIILiteral("VRDisplay cannot present"));
 144 return;
 145 }
 146
 147 if (!layers.size() || layers.size() > m_capabilities->maxLayers()) {
 148 rejectRequestAndStopPresenting(promise, InvalidStateError, ASCIILiteral(layers.size() ? "Too many layers" : "Not enough layers"));
 149 return;
 150 }
 151
 152 if (!m_presentingLayer && !UserGestureIndicator::processingUserGesture()) {
 153 rejectRequestAndStopPresenting(promise, InvalidAccessError, ASCIILiteral("Must request presentation from a user gesture handler."));
 154 return;
 155 }
 156
 157 RELEASE_ASSERT(layers.size() == 1);
 158 auto layer = layers[0];
 159
 160 if (!layer.source) {
 161 rejectRequestAndStopPresenting(promise, InvalidStateError, ASCIILiteral("Layer does not contain any source"));
 162 return;
 163 }
 164
 165 auto* canvasContext = layer.source->getContext("webgl");
 166 if (!canvasContext || !canvasContext->isWebGL()) {
 167 rejectRequestAndStopPresenting(promise, NotSupportedError, ASCIILiteral("WebVR requires VRLayerInit with WebGL context."));
 168 return;
 169 }
 170
 171 if ((layer.leftBounds.size() && layer.leftBounds.size() != 4)
 172 || (layer.rightBounds.size() && layer.rightBounds.size() != 4)) {
 173 rejectRequestAndStopPresenting(promise, InvalidStateError, ASCIILiteral("Layer bounds must be either 0 or 4"));
 174 return;
 175 }
 176
 177 m_presentingLayer = layer;
 178 promise->resolve();
 179}
 180
 181void VRDisplay::stopPresenting()
136182{
 183 m_presentingLayer = std::nullopt;
137184}
138185
139 void VRDisplay::exitPresent(Ref<DeferredPromise>&&)
 186void VRDisplay::exitPresent(Ref<DeferredPromise>&& promise)
140187{
 188 if (!m_presentingLayer) {
 189 promise->reject(Exception { InvalidStateError, ASCIILiteral("VRDisplay is not presenting") });
 190 return;
 191 }
 192
 193 stopPresenting();
141194}
142195
143 const Vector<VRLayerInit>& VRDisplay::getLayers() const
 196Vector<VRLayerInit> VRDisplay::getLayers() const
144197{
145  static auto mockLayers = makeNeverDestroyed(Vector<VRLayerInit> { });
146  return mockLayers;
 198 Vector<VRLayerInit> layers;
 199 if (m_presentingLayer)
 200 layers.append(m_presentingLayer.value());
 201 return layers;
147202}
148203
149204void VRDisplay::submitFrame()

Source/WebCore/Modules/webvr/VRDisplay.h

2929#include "EventTarget.h"
3030#include "JSDOMPromiseDeferred.h"
3131#include "VREye.h"
 32#include "VRLayerInit.h"
3233#include <wtf/RefCounted.h>
3334
3435namespace WebCore {
3536
 37enum ExceptionCode;
3638class RequestAnimationFrameCallback;
3739class ScriptedAnimationController;
3840class VRDisplayCapabilities;

@@class VRFrameData;
4143class VRPlatformDisplay;
4244class VRPose;
4345class VRStageParameters;
44 struct VRLayerInit;
4546
4647class VRDisplay : public RefCounted<VRDisplay>, public EventTargetWithInlineData, public ActiveDOMObject {
4748public:

@@public:
5354 using RefCounted<VRDisplay>::deref;
5455
5556 bool isConnected() const;
56  bool isPresenting() const;
 57 bool isPresenting() const { return !!m_presentingLayer; };
5758
5859 const VRDisplayCapabilities& capabilities() const;
5960 RefPtr<VRStageParameters> stageParameters() const;

@@public:
7980 void requestPresent(const Vector<VRLayerInit>&, Ref<DeferredPromise>&&);
8081 void exitPresent(Ref<DeferredPromise>&&);
8182
82  const Vector<VRLayerInit>& getLayers() const;
 83 Vector<VRLayerInit> getLayers() const;
8384
8485 void submitFrame();
8586

@@private:
9899 bool canSuspendForDocumentSuspension() const override;
99100 void stop() override;
100101
 102 void rejectRequestAndStopPresenting(Ref<DeferredPromise>&, ExceptionCode, const String& message = emptyString());
 103 void stopPresenting();
 104
101105 WeakPtr<VRPlatformDisplay> m_display;
102106
103107 RefPtr<VRDisplayCapabilities> m_capabilities;

@@private:
114118 double m_depthFar { 10000 }; // Default value from the specs.
115119
116120 RefPtr<ScriptedAnimationController> m_scriptedAnimationController;
 121
 122 std::optional<VRLayerInit> m_presentingLayer;
117123};
118124
119125} // namespace WebCore

Source/WebCore/Modules/webvr/VRDisplayCapabilities.h

@@public:
4343 bool hasOrientation() const { return m_flags & VRDisplayCapabilityFlagOrientation; }
4444 bool hasExternalDisplay() const { return m_flags & VRDisplayCapabilityFlagExternalDisplay; }
4545 bool canPresent() const { return m_flags & VRDisplayCapabilityFlagPresent; }
46  unsigned maxLayer() const { return canPresent() ? 1 : 0; }
 46 unsigned maxLayers() const { return canPresent() ? 1 : 0; }
4747
4848private:
4949 VRDisplayCapabilities(unsigned capabilityFlags)

Source/WebCore/Modules/webvr/VRDisplayCapabilities.idl

3131 readonly attribute boolean hasOrientation;
3232 readonly attribute boolean hasExternalDisplay;
3333 readonly attribute boolean canPresent;
34  readonly attribute unsigned long maxLayer;
 34 readonly attribute unsigned long maxLayers;
3535};