2014-07-09 23:24:49 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#ifndef GFX_VR_H
|
|
|
|
#define GFX_VR_H
|
|
|
|
|
|
|
|
#include "nsTArray.h"
|
2015-04-07 20:26:44 +03:00
|
|
|
#include "nsString.h"
|
2014-07-09 23:24:49 +04:00
|
|
|
#include "nsCOMPtr.h"
|
2015-10-18 08:24:48 +03:00
|
|
|
#include "mozilla/RefPtr.h"
|
2014-07-09 23:24:49 +04:00
|
|
|
|
|
|
|
#include "mozilla/gfx/2D.h"
|
2015-04-07 20:26:44 +03:00
|
|
|
#include "mozilla/Atomics.h"
|
2015-09-18 00:23:13 +03:00
|
|
|
#include "mozilla/EnumeratedArray.h"
|
|
|
|
#include "mozilla/TimeStamp.h"
|
|
|
|
#include "mozilla/TypedEnumBits.h"
|
2014-07-09 23:24:49 +04:00
|
|
|
|
|
|
|
namespace mozilla {
|
2015-07-02 18:58:24 +03:00
|
|
|
namespace layers {
|
|
|
|
class Compositor;
|
|
|
|
class CompositingRenderTarget;
|
|
|
|
}
|
|
|
|
|
2014-07-09 23:24:49 +04:00
|
|
|
namespace gfx {
|
|
|
|
|
2015-01-26 01:22:07 +03:00
|
|
|
enum class VRHMDType : uint16_t {
|
2014-07-09 23:24:49 +04:00
|
|
|
Oculus,
|
2015-04-01 23:02:20 +03:00
|
|
|
Cardboard,
|
2015-06-05 20:14:10 +03:00
|
|
|
Oculus050,
|
2014-07-09 23:24:49 +04:00
|
|
|
NumHMDTypes
|
2015-01-26 01:22:07 +03:00
|
|
|
};
|
2014-07-09 23:24:49 +04:00
|
|
|
|
2015-09-18 00:23:13 +03:00
|
|
|
enum class VRStateValidFlags : uint16_t {
|
|
|
|
State_None = 0,
|
|
|
|
State_Position = 1 << 1,
|
|
|
|
State_Orientation = 1 << 2,
|
|
|
|
// State_All used for validity checking during IPC serialization
|
|
|
|
State_All = (1 << 3) - 1
|
|
|
|
};
|
|
|
|
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(VRStateValidFlags)
|
|
|
|
|
2014-07-09 23:24:49 +04:00
|
|
|
struct VRFieldOfView {
|
|
|
|
VRFieldOfView() {}
|
|
|
|
VRFieldOfView(double up, double right, double down, double left)
|
|
|
|
: upDegrees(up), rightDegrees(right), downDegrees(down), leftDegrees(left)
|
|
|
|
{}
|
|
|
|
|
|
|
|
bool operator==(const VRFieldOfView& other) const {
|
|
|
|
return other.upDegrees == upDegrees &&
|
|
|
|
other.downDegrees == downDegrees &&
|
|
|
|
other.rightDegrees == rightDegrees &&
|
|
|
|
other.leftDegrees == leftDegrees;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator!=(const VRFieldOfView& other) const {
|
|
|
|
return !(*this == other);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsZero() const {
|
|
|
|
return upDegrees == 0.0 ||
|
|
|
|
rightDegrees == 0.0 ||
|
|
|
|
downDegrees == 0.0 ||
|
|
|
|
leftDegrees == 0.0;
|
|
|
|
}
|
|
|
|
|
2015-07-02 18:58:24 +03:00
|
|
|
Matrix4x4 ConstructProjectionMatrix(float zNear, float zFar, bool rightHanded);
|
|
|
|
|
2014-07-09 23:24:49 +04:00
|
|
|
double upDegrees;
|
|
|
|
double rightDegrees;
|
|
|
|
double downDegrees;
|
|
|
|
double leftDegrees;
|
|
|
|
};
|
|
|
|
|
2015-09-18 00:23:13 +03:00
|
|
|
struct VRDistortionVertex {
|
|
|
|
float values[12];
|
|
|
|
};
|
|
|
|
|
|
|
|
struct VRDistortionMesh {
|
|
|
|
nsTArray<VRDistortionVertex> mVertices;
|
|
|
|
nsTArray<uint16_t> mIndices;
|
|
|
|
};
|
|
|
|
|
2014-07-09 23:24:49 +04:00
|
|
|
// 12 floats per vertex. Position, tex coordinates
|
|
|
|
// for each channel, and 4 generic attributes
|
|
|
|
struct VRDistortionConstants {
|
|
|
|
float eyeToSourceScaleAndOffset[4];
|
|
|
|
float destinationScaleAndOffset[4];
|
|
|
|
};
|
|
|
|
|
2015-09-18 00:23:13 +03:00
|
|
|
struct VRDeviceInfo
|
|
|
|
{
|
|
|
|
VRHMDType GetType() const { return mType; }
|
|
|
|
uint32_t GetDeviceID() const { return mDeviceID; }
|
|
|
|
const nsCString& GetDeviceName() const { return mDeviceName; }
|
|
|
|
VRStateValidFlags GetSupportedSensorStateBits() const { return mSupportedSensorBits; }
|
|
|
|
const VRFieldOfView& GetRecommendedEyeFOV(uint32_t whichEye) const { return mRecommendedEyeFOV[whichEye]; }
|
|
|
|
const VRFieldOfView& GetMaximumEyeFOV(uint32_t whichEye) const { return mMaximumEyeFOV[whichEye]; }
|
2014-07-09 23:24:49 +04:00
|
|
|
|
2015-09-18 00:23:13 +03:00
|
|
|
const IntSize& SuggestedEyeResolution() const { return mEyeResolution; }
|
|
|
|
const Point3D& GetEyeTranslation(uint32_t whichEye) const { return mEyeTranslation[whichEye]; }
|
|
|
|
const Matrix4x4& GetEyeProjectionMatrix(uint32_t whichEye) const { return mEyeProjectionMatrix[whichEye]; }
|
|
|
|
const VRFieldOfView& GetEyeFOV(uint32_t whichEye) const { return mEyeFOV[whichEye]; }
|
|
|
|
bool GetUseMainThreadOrientation() const { return mUseMainThreadOrientation; }
|
|
|
|
|
|
|
|
enum Eye {
|
|
|
|
Eye_Left,
|
|
|
|
Eye_Right,
|
|
|
|
NumEyes
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32_t mDeviceID;
|
|
|
|
VRHMDType mType;
|
|
|
|
nsCString mDeviceName;
|
|
|
|
VRStateValidFlags mSupportedSensorBits;
|
|
|
|
VRFieldOfView mMaximumEyeFOV[VRDeviceInfo::NumEyes];
|
|
|
|
VRFieldOfView mRecommendedEyeFOV[VRDeviceInfo::NumEyes];
|
|
|
|
VRFieldOfView mEyeFOV[VRDeviceInfo::NumEyes];
|
|
|
|
Point3D mEyeTranslation[VRDeviceInfo::NumEyes];
|
|
|
|
Matrix4x4 mEyeProjectionMatrix[VRDeviceInfo::NumEyes];
|
|
|
|
/* Suggested resolution for rendering a single eye.
|
|
|
|
* Assumption is that left/right rendering will be 2x of this size.
|
|
|
|
* XXX fix this for vertical displays
|
|
|
|
*/
|
|
|
|
IntSize mEyeResolution;
|
|
|
|
IntRect mScreenRect;
|
|
|
|
|
|
|
|
bool mIsFakeScreen;
|
|
|
|
bool mUseMainThreadOrientation;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool operator==(const VRDeviceInfo& other) const {
|
|
|
|
return mType == other.mType &&
|
|
|
|
mDeviceID == other.mDeviceID &&
|
|
|
|
mDeviceName == other.mDeviceName &&
|
|
|
|
mSupportedSensorBits == other.mSupportedSensorBits &&
|
|
|
|
mEyeResolution == other.mEyeResolution &&
|
|
|
|
mScreenRect == other.mScreenRect &&
|
|
|
|
mIsFakeScreen == other.mIsFakeScreen &&
|
|
|
|
mUseMainThreadOrientation == other.mUseMainThreadOrientation &&
|
|
|
|
mMaximumEyeFOV[0] == other.mMaximumEyeFOV[0] &&
|
|
|
|
mMaximumEyeFOV[1] == other.mMaximumEyeFOV[1] &&
|
|
|
|
mRecommendedEyeFOV[0] == other.mRecommendedEyeFOV[0] &&
|
|
|
|
mRecommendedEyeFOV[1] == other.mRecommendedEyeFOV[1] &&
|
|
|
|
mEyeFOV[0] == other.mEyeFOV[0] &&
|
|
|
|
mEyeFOV[1] == other.mEyeFOV[1] &&
|
|
|
|
mEyeTranslation[0] == other.mEyeTranslation[0] &&
|
|
|
|
mEyeTranslation[1] == other.mEyeTranslation[1] &&
|
|
|
|
mEyeProjectionMatrix[0] == other.mEyeProjectionMatrix[0] &&
|
|
|
|
mEyeProjectionMatrix[1] == other.mEyeProjectionMatrix[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator!=(const VRDeviceInfo& other) const {
|
|
|
|
return !(*this == other);
|
|
|
|
}
|
2014-07-09 23:24:49 +04:00
|
|
|
};
|
|
|
|
|
2015-09-18 00:23:13 +03:00
|
|
|
|
|
|
|
|
2014-07-09 23:24:49 +04:00
|
|
|
struct VRHMDSensorState {
|
|
|
|
double timestamp;
|
2016-01-09 05:50:10 +03:00
|
|
|
int32_t inputFrameID;
|
2015-09-18 00:23:13 +03:00
|
|
|
VRStateValidFlags flags;
|
2014-07-09 23:24:49 +04:00
|
|
|
float orientation[4];
|
|
|
|
float position[3];
|
|
|
|
float angularVelocity[3];
|
|
|
|
float angularAcceleration[3];
|
|
|
|
float linearVelocity[3];
|
|
|
|
float linearAcceleration[3];
|
|
|
|
|
|
|
|
void Clear() {
|
|
|
|
memset(this, 0, sizeof(VRHMDSensorState));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-09-18 00:23:13 +03:00
|
|
|
struct VRSensorUpdate {
|
|
|
|
VRSensorUpdate() { }; // Required for ipdl binding
|
|
|
|
VRSensorUpdate(uint32_t aDeviceID, const VRHMDSensorState& aSensorState)
|
|
|
|
: mDeviceID(aDeviceID)
|
|
|
|
, mSensorState(aSensorState) { };
|
|
|
|
|
|
|
|
uint32_t mDeviceID;
|
|
|
|
VRHMDSensorState mSensorState;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct VRDeviceUpdate {
|
|
|
|
VRDeviceUpdate() { }; // Required for ipdl binding
|
|
|
|
VRDeviceUpdate(const VRDeviceInfo& aDeviceInfo,
|
|
|
|
const VRHMDSensorState& aSensorState)
|
|
|
|
: mDeviceInfo(aDeviceInfo)
|
|
|
|
, mSensorState(aSensorState) { };
|
|
|
|
|
|
|
|
VRDeviceInfo mDeviceInfo;
|
|
|
|
VRHMDSensorState mSensorState;
|
|
|
|
};
|
|
|
|
|
2014-07-09 23:24:49 +04:00
|
|
|
/* A pure data struct that can be used to see if
|
|
|
|
* the configuration of one HMDInfo matches another; for rendering purposes,
|
|
|
|
* really asking "can the rendering details of this one be used for the other"
|
|
|
|
*/
|
|
|
|
struct VRHMDConfiguration {
|
|
|
|
VRHMDConfiguration() : hmdType(VRHMDType::NumHMDTypes) {}
|
|
|
|
|
|
|
|
bool operator==(const VRHMDConfiguration& other) const {
|
|
|
|
return hmdType == other.hmdType &&
|
|
|
|
value == other.value &&
|
|
|
|
fov[0] == other.fov[0] &&
|
|
|
|
fov[1] == other.fov[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator!=(const VRHMDConfiguration& other) const {
|
|
|
|
return hmdType != other.hmdType ||
|
|
|
|
value != other.value ||
|
|
|
|
fov[0] != other.fov[0] ||
|
|
|
|
fov[1] != other.fov[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsValid() const {
|
|
|
|
return hmdType != VRHMDType::NumHMDTypes;
|
|
|
|
}
|
|
|
|
|
|
|
|
VRHMDType hmdType;
|
|
|
|
uint32_t value;
|
|
|
|
VRFieldOfView fov[2];
|
|
|
|
};
|
|
|
|
|
2015-07-02 18:58:24 +03:00
|
|
|
class VRHMDRenderingSupport {
|
|
|
|
public:
|
|
|
|
struct RenderTargetSet {
|
|
|
|
RenderTargetSet();
|
|
|
|
|
|
|
|
NS_INLINE_DECL_REFCOUNTING(RenderTargetSet)
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<layers::Compositor> compositor;
|
2015-07-02 18:58:24 +03:00
|
|
|
IntSize size;
|
2015-10-18 08:24:48 +03:00
|
|
|
nsTArray<RefPtr<layers::CompositingRenderTarget>> renderTargets;
|
2015-07-02 18:58:24 +03:00
|
|
|
int32_t currentRenderTarget;
|
|
|
|
|
|
|
|
virtual already_AddRefed<layers::CompositingRenderTarget> GetNextRenderTarget() = 0;
|
|
|
|
protected:
|
|
|
|
virtual ~RenderTargetSet();
|
|
|
|
};
|
|
|
|
|
|
|
|
virtual already_AddRefed<RenderTargetSet> CreateRenderTargetSet(layers::Compositor *aCompositor, const IntSize& aSize) = 0;
|
|
|
|
virtual void DestroyRenderTargetSet(RenderTargetSet *aRTSet) = 0;
|
2016-01-09 05:50:10 +03:00
|
|
|
virtual void SubmitFrame(RenderTargetSet *aRTSet, int32_t aInputFrameID) = 0;
|
2015-07-02 18:58:24 +03:00
|
|
|
protected:
|
|
|
|
VRHMDRenderingSupport() { }
|
|
|
|
};
|
|
|
|
|
2014-07-09 23:24:49 +04:00
|
|
|
class VRHMDInfo {
|
|
|
|
|
|
|
|
public:
|
|
|
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRHMDInfo)
|
|
|
|
|
|
|
|
const VRHMDConfiguration& GetConfiguration() const { return mConfiguration; }
|
2015-09-18 00:23:13 +03:00
|
|
|
const VRDeviceInfo& GetDeviceInfo() const { return mDeviceInfo; }
|
2014-07-09 23:24:49 +04:00
|
|
|
|
|
|
|
/* set the FOV for this HMD unit; this triggers a computation of all the remaining bits. Returns false if it fails */
|
|
|
|
virtual bool SetFOV(const VRFieldOfView& aFOVLeft, const VRFieldOfView& aFOVRight,
|
|
|
|
double zNear, double zFar) = 0;
|
|
|
|
|
2015-09-18 00:23:13 +03:00
|
|
|
virtual bool KeepSensorTracking() = 0;
|
|
|
|
virtual void NotifyVsync(const TimeStamp& aVsyncTimestamp) = 0;
|
2014-07-09 23:24:49 +04:00
|
|
|
virtual VRHMDSensorState GetSensorState(double timeOffset = 0.0) = 0;
|
|
|
|
|
|
|
|
virtual void ZeroSensor() = 0;
|
|
|
|
|
2015-07-02 18:58:24 +03:00
|
|
|
// if rendering is offloaded
|
|
|
|
virtual VRHMDRenderingSupport *GetRenderingSupport() { return nullptr; }
|
|
|
|
|
|
|
|
// distortion mesh stuff; we should implement renderingsupport for this
|
2014-07-09 23:24:49 +04:00
|
|
|
virtual void FillDistortionConstants(uint32_t whichEye,
|
|
|
|
const IntSize& textureSize, // the full size of the texture
|
|
|
|
const IntRect& eyeViewport, // the viewport within the texture for the current eye
|
|
|
|
const Size& destViewport, // the size of the destination viewport
|
|
|
|
const Rect& destRect, // the rectangle within the dest viewport that this should be rendered
|
|
|
|
VRDistortionConstants& values) = 0;
|
|
|
|
|
2015-09-18 00:23:13 +03:00
|
|
|
const VRDistortionMesh& GetDistortionMesh(uint32_t whichEye) const { return mDistortionMesh[whichEye]; }
|
2014-07-09 23:24:49 +04:00
|
|
|
protected:
|
2015-09-18 00:23:13 +03:00
|
|
|
explicit VRHMDInfo(VRHMDType aType, bool aUseMainThreadOrientation);
|
|
|
|
virtual ~VRHMDInfo();
|
2014-07-09 23:24:49 +04:00
|
|
|
|
|
|
|
VRHMDConfiguration mConfiguration;
|
2015-09-18 00:23:13 +03:00
|
|
|
VRDeviceInfo mDeviceInfo;
|
|
|
|
VRDistortionMesh mDistortionMesh[VRDeviceInfo::NumEyes];
|
2014-07-09 23:24:49 +04:00
|
|
|
};
|
|
|
|
|
2015-04-01 23:02:20 +03:00
|
|
|
class VRHMDManager {
|
2014-07-09 23:24:49 +04:00
|
|
|
public:
|
2015-09-18 00:23:13 +03:00
|
|
|
static uint32_t AllocateDeviceID();
|
2015-04-01 23:02:20 +03:00
|
|
|
|
|
|
|
protected:
|
2015-04-07 20:26:44 +03:00
|
|
|
static Atomic<uint32_t> sDeviceBase;
|
2015-04-01 23:02:20 +03:00
|
|
|
|
2015-09-18 00:23:13 +03:00
|
|
|
|
2015-04-01 23:02:20 +03:00
|
|
|
public:
|
|
|
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRHMDManager)
|
|
|
|
|
|
|
|
virtual bool Init() = 0;
|
|
|
|
virtual void Destroy() = 0;
|
2015-10-18 08:24:48 +03:00
|
|
|
virtual void GetHMDs(nsTArray<RefPtr<VRHMDInfo>>& aHMDResult) = 0;
|
2015-04-01 23:02:20 +03:00
|
|
|
|
|
|
|
protected:
|
|
|
|
VRHMDManager() { }
|
2015-04-01 23:02:20 +03:00
|
|
|
virtual ~VRHMDManager() { }
|
2014-07-09 23:24:49 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace gfx
|
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
#endif /* GFX_VR_H */
|