tor-browser

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

ImageMemoryReporter.cpp (6259B)


      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 "ImageMemoryReporter.h"
      8 #include "Image.h"
      9 #include "base/process_util.h"
     10 #include "mozilla/ipc/SharedMemoryMapping.h"
     11 #include "mozilla/layers/SharedSurfacesParent.h"
     12 #include "mozilla/StaticPrefs_image.h"
     13 #include "nsIMemoryReporter.h"
     14 #include "nsISupportsImpl.h"
     15 
     16 namespace mozilla {
     17 namespace image {
     18 
     19 ImageMemoryReporter::WebRenderReporter* ImageMemoryReporter::sWrReporter;
     20 
     21 class ImageMemoryReporter::WebRenderReporter final : public nsIMemoryReporter {
     22 public:
     23  NS_DECL_ISUPPORTS
     24 
     25  WebRenderReporter() {}
     26 
     27  NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
     28                            nsISupports* aData, bool aAnonymize) override {
     29    layers::SharedSurfacesMemoryReport report;
     30    layers::SharedSurfacesParent::AccumulateMemoryReport(report);
     31    ReportSharedSurfaces(aHandleReport, aData, /* aIsForCompositor */ true,
     32                         report);
     33    return NS_OK;
     34  }
     35 
     36 private:
     37  virtual ~WebRenderReporter() {}
     38 };
     39 
     40 NS_IMPL_ISUPPORTS(ImageMemoryReporter::WebRenderReporter, nsIMemoryReporter)
     41 
     42 /* static */
     43 void ImageMemoryReporter::InitForWebRender() {
     44  MOZ_ASSERT(XRE_IsParentProcess() || XRE_IsGPUProcess());
     45  if (!sWrReporter) {
     46    sWrReporter = new WebRenderReporter();
     47    RegisterStrongMemoryReporter(sWrReporter);
     48  }
     49 }
     50 
     51 /* static */
     52 void ImageMemoryReporter::ShutdownForWebRender() {
     53  MOZ_ASSERT(XRE_IsParentProcess() || XRE_IsGPUProcess());
     54  if (sWrReporter) {
     55    UnregisterStrongMemoryReporter(sWrReporter);
     56    sWrReporter = nullptr;
     57  }
     58 }
     59 
     60 /* static */
     61 void ImageMemoryReporter::ReportSharedSurfaces(
     62    nsIHandleReportCallback* aHandleReport, nsISupports* aData,
     63    const layers::SharedSurfacesMemoryReport& aSharedSurfaces) {
     64  ReportSharedSurfaces(aHandleReport, aData,
     65                       /* aIsForCompositor */ false, aSharedSurfaces);
     66 }
     67 
     68 /* static */
     69 void ImageMemoryReporter::ReportSharedSurfaces(
     70    nsIHandleReportCallback* aHandleReport, nsISupports* aData,
     71    bool aIsForCompositor,
     72    const layers::SharedSurfacesMemoryReport& aSharedSurfaces) {
     73  MOZ_ASSERT_IF(aIsForCompositor, XRE_IsParentProcess() || XRE_IsGPUProcess());
     74  MOZ_ASSERT_IF(!aIsForCompositor,
     75                XRE_IsParentProcess() || XRE_IsContentProcess());
     76 
     77  for (auto i = aSharedSurfaces.mSurfaces.begin();
     78       i != aSharedSurfaces.mSurfaces.end(); ++i) {
     79    ReportSharedSurface(aHandleReport, aData, aIsForCompositor, i->first,
     80                        i->second);
     81  }
     82 }
     83 
     84 /* static */
     85 void ImageMemoryReporter::ReportSharedSurface(
     86    nsIHandleReportCallback* aHandleReport, nsISupports* aData,
     87    bool aIsForCompositor, uint64_t aExternalId,
     88    const layers::SharedSurfacesMemoryReport::SurfaceEntry& aEntry) {
     89  nsAutoCString path;
     90  if (aIsForCompositor) {
     91    path.AppendLiteral("gfx/webrender/images/mapped_from_owner/");
     92  } else {
     93    path.AppendLiteral("gfx/webrender/images/owner_cache_missing/");
     94  }
     95 
     96  if (aIsForCompositor) {
     97    path.AppendLiteral("pid=");
     98    path.AppendInt(uint32_t(aEntry.mCreatorPid));
     99    path.AppendLiteral("/");
    100  }
    101 
    102  if (StaticPrefs::image_mem_debug_reporting()) {
    103    path.AppendInt(aExternalId, 16);
    104    path.AppendLiteral("/");
    105  }
    106 
    107  path.AppendLiteral("image(");
    108  path.AppendInt(aEntry.mSize.width);
    109  path.AppendLiteral("x");
    110  path.AppendInt(aEntry.mSize.height);
    111  path.AppendLiteral(", compositor_ref:");
    112  path.AppendInt(aEntry.mConsumers);
    113  path.AppendLiteral(", creator_ref:");
    114  path.AppendInt(aEntry.mCreatorRef);
    115  path.AppendLiteral(")/decoded-");
    116 
    117  size_t surfaceSize = mozilla::ipc::shared_memory::PageAlignedSize(
    118      aEntry.mSize.height * aEntry.mStride);
    119 
    120  // If this memory has already been reported elsewhere (e.g. as part of our
    121  // explicit section in the surface cache), we don't want report it again as
    122  // KIND_NONHEAP and have it counted again. The paths must be different if the
    123  // kinds are different to avoid problems when diffing memory reports.
    124  bool sameProcess = aEntry.mCreatorPid == base::GetCurrentProcId();
    125  int32_t kind;
    126  if (aIsForCompositor && !sameProcess) {
    127    path.AppendLiteral("nonheap");
    128    kind = nsIMemoryReporter::KIND_NONHEAP;
    129  } else {
    130    path.AppendLiteral("other");
    131    kind = nsIMemoryReporter::KIND_OTHER;
    132  }
    133 
    134  constexpr auto desc = "Decoded image data stored in shared memory."_ns;
    135  aHandleReport->Callback(""_ns, path, kind, nsIMemoryReporter::UNITS_BYTES,
    136                          surfaceSize, desc, aData);
    137 }
    138 
    139 /* static */
    140 void ImageMemoryReporter::AppendSharedSurfacePrefix(
    141    nsACString& aPathPrefix, const SurfaceMemoryCounter& aCounter,
    142    layers::SharedSurfacesMemoryReport& aSharedSurfaces) {
    143  uint64_t extId = aCounter.Values().ExternalId();
    144  if (extId) {
    145    auto gpuEntry = aSharedSurfaces.mSurfaces.find(extId);
    146 
    147    if (StaticPrefs::image_mem_debug_reporting()) {
    148      aPathPrefix.AppendLiteral(", external_id:");
    149      aPathPrefix.AppendInt(extId, 16);
    150      if (gpuEntry != aSharedSurfaces.mSurfaces.end()) {
    151        aPathPrefix.AppendLiteral(", compositor_ref:");
    152        aPathPrefix.AppendInt(gpuEntry->second.mConsumers);
    153      } else {
    154        aPathPrefix.AppendLiteral(", compositor_ref:missing");
    155      }
    156    }
    157 
    158    if (gpuEntry != aSharedSurfaces.mSurfaces.end()) {
    159      MOZ_ASSERT(gpuEntry->second.mCreatorRef);
    160      aSharedSurfaces.mSurfaces.erase(gpuEntry);
    161    }
    162  }
    163 }
    164 
    165 /* static */
    166 void ImageMemoryReporter::TrimSharedSurfaces(
    167    const ImageMemoryCounter& aCounter,
    168    layers::SharedSurfacesMemoryReport& aSharedSurfaces) {
    169  if (aSharedSurfaces.mSurfaces.empty()) {
    170    return;
    171  }
    172 
    173  for (const SurfaceMemoryCounter& counter : aCounter.Surfaces()) {
    174    uint64_t extId = counter.Values().ExternalId();
    175    if (extId) {
    176      auto gpuEntry = aSharedSurfaces.mSurfaces.find(extId);
    177      if (gpuEntry != aSharedSurfaces.mSurfaces.end()) {
    178        MOZ_ASSERT(gpuEntry->second.mCreatorRef);
    179        aSharedSurfaces.mSurfaces.erase(gpuEntry);
    180      }
    181    }
    182  }
    183 }
    184 
    185 }  // namespace image
    186 }  // namespace mozilla