• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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