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"
14 #include "base/logging.h"
16 TextureGenerator::TextureGenerator(RenderNode
* root
)
17 : stage_(DiscoveryStage
),
18 images_generated_(0) {
19 DiscoverInputIDs(root
);
24 BuildTextureImages(root
);
27 TextureGenerator::~TextureGenerator() {
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
,
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
;
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
79 typedef std::set
<int>::iterator id_itr
;
80 for (id_itr i
= discovered_ids_
.begin();
81 i
!= discovered_ids_
.end();
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
;
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
104 stage_
= ImageGenerationStage
;
108 void TextureGenerator::HandleTexture(int* texID
,
113 return; // -1 means it's not a real texture.
116 discovered_ids_
.insert(*texID
);
119 *texID
= remapped_ids_
[*texID
];
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
))
126 GenerateImageForTexture(*texID
, width
, height
, format
);
127 ids_for_completed_textures_
.insert(*texID
);
132 void TextureGenerator::GenerateImageForTexture(int texID
,
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
,
172 image_data_
[imgID
].get());