tor-browser

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

VRLayerChild.cpp (4659B)


      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 "VRLayerChild.h"
      8 
      9 #include "mozilla/dom/HTMLCanvasElement.h"
     10 #include "mozilla/layers/ImageBridgeChild.h"
     11 #include "mozilla/layers/LayersMessages.h"  // for TimedTexture
     12 #include "mozilla/layers/SyncObject.h"      // for SyncObjectClient
     13 #include "mozilla/StaticPrefs_dom.h"
     14 #include "mozilla/StaticPrefs_webgl.h"
     15 
     16 #include "ClientWebGLContext.h"
     17 #include "gfxPlatform.h"
     18 #include "GLContext.h"
     19 #include "GLScreenBuffer.h"
     20 #include "SharedSurface.h"    // for SharedSurface
     21 #include "SharedSurfaceGL.h"  // for SharedSurface
     22 
     23 namespace mozilla::gfx {
     24 
     25 VRLayerChild::VRLayerChild() { MOZ_COUNT_CTOR(VRLayerChild); }
     26 
     27 VRLayerChild::~VRLayerChild() {
     28  ClearSurfaces();
     29 
     30  MOZ_COUNT_DTOR(VRLayerChild);
     31 }
     32 
     33 void VRLayerChild::Initialize(dom::HTMLCanvasElement* aCanvasElement,
     34                              const gfx::Rect& aLeftEyeRect,
     35                              const gfx::Rect& aRightEyeRect) {
     36  MOZ_ASSERT(aCanvasElement);
     37  mLeftEyeRect = aLeftEyeRect;
     38  mRightEyeRect = aRightEyeRect;
     39  mCanvasElement = aCanvasElement;
     40 }
     41 
     42 void VRLayerChild::SetXRFramebuffer(WebGLFramebufferJS* fb) {
     43  mFramebuffer = fb;
     44 }
     45 
     46 static constexpr bool kIsAndroid =
     47 #if defined(MOZ_WIDGET_ANDROID)
     48    true;
     49 #else
     50    false;
     51 #endif
     52 
     53 void VRLayerChild::SubmitFrame(const VRDisplayInfo& aDisplayInfo) {
     54  uint64_t frameId = aDisplayInfo.GetFrameId();
     55 
     56  // aFrameId will not increment unless the previuosly submitted
     57  // frame was received by the VR thread and submitted to the VR
     58  // compositor.  We early-exit here in the event that SubmitFrame
     59  // was called twice for the same aFrameId.
     60  if (!mCanvasElement || frameId == mLastSubmittedFrameId) {
     61    return;
     62  }
     63 
     64  const auto& webgl = mCanvasElement->GetWebGLContext();
     65  if (!webgl) return;
     66 
     67  // Keep the SharedSurfaceTextureClient alive long enough for
     68  // 1 extra frame, accomodating overlapped asynchronous rendering.
     69  mLastFrameTextureDesc = mThisFrameTextureDesc;
     70 
     71  bool getNewFrame = true;
     72  if (kIsAndroid) {
     73    /**
     74     * Do not blit WebGL to a SurfaceTexture until the last submitted frame is
     75     * already processed and the new frame poses are ready. SurfaceTextures need
     76     * to be released in the VR render thread in order to allow to be used again
     77     * in the WebGLContext GLScreenBuffer producer. Not doing so causes some
     78     * freezes, crashes or other undefined behaviour.
     79     */
     80    getNewFrame = (!mThisFrameTextureDesc ||
     81                   aDisplayInfo.mDisplayState.lastSubmittedFrameId ==
     82                       mLastSubmittedFrameId);
     83  }
     84  if (getNewFrame) {
     85    const RefPtr<layers::ImageBridgeChild> imageBridge =
     86        layers::ImageBridgeChild::GetSingleton();
     87 
     88    auto texType = layers::TextureType::Unknown;
     89    if (imageBridge) {
     90      texType = layers::PreferredCanvasTextureType(imageBridge);
     91    }
     92    if (kIsAndroid && StaticPrefs::webgl_enable_surface_texture()) {
     93      texType = layers::TextureType::AndroidNativeWindow;
     94    }
     95 
     96    webgl->Present(mFramebuffer, texType, true);
     97    mThisFrameTextureDesc = webgl->GetFrontBuffer(mFramebuffer, true);
     98  }
     99 
    100  mLastSubmittedFrameId = frameId;
    101 
    102  if (!mThisFrameTextureDesc) {
    103    gfxCriticalError() << "ToSurfaceDescriptor failed in "
    104                          "VRLayerChild::SubmitFrame";
    105    return;
    106  }
    107 
    108  SendSubmitFrame(*mThisFrameTextureDesc, frameId, mLeftEyeRect, mRightEyeRect);
    109 }
    110 
    111 bool VRLayerChild::IsIPCOpen() { return mIPCOpen; }
    112 
    113 void VRLayerChild::ClearSurfaces() {
    114  mThisFrameTextureDesc = Nothing();
    115  mLastFrameTextureDesc = Nothing();
    116  const auto& webgl = mCanvasElement->GetWebGLContext();
    117  if (!mFramebuffer && webgl) {
    118    webgl->ClearVRSwapChain();
    119  }
    120 }
    121 
    122 void VRLayerChild::ActorDestroy(ActorDestroyReason aWhy) { mIPCOpen = false; }
    123 
    124 // static
    125 PVRLayerChild* VRLayerChild::CreateIPDLActor() {
    126  if (!StaticPrefs::dom_vr_enabled() && !StaticPrefs::dom_vr_webxr_enabled()) {
    127    return nullptr;
    128  }
    129 
    130  VRLayerChild* c = new VRLayerChild();
    131  c->AddIPDLReference();
    132  return c;
    133 }
    134 
    135 // static
    136 bool VRLayerChild::DestroyIPDLActor(PVRLayerChild* actor) {
    137  static_cast<VRLayerChild*>(actor)->ReleaseIPDLReference();
    138  return true;
    139 }
    140 
    141 void VRLayerChild::AddIPDLReference() {
    142  MOZ_ASSERT(mIPCOpen == false);
    143  mIPCOpen = true;
    144  AddRef();
    145 }
    146 void VRLayerChild::ReleaseIPDLReference() {
    147  MOZ_ASSERT(mIPCOpen == false);
    148  Release();
    149 }
    150 
    151 }  // namespace mozilla::gfx