tor-browser

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

SharedRGBImage.cpp (5898B)


      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 "SharedRGBImage.h"
      8 #include "ImageTypes.h"         // for ImageFormat::SHARED_RGB, etc
      9 #include "mozilla/ipc/Shmem.h"  // for Shmem
     10 #include "gfx2DGlue.h"          // for ImageFormatToSurfaceFormat, etc
     11 #include "gfxPlatform.h"        // for gfxPlatform, gfxImageFormat
     12 #include "mozilla/gfx/Point.h"  // for IntSIze
     13 #include "mozilla/layers/BufferTexture.h"
     14 #include "mozilla/layers/ISurfaceAllocator.h"  // for ISurfaceAllocator, etc
     15 #include "mozilla/layers/ImageClient.h"        // for ImageClient
     16 #include "mozilla/layers/LayersSurfaces.h"     // for SurfaceDescriptor, etc
     17 #include "mozilla/layers/TextureClient.h"      // for BufferTextureClient, etc
     18 #include "mozilla/layers/TextureClientRecycleAllocator.h"  // for ITextureClientAllocationHelper
     19 #include "mozilla/layers/ImageBridgeChild.h"  // for ImageBridgeChild
     20 #include "mozilla/mozalloc.h"                 // for operator delete, etc
     21 #include "nsDebug.h"                          // for NS_WARNING, NS_ASSERTION
     22 #include "nsISupportsImpl.h"                  // for Image::AddRef, etc
     23 #include "nsProxyRelease.h"
     24 #include "nsRect.h"  // for mozilla::gfx::IntRect
     25 
     26 // Just big enough for a 1080p RGBA32 frame
     27 #define MAX_FRAME_SIZE (16 * 1024 * 1024)
     28 
     29 namespace mozilla {
     30 namespace layers {
     31 
     32 class TextureClientForRawBufferAccessAllocationHelper
     33    : public ITextureClientAllocationHelper {
     34 public:
     35  TextureClientForRawBufferAccessAllocationHelper(gfx::SurfaceFormat aFormat,
     36                                                  gfx::IntSize aSize,
     37                                                  TextureFlags aTextureFlags)
     38      : ITextureClientAllocationHelper(aFormat, aSize, BackendSelector::Content,
     39                                       aTextureFlags, ALLOC_DEFAULT) {}
     40 
     41  bool IsCompatible(TextureClient* aTextureClient) override {
     42    bool ret = aTextureClient->GetFormat() == mFormat &&
     43               aTextureClient->GetSize() == mSize;
     44    return ret;
     45  }
     46 
     47  already_AddRefed<TextureClient> Allocate(
     48      KnowsCompositor* aAllocator) override {
     49    return TextureClient::CreateForRawBufferAccess(
     50        aAllocator, mFormat, mSize, gfx::BackendType::NONE, mTextureFlags);
     51  }
     52 };
     53 
     54 SharedRGBImage::SharedRGBImage(ImageClient* aCompositable)
     55    : Image(nullptr, ImageFormat::SHARED_RGB), mCompositable(aCompositable) {
     56  MOZ_COUNT_CTOR(SharedRGBImage);
     57 }
     58 
     59 SharedRGBImage::SharedRGBImage(TextureClientRecycleAllocator* aRecycleAllocator)
     60    : Image(nullptr, ImageFormat::SHARED_RGB),
     61      mRecycleAllocator(aRecycleAllocator) {
     62  MOZ_COUNT_CTOR(SharedRGBImage);
     63 }
     64 
     65 SharedRGBImage::~SharedRGBImage() {
     66  MOZ_COUNT_DTOR(SharedRGBImage);
     67  NS_ReleaseOnMainThread("SharedRGBImage::mSourceSurface",
     68                         mSourceSurface.forget());
     69 }
     70 
     71 TextureClientRecycleAllocator* SharedRGBImage::RecycleAllocator() {
     72  static const uint32_t MAX_POOLED_VIDEO_COUNT = 5;
     73 
     74  if (!mRecycleAllocator && mCompositable) {
     75    if (!mCompositable->HasTextureClientRecycler()) {
     76      // Initialize TextureClientRecycler
     77      mCompositable->GetTextureClientRecycler()->SetMaxPoolSize(
     78          MAX_POOLED_VIDEO_COUNT);
     79    }
     80    mRecycleAllocator = mCompositable->GetTextureClientRecycler();
     81  }
     82  return mRecycleAllocator;
     83 }
     84 
     85 bool SharedRGBImage::Allocate(gfx::IntSize aSize, gfx::SurfaceFormat aFormat) {
     86  mSize = aSize;
     87 
     88  TextureFlags flags =
     89      mCompositable ? mCompositable->GetTextureFlags() : TextureFlags::DEFAULT;
     90  {
     91    TextureClientForRawBufferAccessAllocationHelper helper(aFormat, aSize,
     92                                                           flags);
     93    mTextureClient =
     94        RecycleAllocator()->CreateOrRecycle(helper).unwrapOr(nullptr);
     95  }
     96 
     97  return !!mTextureClient;
     98 }
     99 
    100 gfx::IntSize SharedRGBImage::GetSize() const { return mSize; }
    101 
    102 TextureClient* SharedRGBImage::GetTextureClient(
    103    KnowsCompositor* aKnowsCompositor) {
    104  return mTextureClient.get();
    105 }
    106 
    107 static void ReleaseTextureClient(void* aData) {
    108  RELEASE_MANUALLY(static_cast<TextureClient*>(aData));
    109 }
    110 
    111 static gfx::UserDataKey sTextureClientKey;
    112 
    113 already_AddRefed<gfx::SourceSurface> SharedRGBImage::GetAsSourceSurface() {
    114  NS_ASSERTION(NS_IsMainThread(), "Must be main thread");
    115 
    116  if (mSourceSurface) {
    117    RefPtr<gfx::SourceSurface> surface(mSourceSurface);
    118    return surface.forget();
    119  }
    120 
    121  RefPtr<gfx::SourceSurface> surface;
    122  {
    123    // We are 'borrowing' the DrawTarget and retaining a permanent reference to
    124    // the underlying data (via the surface). It is in this instance since we
    125    // know that the TextureClient is always wrapping a BufferTextureData and
    126    // therefore it won't go away underneath us.
    127    BufferTextureData* decoded_buffer =
    128        mTextureClient->GetInternalData()->AsBufferTextureData();
    129    RefPtr<gfx::DrawTarget> drawTarget = decoded_buffer->BorrowDrawTarget();
    130 
    131    if (!drawTarget) {
    132      return nullptr;
    133    }
    134 
    135    surface = drawTarget->Snapshot();
    136    if (!surface) {
    137      return nullptr;
    138    }
    139 
    140    // The surface may outlive the owning TextureClient. So, we need to ensure
    141    // that the surface keeps the TextureClient alive via a reference held in
    142    // user data. The TextureClient's DrawTarget only has a weak reference to
    143    // the surface, so we won't create any cycles by just referencing the
    144    // TextureClient.
    145    if (!surface->GetUserData(&sTextureClientKey)) {
    146      surface->AddUserData(&sTextureClientKey, mTextureClient,
    147                           ReleaseTextureClient);
    148      ADDREF_MANUALLY(mTextureClient);
    149    }
    150  }
    151 
    152  mSourceSurface = surface;
    153  return surface.forget();
    154 }
    155 
    156 }  // namespace layers
    157 }  // namespace mozilla