Chromium Code Reviews| Index: gpu/tools/compositor_model_bench/render_model_utils.cc |
| =================================================================== |
| --- gpu/tools/compositor_model_bench/render_model_utils.cc (revision 0) |
| +++ gpu/tools/compositor_model_bench/render_model_utils.cc (revision 0) |
| @@ -0,0 +1,175 @@ |
| +// 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() OVERRIDE { |
| + if (tex_ids_.get()) { |
| + glDeleteTextures(discovered_ids_.size(), tex_ids_.get()); |
| + } |
| +} |
| + |
| +void TextureGenerator::BeginVisitRenderNode(RenderNode* node) OVERRIDE { |
| + typedef std::vector<Tile>::iterator tile_itr; |
| + for (tile_itr i = node->tiles.begin(); i != node->tiles.end(); ++i) { |
| + HandleTexture(&i->texID, |
| + node->tile_width, |
|
piman
2011/08/26 02:24:16
nit: indentation (align arguments)
|
| + node->tile_height, |
| + GL_RGBA); |
| + } |
| +} |
| + |
| +void TextureGenerator::BeginVisitCCNode(CCNode* node) OVERRIDE { |
| + typedef std::vector<Texture>::iterator tex_itr; |
| + for (tex_itr i = node->textures.begin(); i != node->textures.end(); ++i) { |
| + 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(); |
|
piman
2011/08/26 02:24:16
nit: indentation (align all 3 statements)
|
| + ++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, |
|
piman
2011/08/26 02:24:16
nit:indentation (align parameters)
|
| + int height, |
| + GLenum format) { |
| + if (*texID == -1) return; // -1 means it's not a real texture. |
|
piman
2011/08/26 02:24:16
nit: return on a separate line
|
| + 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, |
|
piman
2011/08/26 02:24:16
nit: indentation
|
| + 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, |
|
piman
2011/08/26 02:24:16
nit: align arguments
|
| + format, |
| + width, height, |
| + 0, |
| + format, |
| + GL_UNSIGNED_BYTE, |
| + image_data_[imgID].get()); |
| +} |
| + |