render_model_utils.cc 5.8 KB

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