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. 4 5 #include "gpu/tools/compositor_model_bench/render_tree.h" 6 7 #include <sstream> 8 #include <vector> 9 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" 17 18 #include "gpu/tools/compositor_model_bench/shaders.h" 19 20 using base::JSONReader; 21 using base::JSONWriter; 22 using base::ReadFileToString; 23 using std::string; 24 using std::vector; 25 TextureFormatFromString(std::string format)26 GLenum TextureFormatFromString(std::string format) { 27 if (format == "RGBA") 28 return GL_RGBA; 29 if (format == "RGB") 30 return GL_RGB; 31 if (format == "LUMINANCE") 32 return GL_LUMINANCE; 33 return GL_INVALID_ENUM; 34 } 35 TextureFormatName(GLenum format)36 const char* TextureFormatName(GLenum format) { 37 switch (format) { 38 case GL_RGBA: 39 return "RGBA"; 40 case GL_RGB: 41 return "RGB"; 42 case GL_LUMINANCE: 43 return "LUMINANCE"; 44 default: 45 return "(unknown format)"; 46 } 47 } 48 FormatBytesPerPixel(GLenum format)49 int FormatBytesPerPixel(GLenum format) { 50 switch (format) { 51 case GL_RGBA: 52 return 4; 53 case GL_RGB: 54 return 3; 55 case GL_LUMINANCE: 56 return 1; 57 default: 58 return 0; 59 } 60 } 61 RenderNode()62 RenderNode::RenderNode() { 63 } 64 ~RenderNode()65 RenderNode::~RenderNode() { 66 } 67 Accept(RenderNodeVisitor * v)68 void RenderNode::Accept(RenderNodeVisitor* v) { 69 v->BeginVisitRenderNode(this); 70 v->EndVisitRenderNode(this); 71 } 72 ContentLayerNode()73 ContentLayerNode::ContentLayerNode() { 74 } 75 ~ContentLayerNode()76 ContentLayerNode::~ContentLayerNode() { 77 } 78 Accept(RenderNodeVisitor * v)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) { 83 (*i)->Accept(v); 84 } 85 v->EndVisitContentLayerNode(this); 86 } 87 CCNode()88 CCNode::CCNode() { 89 } 90 ~CCNode()91 CCNode::~CCNode() { 92 } 93 Accept(RenderNodeVisitor * v)94 void CCNode::Accept(RenderNodeVisitor* v) { 95 v->BeginVisitCCNode(this); 96 v->EndVisitCCNode(this); 97 } 98 ~RenderNodeVisitor()99 RenderNodeVisitor::~RenderNodeVisitor() { 100 } 101 BeginVisitContentLayerNode(ContentLayerNode * v)102 void RenderNodeVisitor::BeginVisitContentLayerNode(ContentLayerNode* v) { 103 this->BeginVisitRenderNode(v); 104 } 105 BeginVisitCCNode(CCNode * v)106 void RenderNodeVisitor::BeginVisitCCNode(CCNode* v) { 107 this->BeginVisitRenderNode(v); 108 } 109 EndVisitRenderNode(RenderNode * v)110 void RenderNodeVisitor::EndVisitRenderNode(RenderNode* v) { 111 } 112 EndVisitContentLayerNode(ContentLayerNode * v)113 void RenderNodeVisitor::EndVisitContentLayerNode(ContentLayerNode* v) { 114 this->EndVisitRenderNode(v); 115 } 116 EndVisitCCNode(CCNode * v)117 void RenderNodeVisitor::EndVisitCCNode(CCNode* v) { 118 this->EndVisitRenderNode(v); 119 } 120 121 RenderNode* InterpretNode(base::DictionaryValue* node); 122 ValueTypeAsString(base::Value::Type type)123 std::string ValueTypeAsString(base::Value::Type type) { 124 switch (type) { 125 case base::Value::TYPE_NULL: 126 return "NULL"; 127 case base::Value::TYPE_BOOLEAN: 128 return "BOOLEAN"; 129 case base::Value::TYPE_INTEGER: 130 return "INTEGER"; 131 case base::Value::TYPE_DOUBLE: 132 return "DOUBLE"; 133 case base::Value::TYPE_STRING: 134 return "STRING"; 135 case base::Value::TYPE_BINARY: 136 return "BINARY"; 137 case base::Value::TYPE_DICTIONARY: 138 return "DICTIONARY"; 139 case base::Value::TYPE_LIST: 140 return "LIST"; 141 default: 142 return "(UNKNOWN TYPE)"; 143 } 144 } 145 146 // Makes sure that the key exists and has the type we expect. VerifyDictionaryEntry(base::DictionaryValue * node,const std::string & key,base::Value::Type type)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; 152 return false; 153 } 154 155 base::Value* child; 156 node->Get(key, &child); 157 if (!child->IsType(type)) { 158 LOG(ERROR) << key << " did not have the expected type " 159 "(expected " << ValueTypeAsString(type) << ")"; 160 return false; 161 } 162 163 return true; 164 } 165 166 // Makes sure that the list entry has the type we expect. VerifyListEntry(base::ListValue * l,int idx,base::Value::Type type,const char * listName=0)167 bool VerifyListEntry(base::ListValue* l, 168 int idx, 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.) 173 base::Value* el; 174 l->Get(idx, &el); 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"; 179 return false; 180 } 181 182 return true; 183 } 184 InterpretCommonContents(base::DictionaryValue * node,RenderNode * c)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) 193 ) { 194 return false; 195 } 196 197 int layerID; 198 node->GetInteger("layerID", &layerID); 199 c->set_layerID(layerID); 200 int width; 201 node->GetInteger("width", &width); 202 c->set_width(width); 203 int height; 204 node->GetInteger("height", &height); 205 c->set_height(height); 206 bool drawsContent; 207 node->GetBoolean("drawsContent", &drawsContent); 208 c->set_drawsContent(drawsContent); 209 int targetSurface; 210 node->GetInteger("targetSurfaceID", &targetSurface); 211 c->set_targetSurface(targetSurface); 212 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"; 217 return false; 218 } 219 float transform_mat[16]; 220 for (int i = 0; i < 16; ++i) { 221 if (!VerifyListEntry(transform, i, base::Value::TYPE_DOUBLE, "Transform")) 222 return false; 223 double el; 224 transform->GetDouble(i, &el); 225 transform_mat[i] = el; 226 } 227 c->set_transform(transform_mat); 228 229 if (node->HasKey("tiles")) { 230 if (!VerifyDictionaryEntry(node, "tiles", base::Value::TYPE_DICTIONARY)) 231 return false; 232 base::DictionaryValue* tiles_dict; 233 node->GetDictionary("tiles", &tiles_dict); 234 if (!VerifyDictionaryEntry(tiles_dict, "dim", base::Value::TYPE_LIST)) 235 return false; 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")) { 240 return false; 241 } 242 int tile_width; 243 dim->GetInteger(0, &tile_width); 244 c->set_tile_width(tile_width); 245 int tile_height; 246 dim->GetInteger(1, &tile_height); 247 c->set_tile_height(tile_height); 248 249 if (!VerifyDictionaryEntry(tiles_dict, "info", base::Value::TYPE_LIST)) 250 return false; 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")) 255 return false; 256 base::DictionaryValue* tdict; 257 tiles->GetDictionary(i, &tdict); 258 259 if (!VerifyDictionaryEntry(tdict, "x", base::Value::TYPE_INTEGER) || 260 !VerifyDictionaryEntry(tdict, "y", base::Value::TYPE_INTEGER)) { 261 return false; 262 } 263 Tile t; 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)) 268 return false; 269 tdict->GetInteger("texID", &t.texID); 270 } else { 271 t.texID = -1; 272 } 273 c->add_tile(t); 274 } 275 } 276 return true; 277 } 278 InterpretCCData(base::DictionaryValue * node,CCNode * c)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)) { 284 return false; 285 } 286 string vertex_shader_name, fragment_shader_name; 287 node->GetString("vertex_shader", &vertex_shader_name); 288 node->GetString("fragment_shader", &fragment_shader_name); 289 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")) 296 return false; 297 base::DictionaryValue* tex; 298 textures->GetDictionary(i, &tex); 299 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)) { 304 return false; 305 } 306 Texture t; 307 tex->GetInteger("texID", &t.texID); 308 tex->GetInteger("height", &t.height); 309 tex->GetInteger("width", &t.width); 310 311 string formatName; 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."; 318 return false; 319 } 320 321 c->add_texture(t); 322 } 323 324 if (c->vertex_shader() == SHADER_UNRECOGNIZED) { 325 LOG(ERROR) << "Unrecognized vertex shader name, layer " << c->layerID() << 326 " (shader: " << vertex_shader_name << ")"; 327 return false; 328 } 329 330 if (c->fragment_shader() == SHADER_UNRECOGNIZED) { 331 LOG(ERROR) << "Unrecognized fragment shader name, layer " << c->layerID() << 332 " (shader: " << fragment_shader_name << ")"; 333 return false; 334 } 335 336 return true; 337 } 338 InterpretContentLayer(base::DictionaryValue * node)339 RenderNode* InterpretContentLayer(base::DictionaryValue* node) { 340 ContentLayerNode* n = new ContentLayerNode; 341 if (!InterpretCommonContents(node, n)) 342 return NULL; 343 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)) { 347 return NULL; 348 } 349 350 string type; 351 node->GetString("type", &type); 352 DCHECK_EQ(type, "ContentLayer"); 353 bool skipsDraw; 354 node->GetBoolean("skipsDraw", &skipsDraw); 355 n->set_skipsDraw(skipsDraw); 356 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); 363 if (child) 364 n->add_child(child); 365 } 366 367 return n; 368 } 369 InterpretCanvasLayer(base::DictionaryValue * node)370 RenderNode* InterpretCanvasLayer(base::DictionaryValue* node) { 371 CCNode* n = new CCNode; 372 if (!InterpretCommonContents(node, n)) 373 return NULL; 374 375 if (!VerifyDictionaryEntry(node, "type", base::Value::TYPE_STRING)) { 376 return NULL; 377 } 378 379 string type; 380 node->GetString("type", &type); 381 assert(type == "CanvasLayer"); 382 383 if (!InterpretCCData(node, n)) 384 return NULL; 385 386 return n; 387 } 388 InterpretVideoLayer(base::DictionaryValue * node)389 RenderNode* InterpretVideoLayer(base::DictionaryValue* node) { 390 CCNode* n = new CCNode; 391 if (!InterpretCommonContents(node, n)) 392 return NULL; 393 394 if (!VerifyDictionaryEntry(node, "type", base::Value::TYPE_STRING)) { 395 return NULL; 396 } 397 398 string type; 399 node->GetString("type", &type); 400 assert(type == "VideoLayer"); 401 402 if (!InterpretCCData(node, n)) 403 return NULL; 404 405 return n; 406 } 407 InterpretImageLayer(base::DictionaryValue * node)408 RenderNode* InterpretImageLayer(base::DictionaryValue* node) { 409 CCNode* n = new CCNode; 410 if (!InterpretCommonContents(node, n)) 411 return NULL; 412 413 if (!VerifyDictionaryEntry(node, "type", base::Value::TYPE_STRING)) { 414 return NULL; 415 } 416 417 string type; 418 node->GetString("type", &type); 419 assert(type == "ImageLayer"); 420 421 if (!InterpretCCData(node, n)) 422 return NULL; 423 424 return n; 425 } 426 InterpretNode(base::DictionaryValue * node)427 RenderNode* InterpretNode(base::DictionaryValue* node) { 428 if (!VerifyDictionaryEntry(node, "type", base::Value::TYPE_STRING)) { 429 return NULL; 430 } 431 432 string type; 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); 442 443 444 string outjson; 445 JSONWriter::WriteWithOptions(node, base::JSONWriter::OPTIONS_PRETTY_PRINT, 446 &outjson); 447 LOG(ERROR) << "Unrecognized node type! JSON:\n\n" 448 "-----------------------\n" << 449 outjson << 450 "-----------------------"; 451 452 return NULL; 453 } 454 BuildRenderTreeFromFile(const base::FilePath & path)455 RenderNode* BuildRenderTreeFromFile(const base::FilePath& path) { 456 LOG(INFO) << "Reading " << path.LossyDisplayName(); 457 string contents; 458 if (!ReadFileToString(path, &contents)) 459 return NULL; 460 461 scoped_ptr<base::Value> root; 462 int error_code = 0; 463 string error_message; 464 root.reset(JSONReader::ReadAndReturnError(contents, 465 base::JSON_ALLOW_TRAILING_COMMAS, 466 &error_code, 467 &error_message)); 468 if (!root.get()) { 469 LOG(ERROR) << "Failed to parse JSON file " << path.LossyDisplayName() << 470 "\n(" << error_message << ")"; 471 return NULL; 472 } 473 474 if (root->IsType(base::Value::TYPE_DICTIONARY)) { 475 base::DictionaryValue* v = static_cast<base::DictionaryValue*>(root.get()); 476 RenderNode* tree = InterpretContentLayer(v); 477 return tree; 478 } else { 479 LOG(ERROR) << path.LossyDisplayName() << 480 " doesn not encode a JSON dictionary."; 481 return NULL; 482 } 483 } 484 485