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/file_util.h"
11 #include "base/files/file_path.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
;
23 using base::ReadFileToString
;
27 GLenum
TextureFormatFromString(std::string format
) {
32 if (format
== "LUMINANCE")
34 return GL_INVALID_ENUM
;
37 const char* TextureFormatName(GLenum format
) {
46 return "(unknown format)";
50 int FormatBytesPerPixel(GLenum format
) {
63 RenderNode::RenderNode() {
66 RenderNode::~RenderNode() {
69 void RenderNode::Accept(RenderNodeVisitor
* v
) {
70 v
->BeginVisitRenderNode(this);
71 v
->EndVisitRenderNode(this);
74 ContentLayerNode::ContentLayerNode() {
77 ContentLayerNode::~ContentLayerNode() {
80 void ContentLayerNode::Accept(RenderNodeVisitor
* v
) {
81 v
->BeginVisitContentLayerNode(this);
82 typedef vector
<RenderNode
*>::iterator node_itr
;
83 for (node_itr i
= children_
.begin(); i
!= children_
.end(); ++i
) {
86 v
->EndVisitContentLayerNode(this);
95 void CCNode::Accept(RenderNodeVisitor
* v
) {
96 v
->BeginVisitCCNode(this);
97 v
->EndVisitCCNode(this);
100 RenderNodeVisitor::~RenderNodeVisitor() {
103 void RenderNodeVisitor::BeginVisitContentLayerNode(ContentLayerNode
* v
) {
104 this->BeginVisitRenderNode(v
);
107 void RenderNodeVisitor::BeginVisitCCNode(CCNode
* v
) {
108 this->BeginVisitRenderNode(v
);
111 void RenderNodeVisitor::EndVisitRenderNode(RenderNode
* v
) {
114 void RenderNodeVisitor::EndVisitContentLayerNode(ContentLayerNode
* v
) {
115 this->EndVisitRenderNode(v
);
118 void RenderNodeVisitor::EndVisitCCNode(CCNode
* v
) {
119 this->EndVisitRenderNode(v
);
122 RenderNode
* InterpretNode(DictionaryValue
* node
);
124 std::string
ValueTypeAsString(Value::Type type
) {
126 case Value::TYPE_NULL
:
128 case Value::TYPE_BOOLEAN
:
130 case Value::TYPE_INTEGER
:
132 case Value::TYPE_DOUBLE
:
134 case Value::TYPE_STRING
:
136 case Value::TYPE_BINARY
:
138 case Value::TYPE_DICTIONARY
:
140 case Value::TYPE_LIST
:
143 return "(UNKNOWN TYPE)";
147 // Makes sure that the key exists and has the type we expect.
148 bool VerifyDictionaryEntry(DictionaryValue
* node
,
149 const std::string
& key
,
151 if (!node
->HasKey(key
)) {
152 LOG(ERROR
) << "Missing value for key: " << key
;
157 node
->Get(key
, &child
);
158 if (!child
->IsType(type
)) {
159 LOG(ERROR
) << key
<< " did not have the expected type "
160 "(expected " << ValueTypeAsString(type
) << ")";
167 // Makes sure that the list entry has the type we expect.
168 bool VerifyListEntry(ListValue
* l
,
171 const char* listName
= 0) {
172 // Assume the idx is valid (since we'll be able to generate a better
173 // error message for this elsewhere.)
176 if (!el
->IsType(type
)) {
177 LOG(ERROR
) << (listName
? listName
: "List") << "element " << idx
<<
178 " did not have the expected type (expected " <<
179 ValueTypeAsString(type
) << ")\n";
186 bool InterpretCommonContents(DictionaryValue
* node
, RenderNode
* c
) {
187 if (!VerifyDictionaryEntry(node
, "layerID", Value::TYPE_INTEGER
) ||
188 !VerifyDictionaryEntry(node
, "width", Value::TYPE_INTEGER
) ||
189 !VerifyDictionaryEntry(node
, "height", Value::TYPE_INTEGER
) ||
190 !VerifyDictionaryEntry(node
, "drawsContent", Value::TYPE_BOOLEAN
) ||
191 !VerifyDictionaryEntry(node
, "targetSurfaceID", Value::TYPE_INTEGER
) ||
192 !VerifyDictionaryEntry(node
, "transform", 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 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
, 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", Value::TYPE_DICTIONARY
))
232 DictionaryValue
* tiles_dict
;
233 node
->GetDictionary("tiles", &tiles_dict
);
234 if (!VerifyDictionaryEntry(tiles_dict
, "dim", Value::TYPE_LIST
))
237 tiles_dict
->GetList("dim", &dim
);
238 if (!VerifyListEntry(dim
, 0, Value::TYPE_INTEGER
, "Tile dimension") ||
239 !VerifyListEntry(dim
, 1, 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", Value::TYPE_LIST
))
252 tiles_dict
->GetList("info", &tiles
);
253 for (unsigned int i
= 0; i
< tiles
->GetSize(); ++i
) {
254 if (!VerifyListEntry(tiles
, i
, Value::TYPE_DICTIONARY
, "Tile info"))
256 DictionaryValue
* tdict
;
257 tiles
->GetDictionary(i
, &tdict
);
259 if (!VerifyDictionaryEntry(tdict
, "x", Value::TYPE_INTEGER
) ||
260 !VerifyDictionaryEntry(tdict
, "y", 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", Value::TYPE_INTEGER
))
269 tdict
->GetInteger("texID", &t
.texID
);
279 bool InterpretCCData(DictionaryValue
* node
, CCNode
* c
) {
280 if (!VerifyDictionaryEntry(node
, "vertex_shader", Value::TYPE_STRING
) ||
281 !VerifyDictionaryEntry(node
, "fragment_shader", Value::TYPE_STRING
) ||
282 !VerifyDictionaryEntry(node
, "textures", Value::TYPE_LIST
)) {
285 string vertex_shader_name
, fragment_shader_name
;
286 node
->GetString("vertex_shader", &vertex_shader_name
);
287 node
->GetString("fragment_shader", &fragment_shader_name
);
289 c
->set_vertex_shader(ShaderIDFromString(vertex_shader_name
));
290 c
->set_fragment_shader(ShaderIDFromString(fragment_shader_name
));
292 node
->GetList("textures", &textures
);
293 for (unsigned int i
= 0; i
< textures
->GetSize(); ++i
) {
294 if (!VerifyListEntry(textures
, i
, Value::TYPE_DICTIONARY
, "Tex list"))
296 DictionaryValue
* tex
;
297 textures
->GetDictionary(i
, &tex
);
299 if (!VerifyDictionaryEntry(tex
, "texID", Value::TYPE_INTEGER
) ||
300 !VerifyDictionaryEntry(tex
, "height", Value::TYPE_INTEGER
) ||
301 !VerifyDictionaryEntry(tex
, "width", Value::TYPE_INTEGER
) ||
302 !VerifyDictionaryEntry(tex
, "format", Value::TYPE_STRING
)) {
306 tex
->GetInteger("texID", &t
.texID
);
307 tex
->GetInteger("height", &t
.height
);
308 tex
->GetInteger("width", &t
.width
);
311 tex
->GetString("format", &formatName
);
312 t
.format
= TextureFormatFromString(formatName
);
313 if (t
.format
== GL_INVALID_ENUM
) {
314 LOG(ERROR
) << "Unrecognized texture format in layer " << c
->layerID() <<
315 " (format: " << formatName
<< ")\n"
316 "The layer had " << textures
->GetSize() << " children.";
323 if (c
->vertex_shader() == SHADER_UNRECOGNIZED
) {
324 LOG(ERROR
) << "Unrecognized vertex shader name, layer " << c
->layerID() <<
325 " (shader: " << vertex_shader_name
<< ")";
329 if (c
->fragment_shader() == SHADER_UNRECOGNIZED
) {
330 LOG(ERROR
) << "Unrecognized fragment shader name, layer " << c
->layerID() <<
331 " (shader: " << fragment_shader_name
<< ")";
338 RenderNode
* InterpretContentLayer(DictionaryValue
* node
) {
339 ContentLayerNode
* n
= new ContentLayerNode
;
340 if (!InterpretCommonContents(node
, n
))
343 if (!VerifyDictionaryEntry(node
, "type", Value::TYPE_STRING
) ||
344 !VerifyDictionaryEntry(node
, "skipsDraw", Value::TYPE_BOOLEAN
) ||
345 !VerifyDictionaryEntry(node
, "children", Value::TYPE_LIST
)) {
350 node
->GetString("type", &type
);
351 DCHECK_EQ(type
, "ContentLayer");
353 node
->GetBoolean("skipsDraw", &skipsDraw
);
354 n
->set_skipsDraw(skipsDraw
);
357 node
->GetList("children", &children
);
358 for (unsigned int i
= 0; i
< children
->GetSize(); ++i
) {
359 DictionaryValue
* childNode
;
360 children
->GetDictionary(i
, &childNode
);
361 RenderNode
* child
= InterpretNode(childNode
);
369 RenderNode
* InterpretCanvasLayer(DictionaryValue
* node
) {
370 CCNode
* n
= new CCNode
;
371 if (!InterpretCommonContents(node
, n
))
374 if (!VerifyDictionaryEntry(node
, "type", Value::TYPE_STRING
)) {
379 node
->GetString("type", &type
);
380 assert(type
== "CanvasLayer");
382 if (!InterpretCCData(node
, n
))
388 RenderNode
* InterpretVideoLayer(DictionaryValue
* node
) {
389 CCNode
* n
= new CCNode
;
390 if (!InterpretCommonContents(node
, n
))
393 if (!VerifyDictionaryEntry(node
, "type", Value::TYPE_STRING
)) {
398 node
->GetString("type", &type
);
399 assert(type
== "VideoLayer");
401 if (!InterpretCCData(node
, n
))
407 RenderNode
* InterpretImageLayer(DictionaryValue
* node
) {
408 CCNode
* n
= new CCNode
;
409 if (!InterpretCommonContents(node
, n
))
412 if (!VerifyDictionaryEntry(node
, "type", Value::TYPE_STRING
)) {
417 node
->GetString("type", &type
);
418 assert(type
== "ImageLayer");
420 if (!InterpretCCData(node
, n
))
426 RenderNode
* InterpretNode(DictionaryValue
* node
) {
427 if (!VerifyDictionaryEntry(node
, "type", Value::TYPE_STRING
)) {
432 node
->GetString("type", &type
);
433 if (type
== "ContentLayer")
434 return InterpretContentLayer(node
);
435 if (type
== "CanvasLayer")
436 return InterpretCanvasLayer(node
);
437 if (type
== "VideoLayer")
438 return InterpretVideoLayer(node
);
439 if (type
== "ImageLayer")
440 return InterpretImageLayer(node
);
444 JSONWriter::WriteWithOptions(node
, base::JSONWriter::OPTIONS_PRETTY_PRINT
,
446 LOG(ERROR
) << "Unrecognized node type! JSON:\n\n"
447 "-----------------------\n" <<
449 "-----------------------";
454 RenderNode
* BuildRenderTreeFromFile(const base::FilePath
& path
) {
455 LOG(INFO
) << "Reading " << path
.LossyDisplayName();
457 if (!ReadFileToString(path
, &contents
))
460 scoped_ptr
<Value
> root
;
462 string error_message
;
463 root
.reset(JSONReader::ReadAndReturnError(contents
,
464 base::JSON_ALLOW_TRAILING_COMMAS
,
468 LOG(ERROR
) << "Failed to parse JSON file " << path
.LossyDisplayName() <<
469 "\n(" << error_message
<< ")";
473 if (root
->IsType(Value::TYPE_DICTIONARY
)) {
474 DictionaryValue
* v
= static_cast<DictionaryValue
*>(root
.get());
475 RenderNode
* tree
= InterpretContentLayer(v
);
478 LOG(ERROR
) << path
.LossyDisplayName() <<
479 " doesn not encode a JSON dictionary.";