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