Adding Peter Thatcher to the owners file.
[chromium-blink-merge.git] / gpu / tools / compositor_model_bench / render_model_utils.cc
blob7e1eb5cc3e0816f9a6e1c137ffff5486040ce5d8
1 // Copyright (c) 2011 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.
5 // Whole-tree processing that's likely to be helpful in multiple render models.
7 #include "gpu/tools/compositor_model_bench/render_model_utils.h"
9 #include <cstdlib>
10 #include <map>
11 #include <set>
12 #include <vector>
14 #include "base/logging.h"
16 TextureGenerator::TextureGenerator(RenderNode* root)
17 : stage_(DiscoveryStage),
18 images_generated_(0) {
19 DiscoverInputIDs(root);
20 GenerateGLTexIDs();
21 AssignIDMapping();
22 WriteOutNewIDs(root);
23 AllocateImageArray();
24 BuildTextureImages(root);
27 TextureGenerator::~TextureGenerator() {
28 if (tex_ids_.get()) {
29 glDeleteTextures(discovered_ids_.size(), tex_ids_.get());
33 void TextureGenerator::BeginVisitRenderNode(RenderNode* node) {
34 for (size_t n = 0; n < node->num_tiles(); ++n) {
35 Tile* i = node->tile(n);
36 HandleTexture(&i->texID,
37 node->tile_width(),
38 node->tile_height(),
39 GL_RGBA);
43 void TextureGenerator::BeginVisitCCNode(CCNode* node) {
44 for (size_t n = 0; n < node->num_textures(); ++n) {
45 Texture* i = node->texture(n);
46 HandleTexture(&i->texID, i->width, i->height, i->format);
48 BeginVisitRenderNode(node);
51 void TextureGenerator::DiscoverInputIDs(RenderNode* root) {
52 // Pass 1: see which texture ID's have been used.
53 stage_ = DiscoveryStage;
54 root->Accept(this);
57 void TextureGenerator::GenerateGLTexIDs() {
58 int numTextures = discovered_ids_.size();
59 tex_ids_.reset(new GLuint[numTextures]);
60 glGenTextures(numTextures, tex_ids_.get());
63 void TextureGenerator::AssignIDMapping() {
64 // In the original version of this code the assigned ID's were not
65 // GL tex ID's, but newly generated consecutive ID's that indexed
66 // into an array of GL tex ID's. There's no need for this and now
67 // I'm instead generating the GL tex ID's upfront and assigning
68 // *those* in the remapping -- this more accurately reflects the
69 // behavior in Chromium, and it also takes out some design
70 // complexity that came from the extra layer of indirection.
71 // HOWEVER -- when I was assigning my own ID's before, I did some
72 // clever tricks to make sure the assignation was idempotent.
73 // Instead of going to even more clever lengths to preserve that
74 // property, I now just assume that the visitor will encounter each
75 // node (and consequently each texture) exactly once during a
76 // traversal of the tree -- this shouldn't be a hard guarantee
77 // to make.
78 int j = 0;
79 typedef std::set<int>::iterator id_itr;
80 for (id_itr i = discovered_ids_.begin();
81 i != discovered_ids_.end();
82 ++i, ++j) {
83 remapped_ids_[*i] = tex_ids_[j];
87 void TextureGenerator::WriteOutNewIDs(RenderNode* root) {
88 // Pass 2: write the new texture ID's back into the texture objects.
89 stage_ = RemappingStage;
90 root->Accept(this);
93 void TextureGenerator::AllocateImageArray() {
94 image_data_.reset(new ImagePtr[discovered_ids_.size()]);
95 images_generated_ = 0;
98 void TextureGenerator::BuildTextureImages(RenderNode* root) {
99 // Pass 3: use the texture metadata to generate images for the
100 // textures, and set up the textures for use by OpenGL. This
101 // doesn't *have* to be a separate pass (it could be rolled
102 // into pass 2) but I think this is more clear and performance
103 // shouldn't be bad.
104 stage_ = ImageGenerationStage;
105 root->Accept(this);
108 void TextureGenerator::HandleTexture(int* texID,
109 int width,
110 int height,
111 GLenum format) {
112 if (*texID == -1)
113 return; // -1 means it's not a real texture.
114 switch (stage_) {
115 case DiscoveryStage:
116 discovered_ids_.insert(*texID);
117 break;
118 case RemappingStage:
119 *texID = remapped_ids_[*texID];
120 break;
121 case ImageGenerationStage:
122 // Only handle this one if we haven't already built a
123 // texture for its ID.
124 if (ids_for_completed_textures_.count(*texID))
125 return;
126 GenerateImageForTexture(*texID, width, height, format);
127 ids_for_completed_textures_.insert(*texID);
128 break;
132 void TextureGenerator::GenerateImageForTexture(int texID,
133 int width,
134 int height,
135 GLenum format) {
136 int bytes_per_pixel = FormatBytesPerPixel(format);
137 DCHECK_LE(bytes_per_pixel, 4);
138 int imgID = images_generated_++;
139 image_data_[imgID].reset(new uint8[width*height*bytes_per_pixel]);
140 // Pick random colors to use for this texture.
141 uint8 random_color[4];
142 for (int c = 0; c < 4; ++c) {
143 random_color[c] = std::rand() % 255;
145 // Create the image from those colors.
146 for (int x = 0; x < width; ++x) {
147 for (int y = 0; y < height; ++y) {
148 int pix_addr = (y * width + x) * bytes_per_pixel;
149 for (int c = 0; c < bytes_per_pixel; ++c) {
150 bool on = ((x/8) + (y/8)) % 2;
151 uint8 v = on ? random_color[c] : ~random_color[c];
152 (image_data_[imgID])[pix_addr + c] = v;
154 if (bytes_per_pixel == 4) { // Randomize alpha.
155 image_data_[imgID][pix_addr + 3] = std::rand() % 255;
159 // Set up GL texture.
160 glBindTexture(GL_TEXTURE_2D, texID);
161 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
162 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
163 glPixelStorei(GL_PACK_ALIGNMENT, 1);
164 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
165 glTexImage2D(GL_TEXTURE_2D,
167 format,
168 width, height,
170 format,
171 GL_UNSIGNED_BYTE,
172 image_data_[imgID].get());