Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

pandatool/src/egg-palettize/textureMemoryCounter.cxx

Go to the documentation of this file.
00001 // Filename: textureMemoryCounter.cxx
00002 // Created by:  drose (19Dec00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "textureMemoryCounter.h"
00020 #include "paletteImage.h"
00021 #include "textureImage.h"
00022 #include "destTextureImage.h"
00023 #include "omitReason.h"
00024 #include "texturePlacement.h"
00025 
00026 #include <indent.h>
00027 #include <math.h>
00028 
00029 ////////////////////////////////////////////////////////////////////
00030 //     Function: TextureMemoryCounter::Constructor
00031 //       Access: Public
00032 //  Description:
00033 ////////////////////////////////////////////////////////////////////
00034 TextureMemoryCounter::
00035 TextureMemoryCounter() {
00036   reset();
00037 }
00038 
00039 ////////////////////////////////////////////////////////////////////
00040 //     Function: TextureMemoryCounter::reset
00041 //       Access: Public
00042 //  Description: Resets the count to zero.
00043 ////////////////////////////////////////////////////////////////////
00044 void TextureMemoryCounter::
00045 reset() {
00046   _num_textures = 0;
00047   _num_unplaced = 0;
00048   _num_placed = 0;
00049   _num_palettes = 0;
00050 
00051   _bytes = 0;
00052   _unused_bytes = 0;
00053   _duplicate_bytes = 0;
00054   _coverage_bytes = 0;
00055   _textures.clear();
00056   _palettes.clear();
00057 }
00058 
00059 ////////////////////////////////////////////////////////////////////
00060 //     Function: TextureMemoryCounter::add_placement
00061 //       Access: Public
00062 //  Description: Adds the indicated TexturePlacement to the counter.
00063 ////////////////////////////////////////////////////////////////////
00064 void TextureMemoryCounter::
00065 add_placement(TexturePlacement *placement) {
00066   TextureImage *texture = placement->get_texture();
00067   nassertv(texture != (TextureImage *)NULL);
00068 
00069   if (placement->get_omit_reason() == OR_none) {
00070     PaletteImage *image = placement->get_image();
00071     nassertv(image != (PaletteImage *)NULL);
00072     add_palette(image);
00073 
00074     int bytes = count_bytes(image, placement->get_placed_x_size(),
00075                             placement->get_placed_y_size());
00076     add_texture(texture, bytes);
00077     _num_placed++;
00078 
00079   } else {
00080     DestTextureImage *dest = placement->get_dest();
00081     nassertv(dest != (DestTextureImage *)NULL);
00082 
00083     int bytes = count_bytes(dest);
00084     add_texture(texture, bytes);
00085 
00086     _bytes += bytes;
00087     _num_unplaced++;
00088   }
00089 }
00090 
00091 ////////////////////////////////////////////////////////////////////
00092 //     Function: TextureMemoryCounter::report
00093 //       Access: Public
00094 //  Description: Reports the measured texture memory usage.
00095 ////////////////////////////////////////////////////////////////////
00096 void TextureMemoryCounter::
00097 report(ostream &out, int indent_level) {
00098   indent(out, indent_level)
00099     << _num_placed << " of " << _num_textures << " textures appear on "
00100     << _num_palettes << " palette images with " << _num_unplaced
00101     << " unplaced.\n";
00102 
00103   indent(out, indent_level)
00104     << (_bytes + 512) / 1024 << "k estimated texture memory required.\n";
00105 
00106   if (_bytes != 0) {
00107     if (_unused_bytes != 0) {
00108       indent(out, indent_level + 2);
00109       format_memory_fraction(out, _unused_bytes, _bytes)
00110         << " is wasted because of unused palette space.\n";
00111     }
00112 
00113     if (_coverage_bytes > 0) {
00114       indent(out, indent_level + 2);
00115       format_memory_fraction(out, _coverage_bytes, _bytes)
00116         << " is wasted for repeating textures and margins.\n";
00117 
00118     } else if (_coverage_bytes < 0) {
00119       indent(out, indent_level + 2);
00120       format_memory_fraction(out, -_coverage_bytes, _bytes)
00121         << " is *saved* for palettizing partial textures.\n";
00122     }
00123 
00124     if (_duplicate_bytes != 0) {
00125       indent(out, indent_level + 2);
00126       format_memory_fraction(out, _duplicate_bytes, _bytes)
00127         << " is wasted because of a texture appearing in multiple groups.\n";
00128     }
00129   }
00130 }
00131 
00132 ////////////////////////////////////////////////////////////////////
00133 //     Function: TextureMemoryCounter::format_memory_fraction
00134 //       Access: Private, Static
00135 //  Description: Writes to the indicated ostream an indication of the
00136 //               fraction of the total memory usage that is
00137 //               represented by fraction_bytes.
00138 ////////////////////////////////////////////////////////////////////
00139 ostream &TextureMemoryCounter::
00140 format_memory_fraction(ostream &out, int fraction_bytes, int palette_bytes) {
00141   out << floor(1000.0 * (double)fraction_bytes / (double)palette_bytes + 0.5) / 10.0
00142       << "% (" << (fraction_bytes + 512) / 1024 << "k)";
00143   return out;
00144 }
00145 
00146 ////////////////////////////////////////////////////////////////////
00147 //     Function: TextureMemoryCounter::add_palette
00148 //       Access: Private
00149 //  Description: Adds the indicated PaletteImage to the count.  If
00150 //               this is called twice for a given PaletteImage it does
00151 //               nothing.
00152 ////////////////////////////////////////////////////////////////////
00153 void TextureMemoryCounter::
00154 add_palette(PaletteImage *image) {
00155   bool inserted = _palettes.insert(image).second;
00156   if (!inserted) {
00157     // We've already added this palette image.
00158     return;
00159   }
00160 
00161   int bytes = count_bytes(image);
00162   double unused = 1.0 - image->count_utilization();
00163   double coverage = image->count_coverage();
00164 
00165   _bytes += bytes;
00166   _unused_bytes += (int)(unused * bytes);
00167   _coverage_bytes += (int)(coverage * bytes);
00168 
00169   _num_palettes++;
00170 }
00171 
00172 ////////////////////////////////////////////////////////////////////
00173 //     Function: TextureMemoryCounter::add_texture
00174 //       Access: Private
00175 //  Description: Adds the given TextureImage to the counter.  If the
00176 //               texture image has already been added, this counts the
00177 //               smaller of the two as duplicate bytes.
00178 ////////////////////////////////////////////////////////////////////
00179 void TextureMemoryCounter::
00180 add_texture(TextureImage *texture, int bytes) {
00181   pair<Textures::iterator, bool> result;
00182   result = _textures.insert(Textures::value_type(texture, bytes));
00183   if (result.second) {
00184     // If it was inserted, no problem--no duplicates.
00185     _num_textures++;
00186     return;
00187   }
00188 
00189   // If it was not inserted, we have a duplicate.
00190   Textures::iterator ti = result.first;
00191 
00192   _duplicate_bytes += min(bytes, (*ti).second);
00193   (*ti).second = max(bytes, (*ti).second);
00194 }
00195 
00196 ////////////////////////////////////////////////////////////////////
00197 //     Function: TextureMemoryCounter::count_bytes
00198 //       Access: Private
00199 //  Description: Attempts to estimate the number of bytes the given
00200 //               image file will use in texture memory.
00201 ////////////////////////////////////////////////////////////////////
00202 int TextureMemoryCounter::
00203 count_bytes(ImageFile *image) {
00204   return count_bytes(image, image->get_x_size(), image->get_y_size());
00205 }
00206 
00207 ////////////////////////////////////////////////////////////////////
00208 //     Function: TextureMemoryCounter::count_bytes
00209 //       Access: Private
00210 //  Description: Attempts to estimate the number of bytes the given
00211 //               image file will use in texture memory.
00212 ////////////////////////////////////////////////////////////////////
00213 int TextureMemoryCounter::
00214 count_bytes(ImageFile *image, int x_size, int y_size) {
00215   int pixels = x_size * y_size;
00216 
00217   // Try to guess the number of bytes per pixel this texture will
00218   // consume in texture memory, based on its requested format.  This
00219   // is only a loose guess, because this depends of course on the
00220   // pecularities of the particular rendering engine.
00221   int bpp = 0;
00222   switch (image->get_properties()._format) {
00223   case EggTexture::F_rgba12:
00224     bpp = 6;
00225     break;
00226 
00227   case EggTexture::F_rgba:
00228   case EggTexture::F_rgbm:
00229   case EggTexture::F_rgba8:
00230     bpp = 4;
00231     break;
00232 
00233   case EggTexture::F_rgb:
00234   case EggTexture::F_rgb12:
00235     bpp = 3;
00236     break;
00237 
00238   case EggTexture::F_rgba4:
00239   case EggTexture::F_rgba5:
00240   case EggTexture::F_rgb8:
00241   case EggTexture::F_rgb5:
00242   case EggTexture::F_luminance_alpha:
00243   case EggTexture::F_luminance_alphamask:
00244     bpp = 2;
00245     break;
00246 
00247   case EggTexture::F_rgb332:
00248   case EggTexture::F_red:
00249   case EggTexture::F_green:
00250   case EggTexture::F_blue:
00251   case EggTexture::F_alpha:
00252   case EggTexture::F_luminance:
00253     bpp = 1;
00254     break;
00255 
00256   default:
00257     bpp = image->get_num_channels();
00258   }
00259 
00260   int bytes = pixels * bpp;
00261 
00262   // If we're mipmapping, it's worth 1/3 more bytes.
00263   switch (image->get_properties()._minfilter) {
00264   case EggTexture::FT_nearest_mipmap_nearest:
00265   case EggTexture::FT_linear_mipmap_nearest:
00266   case EggTexture::FT_nearest_mipmap_linear:
00267   case EggTexture::FT_linear_mipmap_linear:
00268     bytes = (bytes * 4) / 3;
00269     break;
00270 
00271   default:
00272     break;
00273   }
00274 
00275   return bytes;
00276 }

Generated on Fri May 2 03:18:11 2003 for Panda-Tool by doxygen1.3