tor-browser

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

ShareableCanvasRenderer.cpp (6411B)


      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 "ShareableCanvasRenderer.h"
      8 
      9 #include "mozilla/dom/WebGLTypes.h"
     10 #include "mozilla/gfx/2D.h"
     11 #include "mozilla/layers/TextureClientSharedSurface.h"
     12 #include "mozilla/layers/CompositableForwarder.h"
     13 #include "mozilla/layers/TextureForwarder.h"
     14 
     15 #include "ClientWebGLContext.h"
     16 #include "gfxUtils.h"
     17 #include "GLScreenBuffer.h"
     18 #include "nsICanvasRenderingContextInternal.h"
     19 #include "SharedSurfaceGL.h"
     20 
     21 using namespace mozilla::gfx;
     22 
     23 namespace mozilla {
     24 namespace layers {
     25 
     26 ShareableCanvasRenderer::ShareableCanvasRenderer() {
     27  MOZ_COUNT_CTOR(ShareableCanvasRenderer);
     28 }
     29 
     30 ShareableCanvasRenderer::~ShareableCanvasRenderer() {
     31  MOZ_COUNT_DTOR(ShareableCanvasRenderer);
     32 
     33  mFrontBufferFromDesc = nullptr;
     34  DisconnectClient();
     35 }
     36 
     37 void ShareableCanvasRenderer::Initialize(const CanvasRendererData& aData) {
     38  CanvasRenderer::Initialize(aData);
     39  mCanvasClient = nullptr;
     40 }
     41 
     42 void ShareableCanvasRenderer::ClearCachedResources() {
     43  CanvasRenderer::ClearCachedResources();
     44 
     45  if (mCanvasClient) {
     46    mCanvasClient->Clear();
     47  }
     48 }
     49 
     50 void ShareableCanvasRenderer::DisconnectClient() {
     51  if (mCanvasClient) {
     52    mCanvasClient->OnDetach();
     53    mCanvasClient = nullptr;
     54  }
     55 }
     56 
     57 RefPtr<layers::TextureClient> ShareableCanvasRenderer::GetFrontBufferFromDesc(
     58    const layers::SurfaceDescriptor& desc, TextureFlags flags) {
     59  if (mFrontBufferFromDesc && mFrontBufferDesc == desc)
     60    return mFrontBufferFromDesc;
     61  mFrontBufferFromDesc = nullptr;
     62 
     63  // Test the validity of aAllocator
     64  const auto& compositableForwarder = GetForwarder();
     65  if (!compositableForwarder) {
     66    return nullptr;
     67  }
     68  const auto& textureForwarder = compositableForwarder->GetTextureForwarder();
     69 
     70  auto format = gfx::SurfaceFormat::R8G8B8X8;
     71  if (!mData.mIsOpaque) {
     72    format = gfx::SurfaceFormat::R8G8B8A8;
     73 
     74    if (!mData.mIsAlphaPremult) {
     75      flags |= TextureFlags::NON_PREMULTIPLIED;
     76    }
     77  }
     78 
     79  mFrontBufferFromDesc = SharedSurfaceTextureData::CreateTextureClient(
     80      desc, format, mData.mSize, flags, textureForwarder);
     81  mFrontBufferDesc = desc;
     82  return mFrontBufferFromDesc;
     83 }
     84 
     85 void ShareableCanvasRenderer::UpdateCompositableClient() {
     86  if (!CreateCompositable()) {
     87    return;
     88  }
     89 
     90  if (!IsDirty()) {
     91    const auto context = mData.GetContext();
     92    if (!context) {
     93      return;
     94    }
     95    const auto& forwarder = GetForwarder();
     96    RefPtr<FwdTransactionTracker> tracker =
     97        context->UseCompositableForwarder(forwarder);
     98    if (forwarder && tracker) {
     99      forwarder->TrackFwdTransaction(tracker);
    100    }
    101    return;
    102  }
    103  ResetDirty();
    104 
    105  const auto context = mData.GetContext();
    106  if (!context) return;
    107  const auto& provider = context->GetBufferProvider();
    108  const auto& forwarder = GetForwarder();
    109 
    110  // -
    111 
    112  auto flags = TextureFlags::IMMUTABLE;
    113  if (!YIsDown()) {
    114    flags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
    115  }
    116  if (IsOpaque()) {
    117    flags |= TextureFlags::IS_OPAQUE;
    118  }
    119  if (provider) {
    120    flags |= TextureFlags::ALLOC_BY_BUFFER_PROVIDER;
    121  }
    122 
    123  // -
    124 
    125  const auto fnGetExistingTc =
    126      [&](const Maybe<SurfaceDescriptor>& aDesc,
    127          bool& aOutLostFrontTexture) -> RefPtr<TextureClient> {
    128    if (aDesc) {
    129      return GetFrontBufferFromDesc(*aDesc, flags);
    130    }
    131    if (provider) {
    132      if (!provider->SetKnowsCompositor(forwarder, aOutLostFrontTexture)) {
    133        gfxCriticalNote << "BufferProvider::SetForwarder failed";
    134        return nullptr;
    135      }
    136      if (aOutLostFrontTexture) {
    137        return nullptr;
    138      }
    139 
    140      return provider->GetTextureClient();
    141    }
    142    return nullptr;
    143  };
    144 
    145  // -
    146 
    147  const auto fnMakeTcFromSnapshot = [&]() -> RefPtr<TextureClient> {
    148    const auto& size = mData.mSize;
    149 
    150    auto contentType = gfxContentType::COLOR;
    151    if (!mData.mIsOpaque) {
    152      contentType = gfxContentType::COLOR_ALPHA;
    153    }
    154    const auto surfaceFormat =
    155        gfxPlatform::GetPlatform()->Optimal2DFormatForContent(contentType);
    156 
    157    const auto tc =
    158        mCanvasClient->CreateTextureClientForCanvas(surfaceFormat, size, flags);
    159    if (!tc) {
    160      return nullptr;
    161    }
    162 
    163    {
    164      TextureClientAutoLock tcLock(tc, OpenMode::OPEN_WRITE_ONLY);
    165      if (!tcLock.Succeeded()) {
    166        return nullptr;
    167      }
    168 
    169      const RefPtr<DrawTarget> dt = tc->BorrowDrawTarget();
    170 
    171      const bool requireAlphaPremult = false;
    172      auto borrowed = BorrowSnapshot(requireAlphaPremult);
    173      if (!borrowed) {
    174        return nullptr;
    175      }
    176      dt->CopySurface(borrowed->mSurf, borrowed->mSurf->GetRect(), {0, 0});
    177    }
    178 
    179    return tc;
    180  };
    181 
    182  // -
    183 
    184  {
    185    FirePreTransactionCallback();
    186 
    187    const auto desc = context->GetFrontBuffer(nullptr);
    188    if (desc &&
    189        desc->type() == SurfaceDescriptor::TSurfaceDescriptorRemoteTexture) {
    190      const auto& forwarder = GetForwarder();
    191      const auto& textureDesc = desc->get_SurfaceDescriptorRemoteTexture();
    192      if (!mData.mIsAlphaPremult) {
    193        flags |= TextureFlags::NON_PREMULTIPLIED;
    194      }
    195      EnsurePipeline();
    196      RefPtr<FwdTransactionTracker> tracker =
    197          context->UseCompositableForwarder(forwarder);
    198      if (tracker) {
    199        flags |= TextureFlags::WAIT_FOR_REMOTE_TEXTURE_OWNER;
    200      }
    201      forwarder->UseRemoteTexture(mCanvasClient, textureDesc.textureId(),
    202                                  textureDesc.ownerId(), mData.mSize, flags,
    203                                  tracker);
    204      FireDidTransactionCallback();
    205      return;
    206    }
    207 
    208    EnsurePipeline();
    209 
    210    // Let's see if we can get a no-copy TextureClient from the canvas.
    211    bool lostFrontTexture = false;
    212    auto tc = fnGetExistingTc(desc, lostFrontTexture);
    213    if (lostFrontTexture) {
    214      // Device reset could cause this.
    215      return;
    216    }
    217    if (!tc) {
    218      // Otherwise, snapshot the surface and copy into a TexClient.
    219      tc = fnMakeTcFromSnapshot();
    220    }
    221    if (tc != mFrontBufferFromDesc) {
    222      mFrontBufferFromDesc = nullptr;
    223    }
    224 
    225    if (!tc) {
    226      NS_WARNING("Couldn't make TextureClient for CanvasRenderer.");
    227      return;
    228    }
    229 
    230    mCanvasClient->UseTexture(tc);
    231 
    232    FireDidTransactionCallback();
    233  }
    234 }
    235 
    236 }  // namespace layers
    237 }  // namespace mozilla