1 /*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "dm/DMJsonWriter.h"
9
10 #include "include/core/SkData.h"
11 #include "include/core/SkStream.h"
12 #include "include/private/base/SkMutex.h"
13 #include "include/private/base/SkTArray.h"
14 #include "src/core/SkOSFile.h"
15 #include "src/utils/SkJSON.h"
16 #include "src/utils/SkJSONWriter.h"
17 #include "src/utils/SkOSPath.h"
18 #include "tools/ProcStats.h"
19
20 using namespace skia_private;
21
22 namespace DM {
23
24 TArray<JsonWriter::BitmapResult> gBitmapResults;
bitmap_result_mutex()25 static SkMutex& bitmap_result_mutex() {
26 static SkMutex& mutex = *(new SkMutex);
27 return mutex;
28 }
29
30
AddBitmapResult(const BitmapResult & result)31 void JsonWriter::AddBitmapResult(const BitmapResult& result) {
32 SkAutoMutexExclusive lock(bitmap_result_mutex());
33 gBitmapResults.push_back(result);
34 }
35
DumpJson(const char * dir,CommandLineFlags::StringArray key,CommandLineFlags::StringArray properties)36 void JsonWriter::DumpJson(const char* dir,
37 CommandLineFlags::StringArray key,
38 CommandLineFlags::StringArray properties) {
39 if (0 == strcmp(dir, "")) {
40 return;
41 }
42
43 SkString path = SkOSPath::Join(dir, "dm.json");
44 sk_mkdir(dir);
45 SkFILEWStream stream(path.c_str());
46 SkJSONWriter writer(&stream, SkJSONWriter::Mode::kPretty);
47
48 writer.beginObject(); // root
49
50 for (int i = 1; i < properties.size(); i += 2) {
51 writer.appendCString(properties[i-1], properties[i]);
52 }
53
54 writer.beginObject("key");
55 for (int i = 1; i < key.size(); i += 2) {
56 writer.appendCString(key[i-1], key[i]);
57 }
58 writer.endObject();
59
60 int maxResidentSetSizeMB = sk_tools::getMaxResidentSetSizeMB();
61 if (maxResidentSetSizeMB != -1) {
62 writer.appendS32("max_rss_MB", maxResidentSetSizeMB);
63 }
64
65 {
66 SkAutoMutexExclusive lock(bitmap_result_mutex());
67 writer.beginArray("results");
68 for (int i = 0; i < gBitmapResults.size(); i++) {
69 writer.beginObject();
70
71 writer.beginObject("key");
72 writer.appendString("name" , gBitmapResults[i].name);
73 writer.appendString("config" , gBitmapResults[i].config);
74 writer.appendString("source_type", gBitmapResults[i].sourceType);
75
76 // Source options only need to be part of the key if they exist.
77 // Source type by source type, we either always set options or never set options.
78 if (!gBitmapResults[i].sourceOptions.isEmpty()) {
79 writer.appendString("source_options", gBitmapResults[i].sourceOptions);
80 }
81 writer.endObject(); // key
82
83 writer.beginObject("options");
84 writer.appendString("ext" , gBitmapResults[i].ext);
85 writer.appendString("gamut", gBitmapResults[i].gamut);
86 writer.appendString("transfer_fn", gBitmapResults[i].transferFn);
87 writer.appendString("color_type", gBitmapResults[i].colorType);
88 writer.appendString("alpha_type", gBitmapResults[i].alphaType);
89 writer.appendString("color_depth", gBitmapResults[i].colorDepth);
90 writer.endObject(); // options
91
92 writer.appendString("md5", gBitmapResults[i].md5);
93
94 writer.endObject(); // 1 result
95 }
96 writer.endArray(); // results
97 }
98
99 writer.endObject(); // root
100 writer.flush();
101 stream.flush();
102 }
103
104 using namespace skjson;
105
ReadJson(const char * path,void (* callback)(BitmapResult))106 bool JsonWriter::ReadJson(const char* path, void(*callback)(BitmapResult)) {
107 sk_sp<SkData> json(SkData::MakeFromFileName(path));
108 if (!json) {
109 return false;
110 }
111
112 DOM dom((const char*)json->data(), json->size());
113 const ObjectValue* root = dom.root();
114 if (!root) {
115 return false;
116 }
117
118 const ArrayValue* results = (*root)["results"];
119 if (!results) {
120 return false;
121 }
122
123 BitmapResult br;
124 for (const ObjectValue* r : *results) {
125 const ObjectValue& key = (*r)["key"].as<ObjectValue>();
126 const ObjectValue& options = (*r)["options"].as<ObjectValue>();
127
128 br.name = key["name"].as<StringValue>().begin();
129 br.config = key["config"].as<StringValue>().begin();
130 br.sourceType = key["source_type"].as<StringValue>().begin();
131 br.ext = options["ext"].as<StringValue>().begin();
132 br.gamut = options["gamut"].as<StringValue>().begin();
133 br.transferFn = options["transfer_fn"].as<StringValue>().begin();
134 br.colorType = options["color_type"].as<StringValue>().begin();
135 br.alphaType = options["alpha_type"].as<StringValue>().begin();
136 br.colorDepth = options["color_depth"].as<StringValue>().begin();
137 br.md5 = (*r)["md5"].as<StringValue>().begin();
138
139 if (const StringValue* so = key["source_options"]) {
140 br.sourceOptions = so->begin();
141 }
142 callback(br);
143 }
144 return true;
145 }
146
147 } // namespace DM
148