123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- // 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 <stddef.h>
- #include <stdint.h>
- #include <cstdlib>
- #include <map>
- #include <set>
- #include <vector>
- #include "base/check_op.h"
- TextureGenerator::TextureGenerator(RenderNode* root)
- : stage_(DiscoveryStage),
- 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_t[width * height * bytes_per_pixel]);
- // Pick random colors to use for this texture.
- uint8_t 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_t 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());
- }
|