diff --git a/dom/bindings/TypedArray.h b/dom/bindings/TypedArray.h index 9d290068eb7b6688537c84ea827829aae2b73ef3..fa2e63cf59acd3725fcb0645da8a48c628fe2c25 100644 --- a/dom/bindings/TypedArray.h +++ b/dom/bindings/TypedArray.h @@ -475,6 +475,25 @@ struct TypedArray_base : public SpiderMonkeyInterfaceObjectStorage, std::forward<Calculator>(aCalculator)...); } + template <typename T, size_t N, typename... Calculator> + [[nodiscard]] bool CopyDataTo(std::array<T, N>* const aResult, + Calculator&&... aCalculator) const { + static_assert(sizeof...(aCalculator) <= 1, + "CopyDataTo takes at most one aCalculator"); + + return ProcessDataHelper( + [&](const Span<const element_type>& aData, JS::AutoCheckCannotGC&&) { + if (aData.Length() != N) { + return false; + } + for (size_t i = 0; i < N; ++i) { + (*aResult).at(i) = aData[i]; + } + return true; + }, + std::forward<Calculator>(aCalculator)...); + } + /** * Helper functions to copy this typed array's data to a newly created * container. Returns Nothing() if creating the container with the right size diff --git a/dom/canvas/TiedFields.h b/dom/canvas/TiedFields.h index b273aec3a8ec9d57c7f75483144240b759dc8f0a..20c3d635f0003647d40f674981a90c9c17644ac8 100644 --- a/dom/canvas/TiedFields.h +++ b/dom/canvas/TiedFields.h @@ -7,6 +7,8 @@ #include "TupleUtils.h" +#include <array> + namespace mozilla { // - diff --git a/dom/vr/VRDisplay.cpp b/dom/vr/VRDisplay.cpp index 4fe272e33851a75e7a52c512ad30e70487609136..740d9dba3da437f4eac3ad688fa46e45334be6b0 100644 --- a/dom/vr/VRDisplay.cpp +++ b/dom/vr/VRDisplay.cpp @@ -236,7 +236,7 @@ void VRPose::GetPosition(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval, bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_PositionEmulated); SetFloat32Array(aCx, this, aRetval, mPosition, - valid ? mVRState.pose.position : nullptr, 3, aRv); + valid ? mVRState.pose.position.data() : nullptr, 3, aRv); } void VRPose::GetLinearVelocity(JSContext* aCx, @@ -247,7 +247,8 @@ void VRPose::GetLinearVelocity(JSContext* aCx, bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_PositionEmulated); SetFloat32Array(aCx, this, aRetval, mLinearVelocity, - valid ? mVRState.pose.linearVelocity : nullptr, 3, aRv); + valid ? mVRState.pose.linearVelocity.data() : nullptr, 3, + aRv); } void VRPose::GetLinearAcceleration(JSContext* aCx, @@ -256,7 +257,8 @@ void VRPose::GetLinearAcceleration(JSContext* aCx, const bool valid = bool( mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_LinearAcceleration); SetFloat32Array(aCx, this, aRetval, mLinearAcceleration, - valid ? mVRState.pose.linearAcceleration : nullptr, 3, aRv); + valid ? mVRState.pose.linearAcceleration.data() : nullptr, 3, + aRv); } void VRPose::GetOrientation(JSContext* aCx, @@ -265,7 +267,7 @@ void VRPose::GetOrientation(JSContext* aCx, const bool valid = bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Orientation); SetFloat32Array(aCx, this, aRetval, mOrientation, - valid ? mVRState.pose.orientation : nullptr, 4, aRv); + valid ? mVRState.pose.orientation.data() : nullptr, 4, aRv); } void VRPose::GetAngularVelocity(JSContext* aCx, @@ -274,7 +276,8 @@ void VRPose::GetAngularVelocity(JSContext* aCx, const bool valid = bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Orientation); SetFloat32Array(aCx, this, aRetval, mAngularVelocity, - valid ? mVRState.pose.angularVelocity : nullptr, 3, aRv); + valid ? mVRState.pose.angularVelocity.data() : nullptr, 3, + aRv); } void VRPose::GetAngularAcceleration(JSContext* aCx, @@ -283,7 +286,8 @@ void VRPose::GetAngularAcceleration(JSContext* aCx, const bool valid = bool( mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_AngularAcceleration); SetFloat32Array(aCx, this, aRetval, mAngularAcceleration, - valid ? mVRState.pose.angularAcceleration : nullptr, 3, aRv); + valid ? mVRState.pose.angularAcceleration.data() : nullptr, 3, + aRv); } void VRPose::Update(const gfx::VRHMDSensorState& aState) { mVRState = aState; } @@ -759,9 +763,9 @@ void VRFrameInfo::Update(const gfx::VRDisplayInfo& aInfo, aInfo.mDisplayState.eyeFOV[gfx::VRDisplayState::Eye_Right]; mRightProjection = rightFOV.ConstructProjectionMatrix(aDepthNear, aDepthFar, true); - memcpy(mLeftView.components, aState.leftViewMatrix, + memcpy(mLeftView.components, aState.leftViewMatrix.data(), sizeof(aState.leftViewMatrix)); - memcpy(mRightView.components, aState.rightViewMatrix, + memcpy(mRightView.components, aState.rightViewMatrix.data(), sizeof(aState.rightViewMatrix)); } diff --git a/dom/vr/VRServiceTest.cpp b/dom/vr/VRServiceTest.cpp index 4e7691638d366cc871e10033a8a716a9b8d42f00..085b7b339d3a59c731e1826f3ee864a8cbbd8bf3 100644 --- a/dom/vr/VRServiceTest.cpp +++ b/dom/vr/VRServiceTest.cpp @@ -24,7 +24,7 @@ NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(VRMockDisplay, namespace { template <class T> -bool ReadFloat32Array(T& aDestination, const Float32Array& aSource, +bool ReadFloat32Array(T* aDestination, const Float32Array& aSource, ErrorResult& aRv) { if (!aSource.CopyDataTo(aDestination)) { aRv.Throw(NS_ERROR_INVALID_ARG); @@ -65,7 +65,7 @@ void VRMockDisplay::Create() { Clear(); VRDisplayState& state = DisplayState(); - strncpy(state.displayName, "Puppet HMD", kVRDisplayNameMaxLen); + strncpy(state.displayName.data(), "Puppet HMD", kVRDisplayNameMaxLen); state.eightCC = GFX_VR_EIGHTCC('P', 'u', 'p', 'p', 'e', 't', ' ', ' '); state.isConnected = true; state.isMounted = false; @@ -271,7 +271,7 @@ void VRMockDisplay::SetStageSize(double aWidth, double aHeight) { void VRMockDisplay::SetSittingToStandingTransform( const Float32Array& aTransform, ErrorResult& aRv) { - Unused << ReadFloat32Array(DisplayState().sittingToStandingTransform, + Unused << ReadFloat32Array(&DisplayState().sittingToStandingTransform, aTransform, aRv); } @@ -289,41 +289,41 @@ void VRMockDisplay::SetPose(const Nullable<Float32Array>& aPosition, // puppet script execution if (!aOrientation.IsNull()) { - if (!ReadFloat32Array(sensorState.pose.orientation, aOrientation.Value(), + if (!ReadFloat32Array(&sensorState.pose.orientation, aOrientation.Value(), aRv)) { return; } sensorState.flags |= VRDisplayCapabilityFlags::Cap_Orientation; } if (!aAngularVelocity.IsNull()) { - if (!ReadFloat32Array(sensorState.pose.angularVelocity, + if (!ReadFloat32Array(&sensorState.pose.angularVelocity, aAngularVelocity.Value(), aRv)) { return; } sensorState.flags |= VRDisplayCapabilityFlags::Cap_AngularAcceleration; } if (!aAngularAcceleration.IsNull()) { - if (!ReadFloat32Array(sensorState.pose.angularAcceleration, + if (!ReadFloat32Array(&sensorState.pose.angularAcceleration, aAngularAcceleration.Value(), aRv)) { return; } sensorState.flags |= VRDisplayCapabilityFlags::Cap_AngularAcceleration; } if (!aPosition.IsNull()) { - if (!ReadFloat32Array(sensorState.pose.position, aPosition.Value(), aRv)) { + if (!ReadFloat32Array(&sensorState.pose.position, aPosition.Value(), aRv)) { return; } sensorState.flags |= VRDisplayCapabilityFlags::Cap_Position; } if (!aLinearVelocity.IsNull()) { - if (!ReadFloat32Array(sensorState.pose.linearVelocity, + if (!ReadFloat32Array(&sensorState.pose.linearVelocity, aLinearVelocity.Value(), aRv)) { return; } sensorState.flags |= VRDisplayCapabilityFlags::Cap_LinearAcceleration; } if (!aLinearAcceleration.IsNull()) { - if (!ReadFloat32Array(sensorState.pose.linearAcceleration, + if (!ReadFloat32Array(&sensorState.pose.linearAcceleration, aLinearAcceleration.Value(), aRv)) { return; } @@ -360,7 +360,8 @@ void VRMockController::Create() { // puppet. Clear(); VRControllerState& state = ControllerState(); - strncpy(state.controllerName, "Puppet Gamepad", kVRControllerNameMaxLen); + strncpy(state.controllerName.data(), "Puppet Gamepad", + kVRControllerNameMaxLen); state.hand = GamepadHand::Left; state.flags = GamepadCapabilityFlags::Cap_Position | GamepadCapabilityFlags::Cap_Orientation; @@ -488,42 +489,42 @@ void VRMockController::SetPose( controllerState.flags = GamepadCapabilityFlags::Cap_None; if (!aOrientation.IsNull()) { - if (!ReadFloat32Array(controllerState.pose.orientation, + if (!ReadFloat32Array(&controllerState.pose.orientation, aOrientation.Value(), aRv)) { return; } controllerState.flags |= GamepadCapabilityFlags::Cap_Orientation; } if (!aAngularVelocity.IsNull()) { - if (!ReadFloat32Array(controllerState.pose.angularVelocity, + if (!ReadFloat32Array(&controllerState.pose.angularVelocity, aAngularVelocity.Value(), aRv)) { return; } controllerState.flags |= GamepadCapabilityFlags::Cap_AngularAcceleration; } if (!aAngularAcceleration.IsNull()) { - if (!ReadFloat32Array(controllerState.pose.angularAcceleration, + if (!ReadFloat32Array(&controllerState.pose.angularAcceleration, aAngularAcceleration.Value(), aRv)) { return; } controllerState.flags |= GamepadCapabilityFlags::Cap_AngularAcceleration; } if (!aPosition.IsNull()) { - if (!ReadFloat32Array(controllerState.pose.position, aPosition.Value(), + if (!ReadFloat32Array(&controllerState.pose.position, aPosition.Value(), aRv)) { return; } controllerState.flags |= GamepadCapabilityFlags::Cap_Position; } if (!aLinearVelocity.IsNull()) { - if (!ReadFloat32Array(controllerState.pose.linearVelocity, + if (!ReadFloat32Array(&controllerState.pose.linearVelocity, aLinearVelocity.Value(), aRv)) { return; } controllerState.flags |= GamepadCapabilityFlags::Cap_LinearAcceleration; } if (!aLinearAcceleration.IsNull()) { - if (!ReadFloat32Array(controllerState.pose.linearAcceleration, + if (!ReadFloat32Array(&controllerState.pose.linearAcceleration, aLinearAcceleration.Value(), aRv)) { return; } diff --git a/gfx/vr/VRDisplayClient.cpp b/gfx/vr/VRDisplayClient.cpp index 914fb05893c34c94f38f2c0299d5d75e0f805d7f..d1ecc34b0487ef9550dad26d3a05b4dffc6033d5 100644 --- a/gfx/vr/VRDisplayClient.cpp +++ b/gfx/vr/VRDisplayClient.cpp @@ -175,9 +175,7 @@ void VRDisplayClient::FireEvents() { void VRDisplayClient::GamepadMappingForWebVR( VRControllerState& aControllerState) { - float triggerValue[kVRControllerMaxButtons]; - memcpy(triggerValue, aControllerState.triggerValue, - sizeof(aControllerState.triggerValue)); + auto triggerValue = aControllerState.triggerValue; const uint64_t buttonPressed = aControllerState.buttonPressed; const uint64_t buttonTouched = aControllerState.buttonTouched; @@ -481,7 +479,7 @@ void VRDisplayClient::FireGamepadEvents() { // axis count. So, we need to check if they are more than zero. if ((lastState.controllerName[0] == '\0' || !existing) && (state.numButtons > 0 || state.numAxes > 0)) { - dom::GamepadAdded info(NS_ConvertUTF8toUTF16(state.controllerName), + dom::GamepadAdded info(NS_ConvertUTF8toUTF16(state.controllerName.data()), dom::GamepadMappingType::_empty, state.hand, mDisplayInfo.mDisplayID, state.numButtons, state.numAxes, state.numHaptics, 0, 0); @@ -578,10 +576,7 @@ void VRDisplayClient::FireGamepadEvents() { } } - // Note that VRControllerState is asserted to be a POD type and memcpy is - // safe. - memcpy(mLastEventControllerState, mDisplayInfo.mControllerState, - sizeof(VRControllerState) * kVRControllerMaxCount); + mLastEventControllerState = mDisplayInfo.mControllerState; } const VRHMDSensorState& VRDisplayClient::GetSensorState() const { diff --git a/gfx/vr/VRDisplayClient.h b/gfx/vr/VRDisplayClient.h index 19f8fdc41384e3b30a1c002502acc78d430c8c2c..c3a8c13023da9203620f90443db689fbfe89daab 100644 --- a/gfx/vr/VRDisplayClient.h +++ b/gfx/vr/VRDisplayClient.h @@ -7,12 +7,13 @@ #ifndef GFX_VR_DISPLAY_CLIENT_H #define GFX_VR_DISPLAY_CLIENT_H -#include "nsCOMPtr.h" +#include "gfxVR.h" #include "mozilla/Attributes.h" #include "mozilla/RefPtr.h" #include "mozilla/dom/VRDisplayBinding.h" +#include "nsCOMPtr.h" -#include "gfxVR.h" +#include <array> namespace mozilla { namespace dom { @@ -79,7 +80,8 @@ class VRDisplayClient { // Difference between mDisplayInfo.mControllerState and // mLastEventControllerState determines what gamepad events to fire when // updated. - VRControllerState mLastEventControllerState[kVRControllerMaxCount]; + std::array<VRControllerState, kVRControllerMaxCount> + mLastEventControllerState; /** * mSessions is cleared in VRDisplayClient::SessionEnded. diff --git a/gfx/vr/VRManager.cpp b/gfx/vr/VRManager.cpp index 5e3f349a60f01986bd206b6455080dee4905ebea..32296dfeaab113ef1bde65a05d493734b2731414 100644 --- a/gfx/vr/VRManager.cpp +++ b/gfx/vr/VRManager.cpp @@ -1043,7 +1043,7 @@ void VRManager::PullState( const std::function<bool()>& aWaitCondition /* = nullptr */) { if (mShmem != nullptr) { mShmem->PullSystemState(mDisplayInfo.mDisplayState, mLastSensorState, - mDisplayInfo.mControllerState, + &mDisplayInfo.mControllerState, mEnumerationCompleted, aWaitCondition); } } diff --git a/gfx/vr/VRShMem.cpp b/gfx/vr/VRShMem.cpp index b7d071cb882119fe1546a7416b2dfae0785599c5..9295b5896616537d4dd44bf91f7807faaf1a22b0 100644 --- a/gfx/vr/VRShMem.cpp +++ b/gfx/vr/VRShMem.cpp @@ -526,7 +526,8 @@ void VRShMem::PushSystemState(const mozilla::gfx::VRSystemState& aState) { #if defined(MOZ_WIDGET_ANDROID) void VRShMem::PullSystemState( VRDisplayState& aDisplayState, VRHMDSensorState& aSensorState, - VRControllerState (&aControllerState)[kVRControllerMaxCount], + std::array<VRControllerState, kVRControllerMaxCount>* const + aControllerState, bool& aEnumerationCompleted, const std::function<bool()>& aWaitCondition /* = nullptr */) { if (!mExternalShmem) { @@ -541,9 +542,9 @@ void VRShMem::PullSystemState( sizeof(VRDisplayState)); memcpy(&aSensorState, (void*)&(mExternalShmem->state.sensorState), sizeof(VRHMDSensorState)); - memcpy(aControllerState, + memcpy(aControllerState->data(), (void*)&(mExternalShmem->state.controllerState), - sizeof(VRControllerState) * kVRControllerMaxCount); + sizeof(aControllerState->at(0)) * aControllerState->size()); aEnumerationCompleted = mExternalShmem->state.enumerationCompleted; if (!aWaitCondition || aWaitCondition()) { done = true; @@ -565,7 +566,8 @@ void VRShMem::PullSystemState( #else void VRShMem::PullSystemState( VRDisplayState& aDisplayState, VRHMDSensorState& aSensorState, - VRControllerState (&aControllerState)[kVRControllerMaxCount], + std::array<VRControllerState, kVRControllerMaxCount>* const + aControllerState, bool& aEnumerationCompleted, const std::function<bool()>& aWaitCondition /* = nullptr */) { MOZ_ASSERT(mExternalShmem); @@ -589,10 +591,8 @@ void VRShMem::PullSystemState( sizeof(VRDisplayState)); memcpy(&aSensorState, &tmp.state.sensorState, sizeof(VRHMDSensorState)); - memcpy(aControllerState, - (void*)&(mExternalShmem->state.controllerState), - sizeof(VRControllerState) * kVRControllerMaxCount); - aEnumerationCompleted = mExternalShmem->state.enumerationCompleted; + *aControllerState = tmp.state.controllerState; + aEnumerationCompleted = tmp.state.enumerationCompleted; // Check for wait condition if (!aWaitCondition || aWaitCondition()) { return; diff --git a/gfx/vr/VRShMem.h b/gfx/vr/VRShMem.h index a10b8189a81ad35260156021c8bc508e5acb8a59..a6819798b6718cc465fbbe2a81faaeb686149843 100644 --- a/gfx/vr/VRShMem.h +++ b/gfx/vr/VRShMem.h @@ -37,11 +37,11 @@ class VRShMem final { void PullBrowserState(mozilla::gfx::VRBrowserState& aState); void PushSystemState(const mozilla::gfx::VRSystemState& aState); - void PullSystemState( - VRDisplayState& aDisplayState, VRHMDSensorState& aSensorState, - VRControllerState (&aControllerState)[kVRControllerMaxCount], - bool& aEnumerationCompleted, - const std::function<bool()>& aWaitCondition = nullptr); + void PullSystemState(VRDisplayState& aDisplayState, + VRHMDSensorState& aSensorState, + std::array<VRControllerState, kVRControllerMaxCount>*, + bool& aEnumerationCompleted, + const std::function<bool()>& aWaitCondition = nullptr); void PushWindowState(VRWindowState& aState); void PullWindowState(VRWindowState& aState); diff --git a/gfx/vr/external_api/moz_external_vr.h b/gfx/vr/external_api/moz_external_vr.h index 1777c57b9b467836617ffb3d0c921253ab8e8a28..e3049f3ce3c1212da43e4a497903613eb0ec9bc6 100644 --- a/gfx/vr/external_api/moz_external_vr.h +++ b/gfx/vr/external_api/moz_external_vr.h @@ -18,16 +18,17 @@ # include <stdlib.h> # include <string.h> # include "mozilla/TypedEnumBits.h" +# include "mozilla/dom/TiedFields.h" # include "mozilla/gfx/2D.h" # include <stddef.h> # include <stdint.h> -# include <type_traits> #endif // MOZILLA_INTERNAL_API #if defined(__ANDROID__) # include <pthread.h> #endif // defined(__ANDROID__) +#include <array> #include <cstdint> #include <type_traits> @@ -47,8 +48,8 @@ namespace gfx { // and mapped files if we have both release and nightlies // running at the same time? Or...what if we have multiple // release builds running on same machine? (Bug 1563232) -#define SHMEM_VERSION "0.0.11" -static const int32_t kVRExternalVersion = 18; +#define SHMEM_VERSION "0.0.12" +static const int32_t kVRExternalVersion = 19; // We assign VR presentations to groups with a bitmask. // Currently, we will only display either content or chrome. @@ -81,16 +82,40 @@ struct Point3D_POD { float x; float y; float z; + +#ifdef MOZILLA_INTERNAL_API + auto MutTiedFields() { return std::tie(x, y, z); } + + bool operator==(const Point3D_POD& other) const { + return TiedFields(*this) == TiedFields(other); + } +#endif }; struct IntSize_POD { int32_t width; int32_t height; + +#ifdef MOZILLA_INTERNAL_API + auto MutTiedFields() { return std::tie(width, height); } + + bool operator==(const IntSize_POD& other) const { + return TiedFields(*this) == TiedFields(other); + } +#endif }; struct FloatSize_POD { float width; float height; + +#ifdef MOZILLA_INTERNAL_API + auto MutTiedFields() { return std::tie(width, height); } + + bool operator==(const FloatSize_POD& other) const { + return TiedFields(*this) == TiedFields(other); + } +#endif }; #ifndef MOZILLA_INTERNAL_API @@ -154,12 +179,72 @@ enum class VRControllerType : uint8_t { _end }; +inline constexpr bool IsEnumCase(const VRControllerType raw) { + switch (raw) { + case VRControllerType::_empty: + case VRControllerType::HTCVive: + case VRControllerType::HTCViveCosmos: + case VRControllerType::HTCViveFocus: + case VRControllerType::HTCViveFocusPlus: + case VRControllerType::MSMR: + case VRControllerType::ValveIndex: + case VRControllerType::OculusGo: + case VRControllerType::OculusTouch: + case VRControllerType::OculusTouch2: + case VRControllerType::OculusTouch3: + case VRControllerType::PicoGaze: + case VRControllerType::PicoG2: + case VRControllerType::PicoNeo2: + case VRControllerType::_end: + return true; + } + return false; +} + +// - + enum class TargetRayMode : uint8_t { Gaze, TrackedPointer, Screen }; +inline constexpr bool IsEnumCase(const TargetRayMode raw) { + switch (raw) { + case TargetRayMode::Gaze: + case TargetRayMode::TrackedPointer: + case TargetRayMode::Screen: + return true; + } + return false; +} + +// - + enum class GamepadMappingType : uint8_t { _empty, Standard, XRStandard }; +inline constexpr bool IsEnumCase(const GamepadMappingType raw) { + switch (raw) { + case GamepadMappingType::_empty: + case GamepadMappingType::Standard: + case GamepadMappingType::XRStandard: + return true; + } + return false; +} + +// - + enum class VRDisplayBlendMode : uint8_t { Opaque, Additive, AlphaBlend }; +inline constexpr bool IsEnumCase(const VRDisplayBlendMode raw) { + switch (raw) { + case VRDisplayBlendMode::Opaque: + case VRDisplayBlendMode::Additive: + case VRDisplayBlendMode::AlphaBlend: + return true; + } + return false; +} + +// - + enum class VRDisplayCapabilityFlags : uint16_t { Cap_None = 0, /** @@ -249,26 +334,43 @@ MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(VRDisplayBlendMode) #endif // MOZILLA_INTERNAL_API struct VRPose { - float orientation[4]; - float position[3]; - float angularVelocity[3]; - float angularAcceleration[3]; - float linearVelocity[3]; - float linearAcceleration[3]; + std::array<float, 4> orientation; + std::array<float, 3> position; + std::array<float, 3> angularVelocity; + std::array<float, 3> angularAcceleration; + std::array<float, 3> linearVelocity; + std::array<float, 3> linearAcceleration; + +#ifdef MOZILLA_INTERNAL_API + auto MutTiedFields() { + return std::tie(orientation, position, angularVelocity, angularAcceleration, + linearVelocity, linearAcceleration); + } + + bool operator==(const VRPose& other) const { + return TiedFields(*this) == TiedFields(other); + } +#endif // MOZILLA_INTERNAL_API }; struct VRHMDSensorState { uint64_t inputFrameID; double timestamp; VRDisplayCapabilityFlags flags; + uint16_t _padding; // These members will only change with inputFrameID: VRPose pose; - float leftViewMatrix[16]; - float rightViewMatrix[16]; + std::array<float, 16> leftViewMatrix; + std::array<float, 16> rightViewMatrix; #ifdef MOZILLA_INTERNAL_API + auto MutTiedFields() { + return std::tie(inputFrameID, timestamp, flags, _padding, pose, + leftViewMatrix, rightViewMatrix); + } + void Clear() { memset(this, 0, sizeof(VRHMDSensorState)); } bool operator==(const VRHMDSensorState& other) const { @@ -291,6 +393,13 @@ struct VRFieldOfView { double leftDegrees; #ifdef MOZILLA_INTERNAL_API + auto MutTiedFields() { + return std::tie(upDegrees, rightDegrees, downDegrees, leftDegrees); + } + + bool operator==(const VRFieldOfView& other) const { + return TiedFields(*this) == TiedFields(other); + } VRFieldOfView() = default; VRFieldOfView(double up, double right, double down, double left) @@ -306,12 +415,6 @@ struct VRFieldOfView { leftDegrees = atan(left) * 180.0 / M_PI; } - 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); } @@ -332,10 +435,11 @@ struct VRDisplayState { // When true, indicates that the VR service has shut down bool shutdown; + std::array<uint8_t, 3> _padding1; // Minimum number of milliseconds to wait before attempting // to start the VR service again uint32_t minRestartInterval; - char displayName[kVRDisplayNameMaxLen]; + std::array<char, kVRDisplayNameMaxLen> displayName; // eight byte character code identifier // LSB first, so "ABCDEFGH" -> ('H'<<56) + ('G'<<48) + ('F'<<40) + // ('E'<<32) + ('D'<<24) + ('C'<<16) + @@ -343,30 +447,54 @@ struct VRDisplayState { uint64_t eightCC; VRDisplayCapabilityFlags capabilityFlags; VRDisplayBlendMode blendMode; - VRFieldOfView eyeFOV[VRDisplayState::NumEyes]; - Point3D_POD eyeTranslation[VRDisplayState::NumEyes]; + std::array<uint8_t, 5> _padding2; + std::array<VRFieldOfView, VRDisplayState::NumEyes> eyeFOV; + static_assert(std::is_pod<VRFieldOfView>::value); + std::array<Point3D_POD, VRDisplayState::NumEyes> eyeTranslation; + static_assert(std::is_pod<Point3D_POD>::value); IntSize_POD eyeResolution; + static_assert(std::is_pod<IntSize_POD>::value); float nativeFramebufferScaleFactor; bool suppressFrames; bool isConnected; bool isMounted; + uint8_t _padding3; FloatSize_POD stageSize; + static_assert(std::is_pod<FloatSize_POD>::value); // We can't use a Matrix4x4 here unless we ensure it's a POD type - float sittingToStandingTransform[16]; + std::array<float, 16> sittingToStandingTransform; uint64_t lastSubmittedFrameId; bool lastSubmittedFrameSuccessful; + std::array<uint8_t, 3> _padding4; uint32_t presentingGeneration; // Telemetry bool reportsDroppedFrames; + std::array<uint8_t, 7> _padding5; uint64_t droppedFrameCount; #ifdef MOZILLA_INTERNAL_API + auto MutTiedFields() { + return std::tie(shutdown, _padding1, minRestartInterval, displayName, + eightCC, capabilityFlags, blendMode, _padding2, eyeFOV, + eyeTranslation, eyeResolution, nativeFramebufferScaleFactor, + suppressFrames, isConnected, isMounted, _padding3, + stageSize, sittingToStandingTransform, lastSubmittedFrameId, + lastSubmittedFrameSuccessful, _padding4, + presentingGeneration, reportsDroppedFrames, _padding5, + droppedFrameCount); + } + + bool operator==(const VRDisplayState& other) const { + return TiedFields(*this) == TiedFields(other); + } + void Clear() { memset(this, 0, sizeof(VRDisplayState)); } #endif }; +static_assert(std::is_pod<VRDisplayState>::value); struct VRControllerState { - char controllerName[kVRControllerNameMaxLen]; + std::array<char, kVRControllerNameMaxLen> controllerName; #ifdef MOZILLA_INTERNAL_API dom::GamepadHand hand; #else @@ -381,6 +509,8 @@ struct VRControllerState { // https://immersive-web.github.io/webxr-gamepads-module/#enumdef-gamepadmappingtype GamepadMappingType mappingType; + uint32_t _padding1; + // Start frame ID of the most recent primary select // action, or 0 if the select action has never occurred. uint64_t selectActionStartFrameId; @@ -404,12 +534,13 @@ struct VRControllerState { uint32_t numButtons; uint32_t numAxes; uint32_t numHaptics; + uint32_t _padding2; // The current button pressed bit of button mask. uint64_t buttonPressed; // The current button touched bit of button mask. uint64_t buttonTouched; - float triggerValue[kVRControllerMaxButtons]; - float axisValue[kVRControllerMaxAxis]; + std::array<float, kVRControllerMaxButtons> triggerValue; + std::array<float, kVRControllerMaxAxis> axisValue; #ifdef MOZILLA_INTERNAL_API dom::GamepadCapabilityFlags flags; @@ -417,6 +548,8 @@ struct VRControllerState { ControllerCapabilityFlags flags; #endif + uint16_t _padding3; + // When Cap_Position is set in flags, pose corresponds // to the controllers' pose in grip space: // https://immersive-web.github.io/webxr/#dom-xrinputsource-gripspace @@ -429,8 +562,23 @@ struct VRControllerState { bool isPositionValid; bool isOrientationValid; + uint16_t _padding4; #ifdef MOZILLA_INTERNAL_API + auto MutTiedFields() { + return std::tie(controllerName, hand, type, targetRayMode, mappingType, + _padding1, selectActionStartFrameId, + selectActionStopFrameId, squeezeActionStartFrameId, + squeezeActionStopFrameId, numButtons, numAxes, numHaptics, + _padding2, buttonPressed, buttonTouched, triggerValue, + axisValue, flags, _padding3, pose, targetRayPose, + isPositionValid, isOrientationValid, _padding4); + } + + bool operator==(const VRControllerState& other) const { + return TiedFields(*this) == TiedFields(other); + } + void Clear() { memset(this, 0, sizeof(VRControllerState)); } #endif }; @@ -532,8 +680,13 @@ struct VRSystemState { bool enumerationCompleted; VRDisplayState displayState; VRHMDSensorState sensorState; - VRControllerState controllerState[kVRControllerMaxCount]; + std::array<VRControllerState, kVRControllerMaxCount> controllerState; }; +static_assert(std::is_pod<VRDisplayState>::value); +static_assert(std::is_pod<VRHMDSensorState>::value); +static_assert(std::is_pod<VRControllerState>::value); + +static_assert(std::is_pod<VRSystemState>::value); enum class VRFxEventType : uint8_t { NONE = 0, @@ -662,6 +815,11 @@ struct VRExternalShmem { // As we are memcpy'ing VRExternalShmem and its members around, it must be a POD // type +static_assert(std::is_pod<VRSystemState>::value); +static_assert(std::is_pod<VRBrowserState>::value); +static_assert(std::is_pod<VRWindowState>::value); +static_assert(std::is_pod<VRTelemetryState>::value); + static_assert(std::is_pod<VRExternalShmem>::value, "VRExternalShmem must be a POD type."); diff --git a/gfx/vr/gfxVR.cpp b/gfx/vr/gfxVR.cpp index ed1c6d32d6f6cf9444bd4ec40d190ff476b100fe..6ce16ac5558ad3adc11a4d6247456be14cb27615 100644 --- a/gfx/vr/gfxVR.cpp +++ b/gfx/vr/gfxVR.cpp @@ -60,10 +60,11 @@ void VRHMDSensorState::CalcViewMatrices( gfx::Matrix4x4 matView = matHead * aHeadToEyeTransforms[VRDisplayState::Eye_Left]; matView.Normalize(); - memcpy(leftViewMatrix, matView.components, sizeof(matView.components)); + memcpy(leftViewMatrix.data(), matView.components, sizeof(matView.components)); matView = matHead * aHeadToEyeTransforms[VRDisplayState::Eye_Right]; matView.Normalize(); - memcpy(rightViewMatrix, matView.components, sizeof(matView.components)); + memcpy(rightViewMatrix.data(), matView.components, + sizeof(matView.components)); } const IntSize VRDisplayInfo::SuggestedEyeResolution() const { @@ -85,7 +86,7 @@ const Matrix4x4 VRDisplayInfo::GetSittingToStandingTransform() const { Matrix4x4 m; // If we could replace Matrix4x4 with a pod type, we could // use it directly from the VRDisplayInfo struct. - memcpy(m.components, mDisplayState.sittingToStandingTransform, + memcpy(m.components, mDisplayState.sittingToStandingTransform.data(), sizeof(float) * 16); return m; } diff --git a/gfx/vr/gfxVR.h b/gfx/vr/gfxVR.h index d4d772b6a26e35146277f315ec4a0acba0c8be7d..1f6aa9f26014403ad1f0051e138f2a0d1e6708e2 100644 --- a/gfx/vr/gfxVR.h +++ b/gfx/vr/gfxVR.h @@ -14,6 +14,7 @@ #include "mozilla/RefPtr.h" #include "mozilla/gfx/2D.h" #include "mozilla/Atomics.h" +#include "mozilla/dom/TiedFields.h" #include "mozilla/EnumeratedArray.h" #include "mozilla/TimeStamp.h" #include "mozilla/TypedEnumBits.h" @@ -47,18 +48,31 @@ struct VRDisplayInfo { uint32_t mDisplayID; uint32_t mPresentingGroups; uint32_t mGroupMask; + uint32_t _padding; uint64_t mFrameId; VRDisplayState mDisplayState; - VRControllerState mControllerState[kVRControllerMaxCount]; + std::array<VRControllerState, kVRControllerMaxCount> mControllerState; + std::array<VRHMDSensorState, kVRMaxLatencyFrames> mLastSensorState; + + // - + + auto MutTiedFields() { + return std::tie(mDisplayID, mPresentingGroups, mGroupMask, _padding, + mFrameId, mDisplayState, mControllerState, + mLastSensorState); + } + + // - - VRHMDSensorState mLastSensorState[kVRMaxLatencyFrames]; void Clear() { memset(this, 0, sizeof(VRDisplayInfo)); } const VRHMDSensorState& GetSensorState() const { return mLastSensorState[mFrameId % kVRMaxLatencyFrames]; } uint32_t GetDisplayID() const { return mDisplayID; } - const char* GetDisplayName() const { return mDisplayState.displayName; } + const char* GetDisplayName() const { + return mDisplayState.displayName.data(); + } VRDisplayCapabilityFlags GetCapabilities() const { return mDisplayState.capabilityFlags; } @@ -77,20 +91,7 @@ struct VRDisplayInfo { uint64_t GetFrameId() const { return mFrameId; } bool operator==(const VRDisplayInfo& other) const { - for (size_t i = 0; i < kVRMaxLatencyFrames; i++) { - if (mLastSensorState[i] != other.mLastSensorState[i]) { - return false; - } - } - // Note that mDisplayState and mControllerState are asserted to be POD - // types, so memcmp is safe - return mDisplayID == other.mDisplayID && - memcmp(&mDisplayState, &other.mDisplayState, - sizeof(VRDisplayState)) == 0 && - memcmp(mControllerState, other.mControllerState, - sizeof(VRControllerState) * kVRControllerMaxCount) == 0 && - mPresentingGroups == other.mPresentingGroups && - mGroupMask == other.mGroupMask && mFrameId == other.mFrameId; + return TiedFields(*this) == TiedFields(other); } bool operator!=(const VRDisplayInfo& other) const { @@ -115,7 +116,7 @@ struct VRSubmitFrameResultInfo { struct VRControllerInfo { uint32_t GetControllerID() const { return mControllerID; } const char* GetControllerName() const { - return mControllerState.controllerName; + return mControllerState.controllerName.data(); } dom::GamepadMappingType GetMappingType() const { return mMappingType; } uint32_t GetDisplayID() const { return mDisplayID; } diff --git a/gfx/vr/ipc/VRMessageUtils.h b/gfx/vr/ipc/VRMessageUtils.h index 0d19c9e4ecff919b3e0070adb410f63523f62a83..18315bdf5be8619a415f9a58d63592aab7a270c7 100644 --- a/gfx/vr/ipc/VRMessageUtils.h +++ b/gfx/vr/ipc/VRMessageUtils.h @@ -12,30 +12,56 @@ #include "mozilla/ArrayUtils.h" #include "mozilla/GfxMessageUtils.h" #include "mozilla/dom/GamepadMessageUtils.h" +#include "mozilla/dom/WebGLIpdl.h" #include "gfxVR.h" namespace IPC { template <> -struct ParamTraits<mozilla::gfx::VRControllerType> - : public ContiguousEnumSerializer<mozilla::gfx::VRControllerType, - mozilla::gfx::VRControllerType::_empty, - mozilla::gfx::VRControllerType::_end> {}; - -// VRHMDSensorState is POD, we can use PlainOldDataSerializer -static_assert(std::is_pod<mozilla::gfx::VRHMDSensorState>::value, - "mozilla::gfx::VRHMDSensorState must be a POD type."); +struct ParamTraits<mozilla::gfx::VRHMDSensorState> final + : public ParamTraits_TiedFields<mozilla::gfx::VRHMDSensorState> {}; +template <> +struct ParamTraits<mozilla::gfx::VRDisplayInfo> final + : public ParamTraits_TiedFields<mozilla::gfx::VRDisplayInfo> {}; +template <> +struct ParamTraits<mozilla::gfx::VRDisplayState> final + : public ParamTraits_TiedFields<mozilla::gfx::VRDisplayState> {}; +template <> +struct ParamTraits<mozilla::gfx::VRControllerState> final + : public ParamTraits_TiedFields<mozilla::gfx::VRControllerState> {}; +template <> +struct ParamTraits<mozilla::gfx::VRFieldOfView> final + : public ParamTraits_TiedFields<mozilla::gfx::VRFieldOfView> {}; +template <> +struct ParamTraits<mozilla::gfx::Point3D_POD> final + : public ParamTraits_TiedFields<mozilla::gfx::Point3D_POD> {}; +template <> +struct ParamTraits<mozilla::gfx::IntSize_POD> final + : public ParamTraits_TiedFields<mozilla::gfx::IntSize_POD> {}; template <> -struct ParamTraits<mozilla::gfx::VRHMDSensorState> - : public PlainOldDataSerializer<mozilla::gfx::VRHMDSensorState> {}; +struct ParamTraits<mozilla::gfx::FloatSize_POD> final + : public ParamTraits_TiedFields<mozilla::gfx::FloatSize_POD> {}; +template <> +struct ParamTraits<mozilla::gfx::VRPose> final + : public ParamTraits_TiedFields<mozilla::gfx::VRPose> {}; + +// - -// VRDisplayInfo is POD, we can use PlainOldDataSerializer -static_assert(std::is_pod<mozilla::gfx::VRDisplayInfo>::value, - "mozilla::gfx::VRDisplayInfo must be a POD type."); template <> -struct ParamTraits<mozilla::gfx::VRDisplayInfo> - : public PlainOldDataSerializer<mozilla::gfx::VRDisplayInfo> {}; +struct ParamTraits<mozilla::gfx::VRControllerType> + : ParamTraits_IsEnumCase<mozilla::gfx::VRControllerType> {}; +template <> +struct ParamTraits<mozilla::gfx::TargetRayMode> + : ParamTraits_IsEnumCase<mozilla::gfx::TargetRayMode> {}; +template <> +struct ParamTraits<mozilla::gfx::GamepadMappingType> + : ParamTraits_IsEnumCase<mozilla::gfx::GamepadMappingType> {}; +template <> +struct ParamTraits<mozilla::gfx::VRDisplayBlendMode> + : ParamTraits_IsEnumCase<mozilla::gfx::VRDisplayBlendMode> {}; + +// - template <> struct ParamTraits<mozilla::gfx::VRSubmitFrameResultInfo> { diff --git a/gfx/vr/moz.build b/gfx/vr/moz.build index ec56fc56341d82e65803dc34234d8088d5064e56..18f5870fd959d58fdccdb138a6edd796ba7edf7f 100644 --- a/gfx/vr/moz.build +++ b/gfx/vr/moz.build @@ -95,6 +95,9 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk": CXXFLAGS += CONFIG["MOZ_GTK3_CFLAGS"] CFLAGS += CONFIG["MOZ_GTK3_CFLAGS"] +if CONFIG["CC_TYPE"] in ("clang", "clang-cl"): + CXXFLAGS += ["-Werror=switch"] + include("/ipc/chromium/chromium-config.mozbuild") FINAL_LIBRARY = "xul" diff --git a/gfx/vr/service/OSVRSession.cpp b/gfx/vr/service/OSVRSession.cpp index 8315bc7f4a18302680f506555701bdd58ce1df13..aeb9606dedede8373f6c036413762ff97c12a715 100644 --- a/gfx/vr/service/OSVRSession.cpp +++ b/gfx/vr/service/OSVRSession.cpp @@ -347,7 +347,7 @@ void OSVRSession::InitializeDisplay() { bool OSVRSession::InitState(mozilla::gfx::VRSystemState& aSystemState) { VRDisplayState& state = aSystemState.displayState; - strncpy(state.displayName, "OSVR HMD", kVRDisplayNameMaxLen); + strncpy(state.displayName.data(), "OSVR HMD", kVRDisplayNameMaxLen); state.eightCC = GFX_VR_EIGHTCC('O', 'S', 'V', 'R', ' ', ' ', ' ', ' '); state.isConnected = true; state.isMounted = false; diff --git a/gfx/vr/service/OculusSession.cpp b/gfx/vr/service/OculusSession.cpp index 07b0f208e327a182e1e3c0ba54a5114590ac8eb1..6485c36488e1d6a617a0e5f10ba4bdb86e207695 100644 --- a/gfx/vr/service/OculusSession.cpp +++ b/gfx/vr/service/OculusSession.cpp @@ -1010,7 +1010,7 @@ void OculusSession::StopRendering() { bool OculusSession::InitState(VRSystemState& aSystemState) { VRDisplayState& state = aSystemState.displayState; - strncpy(state.displayName, "Oculus VR HMD", kVRDisplayNameMaxLen); + strncpy(state.displayName.data(), "Oculus VR HMD", kVRDisplayNameMaxLen); state.isConnected = true; state.isMounted = false; @@ -1147,9 +1147,9 @@ void OculusSession::UpdateEyeParameters(VRSystemState& aState) { aState.sensorState.CalcViewMatrices(headToEyeTransforms); Matrix4x4 matView[2]; - memcpy(matView[0].components, aState.sensorState.leftViewMatrix, + memcpy(matView[0].components, aState.sensorState.leftViewMatrix.data(), sizeof(float) * 16); - memcpy(matView[1].components, aState.sensorState.rightViewMatrix, + memcpy(matView[1].components, aState.sensorState.rightViewMatrix.data(), sizeof(float) * 16); for (uint32_t eye = 0; eye < VRDisplayState::NumEyes; eye++) { @@ -1329,8 +1329,9 @@ void OculusSession::EnumerateControllers(VRSystemState& aState, // Touch Controller detected if (controllerState.controllerName[0] == '\0') { // Controller has been just enumerated - strncpy(controllerState.controllerName, OculusControllerNames[handIdx], - kVRControllerNameMaxLen); + strncpy(controllerState.controllerName.data(), + OculusControllerNames[handIdx], + controllerState.controllerName.size()); controllerState.hand = OculusControllerHand[handIdx]; controllerState.targetRayMode = gfx::TargetRayMode::TrackedPointer; controllerState.numButtons = kNumOculusButtons; diff --git a/gfx/vr/service/OpenVRSession.cpp b/gfx/vr/service/OpenVRSession.cpp index bfb486799db342222bdaa09dce7da5f8cd4317d4..9f5d332b4eb0661b4eed4ffbe6190acdd612a3b1 100644 --- a/gfx/vr/service/OpenVRSession.cpp +++ b/gfx/vr/service/OpenVRSession.cpp @@ -697,7 +697,7 @@ void OpenVRSession::Shutdown() { bool OpenVRSession::InitState(VRSystemState& aSystemState) { VRDisplayState& state = aSystemState.displayState; - strncpy(state.displayName, "OpenVR HMD", kVRDisplayNameMaxLen); + strncpy(state.displayName.data(), "OpenVR HMD", kVRDisplayNameMaxLen); state.eightCC = GFX_VR_EIGHTCC('O', 'p', 'e', 'n', 'V', 'R', ' ', ' '); state.isConnected = mVRSystem->IsTrackedDeviceConnected(::vr::k_unTrackedDeviceIndex_Hmd); @@ -987,8 +987,8 @@ void OpenVRSession::EnumerateControllers(VRSystemState& aState) { MOZ_ASSERT(controllerType == contrlType || controllerType == VRControllerType::_empty); controllerType = contrlType; - strncpy(controllerState.controllerName, deviceId.BeginReading(), - kVRControllerNameMaxLen); + strncpy(controllerState.controllerName.data(), deviceId.BeginReading(), + controllerState.controllerName.size()); controllerState.numHaptics = kNumOpenVRHaptics; controllerState.targetRayMode = gfx::TargetRayMode::TrackedPointer; controllerState.type = controllerType; diff --git a/ipc/chromium/src/base/pickle.cc b/ipc/chromium/src/base/pickle.cc index fa72edca2085d20fb05b138765cf7868d97bc57e..21d643b233a53ee54253a8c54f7515f4dc742ca2 100644 --- a/ipc/chromium/src/base/pickle.cc +++ b/ipc/chromium/src/base/pickle.cc @@ -96,6 +96,7 @@ void PickleIterator::CopyInto(T* dest) { (MOZ_ALIGNOF(T) <= sizeof(Pickle::memberAlignmentType))>::Copy(dest, iter_.Data()); } +template void PickleIterator::CopyInto<char>(char*); bool Pickle::IteratorHasRoomFor(const PickleIterator& iter, uint32_t len) const { diff --git a/ipc/chromium/src/base/pickle.h b/ipc/chromium/src/base/pickle.h index 5f648808486394b72aa365f603cd8c994fdcbb52..45779546108e3f13e00b9e0d7d3bb584d16ed875 100644 --- a/ipc/chromium/src/base/pickle.h +++ b/ipc/chromium/src/base/pickle.h @@ -128,6 +128,9 @@ class Pickle { template <class T> [[nodiscard]] bool ReadScalar(PickleIterator* iter, T* result) const { + static_assert(std::is_arithmetic<T>::value); + static_assert(!std::is_same<typename std::remove_cv<T>::type, bool>::value); + DCHECK(iter); if (!IteratorHasRoomFor(*iter, sizeof(*result))) @@ -168,6 +171,15 @@ class Pickle { // appended to the end of the Pickle's payload. When reading values from a // Pickle, it is important to read them in the order in which they were added // to the Pickle. + bool WriteBytes(const void* data, uint32_t data_len); + + template <class T> + bool WriteScalar(const T& value) { + static_assert(std::is_arithmetic<T>::value); + static_assert(!std::is_same<typename std::remove_cv<T>::type, bool>::value); + return WriteBytes(&value, sizeof(value)); + } + bool WriteBool(bool value); bool WriteInt16(int16_t value); bool WriteUInt16(uint16_t value); @@ -184,7 +196,7 @@ class Pickle { bool WriteString(const std::string& value); bool WriteWString(const std::wstring& value); bool WriteData(const char* data, uint32_t length); - bool WriteBytes(const void* data, uint32_t data_len); + // Takes ownership of data bool WriteBytesZeroCopy(void* data, uint32_t data_len, uint32_t capacity); diff --git a/ipc/chromium/src/chrome/common/ipc_message_utils.h b/ipc/chromium/src/chrome/common/ipc_message_utils.h index a2a38becefdcb909301aa30d074df3396df46e73..ec6b23eacbd86fae043a7f6db5c33d3068ee23a5 100644 --- a/ipc/chromium/src/chrome/common/ipc_message_utils.h +++ b/ipc/chromium/src/chrome/common/ipc_message_utils.h @@ -82,6 +82,11 @@ class MOZ_STACK_CLASS MessageWriter final { #undef FORWARD_WRITE + template <class T> + bool WriteScalar(const T& result) { + return message_.WriteScalar(result); + } + bool WriteData(const char* data, uint32_t length) { return message_.WriteData(data, length); } @@ -167,6 +172,11 @@ class MOZ_STACK_CLASS MessageReader final { #undef FORWARD_READ + template <class T> + [[nodiscard]] bool ReadScalar(T* const result) { + return message_.ReadScalar(&iter_, result); + } + [[nodiscard]] bool ReadBytesInto(void* data, uint32_t length) { return message_.ReadBytesInto(&iter_, data, length); } @@ -720,6 +730,17 @@ struct ParamTraitsFundamental<bool> { } }; +template <> +struct ParamTraitsFundamental<char> { + typedef char param_type; + static void Write(MessageWriter* writer, const param_type& p) { + writer->WriteScalar(p); + } + static bool Read(MessageReader* reader, param_type* r) { + return reader->ReadScalar(r); + } +}; + template <> struct ParamTraitsFundamental<int> { typedef int param_type; @@ -791,6 +812,28 @@ struct ParamTraitsFundamental<double> { template <class P> struct ParamTraitsFixed : ParamTraitsFundamental<P> {}; +template <> +struct ParamTraitsFixed<int8_t> { + typedef int8_t param_type; + static void Write(MessageWriter* writer, const param_type& p) { + writer->WriteScalar(p); + } + static bool Read(MessageReader* reader, param_type* r) { + return reader->ReadScalar(r); + } +}; + +template <> +struct ParamTraitsFixed<uint8_t> { + typedef uint8_t param_type; + static void Write(MessageWriter* writer, const param_type& p) { + writer->WriteScalar(p); + } + static bool Read(MessageReader* reader, param_type* r) { + return reader->ReadScalar(r); + } +}; + template <> struct ParamTraitsFixed<int16_t> { typedef int16_t param_type;