123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "gpu/tools/compositor_model_bench/render_tree.h"
- #include <memory>
- #include <sstream>
- #include <vector>
- #include "base/files/file_path.h"
- #include "base/files/file_util.h"
- #include "base/json/json_reader.h"
- #include "base/json/json_writer.h"
- #include "base/logging.h"
- #include "base/values.h"
- #include "gpu/tools/compositor_model_bench/shaders.h"
- using base::JSONReader;
- using base::JSONWriter;
- using base::ReadFileToString;
- using base::Value;
- GLenum TextureFormatFromString(const std::string& format) {
- if (format == "RGBA")
- return GL_RGBA;
- if (format == "RGB")
- return GL_RGB;
- if (format == "LUMINANCE")
- return GL_LUMINANCE;
- return GL_INVALID_ENUM;
- }
- const char* TextureFormatName(GLenum format) {
- switch (format) {
- case GL_RGBA:
- return "RGBA";
- case GL_RGB:
- return "RGB";
- case GL_LUMINANCE:
- return "LUMINANCE";
- default:
- return "(unknown format)";
- }
- }
- int FormatBytesPerPixel(GLenum format) {
- switch (format) {
- case GL_RGBA:
- return 4;
- case GL_RGB:
- return 3;
- case GL_LUMINANCE:
- return 1;
- default:
- return 0;
- }
- }
- RenderNode::RenderNode() {
- }
- RenderNode::~RenderNode() {
- }
- void RenderNode::Accept(RenderNodeVisitor* v) {
- v->BeginVisitRenderNode(this);
- v->EndVisitRenderNode(this);
- }
- ContentLayerNode::ContentLayerNode() {
- }
- ContentLayerNode::~ContentLayerNode() {
- }
- void ContentLayerNode::Accept(RenderNodeVisitor* v) {
- v->BeginVisitContentLayerNode(this);
- for (auto& child : children_) {
- child->Accept(v);
- }
- v->EndVisitContentLayerNode(this);
- }
- CCNode::CCNode() {
- }
- CCNode::~CCNode() {
- }
- void CCNode::Accept(RenderNodeVisitor* v) {
- v->BeginVisitCCNode(this);
- v->EndVisitCCNode(this);
- }
- RenderNodeVisitor::~RenderNodeVisitor() {
- }
- void RenderNodeVisitor::BeginVisitContentLayerNode(ContentLayerNode* v) {
- this->BeginVisitRenderNode(v);
- }
- void RenderNodeVisitor::BeginVisitCCNode(CCNode* v) {
- this->BeginVisitRenderNode(v);
- }
- void RenderNodeVisitor::EndVisitRenderNode(RenderNode* v) {
- }
- void RenderNodeVisitor::EndVisitContentLayerNode(ContentLayerNode* v) {
- this->EndVisitRenderNode(v);
- }
- void RenderNodeVisitor::EndVisitCCNode(CCNode* v) {
- this->EndVisitRenderNode(v);
- }
- std::unique_ptr<RenderNode> InterpretNode(const base::Value& node);
- // Makes sure that the key exists and has the type we expect.
- bool VerifyDictionaryEntry(const base::Value& node,
- const std::string& key,
- Value::Type type) {
- const Value* value = node.FindKey(key);
- if (!value) {
- LOG(ERROR) << "Missing value for key: " << key;
- return false;
- }
- if (value->type() != type) {
- LOG(ERROR) << key
- << " did not have the expected type "
- "(expected "
- << base::Value::GetTypeName(type) << ")";
- return false;
- }
- return true;
- }
- // Makes sure that the list entry has the type we expect.
- bool VerifyListEntry(const base::Value& list,
- int index,
- Value::Type type,
- const char* listName = nullptr) {
- // Assume the index is valid (since we'll be able to generate a better
- // error message for this elsewhere.)
- if (list.GetListDeprecated()[index].type() != type) {
- LOG(ERROR) << (listName ? listName : "List") << "element " << index
- << " did not have the expected type (expected "
- << base::Value::GetTypeName(type) << ")\n";
- return false;
- }
- return true;
- }
- bool InterpretCommonContents(const base::Value& node, RenderNode* c) {
- if (!VerifyDictionaryEntry(node, "layerID", Value::Type::INTEGER) ||
- !VerifyDictionaryEntry(node, "width", Value::Type::INTEGER) ||
- !VerifyDictionaryEntry(node, "height", Value::Type::INTEGER) ||
- !VerifyDictionaryEntry(node, "drawsContent", Value::Type::BOOLEAN) ||
- !VerifyDictionaryEntry(node, "targetSurfaceID", Value::Type::INTEGER) ||
- !VerifyDictionaryEntry(node, "transform", Value::Type::LIST)) {
- return false;
- }
- c->set_layerID(node.FindIntKey("layerID").value());
- c->set_width(node.FindIntKey("width").value());
- c->set_height(node.FindIntKey("height").value());
- c->set_drawsContent(node.FindBoolKey("drawsContent").value());
- c->set_targetSurface(node.FindIntKey("targetSurfaceID").value());
- const Value* transform = node.FindKey("transform");
- if (transform->GetListDeprecated().size() != 16) {
- LOG(ERROR) << "4x4 transform matrix did not have 16 elements";
- return false;
- }
- float transform_mat[16];
- for (int i = 0; i < 16; ++i) {
- if (!VerifyListEntry(*transform, i, Value::Type::DOUBLE, "Transform"))
- return false;
- transform_mat[i] = transform->GetListDeprecated()[i].GetDouble();
- }
- c->set_transform(transform_mat);
- const Value* tiles_dict = node.FindKey("tiles");
- if (!tiles_dict)
- return true;
- if (!VerifyDictionaryEntry(node, "tiles", Value::Type::DICTIONARY))
- return false;
- if (!VerifyDictionaryEntry(*tiles_dict, "dim", Value::Type::LIST))
- return false;
- const Value* dim = tiles_dict->FindKey("dim");
- if (!VerifyListEntry(*dim, 0, Value::Type::INTEGER, "Tile dimension") ||
- !VerifyListEntry(*dim, 1, Value::Type::INTEGER, "Tile dimension")) {
- return false;
- }
- c->set_tile_width(dim->GetListDeprecated()[0].GetInt());
- c->set_tile_height(dim->GetListDeprecated()[1].GetInt());
- if (!VerifyDictionaryEntry(*tiles_dict, "info", Value::Type::LIST))
- return false;
- const Value* tiles = tiles_dict->FindKey("info");
- for (unsigned int i = 0; i < tiles->GetListDeprecated().size(); ++i) {
- if (!VerifyListEntry(*tiles, i, Value::Type::DICTIONARY, "Tile info"))
- return false;
- const Value& tdict = tiles->GetListDeprecated()[i];
- if (!VerifyDictionaryEntry(tdict, "x", Value::Type::INTEGER) ||
- !VerifyDictionaryEntry(tdict, "y", Value::Type::INTEGER)) {
- return false;
- }
- Tile t;
- t.x = tdict.FindIntKey("x").value();
- t.y = tdict.FindIntKey("y").value();
- const Value* texID = tdict.FindKey("texID");
- if (texID) {
- if (!VerifyDictionaryEntry(tdict, "texID", Value::Type::INTEGER))
- return false;
- t.texID = texID->GetInt();
- } else {
- t.texID = -1;
- }
- c->add_tile(t);
- }
- return true;
- }
- bool InterpretCCData(const base::Value& node, CCNode* c) {
- if (!VerifyDictionaryEntry(node, "vertex_shader", Value::Type::STRING) ||
- !VerifyDictionaryEntry(node, "fragment_shader", Value::Type::STRING) ||
- !VerifyDictionaryEntry(node, "textures", Value::Type::LIST)) {
- return false;
- }
- std::string vertex_shader_name = *node.FindStringKey("vertex_shader");
- std::string fragment_shader_name = *node.FindStringKey("fragment_shader");
- c->set_vertex_shader(ShaderIDFromString(vertex_shader_name));
- c->set_fragment_shader(ShaderIDFromString(fragment_shader_name));
- const Value* textures = node.FindKey("textures");
- for (unsigned int i = 0; i < textures->GetListDeprecated().size(); ++i) {
- if (!VerifyListEntry(*textures, i, Value::Type::DICTIONARY, "Tex list"))
- return false;
- const Value& tex = textures->GetListDeprecated()[i];
- if (!VerifyDictionaryEntry(tex, "texID", Value::Type::INTEGER) ||
- !VerifyDictionaryEntry(tex, "height", Value::Type::INTEGER) ||
- !VerifyDictionaryEntry(tex, "width", Value::Type::INTEGER) ||
- !VerifyDictionaryEntry(tex, "format", Value::Type::STRING)) {
- return false;
- }
- Texture t;
- t.texID = tex.FindIntKey("texID").value();
- t.height = tex.FindIntKey("height").value();
- t.width = tex.FindIntKey("width").value();
- const std::string* format_name = tex.FindStringKey("format");
- t.format = TextureFormatFromString(*format_name);
- if (t.format == GL_INVALID_ENUM) {
- LOG(ERROR) << "Unrecognized texture format in layer " << c->layerID()
- << " (format: " << *format_name
- << ")\n"
- "The layer had "
- << textures->GetListDeprecated().size() << " children.";
- return false;
- }
- c->add_texture(t);
- }
- if (c->vertex_shader() == SHADER_UNRECOGNIZED) {
- LOG(ERROR) << "Unrecognized vertex shader name, layer " << c->layerID()
- << " (shader: " << vertex_shader_name << ")";
- return false;
- }
- if (c->fragment_shader() == SHADER_UNRECOGNIZED) {
- LOG(ERROR) << "Unrecognized fragment shader name, layer " << c->layerID()
- << " (shader: " << fragment_shader_name << ")";
- return false;
- }
- return true;
- }
- std::unique_ptr<RenderNode> InterpretContentLayer(const base::Value& node) {
- auto n = std::make_unique<ContentLayerNode>();
- if (!InterpretCommonContents(node, n.get()))
- return nullptr;
- if (!VerifyDictionaryEntry(node, "type", Value::Type::STRING) ||
- !VerifyDictionaryEntry(node, "skipsDraw", Value::Type::BOOLEAN) ||
- !VerifyDictionaryEntry(node, "children", Value::Type::LIST)) {
- return nullptr;
- }
- DCHECK_EQ(*node.FindStringKey("type"), "ContentLayer");
- n->set_skipsDraw(node.FindBoolKey("skipsDraw").value());
- const Value* children = node.FindKey("children");
- for (unsigned int i = 0; i < children->GetListDeprecated().size(); ++i) {
- const Value& child_node = children->GetListDeprecated()[i];
- if (!child_node.is_dict())
- continue;
- std::unique_ptr<RenderNode> child = InterpretNode(child_node);
- if (child)
- n->add_child(child.release());
- }
- return std::move(n);
- }
- std::unique_ptr<RenderNode> InterpretCanvasLayer(const base::Value& node) {
- auto n = std::make_unique<CCNode>();
- if (!InterpretCommonContents(node, n.get()))
- return nullptr;
- if (!VerifyDictionaryEntry(node, "type", Value::Type::STRING))
- return nullptr;
- DCHECK_EQ(*node.FindStringKey("type"), "CanvasLayer");
- if (!InterpretCCData(node, n.get()))
- return nullptr;
- return std::move(n);
- }
- std::unique_ptr<RenderNode> InterpretVideoLayer(const base::Value& node) {
- auto n = std::make_unique<CCNode>();
- if (!InterpretCommonContents(node, n.get()))
- return nullptr;
- if (!VerifyDictionaryEntry(node, "type", Value::Type::STRING))
- return nullptr;
- DCHECK_EQ(*node.FindStringKey("type"), "VideoLayer");
- if (!InterpretCCData(node, n.get()))
- return nullptr;
- return std::move(n);
- }
- std::unique_ptr<RenderNode> InterpretImageLayer(const base::Value& node) {
- auto n = std::make_unique<CCNode>();
- if (!InterpretCommonContents(node, n.get()))
- return nullptr;
- if (!VerifyDictionaryEntry(node, "type", Value::Type::STRING))
- return nullptr;
- DCHECK_EQ(*node.FindStringKey("type"), "ImageLayer");
- if (!InterpretCCData(node, n.get()))
- return nullptr;
- return std::move(n);
- }
- std::unique_ptr<RenderNode> InterpretNode(const base::Value& node) {
- if (!VerifyDictionaryEntry(node, "type", Value::Type::STRING))
- return nullptr;
- const std::string* type = node.FindStringKey("type");
- if (*type == "ContentLayer")
- return InterpretContentLayer(node);
- if (*type == "CanvasLayer")
- return InterpretCanvasLayer(node);
- if (*type == "VideoLayer")
- return InterpretVideoLayer(node);
- if (*type == "ImageLayer")
- return InterpretImageLayer(node);
- std::string outjson;
- JSONWriter::WriteWithOptions(node, base::JSONWriter::OPTIONS_PRETTY_PRINT,
- &outjson);
- LOG(ERROR) << "Unrecognized node type! JSON:\n\n"
- "-----------------------\n"
- << outjson << "-----------------------";
- return nullptr;
- }
- std::unique_ptr<RenderNode> BuildRenderTreeFromFile(
- const base::FilePath& path) {
- LOG(INFO) << "Reading " << path.LossyDisplayName();
- std::string contents;
- if (!ReadFileToString(path, &contents))
- return nullptr;
- auto result = JSONReader::ReadAndReturnValueWithError(
- contents, base::JSON_ALLOW_TRAILING_COMMAS);
- if (!result.has_value()) {
- LOG(ERROR) << "Failed to parse JSON file " << path.LossyDisplayName()
- << "\n(" << result.error().message << ")";
- return nullptr;
- } else if (!result->is_dict()) {
- LOG(ERROR) << "Failed to parse JSON file " << path.LossyDisplayName()
- << "\n(expecting a list.)";
- return nullptr;
- }
- return InterpretContentLayer(*result);
- }
|