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