Index: gpu/tools/compositor_model_bench/render_model_utils.cc |
diff --git a/gpu/tools/compositor_model_bench/render_model_utils.cc b/gpu/tools/compositor_model_bench/render_model_utils.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d2bed4603586a506a0f8c5199b3a54756ad7be30 |
--- /dev/null |
+++ b/gpu/tools/compositor_model_bench/render_model_utils.cc |
@@ -0,0 +1,176 @@ |
+// Copyright (c) 2011 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. |
+ |
+// Whole-tree processing that's likely to be helpful in multiple render models. |
+ |
+#include "gpu/tools/compositor_model_bench/render_model_utils.h" |
+ |
+#include <cstdlib> |
+#include <map> |
+#include <set> |
+#include <vector> |
+ |
+#include "base/logging.h" |
+ |
+TextureGenerator::TextureGenerator(RenderNode* root) |
+ : stage_(DiscoveryStage), |
+ tex_ids_(NULL), |
+ image_data_(NULL), |
+ images_generated_(0) { |
+ DiscoverInputIDs(root); |
+ GenerateGLTexIDs(); |
+ AssignIDMapping(); |
+ WriteOutNewIDs(root); |
+ AllocateImageArray(); |
+ BuildTextureImages(root); |
+} |
+ |
+TextureGenerator::~TextureGenerator() { |
+ if (tex_ids_.get()) { |
+ glDeleteTextures(discovered_ids_.size(), tex_ids_.get()); |
+ } |
+} |
+ |
+void TextureGenerator::BeginVisitRenderNode(RenderNode* node) { |
+ for (size_t n = 0; n < node->num_tiles(); ++n) { |
+ Tile* i = node->tile(n); |
+ HandleTexture(&i->texID, |
+ node->tile_width(), |
+ node->tile_height(), |
+ GL_RGBA); |
+ } |
+} |
+ |
+void TextureGenerator::BeginVisitCCNode(CCNode* node) { |
+ for (size_t n = 0; n < node->num_textures(); ++n) { |
+ Texture* i = node->texture(n); |
+ HandleTexture(&i->texID, i->width, i->height, i->format); |
+ } |
+ BeginVisitRenderNode(node); |
+} |
+ |
+void TextureGenerator::DiscoverInputIDs(RenderNode* root) { |
+ // Pass 1: see which texture ID's have been used. |
+ stage_ = DiscoveryStage; |
+ root->Accept(this); |
+} |
+ |
+void TextureGenerator::GenerateGLTexIDs() { |
+ int numTextures = discovered_ids_.size(); |
+ tex_ids_.reset(new GLuint[numTextures]); |
+ glGenTextures(numTextures, tex_ids_.get()); |
+} |
+ |
+void TextureGenerator::AssignIDMapping() { |
+ // In the original version of this code the assigned ID's were not |
+ // GL tex ID's, but newly generated consecutive ID's that indexed |
+ // into an array of GL tex ID's. There's no need for this and now |
+ // I'm instead generating the GL tex ID's upfront and assigning |
+ // *those* in the remapping -- this more accurately reflects the |
+ // behavior in Chromium, and it also takes out some design |
+ // complexity that came from the extra layer of indirection. |
+ // HOWEVER -- when I was assigning my own ID's before, I did some |
+ // clever tricks to make sure the assignation was idempotent. |
+ // Instead of going to even more clever lengths to preserve that |
+ // property, I now just assume that the visitor will encounter each |
+ // node (and consequently each texture) exactly once during a |
+ // traversal of the tree -- this shouldn't be a hard guarantee |
+ // to make. |
+ int j = 0; |
+ typedef std::set<int>::iterator id_itr; |
+ for (id_itr i = discovered_ids_.begin(); |
+ i != discovered_ids_.end(); |
+ ++i, ++j) { |
+ remapped_ids_[*i] = tex_ids_[j]; |
+ } |
+} |
+ |
+void TextureGenerator::WriteOutNewIDs(RenderNode* root) { |
+ // Pass 2: write the new texture ID's back into the texture objects. |
+ stage_ = RemappingStage; |
+ root->Accept(this); |
+} |
+ |
+void TextureGenerator::AllocateImageArray() { |
+ image_data_.reset(new ImagePtr[discovered_ids_.size()]); |
+ images_generated_ = 0; |
+} |
+ |
+void TextureGenerator::BuildTextureImages(RenderNode* root) { |
+ // Pass 3: use the texture metadata to generate images for the |
+ // textures, and set up the textures for use by OpenGL. This |
+ // doesn't *have* to be a separate pass (it could be rolled |
+ // into pass 2) but I think this is more clear and performance |
+ // shouldn't be bad. |
+ stage_ = ImageGenerationStage; |
+ root->Accept(this); |
+} |
+ |
+void TextureGenerator::HandleTexture(int* texID, |
+ int width, |
+ int height, |
+ GLenum format) { |
+ if (*texID == -1) |
+ return; // -1 means it's not a real texture. |
+ switch (stage_) { |
+ case DiscoveryStage: |
+ discovered_ids_.insert(*texID); |
+ break; |
+ case RemappingStage: |
+ *texID = remapped_ids_[*texID]; |
+ break; |
+ case ImageGenerationStage: |
+ // Only handle this one if we haven't already built a |
+ // texture for its ID. |
+ if (ids_for_completed_textures_.count(*texID)) |
+ return; |
+ GenerateImageForTexture(*texID, width, height, format); |
+ ids_for_completed_textures_.insert(*texID); |
+ break; |
+ } |
+} |
+ |
+void TextureGenerator::GenerateImageForTexture(int texID, |
+ int width, |
+ int height, |
+ GLenum format) { |
+ int bytes_per_pixel = FormatBytesPerPixel(format); |
+ DCHECK_LE(bytes_per_pixel, 4); |
+ int imgID = images_generated_++; |
+ image_data_[imgID].reset(new uint8[width*height*bytes_per_pixel]); |
+ // Pick random colors to use for this texture. |
+ uint8 random_color[4]; |
+ for (int c = 0; c < 4; ++c) { |
+ random_color[c] = std::rand() % 255; |
+ } |
+ // Create the image from those colors. |
+ for (int x = 0; x < width; ++x) { |
+ for (int y = 0; y < height; ++y) { |
+ int pix_addr = (y * width + x) * bytes_per_pixel; |
+ for (int c = 0; c < bytes_per_pixel; ++c) { |
+ bool on = ((x/8) + (y/8)) % 2; |
+ uint8 v = on ? random_color[c] : ~random_color[c]; |
+ (image_data_[imgID])[pix_addr + c] = v; |
+ } |
+ if (bytes_per_pixel == 4) { // Randomize alpha. |
+ image_data_[imgID][pix_addr + 3] = std::rand() % 255; |
+ } |
+ } |
+ } |
+ // Set up GL texture. |
+ glBindTexture(GL_TEXTURE_2D, texID); |
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
+ glPixelStorei(GL_PACK_ALIGNMENT, 1); |
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1); |
+ glTexImage2D(GL_TEXTURE_2D, |
+ 0, |
+ format, |
+ width, height, |
+ 0, |
+ format, |
+ GL_UNSIGNED_BYTE, |
+ image_data_[imgID].get()); |
+} |
+ |