Home | History | Annotate | Download | only in compositor_model_bench
      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 
     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 
     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 
     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 
     62 RenderNode::RenderNode() {
     63 }
     64 
     65 RenderNode::~RenderNode() {
     66 }
     67 
     68 void RenderNode::Accept(RenderNodeVisitor* v) {
     69   v->BeginVisitRenderNode(this);
     70   v->EndVisitRenderNode(this);
     71 }
     72 
     73 ContentLayerNode::ContentLayerNode() {
     74 }
     75 
     76 ContentLayerNode::~ContentLayerNode() {
     77 }
     78 
     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 
     88 CCNode::CCNode() {
     89 }
     90 
     91 CCNode::~CCNode() {
     92 }
     93 
     94 void CCNode::Accept(RenderNodeVisitor* v) {
     95   v->BeginVisitCCNode(this);
     96   v->EndVisitCCNode(this);
     97 }
     98 
     99 RenderNodeVisitor::~RenderNodeVisitor() {
    100 }
    101 
    102 void RenderNodeVisitor::BeginVisitContentLayerNode(ContentLayerNode* v) {
    103   this->BeginVisitRenderNode(v);
    104 }
    105 
    106 void RenderNodeVisitor::BeginVisitCCNode(CCNode* v) {
    107   this->BeginVisitRenderNode(v);
    108 }
    109 
    110 void RenderNodeVisitor::EndVisitRenderNode(RenderNode* v) {
    111 }
    112 
    113 void RenderNodeVisitor::EndVisitContentLayerNode(ContentLayerNode* v) {
    114   this->EndVisitRenderNode(v);
    115 }
    116 
    117 void RenderNodeVisitor::EndVisitCCNode(CCNode* v) {
    118   this->EndVisitRenderNode(v);
    119 }
    120 
    121 RenderNode* InterpretNode(base::DictionaryValue* node);
    122 
    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.
    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.
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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