LCOV - code coverage report
Current view: top level - gfx/vr - gfxVRPuppet.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 231 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 40 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #if defined(XP_WIN)
       7             : #include "CompositorD3D11.h"
       8             : #include "TextureD3D11.h"
       9             : #include "mozilla/gfx/DeviceManagerDx.h"
      10             : #endif // XP_WIN
      11             : 
      12             : #include "mozilla/Base64.h"
      13             : #include "mozilla/gfx/DataSurfaceHelpers.h"
      14             : #include "gfxUtils.h"
      15             : #include "gfxVRPuppet.h"
      16             : 
      17             : #include "mozilla/dom/GamepadEventTypes.h"
      18             : #include "mozilla/dom/GamepadBinding.h"
      19             : 
      20             : // See CompositorD3D11Shaders.h
      21             : namespace mozilla {
      22             : namespace layers {
      23             : struct ShaderBytes { const void* mData; size_t mLength; };
      24             : extern ShaderBytes sRGBShader;
      25             : extern ShaderBytes sLayerQuadVS;
      26             : } // namespace layers
      27             : } // namespace mozilla
      28             : 
      29             : using namespace mozilla;
      30             : using namespace mozilla::gfx;
      31             : using namespace mozilla::gfx::impl;
      32             : using namespace mozilla::layers;
      33             : 
      34             : // Reminder: changing the order of these buttons may break web content
      35             : static const uint64_t kPuppetButtonMask[] = {
      36             :   1,
      37             :   2,
      38             :   4,
      39             :   8
      40             : };
      41             : 
      42             : static const uint32_t kNumPuppetButtonMask = sizeof(kPuppetButtonMask) /
      43             :                                              sizeof(uint64_t);
      44             : 
      45             : static const uint32_t kPuppetAxes[] = {
      46             :   0,
      47             :   1,
      48             :   2
      49             : };
      50             : 
      51             : static const uint32_t kNumPuppetAxis = sizeof(kPuppetAxes) /
      52             :                                        sizeof(uint32_t);
      53             : 
      54             : static const uint32_t kNumPuppetHaptcs = 1;
      55             : 
      56           0 : VRDisplayPuppet::VRDisplayPuppet()
      57             :  : VRDisplayHost(VRDeviceType::Puppet)
      58           0 :  , mIsPresenting(false)
      59             : {
      60           0 :   MOZ_COUNT_CTOR_INHERITED(VRDisplayPuppet, VRDisplayHost);
      61             : 
      62           0 :   mDisplayInfo.mDisplayName.AssignLiteral("Puppet HMD");
      63           0 :   mDisplayInfo.mIsConnected = true;
      64           0 :   mDisplayInfo.mIsMounted = false;
      65           0 :   mDisplayInfo.mCapabilityFlags = VRDisplayCapabilityFlags::Cap_None |
      66           0 :                                   VRDisplayCapabilityFlags::Cap_Orientation |
      67           0 :                                   VRDisplayCapabilityFlags::Cap_Position |
      68           0 :                                   VRDisplayCapabilityFlags::Cap_External |
      69           0 :                                   VRDisplayCapabilityFlags::Cap_Present |
      70           0 :                                   VRDisplayCapabilityFlags::Cap_StageParameters;
      71           0 :   mDisplayInfo.mEyeResolution.width = 1836; // 1080 * 1.7
      72           0 :   mDisplayInfo.mEyeResolution.height = 2040; // 1200 * 1.7
      73             : 
      74             :   // SteamVR gives the application a single FOV to use; it's not configurable as with Oculus
      75           0 :   for (uint32_t eye = 0; eye < 2; ++eye) {
      76           0 :     mDisplayInfo.mEyeTranslation[eye].x = 0.0f;
      77           0 :     mDisplayInfo.mEyeTranslation[eye].y = 0.0f;
      78           0 :     mDisplayInfo.mEyeTranslation[eye].z = 0.0f;
      79           0 :     mDisplayInfo.mEyeFOV[eye] = VRFieldOfView(45.0, 45.0, 45.0, 45.0);
      80             :   }
      81             : 
      82             :   // default: 1m x 1m space, 0.75m high in seated position
      83           0 :   mDisplayInfo.mStageSize.width = 1.0f;
      84           0 :   mDisplayInfo.mStageSize.height = 1.0f;
      85             : 
      86           0 :   mDisplayInfo.mSittingToStandingTransform._11 = 1.0f;
      87           0 :   mDisplayInfo.mSittingToStandingTransform._12 = 0.0f;
      88           0 :   mDisplayInfo.mSittingToStandingTransform._13 = 0.0f;
      89           0 :   mDisplayInfo.mSittingToStandingTransform._14 = 0.0f;
      90             : 
      91           0 :   mDisplayInfo.mSittingToStandingTransform._21 = 0.0f;
      92           0 :   mDisplayInfo.mSittingToStandingTransform._22 = 1.0f;
      93           0 :   mDisplayInfo.mSittingToStandingTransform._23 = 0.0f;
      94           0 :   mDisplayInfo.mSittingToStandingTransform._24 = 0.0f;
      95             : 
      96           0 :   mDisplayInfo.mSittingToStandingTransform._31 = 0.0f;
      97           0 :   mDisplayInfo.mSittingToStandingTransform._32 = 0.0f;
      98           0 :   mDisplayInfo.mSittingToStandingTransform._33 = 1.0f;
      99           0 :   mDisplayInfo.mSittingToStandingTransform._34 = 0.0f;
     100             : 
     101           0 :   mDisplayInfo.mSittingToStandingTransform._41 = 0.0f;
     102           0 :   mDisplayInfo.mSittingToStandingTransform._42 = 0.75f;
     103           0 :   mDisplayInfo.mSittingToStandingTransform._43 = 0.0f;
     104             : 
     105           0 :   gfx::Quaternion rot;
     106             : 
     107           0 :   mSensorState.flags |= VRDisplayCapabilityFlags::Cap_Orientation;
     108           0 :   mSensorState.orientation[0] = rot.x;
     109           0 :   mSensorState.orientation[1] = rot.y;
     110           0 :   mSensorState.orientation[2] = rot.z;
     111           0 :   mSensorState.orientation[3] = rot.w;
     112           0 :   mSensorState.angularVelocity[0] = 0.0f;
     113           0 :   mSensorState.angularVelocity[1] = 0.0f;
     114           0 :   mSensorState.angularVelocity[2] = 0.0f;
     115             : 
     116           0 :   mSensorState.flags |= VRDisplayCapabilityFlags::Cap_Position;
     117           0 :   mSensorState.position[0] = 0.0f;
     118           0 :   mSensorState.position[1] = 0.0f;
     119           0 :   mSensorState.position[2] = 0.0f;
     120           0 :   mSensorState.linearVelocity[0] = 0.0f;
     121           0 :   mSensorState.linearVelocity[1] = 0.0f;
     122           0 :   mSensorState.linearVelocity[2] = 0.0f;
     123           0 : }
     124             : 
     125           0 : VRDisplayPuppet::~VRDisplayPuppet()
     126             : {
     127           0 :   MOZ_COUNT_DTOR_INHERITED(VRDisplayPuppet, VRDisplayHost);
     128           0 : }
     129             : 
     130             : void
     131           0 : VRDisplayPuppet::SetDisplayInfo(const VRDisplayInfo& aDisplayInfo)
     132             : {
     133             :   // We are only interested in the eye and mount info of the display info.
     134           0 :   mDisplayInfo.mEyeResolution = aDisplayInfo.mEyeResolution;
     135           0 :   mDisplayInfo.mIsMounted = aDisplayInfo.mIsMounted;
     136           0 :   memcpy(&mDisplayInfo.mEyeFOV, &aDisplayInfo.mEyeFOV,
     137           0 :          sizeof(mDisplayInfo.mEyeFOV[0]) * VRDisplayInfo::NumEyes);
     138           0 :   memcpy(&mDisplayInfo.mEyeTranslation, &aDisplayInfo.mEyeTranslation,
     139           0 :          sizeof(mDisplayInfo.mEyeTranslation[0]) * VRDisplayInfo::NumEyes);
     140           0 : }
     141             : 
     142             : void
     143           0 : VRDisplayPuppet::Destroy()
     144             : {
     145           0 :   StopPresentation();
     146           0 : }
     147             : 
     148             : void
     149           0 : VRDisplayPuppet::ZeroSensor()
     150             : {
     151           0 : }
     152             : 
     153             : VRHMDSensorState
     154           0 : VRDisplayPuppet::GetSensorState()
     155             : {
     156           0 :   mSensorState.inputFrameID = mDisplayInfo.mFrameId;
     157           0 :   return mSensorState;
     158             : }
     159             : 
     160             : void
     161           0 : VRDisplayPuppet::SetSensorState(const VRHMDSensorState& aSensorState)
     162             : {
     163           0 :   memcpy(&mSensorState, &aSensorState, sizeof(mSensorState));
     164           0 : }
     165             : 
     166             : void
     167           0 : VRDisplayPuppet::StartPresentation()
     168             : {
     169           0 :   if (mIsPresenting) {
     170           0 :     return;
     171             :   }
     172           0 :   mIsPresenting = true;
     173             : 
     174             : #if defined(XP_WIN)
     175             :   if (!mDevice) {
     176             :     mDevice = gfx::DeviceManagerDx::Get()->GetCompositorDevice();
     177             :     if (!mDevice) {
     178             :       NS_WARNING("Failed to get a D3D11Device for Puppet");
     179             :       return;
     180             :     }
     181             :   }
     182             : 
     183             :   mDevice->GetImmediateContext(getter_AddRefs(mContext));
     184             :   if (!mContext) {
     185             :     NS_WARNING("Failed to get immediate context for Puppet");
     186             :     return;
     187             :   }
     188             : 
     189             :   if (FAILED(mDevice->CreateVertexShader(sLayerQuadVS.mData,
     190             :                       sLayerQuadVS.mLength, nullptr, &mQuadVS))) {
     191             :     NS_WARNING("Failed to create vertex shader for Puppet");
     192             :     return;
     193             :   }
     194             : 
     195             :   if (FAILED(mDevice->CreatePixelShader(sRGBShader.mData,
     196             :                       sRGBShader.mLength, nullptr, &mQuadPS))) {
     197             :     NS_WARNING("Failed to create pixel shader for Puppet");
     198             :     return;
     199             :   }
     200             : 
     201             :   CD3D11_BUFFER_DESC cBufferDesc(sizeof(layers::VertexShaderConstants),
     202             :                                  D3D11_BIND_CONSTANT_BUFFER,
     203             :                                  D3D11_USAGE_DYNAMIC,
     204             :                                  D3D11_CPU_ACCESS_WRITE);
     205             : 
     206             :   if (FAILED(mDevice->CreateBuffer(&cBufferDesc, nullptr, getter_AddRefs(mVSConstantBuffer)))) {
     207             :     NS_WARNING("Failed to vertex shader constant buffer for Puppet");
     208             :     return;
     209             :   }
     210             : 
     211             :   cBufferDesc.ByteWidth = sizeof(layers::PixelShaderConstants);
     212             :   if (FAILED(mDevice->CreateBuffer(&cBufferDesc, nullptr, getter_AddRefs(mPSConstantBuffer)))) {
     213             :     NS_WARNING("Failed to pixel shader constant buffer for Puppet");
     214             :     return;
     215             :   }
     216             : 
     217             :   CD3D11_SAMPLER_DESC samplerDesc(D3D11_DEFAULT);
     218             :   if (FAILED(mDevice->CreateSamplerState(&samplerDesc, getter_AddRefs(mLinearSamplerState)))) {
     219             :     NS_WARNING("Failed to create sampler state for Puppet");
     220             :     return;
     221             :   }
     222             : 
     223             :   D3D11_INPUT_ELEMENT_DESC layout[] =
     224             :   {
     225             :     { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
     226             :   };
     227             : 
     228             :   if (FAILED(mDevice->CreateInputLayout(layout,
     229             :                                         sizeof(layout) / sizeof(D3D11_INPUT_ELEMENT_DESC),
     230             :                                         sLayerQuadVS.mData,
     231             :                                         sLayerQuadVS.mLength,
     232             :                                         getter_AddRefs(mInputLayout)))) {
     233             :     NS_WARNING("Failed to create input layout for Puppet");
     234             :     return;
     235             :   }
     236             : 
     237             :   Vertex vertices[] = { { { 0.0, 0.0 } },{ { 1.0, 0.0 } },{ { 0.0, 1.0 } },{ { 1.0, 1.0 } } };
     238             :   CD3D11_BUFFER_DESC bufferDesc(sizeof(vertices), D3D11_BIND_VERTEX_BUFFER);
     239             :   D3D11_SUBRESOURCE_DATA data;
     240             :   data.pSysMem = (void*)vertices;
     241             : 
     242             :   if (FAILED(mDevice->CreateBuffer(&bufferDesc, &data, getter_AddRefs(mVertexBuffer)))) {
     243             :     NS_WARNING("Failed to create vertex buffer for Puppet");
     244             :     return;
     245             :   }
     246             : 
     247             :   memset(&mVSConstants, 0, sizeof(mVSConstants));
     248             :   memset(&mPSConstants, 0, sizeof(mPSConstants));
     249             : #endif // XP_WIN
     250             : }
     251             : 
     252             : void
     253           0 : VRDisplayPuppet::StopPresentation()
     254             : {
     255           0 :   if (!mIsPresenting) {
     256           0 :     return;
     257             :   }
     258             : 
     259           0 :   mIsPresenting = false;
     260             : }
     261             : 
     262             : #if defined(XP_WIN)
     263             : bool
     264             : VRDisplayPuppet::UpdateConstantBuffers()
     265             : {
     266             :   HRESULT hr;
     267             :   D3D11_MAPPED_SUBRESOURCE resource;
     268             :   resource.pData = nullptr;
     269             : 
     270             :   hr = mContext->Map(mVSConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
     271             :   if (FAILED(hr) || !resource.pData) {
     272             :     return false;
     273             :   }
     274             :   *(VertexShaderConstants*)resource.pData = mVSConstants;
     275             :   mContext->Unmap(mVSConstantBuffer, 0);
     276             :   resource.pData = nullptr;
     277             : 
     278             :   hr = mContext->Map(mPSConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
     279             :   if (FAILED(hr) || !resource.pData) {
     280             :     return false;
     281             :   }
     282             :   *(PixelShaderConstants*)resource.pData = mPSConstants;
     283             :   mContext->Unmap(mPSConstantBuffer, 0);
     284             : 
     285             :   ID3D11Buffer *buffer = mVSConstantBuffer;
     286             :   mContext->VSSetConstantBuffers(0, 1, &buffer);
     287             :   buffer = mPSConstantBuffer;
     288             :   mContext->PSSetConstantBuffers(0, 1, &buffer);
     289             :   return true;
     290             : }
     291             : 
     292             : bool
     293             : VRDisplayPuppet::SubmitFrame(TextureSourceD3D11* aSource,
     294             :                              const IntSize& aSize,
     295             :                              const gfx::Rect& aLeftEyeRect,
     296             :                              const gfx::Rect& aRightEyeRect)
     297             : {
     298             :   if (!mIsPresenting) {
     299             :     return false;
     300             :   }
     301             : 
     302             :   VRManager *vm = VRManager::Get();
     303             :   MOZ_ASSERT(vm);
     304             : 
     305             :   switch (gfxPrefs::VRPuppetSubmitFrame()) {
     306             :     case 0:
     307             :       // The VR frame is not displayed.
     308             :       break;
     309             :     case 1:
     310             :     {
     311             :       // The frames are submitted to VR compositor are decoded
     312             :       // into a base64Image and dispatched to the DOM side.
     313             :       D3D11_TEXTURE2D_DESC desc;
     314             :       ID3D11Texture2D* texture = aSource->GetD3D11Texture();
     315             :       texture->GetDesc(&desc);
     316             :       MOZ_ASSERT(desc.Format == DXGI_FORMAT_B8G8R8A8_UNORM,
     317             :                  "Only support B8G8R8A8_UNORM format.");
     318             :       // Map the staging resource
     319             :       ID3D11Texture2D* mappedTexture = nullptr;
     320             :       D3D11_MAPPED_SUBRESOURCE mapInfo;
     321             :       HRESULT hr = mContext->Map(texture,
     322             :                                  0,  // Subsource
     323             :                                  D3D11_MAP_READ,
     324             :                                  0,  // MapFlags
     325             :                                  &mapInfo);
     326             : 
     327             :       if (FAILED(hr)) {
     328             :         // If we can't map this texture, copy it to a staging resource.
     329             :         if (hr == E_INVALIDARG) {
     330             :           D3D11_TEXTURE2D_DESC desc2;
     331             :           desc2.Width = desc.Width;
     332             :           desc2.Height = desc.Height;
     333             :           desc2.MipLevels = desc.MipLevels;
     334             :           desc2.ArraySize = desc.ArraySize;
     335             :           desc2.Format = desc.Format;
     336             :           desc2.SampleDesc = desc.SampleDesc;
     337             :           desc2.Usage = D3D11_USAGE_STAGING;
     338             :           desc2.BindFlags = 0;
     339             :           desc2.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
     340             :           desc2.MiscFlags = 0;
     341             : 
     342             :           ID3D11Texture2D* stagingTexture = nullptr;
     343             :           hr = mDevice->CreateTexture2D(&desc2, nullptr, &stagingTexture);
     344             :           if (FAILED(hr)) {
     345             :             MOZ_ASSERT(false, "Failed to create a staging texture");
     346             :             return false;
     347             :           }
     348             :           // Copy the texture to a staging resource
     349             :           mContext->CopyResource(stagingTexture, texture);
     350             :           // Map the staging resource
     351             :           hr = mContext->Map(stagingTexture,
     352             :                              0,  // Subsource
     353             :                              D3D11_MAP_READ,
     354             :                              0,  // MapFlags
     355             :                              &mapInfo);
     356             :           if (FAILED(hr)) {
     357             :             MOZ_ASSERT(false, "Failed to map staging texture");
     358             :           }
     359             :           mappedTexture = stagingTexture;
     360             :         } else {
     361             :           MOZ_ASSERT(false, "Failed to map staging texture");
     362             :           return false;
     363             :         }
     364             :       } else {
     365             :         mappedTexture = texture;
     366             :       }
     367             :       // Ideally, we should convert the srcData to a PNG image and decode it
     368             :       // to a Base64 string here, but the GPU process does not have the privilege to
     369             :       // access the image library. So, we have to convert the RAW image data
     370             :       // to a base64 string and forward it to let the content process to
     371             :       // do the image conversion.
     372             :       char* srcData = static_cast<char*>(mapInfo.pData);
     373             :       VRSubmitFrameResultInfo result;
     374             :       result.mFormat = SurfaceFormat::B8G8R8A8;
     375             :       // If the original texture size is not pow of 2, CopyResource() will add padding,
     376             :       // so the size is adjusted. We have to get the correct size by (mapInfo.RowPitch /
     377             :       // the format size).
     378             :       result.mWidth = mapInfo.RowPitch / 4;
     379             :       result.mHeight = desc.Height;
     380             :       result.mFrameNum = mDisplayInfo.mFrameId;
     381             :       nsCString rawString(Substring((char*)srcData, mapInfo.RowPitch * desc.Height));
     382             : 
     383             :       if (Base64Encode(rawString, result.mBase64Image) != NS_OK) {
     384             :         MOZ_ASSERT(false, "Failed to encode base64 images.");
     385             :       }
     386             :       mContext->Unmap(mappedTexture, 0);
     387             :       // Dispatch the base64 encoded string to the DOM side. Then, it will be decoded
     388             :       // and convert to a PNG image there.
     389             :       vm->DispatchSubmitFrameResult(mDisplayInfo.mDisplayID, result);
     390             :       break;
     391             :     }
     392             :     case 2:
     393             :     {
     394             :       // The VR compositor sumbmit frame to the screen window,
     395             :       // the current coordinate is at (0, 0, width, height).
     396             :       Matrix viewMatrix = Matrix::Translation(-1.0, 1.0);
     397             :       viewMatrix.PreScale(2.0f / float(aSize.width), 2.0f / float(aSize.height));
     398             :       viewMatrix.PreScale(1.0f, -1.0f);
     399             :       Matrix4x4 projection = Matrix4x4::From2D(viewMatrix);
     400             :       projection._33 = 0.0f;
     401             : 
     402             :       Matrix transform2d;
     403             :       gfx::Matrix4x4 transform = gfx::Matrix4x4::From2D(transform2d);
     404             : 
     405             :       const float posX = 0.0f, posY = 0.0f;
     406             :       D3D11_VIEWPORT viewport;
     407             :       viewport.MinDepth = 0.0f;
     408             :       viewport.MaxDepth = 1.0f;
     409             :       viewport.Width = aSize.width;
     410             :       viewport.Height = aSize.height;
     411             :       viewport.TopLeftX = posX;
     412             :       viewport.TopLeftY = posY;
     413             : 
     414             :       D3D11_RECT scissor;
     415             :       scissor.left = posX;
     416             :       scissor.right = aSize.width + posX;
     417             :       scissor.top = posY;
     418             :       scissor.bottom = aSize.height + posY;
     419             : 
     420             :       memcpy(&mVSConstants.layerTransform, &transform._11, sizeof(mVSConstants.layerTransform));
     421             :       memcpy(&mVSConstants.projection, &projection._11, sizeof(mVSConstants.projection));
     422             :       mVSConstants.renderTargetOffset[0] = 0.0f;
     423             :       mVSConstants.renderTargetOffset[1] = 0.0f;
     424             :       mVSConstants.layerQuad = Rect(0.0f, 0.0f, aSize.width, aSize.height);
     425             :       mVSConstants.textureCoords = Rect(0.0f, 1.0f, 1.0f, -1.0f);
     426             : 
     427             :       mPSConstants.layerOpacity[0] = 1.0f;
     428             : 
     429             :       ID3D11Buffer* vbuffer = mVertexBuffer;
     430             :       UINT vsize = sizeof(Vertex);
     431             :       UINT voffset = 0;
     432             :       mContext->IASetVertexBuffers(0, 1, &vbuffer, &vsize, &voffset);
     433             :       mContext->IASetIndexBuffer(nullptr, DXGI_FORMAT_R16_UINT, 0);
     434             :       mContext->IASetInputLayout(mInputLayout);
     435             :       mContext->RSSetViewports(1, &viewport);
     436             :       mContext->RSSetScissorRects(1, &scissor);
     437             :       mContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
     438             :       mContext->VSSetShader(mQuadVS, nullptr, 0);
     439             :       mContext->PSSetShader(mQuadPS, nullptr, 0);
     440             :       ID3D11ShaderResourceView* srView = aSource->GetShaderResourceView();
     441             :       if (!srView) {
     442             :         NS_WARNING("Failed to get SRV for Puppet");
     443             :         return false;
     444             :       }
     445             :       mContext->PSSetShaderResources(0 /* 0 == TexSlot::RGB */, 1, &srView);
     446             :       // XXX Use Constant from TexSlot in CompositorD3D11.cpp?
     447             : 
     448             :       ID3D11SamplerState *sampler = mLinearSamplerState;
     449             :       mContext->PSSetSamplers(0, 1, &sampler);
     450             : 
     451             :       if (!UpdateConstantBuffers()) {
     452             :         NS_WARNING("Failed to update constant buffers for Puppet");
     453             :         return false;
     454             :       }
     455             :       mContext->Draw(4, 0);
     456             :       break;
     457             :     }
     458             :   }
     459             : 
     460             :   // We will always return false for gfxVRPuppet to ensure that the fallback "watchdog"
     461             :   // code in VRDisplayHost::NotifyVSync() throttles the render loop.  This "watchdog" will
     462             :   // result in a refresh rate that is quite low compared to real hardware, but should be
     463             :   // sufficient for non-performance oriented tests.  If we wish to simulate realistic frame
     464             :   // rates with VRDisplayPuppet, we should block here for the appropriate amount of time and
     465             :   // return true to indicate that we have blocked.
     466             :   return false;
     467             : }
     468             : #else
     469             : bool
     470           0 : VRDisplayPuppet::SubmitFrame(TextureSourceOGL* aSource,
     471             :                              const IntSize& aSize,
     472             :                              const gfx::Rect& aLeftEyeRect,
     473             :                              const gfx::Rect& aRightEyeRect)
     474             : {
     475           0 :   if (!mIsPresenting) {
     476           0 :     return false;
     477             :   }
     478             : 
     479             :   // TODO: Bug 1343730, Need to block until the next simulated
     480             :   // vblank interval and capture frames for use in reftests.
     481             : 
     482           0 :   return false;
     483             : }
     484             : #endif
     485             : 
     486             : void
     487           0 : VRDisplayPuppet::NotifyVSync()
     488             : {
     489             :   // We update mIsConneced once per frame.
     490           0 :   mDisplayInfo.mIsConnected = true;
     491             : 
     492           0 :   VRDisplayHost::NotifyVSync();
     493           0 : }
     494             : 
     495           0 : VRControllerPuppet::VRControllerPuppet(dom::GamepadHand aHand)
     496             :   : VRControllerHost(VRDeviceType::Puppet)
     497           0 :   , mButtonPressState(0)
     498             : {
     499           0 :   MOZ_COUNT_CTOR_INHERITED(VRControllerPuppet, VRControllerHost);
     500           0 :   mControllerInfo.mControllerName.AssignLiteral("Puppet Gamepad");
     501           0 :   mControllerInfo.mMappingType = GamepadMappingType::_empty;
     502           0 :   mControllerInfo.mHand = aHand;
     503           0 :   mControllerInfo.mNumButtons = kNumPuppetButtonMask;
     504           0 :   mControllerInfo.mNumAxes = kNumPuppetAxis;
     505           0 :   mControllerInfo.mNumHaptics = kNumPuppetHaptcs;
     506           0 : }
     507             : 
     508           0 : VRControllerPuppet::~VRControllerPuppet()
     509             : {
     510           0 :   MOZ_COUNT_DTOR_INHERITED(VRControllerPuppet, VRControllerHost);
     511           0 : }
     512             : 
     513             : void
     514           0 : VRControllerPuppet::SetButtonPressState(uint32_t aButton, bool aPressed)
     515             : {
     516           0 :   const uint64_t buttonMask = kPuppetButtonMask[aButton];
     517           0 :   uint64_t pressedBit = GetButtonPressed();
     518             : 
     519           0 :   if (aPressed) {
     520           0 :     pressedBit |= kPuppetButtonMask[aButton];
     521           0 :   } else if (pressedBit & buttonMask) {
     522             :     // this button was pressed but is released now.
     523           0 :     uint64_t mask = 0xff ^ buttonMask;
     524           0 :     pressedBit &= mask;
     525             :   }
     526             : 
     527           0 :   mButtonPressState = pressedBit;
     528           0 : }
     529             : 
     530             : uint64_t
     531           0 : VRControllerPuppet::GetButtonPressState()
     532             : {
     533           0 :   return mButtonPressState;
     534             : }
     535             : 
     536             : void
     537           0 : VRControllerPuppet::SetButtonTouchState(uint32_t aButton, bool aTouched)
     538             : {
     539           0 :   const uint64_t buttonMask = kPuppetButtonMask[aButton];
     540           0 :   uint64_t touchedBit = GetButtonTouched();
     541             : 
     542           0 :   if (aTouched) {
     543           0 :     touchedBit |= kPuppetButtonMask[aButton];
     544           0 :   } else if (touchedBit & buttonMask) {
     545             :     // this button was touched but is released now.
     546           0 :     uint64_t mask = 0xff ^ buttonMask;
     547           0 :     touchedBit &= mask;
     548             :   }
     549             : 
     550           0 :   mButtonTouchState = touchedBit;
     551           0 : }
     552             : 
     553             : uint64_t
     554           0 : VRControllerPuppet::GetButtonTouchState()
     555             : {
     556           0 :   return mButtonTouchState;
     557             : }
     558             : 
     559             : void
     560           0 : VRControllerPuppet::SetAxisMoveState(uint32_t aAxis, double aValue)
     561             : {
     562             :   MOZ_ASSERT((sizeof(mAxisMoveState) / sizeof(float)) == kNumPuppetAxis);
     563           0 :   MOZ_ASSERT(aAxis <= kNumPuppetAxis);
     564             : 
     565           0 :   mAxisMoveState[aAxis] = aValue;
     566           0 : }
     567             : 
     568             : double
     569           0 : VRControllerPuppet::GetAxisMoveState(uint32_t aAxis)
     570             : {
     571           0 :   return mAxisMoveState[aAxis];
     572             : }
     573             : 
     574             : void
     575           0 : VRControllerPuppet::SetPoseMoveState(const dom::GamepadPoseState& aPose)
     576             : {
     577           0 :   mPoseState = aPose;
     578           0 : }
     579             : 
     580             : const dom::GamepadPoseState&
     581           0 : VRControllerPuppet::GetPoseMoveState()
     582             : {
     583           0 :   return mPoseState;
     584             : }
     585             : 
     586             : float
     587           0 : VRControllerPuppet::GetAxisMove(uint32_t aAxis)
     588             : {
     589           0 :   return mAxisMove[aAxis];
     590             : }
     591             : 
     592             : void
     593           0 : VRControllerPuppet::SetAxisMove(uint32_t aAxis, float aValue)
     594             : {
     595           0 :   mAxisMove[aAxis] = aValue;
     596           0 : }
     597             : 
     598           0 : VRSystemManagerPuppet::VRSystemManagerPuppet()
     599             : {
     600           0 : }
     601             : 
     602             : /*static*/ already_AddRefed<VRSystemManagerPuppet>
     603           0 : VRSystemManagerPuppet::Create()
     604             : {
     605           0 :   if (!gfxPrefs::VREnabled() || !gfxPrefs::VRPuppetEnabled()) {
     606           0 :     return nullptr;
     607             :   }
     608             : 
     609           0 :   RefPtr<VRSystemManagerPuppet> manager = new VRSystemManagerPuppet();
     610           0 :   return manager.forget();
     611             : }
     612             : 
     613             : void
     614           0 : VRSystemManagerPuppet::Destroy()
     615             : {
     616           0 :   Shutdown();
     617           0 : }
     618             : 
     619             : void
     620           0 : VRSystemManagerPuppet::Shutdown()
     621             : {
     622           0 :   mPuppetHMD = nullptr;
     623           0 : }
     624             : 
     625             : bool
     626           0 : VRSystemManagerPuppet::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
     627             : {
     628           0 :   if (mPuppetHMD == nullptr) {
     629           0 :     mPuppetHMD = new VRDisplayPuppet();
     630             :   }
     631           0 :   aHMDResult.AppendElement(mPuppetHMD);
     632           0 :   return true;
     633             : }
     634             : 
     635             : bool
     636           0 : VRSystemManagerPuppet::GetIsPresenting()
     637             : {
     638           0 :   if (mPuppetHMD) {
     639           0 :     VRDisplayInfo displayInfo(mPuppetHMD->GetDisplayInfo());
     640           0 :     return displayInfo.GetPresentingGroups() != kVRGroupNone;
     641             :   }
     642             : 
     643           0 :   return false;
     644             : }
     645             : 
     646             : void
     647           0 : VRSystemManagerPuppet::HandleInput()
     648             : {
     649           0 :   RefPtr<impl::VRControllerPuppet> controller;
     650           0 :   for (uint32_t i = 0; i < mPuppetController.Length(); ++i) {
     651           0 :     controller = mPuppetController[i];
     652           0 :     for (uint32_t j = 0; j < kNumPuppetButtonMask; ++j) {
     653           0 :       HandleButtonPress(i, j, kPuppetButtonMask[i], controller->GetButtonPressState(),
     654           0 :                         controller->GetButtonTouchState());
     655             :     }
     656           0 :     controller->SetButtonPressed(controller->GetButtonPressState());
     657             : 
     658           0 :     for (uint32_t j = 0; j < kNumPuppetAxis; ++j) {
     659           0 :       HandleAxisMove(i, j, controller->GetAxisMoveState(j));
     660             :     }
     661           0 :     HandlePoseTracking(i, controller->GetPoseMoveState(), controller);
     662             :   }
     663           0 : }
     664             : 
     665             : void
     666           0 : VRSystemManagerPuppet::HandleButtonPress(uint32_t aControllerIdx,
     667             :                                          uint32_t aButton,
     668             :                                          uint64_t aButtonMask,
     669             :                                          uint64_t aButtonPressed,
     670             :                                          uint64_t aButtonTouched)
     671             : {
     672           0 :   RefPtr<impl::VRControllerPuppet> controller(mPuppetController[aControllerIdx]);
     673           0 :   MOZ_ASSERT(controller);
     674           0 :   const uint64_t pressedDiff = (controller->GetButtonPressed() ^ aButtonPressed);
     675           0 :   const uint64_t touchedDiff = (controller->GetButtonTouched() ^ aButtonTouched);
     676             : 
     677           0 :   if (!pressedDiff && !touchedDiff) {
     678           0 :     return;
     679             :   }
     680             : 
     681           0 :    if (pressedDiff & aButtonMask
     682           0 :       || touchedDiff & aButtonMask) {
     683             :     // diff & (aButtonPressed, aButtonTouched) would be true while a new button pressed or
     684             :     // touched event, otherwise it is an old event and needs to notify
     685             :     // the button has been released.
     686           0 :     NewButtonEvent(aControllerIdx, aButton, aButtonMask & aButtonPressed,
     687           0 :                    aButtonMask & aButtonPressed,
     688           0 :                    (aButtonMask & aButtonPressed) ? 1.0L : 0.0L);
     689             :   }
     690             : }
     691             : 
     692             : void
     693           0 : VRSystemManagerPuppet::HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis,
     694             :                                       float aValue)
     695             : {
     696           0 :   RefPtr<impl::VRControllerPuppet> controller(mPuppetController[aControllerIdx]);
     697           0 :   MOZ_ASSERT(controller);
     698             : 
     699           0 :   if (controller->GetAxisMove(aAxis) != aValue) {
     700           0 :     NewAxisMove(aControllerIdx, aAxis, aValue);
     701           0 :     controller->SetAxisMove(aAxis, aValue);
     702             :   }
     703           0 : }
     704             : 
     705             : void
     706           0 : VRSystemManagerPuppet::HandlePoseTracking(uint32_t aControllerIdx,
     707             :                                           const GamepadPoseState& aPose,
     708             :                                           VRControllerHost* aController)
     709             : {
     710           0 :   MOZ_ASSERT(aController);
     711           0 :   if (aPose != aController->GetPose()) {
     712           0 :     aController->SetPose(aPose);
     713           0 :     NewPoseState(aControllerIdx, aPose);
     714             :   }
     715           0 : }
     716             : 
     717             : void
     718           0 : VRSystemManagerPuppet::VibrateHaptic(uint32_t aControllerIdx,
     719             :                                      uint32_t aHapticIndex,
     720             :                                      double aIntensity,
     721             :                                      double aDuration,
     722             :                                      uint32_t aPromiseID)
     723             : {
     724           0 : }
     725             : 
     726             : void
     727           0 : VRSystemManagerPuppet::StopVibrateHaptic(uint32_t aControllerIdx)
     728             : {
     729           0 : }
     730             : 
     731             : void
     732           0 : VRSystemManagerPuppet::GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult)
     733             : {
     734           0 :   aControllerResult.Clear();
     735           0 :   for (uint32_t i = 0; i < mPuppetController.Length(); ++i) {
     736           0 :     aControllerResult.AppendElement(mPuppetController[i]);
     737             :   }
     738           0 : }
     739             : 
     740             : void
     741           0 : VRSystemManagerPuppet::ScanForControllers()
     742             : {
     743             :   // We make VRSystemManagerPuppet has two controllers always.
     744           0 :   const uint32_t newControllerCount = 2;
     745             : 
     746           0 :   if (newControllerCount != mControllerCount) {
     747           0 :     RemoveControllers();
     748             : 
     749             :     // Re-adding controllers to VRControllerManager.
     750           0 :     for (uint32_t i = 0; i < newControllerCount; ++i) {
     751           0 :       dom::GamepadHand hand = (i % 2) ? dom::GamepadHand::Right :
     752           0 :                                         dom::GamepadHand::Left;
     753           0 :       RefPtr<VRControllerPuppet> puppetController = new VRControllerPuppet(hand);
     754           0 :       mPuppetController.AppendElement(puppetController);
     755             : 
     756             :       // Not already present, add it.
     757           0 :       AddGamepad(puppetController->GetControllerInfo());
     758           0 :       ++mControllerCount;
     759             :     }
     760             :   }
     761           0 : }
     762             : 
     763             : void
     764           0 : VRSystemManagerPuppet::RemoveControllers()
     765             : {
     766             :   // controller count is changed, removing the existing gamepads first.
     767           0 :   for (uint32_t i = 0; i < mPuppetController.Length(); ++i) {
     768           0 :     RemoveGamepad(i);
     769             :   }
     770           0 :   mPuppetController.Clear();
     771           0 :   mControllerCount = 0;
     772           0 : }

Generated by: LCOV version 1.13