tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

VRSession.cpp (6293B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "VRSession.h"
      8 
      9 #include "moz_external_vr.h"
     10 
     11 #include "mozilla/ipc/FileDescriptor.h"
     12 
     13 #if defined(XP_WIN)
     14 #  include <d3d11.h>
     15 #endif  // defined(XP_WIN)
     16 
     17 #if defined(MOZILLA_INTERNAL_API)
     18 #  if defined(XP_WIN)
     19 #    include "mozilla/gfx/Logging.h"
     20 #  endif
     21 #else
     22 #  define NS_WARNING(s)
     23 #endif
     24 
     25 using namespace mozilla::gfx;
     26 
     27 VRSession::VRSession()
     28    : mShouldQuit(false)
     29 #ifdef XP_WIN
     30      ,
     31      mDevice(nullptr),
     32      mContext(nullptr),
     33      mDeviceContextState(nullptr)
     34 #endif
     35 {
     36 }
     37 
     38 #ifdef XP_WIN
     39 VRSession::~VRSession() {
     40  if (mDevice != nullptr) {
     41    mDevice->Release();
     42    mDevice = nullptr;
     43  }
     44 
     45  if (mContext != nullptr) {
     46    mContext->Release();
     47    mContext = nullptr;
     48  }
     49 
     50  if (mDeviceContextState != nullptr) {
     51    mDeviceContextState->Release();
     52    mDeviceContextState = nullptr;
     53  }
     54 }
     55 #endif
     56 
     57 #if defined(XP_WIN)
     58 bool VRSession::CreateD3DContext(ID3D11Device* aDevice) {
     59  if (!mDevice) {
     60    if (!aDevice) {
     61      NS_WARNING("VRSession::CreateD3DObjects failed to get a D3D11Device");
     62      return false;
     63    }
     64    if (FAILED(aDevice->QueryInterface(IID_PPV_ARGS(&mDevice)))) {
     65      NS_WARNING("VRSession::CreateD3DObjects failed to get a D3D11Device1");
     66      return false;
     67    }
     68  }
     69  if (!mContext) {
     70    mDevice->GetImmediateContext1(&mContext);
     71    if (!mContext) {
     72      NS_WARNING(
     73          "VRSession::CreateD3DObjects failed to get an immediate context");
     74      return false;
     75    }
     76  }
     77  if (!mDeviceContextState) {
     78    D3D_FEATURE_LEVEL featureLevels[]{D3D_FEATURE_LEVEL_11_1,
     79                                      D3D_FEATURE_LEVEL_11_0};
     80    mDevice->CreateDeviceContextState(0, featureLevels, 2, D3D11_SDK_VERSION,
     81                                      __uuidof(ID3D11Device1), nullptr,
     82                                      &mDeviceContextState);
     83  }
     84  if (!mDeviceContextState) {
     85    NS_WARNING(
     86        "VRSession::CreateD3DObjects failed to get a D3D11DeviceContextState");
     87    return false;
     88  }
     89  return true;
     90 }
     91 
     92 ID3D11Device1* VRSession::GetD3DDevice() { return mDevice; }
     93 
     94 ID3D11DeviceContext1* VRSession::GetD3DDeviceContext() { return mContext; }
     95 
     96 ID3DDeviceContextState* VRSession::GetD3DDeviceContextState() {
     97  return mDeviceContextState;
     98 }
     99 
    100 #endif  // defined(XP_WIN)
    101 
    102 bool VRSession::SubmitFrame(
    103    const mozilla::gfx::VRLayer_Stereo_Immersive& aLayer) {
    104 #if defined(XP_WIN)
    105  bool success = false;
    106  if (aLayer.textureType ==
    107      VRLayerTextureType::LayerTextureType_D3D10SurfaceDescriptor) {
    108    ID3D11Texture2D* dxTexture = nullptr;
    109    mozilla::ipc::FileDescriptor::UniquePlatformHandle handle(
    110        aLayer.textureHandle);
    111    HRESULT hr =
    112        mDevice->OpenSharedResource1(handle.get(), IID_PPV_ARGS(&dxTexture));
    113    if (SUCCEEDED(hr) && dxTexture != nullptr) {
    114      // Similar to LockD3DTexture in TextureD3D11.cpp
    115      IDXGIKeyedMutex* mutex = nullptr;
    116      hr = dxTexture->QueryInterface(IID_PPV_ARGS(&mutex));
    117      if (SUCCEEDED(hr)) {
    118        hr = mutex->AcquireSync(0, 1000);
    119 #  ifdef MOZILLA_INTERNAL_API
    120        if (hr == WAIT_TIMEOUT) {
    121          gfxDevCrash(LogReason::D3DLockTimeout) << "D3D lock mutex timeout";
    122        } else if (hr == WAIT_ABANDONED) {
    123          gfxCriticalNote << "GFX: D3D11 lock mutex abandoned";
    124        }
    125 #  endif
    126        if (SUCCEEDED(hr)) {
    127          success = SubmitFrame(aLayer, dxTexture);
    128          hr = mutex->ReleaseSync(0);
    129          if (FAILED(hr)) {
    130            NS_WARNING("Failed to unlock the texture");
    131          }
    132        } else {
    133          NS_WARNING("Failed to lock the texture");
    134        }
    135 
    136        mutex->Release();
    137        mutex = nullptr;
    138      }
    139 
    140      dxTexture->Release();
    141      dxTexture = nullptr;
    142    } else {
    143      NS_WARNING("Failed to open shared texture");
    144    }
    145 
    146    return SUCCEEDED(hr) && success;
    147  }
    148 
    149 #elif defined(XP_MACOSX)
    150 
    151  if (aLayer.textureType == VRLayerTextureType::LayerTextureType_MacIOSurface) {
    152    return SubmitFrame(aLayer, aLayer.textureHandle);
    153  }
    154 
    155 #endif
    156 
    157  return false;
    158 }
    159 
    160 void VRSession::UpdateTrigger(VRControllerState& aState, uint32_t aButtonIndex,
    161                              float aValue, float aThreshold) {
    162  // For OpenVR, the threshold value of ButtonPressed and ButtonTouched is 0.55.
    163  // We prefer to let developers to set their own threshold for the adjustment.
    164  // Therefore, we don't check ButtonPressed and ButtonTouched with ButtonMask
    165  // here. we just check the button value is larger than the threshold value or
    166  // not.
    167  uint64_t mask = (1ULL << aButtonIndex);
    168  aState.triggerValue[aButtonIndex] = aValue;
    169  if (aValue > aThreshold) {
    170    aState.buttonPressed |= mask;
    171    aState.buttonTouched |= mask;
    172  } else {
    173    aState.buttonPressed &= ~mask;
    174    aState.buttonTouched &= ~mask;
    175  }
    176 }
    177 
    178 void VRSession::SetControllerSelectionAndSqueezeFrameId(
    179    VRControllerState& controllerState, uint64_t aFrameId) {
    180  // The 1st button, trigger, is its selection action.
    181  const bool selectionPressed = controllerState.buttonPressed & 1ULL;
    182  if (selectionPressed && controllerState.selectActionStopFrameId >=
    183                              controllerState.selectActionStartFrameId) {
    184    controllerState.selectActionStartFrameId = aFrameId;
    185  } else if (!selectionPressed && controllerState.selectActionStartFrameId >
    186                                      controllerState.selectActionStopFrameId) {
    187    controllerState.selectActionStopFrameId = aFrameId;
    188  }
    189  // The 2nd button, squeeze, is its squeeze action.
    190  const bool squeezePressed = controllerState.buttonPressed & (1ULL << 1);
    191  if (squeezePressed && controllerState.squeezeActionStopFrameId >=
    192                            controllerState.squeezeActionStartFrameId) {
    193    controllerState.squeezeActionStartFrameId = aFrameId;
    194  } else if (!squeezePressed && controllerState.squeezeActionStartFrameId >
    195                                    controllerState.squeezeActionStopFrameId) {
    196    controllerState.squeezeActionStopFrameId = aFrameId;
    197  }
    198 }
    199 
    200 bool VRSession::ShouldQuit() const { return mShouldQuit; }