1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <SkString.h>
20 #include <SkTraceMemoryDump.h>
21 
22 #include <string>
23 #include <unordered_map>
24 #include <vector>
25 
26 namespace android {
27 namespace renderengine {
28 namespace skia {
29 
30 // Mapping of resource substrings (1st element) that if found within a trace "dumpName"
31 // should be mapped to the category name (2nd element). All char* used in a resourcePair
32 // are expected to have a lifetime longer than the SkiaMemoryReporter in which they are used.
33 typedef std::pair<const char*, const char*> ResourcePair;
34 
35 /*
36  * Utility class for logging the CPU/GPU usage of Skia caches in a format that is specific
37  * to RenderEngine.  HWUI has a similar logging class, but the data collected and the way
38  * it is formatted and reported on are intended to be unique to each use case.
39  */
40 class SkiaMemoryReporter : public SkTraceMemoryDump {
41 public:
42     /**
43      * Creates the reporter class that can be populated by various Skia entry points, like
44      * SkGraphics and GrContext, as well as format and log the results.
45      * @param resourceMap An array of values that maps a Skia dumpName into a user defined category.
46      *                    The first vector entry that matches the dumpName is used for the mapping.
47      * @param itemize if true when logging the categories the individual elements will be printed
48      *                directly after the category details are printed.  Otherwise, only the category
49      *                totals will be printed.
50      */
51     SkiaMemoryReporter(const std::vector<ResourcePair>& resourceMap, bool itemize);
~SkiaMemoryReporter()52     ~SkiaMemoryReporter() override {}
53 
54     void logOutput(std::string& log, bool wrappedResources = false);
55     void logTotals(std::string& log);
56 
57     void dumpNumericValue(const char* dumpName, const char* valueName, const char* units,
58                           uint64_t value) override;
59 
dumpStringValue(const char * dumpName,const char * valueName,const char * value)60     void dumpStringValue(const char* dumpName, const char* valueName, const char* value) override {
61         // for convenience we just store this in the same format as numerical values
62         dumpNumericValue(dumpName, valueName, value, 0);
63     }
64     void dumpWrappedState(const char* dumpName, bool isWrappedObject) override;
65 
getRequestedDetails()66     LevelOfDetail getRequestedDetails() const override {
67         return SkTraceMemoryDump::kLight_LevelOfDetail;
68     }
69 
shouldDumpWrappedObjects()70     bool shouldDumpWrappedObjects() const override { return true; }
setMemoryBacking(const char *,const char *,const char *)71     void setMemoryBacking(const char*, const char*, const char*) override {}
setDiscardableMemoryBacking(const char *,const SkDiscardableMemory &)72     void setDiscardableMemoryBacking(const char*, const SkDiscardableMemory&) override {}
73 
74 private:
75     struct TraceValue {
TraceValueTraceValue76         TraceValue(const char* units, uint64_t value) : units(units), value(value), count(1) {}
TraceValueTraceValue77         TraceValue(const TraceValue& v) : units(v.units), value(v.value), count(v.count) {}
78 
79         SkString units;
80         float value;
81         int count;
82     };
83 
84     const char* mapName(const char* resourceName);
85     void processCurrentElement();
86     void resetCurrentElement();
87     TraceValue convertUnits(const TraceValue& value);
88 
89     const std::vector<ResourcePair>& mResourceMap;
90     const bool mItemize;
91 
92     // variables storing the size of all non-wrapped elements being dumped
93     TraceValue mTotalSize;
94     TraceValue mPurgeableSize;
95 
96     // variables storing information on the current node being dumped
97     std::string mCurrentElement;
98     std::unordered_map<const char*, TraceValue> mCurrentValues;
99     bool mIsCurrentValueWrapped = false;
100 
101     // variable that stores the final format of the data after the individual elements are processed
102     std::unordered_map<std::string, std::unordered_map<const char*, TraceValue>> mResults;
103     std::unordered_map<std::string, std::unordered_map<const char*, TraceValue>> mWrappedResults;
104 };
105 
106 } /* namespace skia */
107 } /* namespace renderengine */
108 } /* namespace android */
109