- Revision
- 230630
- Author
- [email protected]
- Date
- 2018-04-13 08:19:00 -0700 (Fri, 13 Apr 2018)
Log Message
[WebVR][OpenVR] Implement requestPresent()/exitPresent() and getLayers()
https://bugs.webkit.org/show_bug.cgi?id=184530
Reviewed by Žan Doberšek.
WebVR apps should invoke requestPresent() to start presenting contents of a VRLayerInit
(right now a HTML canvas with a WebGL context) on the VRDisplay. This request might fail for
a variety of reasons and can be eventually cancelled with exitPresent(). Once we are
presenting we could access the presenting layers (right now just one) with getLayers().
Note that we are not presenting anything to the HMD yet, that will be done later in a follow
up patch.
I took the chance to correct a mistak in the VRDisplayCapabilities object which has a method
that should be called maxLayers instead of maxLayer.
* Modules/webvr/VRDisplay.cpp:
(WebCore::VRDisplay::requestPresent):
(WebCore::VRDisplay::stopPresenting):
(WebCore::VRDisplay::exitPresent):
(WebCore::VRDisplay::getLayers const):
(WebCore::VRDisplay::isPresenting const): Deleted. Implemented in the header file.
* Modules/webvr/VRDisplay.h:
(WebCore::VRDisplay::isPresenting const):
* Modules/webvr/VRDisplayCapabilities.h:
(WebCore::VRDisplayCapabilities::maxLayers const): Renamed from maxLayer().
(WebCore::VRDisplayCapabilities::maxLayer const): Deleted.
* Modules/webvr/VRDisplayCapabilities.idl:
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (230629 => 230630)
--- trunk/Source/WebCore/ChangeLog 2018-04-13 13:18:29 UTC (rev 230629)
+++ trunk/Source/WebCore/ChangeLog 2018-04-13 15:19:00 UTC (rev 230630)
@@ -1,3 +1,34 @@
+2018-04-13 Sergio Villar Senin <[email protected]>
+
+ [WebVR][OpenVR] Implement requestPresent()/exitPresent() and getLayers()
+ https://bugs.webkit.org/show_bug.cgi?id=184530
+
+ Reviewed by Žan Doberšek.
+
+ WebVR apps should invoke requestPresent() to start presenting contents of a VRLayerInit
+ (right now a HTML canvas with a WebGL context) on the VRDisplay. This request might fail for
+ a variety of reasons and can be eventually cancelled with exitPresent(). Once we are
+ presenting we could access the presenting layers (right now just one) with getLayers().
+
+ Note that we are not presenting anything to the HMD yet, that will be done later in a follow
+ up patch.
+
+ I took the chance to correct a mistak in the VRDisplayCapabilities object which has a method
+ that should be called maxLayers instead of maxLayer.
+
+ * Modules/webvr/VRDisplay.cpp:
+ (WebCore::VRDisplay::requestPresent):
+ (WebCore::VRDisplay::stopPresenting):
+ (WebCore::VRDisplay::exitPresent):
+ (WebCore::VRDisplay::getLayers const):
+ (WebCore::VRDisplay::isPresenting const): Deleted. Implemented in the header file.
+ * Modules/webvr/VRDisplay.h:
+ (WebCore::VRDisplay::isPresenting const):
+ * Modules/webvr/VRDisplayCapabilities.h:
+ (WebCore::VRDisplayCapabilities::maxLayers const): Renamed from maxLayer().
+ (WebCore::VRDisplayCapabilities::maxLayer const): Deleted.
+ * Modules/webvr/VRDisplayCapabilities.idl:
+
2018-04-13 Miguel Gomez <[email protected]>
REGRESSION(r230627): [GTK][WPE] Possible deadlock when destroying the player in non AC mode
Modified: trunk/Source/WebCore/Modules/webvr/VRDisplay.cpp (230629 => 230630)
--- trunk/Source/WebCore/Modules/webvr/VRDisplay.cpp 2018-04-13 13:18:29 UTC (rev 230629)
+++ trunk/Source/WebCore/Modules/webvr/VRDisplay.cpp 2018-04-13 15:19:00 UTC (rev 230630)
@@ -26,9 +26,12 @@
#include "config.h"
#include "VRDisplay.h"
+#include "CanvasRenderingContext.h"
#include "Chrome.h"
+#include "DOMException.h"
#include "Page.h"
#include "ScriptedAnimationController.h"
+#include "UserGestureIndicator.h"
#include "VRDisplayCapabilities.h"
#include "VREyeParameters.h"
#include "VRFrameData.h"
@@ -68,11 +71,6 @@
return m_display->getDisplayInfo().isConnected();
}
-bool VRDisplay::isPresenting() const
-{
- return false;
-}
-
const VRDisplayCapabilities& VRDisplay::capabilities() const
{
return *m_capabilities;
@@ -132,20 +130,76 @@
m_scriptedAnimationController->cancelCallback(id);
}
-void VRDisplay::requestPresent(const Vector<VRLayerInit>&, Ref<DeferredPromise>&&)
+void VRDisplay::requestPresent(const Vector<VRLayerInit>& layers, Ref<DeferredPromise>&& promise)
{
+ auto rejectRequestAndStopPresenting = [this, &promise] (ExceptionCode exceptionCode, ASCIILiteral message) {
+ promise->reject(Exception { exceptionCode, message });
+ if (m_presentingLayer)
+ stopPresenting();
+ };
+
+ if (!m_capabilities->canPresent()) {
+ rejectRequestAndStopPresenting(NotSupportedError, ASCIILiteral("VRDisplay cannot present"));
+ return;
+ }
+
+ if (!layers.size() || layers.size() > m_capabilities->maxLayers()) {
+ rejectRequestAndStopPresenting(InvalidStateError, ASCIILiteral(layers.size() ? "Too many layers" : "Not enough layers"));
+ return;
+ }
+
+ if (!m_presentingLayer && !UserGestureIndicator::processingUserGesture()) {
+ rejectRequestAndStopPresenting(InvalidAccessError, ASCIILiteral("Must request presentation from a user gesture handler."));
+ return;
+ }
+
+ RELEASE_ASSERT(layers.size() == 1);
+ auto layer = layers[0];
+
+ if (!layer.source) {
+ rejectRequestAndStopPresenting(InvalidStateError, ASCIILiteral("Layer does not contain any source"));
+ return;
+ }
+
+ auto* canvasContext = layer.source->getContext("webgl");
+ if (!canvasContext || !canvasContext->isWebGL()) {
+ rejectRequestAndStopPresenting(NotSupportedError, ASCIILiteral("WebVR requires VRLayerInit with WebGL context."));
+ return;
+ }
+
+ if ((layer.leftBounds.size() && layer.leftBounds.size() != 4)
+ || (layer.rightBounds.size() && layer.rightBounds.size() != 4)) {
+ rejectRequestAndStopPresenting(InvalidStateError, ASCIILiteral("Layer bounds must be either 0 or 4"));
+ return;
+ }
+
+ m_presentingLayer = layer;
+ promise->resolve();
}
-void VRDisplay::exitPresent(Ref<DeferredPromise>&&)
+void VRDisplay::stopPresenting()
{
+ m_presentingLayer = std::nullopt;
}
-const Vector<VRLayerInit>& VRDisplay::getLayers() const
+void VRDisplay::exitPresent(Ref<DeferredPromise>&& promise)
{
- static auto mockLayers = makeNeverDestroyed(Vector<VRLayerInit> { });
- return mockLayers;
+ if (!m_presentingLayer) {
+ promise->reject(Exception { InvalidStateError, ASCIILiteral("VRDisplay is not presenting") });
+ return;
+ }
+
+ stopPresenting();
}
+Vector<VRLayerInit> VRDisplay::getLayers() const
+{
+ Vector<VRLayerInit> layers;
+ if (m_presentingLayer)
+ layers.append(m_presentingLayer.value());
+ return layers;
+}
+
void VRDisplay::submitFrame()
{
}
Modified: trunk/Source/WebCore/Modules/webvr/VRDisplay.h (230629 => 230630)
--- trunk/Source/WebCore/Modules/webvr/VRDisplay.h 2018-04-13 13:18:29 UTC (rev 230629)
+++ trunk/Source/WebCore/Modules/webvr/VRDisplay.h 2018-04-13 15:19:00 UTC (rev 230630)
@@ -29,10 +29,12 @@
#include "EventTarget.h"
#include "JSDOMPromiseDeferred.h"
#include "VREye.h"
+#include "VRLayerInit.h"
#include <wtf/RefCounted.h>
namespace WebCore {
+enum ExceptionCode;
class RequestAnimationFrameCallback;
class ScriptedAnimationController;
class VRDisplayCapabilities;
@@ -41,7 +43,6 @@
class VRPlatformDisplay;
class VRPose;
class VRStageParameters;
-struct VRLayerInit;
class VRDisplay : public RefCounted<VRDisplay>, public EventTargetWithInlineData, public ActiveDOMObject {
public:
@@ -53,7 +54,7 @@
using RefCounted<VRDisplay>::deref;
bool isConnected() const;
- bool isPresenting() const;
+ bool isPresenting() const { return !!m_presentingLayer; };
const VRDisplayCapabilities& capabilities() const;
RefPtr<VRStageParameters> stageParameters() const;
@@ -79,7 +80,7 @@
void requestPresent(const Vector<VRLayerInit>&, Ref<DeferredPromise>&&);
void exitPresent(Ref<DeferredPromise>&&);
- const Vector<VRLayerInit>& getLayers() const;
+ Vector<VRLayerInit> getLayers() const;
void submitFrame();
@@ -98,6 +99,8 @@
bool canSuspendForDocumentSuspension() const override;
void stop() override;
+ void stopPresenting();
+
WeakPtr<VRPlatformDisplay> m_display;
RefPtr<VRDisplayCapabilities> m_capabilities;
@@ -114,6 +117,8 @@
double m_depthFar { 10000 }; // Default value from the specs.
RefPtr<ScriptedAnimationController> m_scriptedAnimationController;
+
+ std::optional<VRLayerInit> m_presentingLayer;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/Modules/webvr/VRDisplayCapabilities.h (230629 => 230630)
--- trunk/Source/WebCore/Modules/webvr/VRDisplayCapabilities.h 2018-04-13 13:18:29 UTC (rev 230629)
+++ trunk/Source/WebCore/Modules/webvr/VRDisplayCapabilities.h 2018-04-13 15:19:00 UTC (rev 230630)
@@ -43,7 +43,7 @@
bool hasOrientation() const { return m_flags & VRDisplayCapabilityFlagOrientation; }
bool hasExternalDisplay() const { return m_flags & VRDisplayCapabilityFlagExternalDisplay; }
bool canPresent() const { return m_flags & VRDisplayCapabilityFlagPresent; }
- unsigned maxLayer() const { return canPresent() ? 1 : 0; }
+ unsigned maxLayers() const { return canPresent() ? 1 : 0; }
private:
VRDisplayCapabilities(unsigned capabilityFlags)
Modified: trunk/Source/WebCore/Modules/webvr/VRDisplayCapabilities.idl (230629 => 230630)
--- trunk/Source/WebCore/Modules/webvr/VRDisplayCapabilities.idl 2018-04-13 13:18:29 UTC (rev 230629)
+++ trunk/Source/WebCore/Modules/webvr/VRDisplayCapabilities.idl 2018-04-13 15:19:00 UTC (rev 230630)
@@ -31,5 +31,5 @@
readonly attribute boolean hasOrientation;
readonly attribute boolean hasExternalDisplay;
readonly attribute boolean canPresent;
- readonly attribute unsigned long maxLayer;
+ readonly attribute unsigned long maxLayers;
};