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