1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "gpu/tools/compositor_model_bench/render_tree.h"
10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h"
12 #include "base/json/json_reader.h"
13 #include "base/json/json_writer.h"
14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/values.h"
18 #include "gpu/tools/compositor_model_bench/shaders.h"
20 using base::JSONReader
;
21 using base::JSONWriter
;
22 using base::ReadFileToString
;
26 GLenum
TextureFormatFromString(std::string format
) {
31 if (format
== "LUMINANCE")
33 return GL_INVALID_ENUM
;
36 const char* TextureFormatName(GLenum format
) {
45 return "(unknown format)";
49 int FormatBytesPerPixel(GLenum format
) {
62 RenderNode::RenderNode() {
65 RenderNode::~RenderNode() {
68 void RenderNode::Accept(RenderNodeVisitor
* v
) {
69 v
->BeginVisitRenderNode(this);
70 v
->EndVisitRenderNode(this);
73 ContentLayerNode::ContentLayerNode() {
76 ContentLayerNode::~ContentLayerNode() {
79 void ContentLayerNode::Accept(RenderNodeVisitor
* v
) {
80 v
->BeginVisitContentLayerNode(this);
81 typedef vector
<RenderNode
*>::iterator node_itr
;
82 for (node_itr i
= children_
.begin(); i
!= children_
.end(); ++i
) {
85 v
->EndVisitContentLayerNode(this);
94 void CCNode::Accept(RenderNodeVisitor
* v
) {
95 v
->BeginVisitCCNode(this);
96 v
->EndVisitCCNode(this);
99 RenderNodeVisitor::~RenderNodeVisitor() {
102 void RenderNodeVisitor::BeginVisitContentLayerNode(ContentLayerNode
* v
) {
103 this->BeginVisitRenderNode(v
);
106 void RenderNodeVisitor::BeginVisitCCNode(CCNode
* v
) {
107 this->BeginVisitRenderNode(v
);
110 void RenderNodeVisitor::EndVisitRenderNode(RenderNode
* v
) {
113 void RenderNodeVisitor::EndVisitContentLayerNode(ContentLayerNode
* v
) {
114 this->EndVisitRenderNode(v
);
117 void RenderNodeVisitor::EndVisitCCNode(CCNode
* v
) {
118 this->EndVisitRenderNode(v
);
121 RenderNode
* InterpretNode(base::DictionaryValue
* node
);
123 std::string
ValueTypeAsString(base::Value::Type type
) {
125 case base::Value::TYPE_NULL
:
127 case base::Value::TYPE_BOOLEAN
:
129 case base::Value::TYPE_INTEGER
:
131 case base::Value::TYPE_DOUBLE
:
133 case base::Value::TYPE_STRING
:
135 case base::Value::TYPE_BINARY
:
137 case base::Value::TYPE_DICTIONARY
:
139 case base::Value::TYPE_LIST
:
142 return "(UNKNOWN TYPE)";
146 // Makes sure that the key exists and has the type we expect.
147 bool VerifyDictionaryEntry(base::DictionaryValue
* node
,
148 const std::string
& key
,
149 base::Value::Type type
) {
150 if (!node
->HasKey(key
)) {
151 LOG(ERROR
) << "Missing value for key: " << key
;
156 node
->Get(key
, &child
);
157 if (!child
->IsType(type
)) {
158 LOG(ERROR
) << key
<< " did not have the expected type "
159 "(expected " << ValueTypeAsString(type
) << ")";
166 // Makes sure that the list entry has the type we expect.
167 bool VerifyListEntry(base::ListValue
* l
,
169 base::Value::Type type
,
170 const char* listName
= 0) {
171 // Assume the idx is valid (since we'll be able to generate a better
172 // error message for this elsewhere.)
175 if (!el
->IsType(type
)) {
176 LOG(ERROR
) << (listName
? listName
: "List") << "element " << idx
<<
177 " did not have the expected type (expected " <<
178 ValueTypeAsString(type
) << ")\n";
185 bool InterpretCommonContents(base::DictionaryValue
* node
, RenderNode
* c
) {
186 if (!VerifyDictionaryEntry(node
, "layerID", base::Value::TYPE_INTEGER
) ||
187 !VerifyDictionaryEntry(node
, "width", base::Value::TYPE_INTEGER
) ||
188 !VerifyDictionaryEntry(node
, "height", base::Value::TYPE_INTEGER
) ||
189 !VerifyDictionaryEntry(node
, "drawsContent", base::Value::TYPE_BOOLEAN
) ||
190 !VerifyDictionaryEntry(node
, "targetSurfaceID",
191 base::Value::TYPE_INTEGER
) ||
192 !VerifyDictionaryEntry(node
, "transform", base::Value::TYPE_LIST
)
198 node
->GetInteger("layerID", &layerID
);
199 c
->set_layerID(layerID
);
201 node
->GetInteger("width", &width
);
204 node
->GetInteger("height", &height
);
205 c
->set_height(height
);
207 node
->GetBoolean("drawsContent", &drawsContent
);
208 c
->set_drawsContent(drawsContent
);
210 node
->GetInteger("targetSurfaceID", &targetSurface
);
211 c
->set_targetSurface(targetSurface
);
213 base::ListValue
* transform
;
214 node
->GetList("transform", &transform
);
215 if (transform
->GetSize() != 16) {
216 LOG(ERROR
) << "4x4 transform matrix did not have 16 elements";
219 float transform_mat
[16];
220 for (int i
= 0; i
< 16; ++i
) {
221 if (!VerifyListEntry(transform
, i
, base::Value::TYPE_DOUBLE
, "Transform"))
224 transform
->GetDouble(i
, &el
);
225 transform_mat
[i
] = el
;
227 c
->set_transform(transform_mat
);
229 if (node
->HasKey("tiles")) {
230 if (!VerifyDictionaryEntry(node
, "tiles", base::Value::TYPE_DICTIONARY
))
232 base::DictionaryValue
* tiles_dict
;
233 node
->GetDictionary("tiles", &tiles_dict
);
234 if (!VerifyDictionaryEntry(tiles_dict
, "dim", base::Value::TYPE_LIST
))
236 base::ListValue
* dim
;
237 tiles_dict
->GetList("dim", &dim
);
238 if (!VerifyListEntry(dim
, 0, base::Value::TYPE_INTEGER
, "Tile dimension") ||
239 !VerifyListEntry(dim
, 1, base::Value::TYPE_INTEGER
, "Tile dimension")) {
243 dim
->GetInteger(0, &tile_width
);
244 c
->set_tile_width(tile_width
);
246 dim
->GetInteger(1, &tile_height
);
247 c
->set_tile_height(tile_height
);
249 if (!VerifyDictionaryEntry(tiles_dict
, "info", base::Value::TYPE_LIST
))
251 base::ListValue
* tiles
;
252 tiles_dict
->GetList("info", &tiles
);
253 for (unsigned int i
= 0; i
< tiles
->GetSize(); ++i
) {
254 if (!VerifyListEntry(tiles
, i
, base::Value::TYPE_DICTIONARY
, "Tile info"))
256 base::DictionaryValue
* tdict
;
257 tiles
->GetDictionary(i
, &tdict
);
259 if (!VerifyDictionaryEntry(tdict
, "x", base::Value::TYPE_INTEGER
) ||
260 !VerifyDictionaryEntry(tdict
, "y", base::Value::TYPE_INTEGER
)) {
264 tdict
->GetInteger("x", &t
.x
);
265 tdict
->GetInteger("y", &t
.y
);
266 if (tdict
->HasKey("texID")) {
267 if (!VerifyDictionaryEntry(tdict
, "texID", base::Value::TYPE_INTEGER
))
269 tdict
->GetInteger("texID", &t
.texID
);
279 bool InterpretCCData(base::DictionaryValue
* node
, CCNode
* c
) {
280 if (!VerifyDictionaryEntry(node
, "vertex_shader", base::Value::TYPE_STRING
) ||
281 !VerifyDictionaryEntry(node
, "fragment_shader",
282 base::Value::TYPE_STRING
) ||
283 !VerifyDictionaryEntry(node
, "textures", base::Value::TYPE_LIST
)) {
286 string vertex_shader_name
, fragment_shader_name
;
287 node
->GetString("vertex_shader", &vertex_shader_name
);
288 node
->GetString("fragment_shader", &fragment_shader_name
);
290 c
->set_vertex_shader(ShaderIDFromString(vertex_shader_name
));
291 c
->set_fragment_shader(ShaderIDFromString(fragment_shader_name
));
292 base::ListValue
* textures
;
293 node
->GetList("textures", &textures
);
294 for (unsigned int i
= 0; i
< textures
->GetSize(); ++i
) {
295 if (!VerifyListEntry(textures
, i
, base::Value::TYPE_DICTIONARY
, "Tex list"))
297 base::DictionaryValue
* tex
;
298 textures
->GetDictionary(i
, &tex
);
300 if (!VerifyDictionaryEntry(tex
, "texID", base::Value::TYPE_INTEGER
) ||
301 !VerifyDictionaryEntry(tex
, "height", base::Value::TYPE_INTEGER
) ||
302 !VerifyDictionaryEntry(tex
, "width", base::Value::TYPE_INTEGER
) ||
303 !VerifyDictionaryEntry(tex
, "format", base::Value::TYPE_STRING
)) {
307 tex
->GetInteger("texID", &t
.texID
);
308 tex
->GetInteger("height", &t
.height
);
309 tex
->GetInteger("width", &t
.width
);
312 tex
->GetString("format", &formatName
);
313 t
.format
= TextureFormatFromString(formatName
);
314 if (t
.format
== GL_INVALID_ENUM
) {
315 LOG(ERROR
) << "Unrecognized texture format in layer " << c
->layerID() <<
316 " (format: " << formatName
<< ")\n"
317 "The layer had " << textures
->GetSize() << " children.";
324 if (c
->vertex_shader() == SHADER_UNRECOGNIZED
) {
325 LOG(ERROR
) << "Unrecognized vertex shader name, layer " << c
->layerID() <<
326 " (shader: " << vertex_shader_name
<< ")";
330 if (c
->fragment_shader() == SHADER_UNRECOGNIZED
) {
331 LOG(ERROR
) << "Unrecognized fragment shader name, layer " << c
->layerID() <<
332 " (shader: " << fragment_shader_name
<< ")";
339 RenderNode
* InterpretContentLayer(base::DictionaryValue
* node
) {
340 ContentLayerNode
* n
= new ContentLayerNode
;
341 if (!InterpretCommonContents(node
, n
))
344 if (!VerifyDictionaryEntry(node
, "type", base::Value::TYPE_STRING
) ||
345 !VerifyDictionaryEntry(node
, "skipsDraw", base::Value::TYPE_BOOLEAN
) ||
346 !VerifyDictionaryEntry(node
, "children", base::Value::TYPE_LIST
)) {
351 node
->GetString("type", &type
);
352 DCHECK_EQ(type
, "ContentLayer");
354 node
->GetBoolean("skipsDraw", &skipsDraw
);
355 n
->set_skipsDraw(skipsDraw
);
357 base::ListValue
* children
;
358 node
->GetList("children", &children
);
359 for (unsigned int i
= 0; i
< children
->GetSize(); ++i
) {
360 base::DictionaryValue
* childNode
;
361 children
->GetDictionary(i
, &childNode
);
362 RenderNode
* child
= InterpretNode(childNode
);
370 RenderNode
* InterpretCanvasLayer(base::DictionaryValue
* node
) {
371 CCNode
* n
= new CCNode
;
372 if (!InterpretCommonContents(node
, n
))
375 if (!VerifyDictionaryEntry(node
, "type", base::Value::TYPE_STRING
)) {
380 node
->GetString("type", &type
);
381 assert(type
== "CanvasLayer");
383 if (!InterpretCCData(node
, n
))
389 RenderNode
* InterpretVideoLayer(base::DictionaryValue
* node
) {
390 CCNode
* n
= new CCNode
;
391 if (!InterpretCommonContents(node
, n
))
394 if (!VerifyDictionaryEntry(node
, "type", base::Value::TYPE_STRING
)) {
399 node
->GetString("type", &type
);
400 assert(type
== "VideoLayer");
402 if (!InterpretCCData(node
, n
))
408 RenderNode
* InterpretImageLayer(base::DictionaryValue
* node
) {
409 CCNode
* n
= new CCNode
;
410 if (!InterpretCommonContents(node
, n
))
413 if (!VerifyDictionaryEntry(node
, "type", base::Value::TYPE_STRING
)) {
418 node
->GetString("type", &type
);
419 assert(type
== "ImageLayer");
421 if (!InterpretCCData(node
, n
))
427 RenderNode
* InterpretNode(base::DictionaryValue
* node
) {
428 if (!VerifyDictionaryEntry(node
, "type", base::Value::TYPE_STRING
)) {
433 node
->GetString("type", &type
);
434 if (type
== "ContentLayer")
435 return InterpretContentLayer(node
);
436 if (type
== "CanvasLayer")
437 return InterpretCanvasLayer(node
);
438 if (type
== "VideoLayer")
439 return InterpretVideoLayer(node
);
440 if (type
== "ImageLayer")
441 return InterpretImageLayer(node
);
445 JSONWriter::WriteWithOptions(*node
, base::JSONWriter::OPTIONS_PRETTY_PRINT
,
447 LOG(ERROR
) << "Unrecognized node type! JSON:\n\n"
448 "-----------------------\n" <<
450 "-----------------------";
455 RenderNode
* BuildRenderTreeFromFile(const base::FilePath
& path
) {
456 LOG(INFO
) << "Reading " << path
.LossyDisplayName();
458 if (!ReadFileToString(path
, &contents
))
462 string error_message
;
463 scoped_ptr
<base::Value
> root
= JSONReader::ReadAndReturnError(
464 contents
, base::JSON_ALLOW_TRAILING_COMMAS
, &error_code
, &error_message
);
466 LOG(ERROR
) << "Failed to parse JSON file " << path
.LossyDisplayName() <<
467 "\n(" << error_message
<< ")";
471 if (root
->IsType(base::Value::TYPE_DICTIONARY
)) {
472 base::DictionaryValue
* v
= static_cast<base::DictionaryValue
*>(root
.get());
473 RenderNode
* tree
= InterpretContentLayer(v
);
476 LOG(ERROR
) << path
.LossyDisplayName() <<
477 " doesn not encode a JSON dictionary.";