image/ImageMemoryReporter.cpp
author Mike Hommey <mh+mozilla@glandium.org>
Tue, 26 Mar 2019 16:29:17 +0000
changeset 466239 12b301ea0f924424f0a5057f1ebccc7cd8098e8e
parent 461891 240e874ed11862376247ea177a88ddf00924e0da
child 475073 2fef10a7cce589dc6af60e675a3751a2201e866f
permissions -rw-r--r--
Bug 1537641 - Make MIDL use clang-cl as a preprocessor. r=dmajor Using clang-cl as a preprocessor fails with: ``` In file included from z:\build\build\src\accessible\ipc\win\handler\HandlerData.idl:8: z:\build\build\src\accessible\ipc\win\handler/AccessibleHandler.h(27,8): error: pasting formed 'Accessible2_3.', an invalid preprocessing token [-Winvalid-token-paste] import NEWEST_IA2_IDL; ^ z:\build\build\src\accessible\ipc\win\handler/AccessibleHandler.h(15,24): note: expanded from macro 'NEWEST_IA2_IDL' ^ z:\build\build\src\accessible\ipc\win\handler/AccessibleHandler.h(14,22): note: expanded from macro 'IDLFOR' ^ z:\build\build\src\accessible\ipc\win\handler/AccessibleHandler.h(13,36): note: expanded from macro '__GENIDL' ^ 1 error generated. midl : command line error MIDL1003 : error returned by the C preprocessor (1) ``` There's only one place using the NEWEST_IA2_IDL and accompanying macros, we can just avoid the issue altogether by expanding it manually (and it's not like the macro buys much, the other arm of the __midl ifdef has a #include "Accessible2_3.h" that doesn't use the macro either, presumably for the same reason). Differential Revision: https://phabricator.services.mozilla.com/D24868

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "ImageMemoryReporter.h"
#include "Image.h"
#include "mozilla/layers/SharedSurfacesParent.h"
#include "nsIMemoryReporter.h"
#include "nsISupportsImpl.h"

namespace mozilla {
namespace image {

ImageMemoryReporter::WebRenderReporter* ImageMemoryReporter::sWrReporter;

class ImageMemoryReporter::WebRenderReporter final : public nsIMemoryReporter {
 public:
  NS_DECL_ISUPPORTS

  WebRenderReporter() {}

  NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
                            nsISupports* aData, bool aAnonymize) override {
    layers::SharedSurfacesMemoryReport report;
    layers::SharedSurfacesParent::AccumulateMemoryReport(report);
    ReportSharedSurfaces(aHandleReport, aData, /* aIsForCompositor */ true,
                         report);
    return NS_OK;
  }

 private:
  virtual ~WebRenderReporter() {}
};

NS_IMPL_ISUPPORTS(ImageMemoryReporter::WebRenderReporter, nsIMemoryReporter)

/* static */
void ImageMemoryReporter::InitForWebRender() {
  MOZ_ASSERT(XRE_IsParentProcess() || XRE_IsGPUProcess());
  if (!sWrReporter) {
    sWrReporter = new WebRenderReporter();
    RegisterStrongMemoryReporter(sWrReporter);
  }
}

/* static */
void ImageMemoryReporter::ShutdownForWebRender() {
  MOZ_ASSERT(XRE_IsParentProcess() || XRE_IsGPUProcess());
  if (sWrReporter) {
    UnregisterStrongMemoryReporter(sWrReporter);
    sWrReporter = nullptr;
  }
}

/* static */
void ImageMemoryReporter::ReportSharedSurfaces(
    nsIHandleReportCallback* aHandleReport, nsISupports* aData,
    const layers::SharedSurfacesMemoryReport& aSharedSurfaces) {
  ReportSharedSurfaces(aHandleReport, aData,
                       /* aIsForCompositor */ false, aSharedSurfaces);
}

/* static */
void ImageMemoryReporter::ReportSharedSurfaces(
    nsIHandleReportCallback* aHandleReport, nsISupports* aData,
    bool aIsForCompositor,
    const layers::SharedSurfacesMemoryReport& aSharedSurfaces) {
  MOZ_ASSERT_IF(aIsForCompositor, XRE_IsParentProcess() || XRE_IsGPUProcess());
  MOZ_ASSERT_IF(!aIsForCompositor,
                XRE_IsParentProcess() || XRE_IsContentProcess());

  for (auto i = aSharedSurfaces.mSurfaces.begin();
       i != aSharedSurfaces.mSurfaces.end(); ++i) {
    ReportSharedSurface(aHandleReport, aData, aIsForCompositor, i->first,
                        i->second);
  }
}

/* static */
void ImageMemoryReporter::ReportSharedSurface(
    nsIHandleReportCallback* aHandleReport, nsISupports* aData,
    bool aIsForCompositor, uint64_t aExternalId,
    const layers::SharedSurfacesMemoryReport::SurfaceEntry& aEntry) {
  nsAutoCString path;
  if (aIsForCompositor) {
    path.AppendLiteral("gfx/webrender/images/mapped_from_owner/");
  } else {
    path.AppendLiteral("gfx/webrender/images/owner_cache_missing/");
  }

  if (aIsForCompositor) {
    path.AppendLiteral("pid=");
    path.AppendInt(uint32_t(aEntry.mCreatorPid));
    path.AppendLiteral("/");
  }

  if (gfxPrefs::ImageMemDebugReporting()) {
    path.AppendInt(aExternalId, 16);
    path.AppendLiteral("/");
  }

  path.AppendLiteral("image(");
  path.AppendInt(aEntry.mSize.width);
  path.AppendLiteral("x");
  path.AppendInt(aEntry.mSize.height);
  path.AppendLiteral(", compositor_ref:");
  path.AppendInt(aEntry.mConsumers);
  path.AppendLiteral(", creator_ref:");
  path.AppendInt(aEntry.mCreatorRef);
  path.AppendLiteral(")/decoded-nonheap");

  size_t surfaceSize = mozilla::ipc::SharedMemory::PageAlignedSize(
      aEntry.mSize.height * aEntry.mStride);

  // If this memory has already been reported elsewhere (e.g. as part of our
  // explicit section in the surface cache), we don't want report it again as
  // KIND_NONHEAP and have it counted again.
  bool sameProcess = aEntry.mCreatorPid == base::GetCurrentProcId();
  int32_t kind = aIsForCompositor && !sameProcess
                     ? nsIMemoryReporter::KIND_NONHEAP
                     : nsIMemoryReporter::KIND_OTHER;

  NS_NAMED_LITERAL_CSTRING(desc, "Decoded image data stored in shared memory.");
  aHandleReport->Callback(EmptyCString(), path, kind,
                          nsIMemoryReporter::UNITS_BYTES, surfaceSize, desc,
                          aData);
}

/* static */
void ImageMemoryReporter::AppendSharedSurfacePrefix(
    nsACString& aPathPrefix, const SurfaceMemoryCounter& aCounter,
    layers::SharedSurfacesMemoryReport& aSharedSurfaces) {
  uint64_t extId = aCounter.Values().ExternalId();
  if (extId) {
    auto gpuEntry = aSharedSurfaces.mSurfaces.find(extId);

    if (gfxPrefs::ImageMemDebugReporting()) {
      aPathPrefix.AppendLiteral(", external_id:");
      aPathPrefix.AppendInt(extId, 16);
      if (gpuEntry != aSharedSurfaces.mSurfaces.end()) {
        aPathPrefix.AppendLiteral(", compositor_ref:");
        aPathPrefix.AppendInt(gpuEntry->second.mConsumers);
      } else {
        aPathPrefix.AppendLiteral(", compositor_ref:missing");
      }
    }

    if (gpuEntry != aSharedSurfaces.mSurfaces.end()) {
      MOZ_ASSERT(gpuEntry->second.mCreatorRef);
      aSharedSurfaces.mSurfaces.erase(gpuEntry);
    }
  }
}

/* static */
void ImageMemoryReporter::TrimSharedSurfaces(
    const ImageMemoryCounter& aCounter,
    layers::SharedSurfacesMemoryReport& aSharedSurfaces) {
  if (aSharedSurfaces.mSurfaces.empty()) {
    return;
  }

  for (const SurfaceMemoryCounter& counter : aCounter.Surfaces()) {
    uint64_t extId = counter.Values().ExternalId();
    if (extId) {
      auto gpuEntry = aSharedSurfaces.mSurfaces.find(extId);
      if (gpuEntry != aSharedSurfaces.mSurfaces.end()) {
        MOZ_ASSERT(gpuEntry->second.mCreatorRef);
        aSharedSurfaces.mSurfaces.erase(gpuEntry);
      }
    }
  }
}

}  // namespace image
}  // namespace mozilla