mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
*** empty log message ***
This commit is contained in:
parent
417ed7154a
commit
8735480f77
@ -22,6 +22,7 @@
|
||||
palettizer.cxx palettizer.h \
|
||||
sourceTextureImage.cxx sourceTextureImage.h \
|
||||
textureImage.cxx textureImage.h \
|
||||
textureMemoryCounter.cxx textureMemoryCounter.h \
|
||||
texturePlacement.cxx texturePlacement.h \
|
||||
texturePosition.cxx texturePosition.h \
|
||||
textureProperties.cxx textureProperties.h textureReference.cxx \
|
||||
|
@ -69,7 +69,7 @@ EggPalettize() : EggMultiFilter(true) {
|
||||
("s", "", 0,
|
||||
"Do not process anything, but report statistics on palette "
|
||||
"and texture utilization.",
|
||||
&EggPalettize::dispatch_none, &_statistics_only);
|
||||
&EggPalettize::dispatch_none, &_report_statistics);
|
||||
|
||||
// We redefine -d using add_option() instead of redescribe_option()
|
||||
// so it gets listed along with these other options that relate.
|
||||
@ -515,6 +515,11 @@ run() {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (_report_statistics) {
|
||||
pal->report_statistics();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
bool okflag = true;
|
||||
|
||||
pal->read_txa_file(_txa_filename);
|
||||
|
@ -44,7 +44,7 @@ private:
|
||||
// The following values control behavior specific to this session.
|
||||
// They're not saved for future sessions.
|
||||
bool _report_pi;
|
||||
bool _statistics_only;
|
||||
bool _report_statistics;
|
||||
bool _all_textures;
|
||||
bool _optimal;
|
||||
bool _redo_all;
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "palettePage.h"
|
||||
#include "texturePlacement.h"
|
||||
#include "textureImage.h"
|
||||
#include "palettizer.h"
|
||||
|
||||
#include <indent.h>
|
||||
#include <datagram.h>
|
||||
@ -25,6 +26,7 @@ PaletteGroup::
|
||||
PaletteGroup() {
|
||||
_egg_count = 0;
|
||||
_dependency_level = 0;
|
||||
_dependency_order = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -73,6 +75,7 @@ void PaletteGroup::
|
||||
clear_depends() {
|
||||
_dependent.clear();
|
||||
_dependency_level = 0;
|
||||
_dependency_order = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -102,6 +105,59 @@ get_groups() const {
|
||||
return _dependent;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PaletteGroup::get_placements
|
||||
// Access: Public
|
||||
// Description: Adds the set of TexturePlacements associated with
|
||||
// this group to the indicated vector. The vector is
|
||||
// not cleared before this operation; if the user wants
|
||||
// to retrieve the set of placements particular to this
|
||||
// group only, it is the user's responsibility to clear
|
||||
// the vector first.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PaletteGroup::
|
||||
get_placements(vector<TexturePlacement *> &placements) const {
|
||||
Placements::iterator pi;
|
||||
for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
|
||||
placements.push_back(*pi);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PaletteGroup::get_complete_placements
|
||||
// Access: Public
|
||||
// Description: Adds the set of TexturePlacements associated with
|
||||
// this group and all dependent groups to the indicated
|
||||
// vector. See get_placements().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PaletteGroup::
|
||||
get_complete_placements(vector<TexturePlacement *> &placements) const {
|
||||
PaletteGroups complete;
|
||||
complete.make_complete(_dependent);
|
||||
|
||||
PaletteGroups::iterator gi;
|
||||
for (gi = complete.begin(); gi != complete.end(); ++gi) {
|
||||
PaletteGroup *group = (*gi);
|
||||
group->get_placements(placements);
|
||||
}
|
||||
|
||||
get_placements(placements);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PaletteGroup::reset_dependency_level
|
||||
// Access: Public
|
||||
// Description: Unconditionally sets the dependency level and order
|
||||
// of this group to zero, in preparation for a later
|
||||
// call to set_dependency_level(). See
|
||||
// set_dependency_level().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PaletteGroup::
|
||||
reset_dependency_level() {
|
||||
_dependency_level = 0;
|
||||
_dependency_order = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PaletteGroup::set_dependency_level
|
||||
// Access: Public
|
||||
@ -120,11 +176,44 @@ set_dependency_level(int level) {
|
||||
_dependency_level = level;
|
||||
PaletteGroups::iterator gi;
|
||||
for (gi = _dependent.begin(); gi != _dependent.end(); ++gi) {
|
||||
(*gi)->set_dependency_level(level + 1);
|
||||
PaletteGroup *group = (*gi);
|
||||
group->set_dependency_level(level + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PaletteGroup::set_dependency_order
|
||||
// Access: Public
|
||||
// Description: Updates the dependency order of this group. This
|
||||
// number is the inverse of the dependency level, and
|
||||
// can be used to rank the groups in order so that all
|
||||
// the groups that a given group depends on will appear
|
||||
// first in the list. See get_dependency_order().
|
||||
//
|
||||
// This function returns true if anything was changed,
|
||||
// false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PaletteGroup::
|
||||
set_dependency_order() {
|
||||
bool any_changed = false;
|
||||
|
||||
PaletteGroups::iterator gi;
|
||||
for (gi = _dependent.begin(); gi != _dependent.end(); ++gi) {
|
||||
PaletteGroup *group = (*gi);
|
||||
if (group->set_dependency_order()) {
|
||||
any_changed = true;
|
||||
}
|
||||
|
||||
if (_dependency_order <= group->get_dependency_order()) {
|
||||
_dependency_order = group->get_dependency_order() + 1;
|
||||
any_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return any_changed;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PaletteGroup::get_dependency_level
|
||||
// Access: Public
|
||||
@ -151,6 +240,26 @@ get_dependency_level() const {
|
||||
return _dependency_level;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PaletteGroup::get_dependency_order
|
||||
// Access: Public
|
||||
// Description: Returns the dependency order of this group. This is
|
||||
// similar in principle to the dependency level, but it
|
||||
// represents the inverse concept: if group a depends on
|
||||
// group b, then a->get_dependency_order() >
|
||||
// b->get_dependency_order().
|
||||
//
|
||||
// This is not exactly the same thing as n -
|
||||
// get_dependency_level(). In particular, this can be
|
||||
// used to sort the groups into an ordering such that
|
||||
// all the groups that group a depends on appear before
|
||||
// group a in the list.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int PaletteGroup::
|
||||
get_dependency_order() const {
|
||||
return _dependency_order;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PaletteGroup::increment_egg_count
|
||||
// Access: Public
|
||||
@ -392,8 +501,8 @@ write_datagram(BamWriter *writer, Datagram &datagram) {
|
||||
datagram.add_string(_dirname);
|
||||
_dependent.write_datagram(writer, datagram);
|
||||
|
||||
// We don't write out _dependency_level. It's best to recompute
|
||||
// that each time.
|
||||
datagram.add_int32(_dependency_level);
|
||||
datagram.add_int32(_dependency_order);
|
||||
|
||||
datagram.add_uint32(_placements.size());
|
||||
Placements::const_iterator pli;
|
||||
@ -504,6 +613,11 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
_dirname = scan.get_string();
|
||||
_dependent.fillin(scan, manager);
|
||||
|
||||
if (Palettizer::_read_pi_version >= 3) {
|
||||
_dependency_level = scan.get_int32();
|
||||
_dependency_order = scan.get_int32();
|
||||
}
|
||||
|
||||
_num_placements = scan.get_uint32();
|
||||
manager->read_pointers(scan, this, _num_placements);
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <typedWriteable.h>
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
class EggFile;
|
||||
class TexturePlacement;
|
||||
@ -44,8 +45,14 @@ public:
|
||||
void group_with(PaletteGroup *other);
|
||||
const PaletteGroups &get_groups() const;
|
||||
|
||||
void get_placements(vector<TexturePlacement *> &placements) const;
|
||||
void get_complete_placements(vector<TexturePlacement *> &placements) const;
|
||||
|
||||
void reset_dependency_level();
|
||||
void set_dependency_level(int level);
|
||||
bool set_dependency_order();
|
||||
int get_dependency_level() const;
|
||||
int get_dependency_order() const;
|
||||
|
||||
void increment_egg_count();
|
||||
int get_egg_count() const;
|
||||
@ -69,6 +76,7 @@ private:
|
||||
int _egg_count;
|
||||
PaletteGroups _dependent;
|
||||
int _dependency_level;
|
||||
int _dependency_order;
|
||||
|
||||
typedef set<TexturePlacement *> Placements;
|
||||
Placements _placements;
|
||||
|
@ -207,6 +207,31 @@ is_empty() const {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PaletteImage::count_utilization
|
||||
// Access: Public
|
||||
// Description: Returns the fraction of the PaletteImage that is
|
||||
// actually used by any textures. This is 1.0 if every
|
||||
// pixel in the PaletteImage is used, or 0.0 if none
|
||||
// are. Normally it will be somewhere in between.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
double PaletteImage::
|
||||
count_utilization() const {
|
||||
int used_pixels = 0;
|
||||
|
||||
Placements::const_iterator pi;
|
||||
for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
|
||||
TexturePlacement *placement = (*pi);
|
||||
|
||||
int texture_pixels = placement->get_x_size() * placement->get_y_size();
|
||||
used_pixels += texture_pixels;
|
||||
}
|
||||
|
||||
int total_pixels = get_x_size() * get_y_size();
|
||||
|
||||
return (double)used_pixels / (double)total_pixels;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PaletteImage::place
|
||||
// Access: Public
|
||||
|
@ -34,6 +34,7 @@ public:
|
||||
PalettePage *get_page() const;
|
||||
|
||||
bool is_empty() const;
|
||||
double count_utilization() const;
|
||||
|
||||
bool place(TexturePlacement *placement);
|
||||
void unplace(TexturePlacement *placement);
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "pal_string_utils.h"
|
||||
#include "paletteGroup.h"
|
||||
#include "filenameUnifier.h"
|
||||
#include "textureMemoryCounter.h"
|
||||
|
||||
#include <pnmImage.h>
|
||||
#include <pnmFileTypeRegistry.h>
|
||||
@ -18,6 +19,7 @@
|
||||
#include <datagramIterator.h>
|
||||
#include <bamReader.h>
|
||||
#include <bamWriter.h>
|
||||
#include <indent.h>
|
||||
|
||||
Palettizer *pal = (Palettizer *)NULL;
|
||||
|
||||
@ -26,9 +28,10 @@ Palettizer *pal = (Palettizer *)NULL;
|
||||
// allows us to easily update egg-palettize to write out additional
|
||||
// information to its pi file, without having it increment the bam
|
||||
// version number for all bam and boo files anywhere in the world.
|
||||
int Palettizer::_pi_version = 2;
|
||||
int Palettizer::_pi_version = 3;
|
||||
// Updated to version 1 on 12/11/00 to add _remap_char_uv.
|
||||
// Updated to version 2 on 12/19/00 to add TexturePlacement::_dest.
|
||||
// Updated to version 3 on 12/19/00 to add PaletteGroup::_dependency_order.
|
||||
|
||||
int Palettizer::_read_pi_version = 0;
|
||||
|
||||
@ -52,6 +55,18 @@ ostream &operator << (ostream &out, Palettizer::RemapUV remap) {
|
||||
return out << "**invalid**(" << (int)remap << ")";
|
||||
}
|
||||
|
||||
|
||||
// This STL function object is used in report_statistics(), below.
|
||||
class SortGroupsByDependencyOrder {
|
||||
public:
|
||||
bool operator ()(PaletteGroup *a, PaletteGroup *b) {
|
||||
if (a->get_dependency_order() != b->get_dependency_order()) {
|
||||
return a->get_dependency_order() < b->get_dependency_order();
|
||||
}
|
||||
return a->get_name() < b->get_name();
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Palettizer::Constructor
|
||||
// Access: Public
|
||||
@ -178,6 +193,63 @@ report_pi() const {
|
||||
cout << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Palettizer::report_statistics
|
||||
// Access: Public
|
||||
// Description: Output a report of the palettization effectiveness,
|
||||
// texture memory utilization, and so on.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Palettizer::
|
||||
report_statistics() const {
|
||||
// Sort the groups into order by dependency order, for the user's
|
||||
// convenience.
|
||||
vector<PaletteGroup *> sorted_groups;
|
||||
|
||||
Groups::const_iterator gi;
|
||||
for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
|
||||
sorted_groups.push_back((*gi).second);
|
||||
}
|
||||
|
||||
sort(sorted_groups.begin(), sorted_groups.end(),
|
||||
SortGroupsByDependencyOrder());
|
||||
|
||||
Placements overall_placements;
|
||||
|
||||
vector<PaletteGroup *>::const_iterator sgi;
|
||||
for (sgi = sorted_groups.begin();
|
||||
sgi != sorted_groups.end();
|
||||
++sgi) {
|
||||
PaletteGroup *group = (*sgi);
|
||||
|
||||
Placements placements;
|
||||
group->get_placements(placements);
|
||||
if (!placements.empty()) {
|
||||
group->get_placements(overall_placements);
|
||||
|
||||
cout << "\n" << group->get_name() << ", by itself:\n";
|
||||
compute_statistics(cout, 2, placements);
|
||||
|
||||
PaletteGroups complete;
|
||||
complete.make_complete(group->get_groups());
|
||||
|
||||
if (complete.size() > 1) {
|
||||
Placements complete_placements;
|
||||
group->get_complete_placements(complete_placements);
|
||||
if (complete_placements.size() != placements.size()) {
|
||||
cout << "\n" << group->get_name()
|
||||
<< ", with dependents (" << complete << "):\n";
|
||||
compute_statistics(cout, 2, complete_placements);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cout << "\nOverall:\n";
|
||||
compute_statistics(cout, 2, overall_placements);
|
||||
|
||||
cout << "\n";
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Palettizer::read_txa_file
|
||||
@ -209,12 +281,28 @@ read_txa_file(const Filename &txa_filename) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Compute the correct dependency level for each group. This will
|
||||
// help us when we assign the textures to their groups.
|
||||
// Compute the correct dependency level and order for each group.
|
||||
// This will help us when we assign the textures to their groups.
|
||||
for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
|
||||
PaletteGroup *group = (*gi).second;
|
||||
group->reset_dependency_level();
|
||||
}
|
||||
|
||||
for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
|
||||
PaletteGroup *group = (*gi).second;
|
||||
group->set_dependency_level(1);
|
||||
}
|
||||
|
||||
bool any_changed;
|
||||
do {
|
||||
any_changed = false;
|
||||
for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
|
||||
PaletteGroup *group = (*gi).second;
|
||||
if (group->set_dependency_order()) {
|
||||
any_changed = true;
|
||||
}
|
||||
}
|
||||
} while (any_changed);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -617,6 +705,17 @@ get_texture(const string &name) {
|
||||
return image;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Palettizer::yesno
|
||||
// Access: Private, Static
|
||||
// Description: A silly function to return "yes" or "no" based on a
|
||||
// bool flag for nicely formatted output.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const char *Palettizer::
|
||||
yesno(bool flag) {
|
||||
return flag ? "yes" : "no";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Palettizer::string_remap
|
||||
// Access: Public, Static
|
||||
@ -641,14 +740,24 @@ string_remap(const string &str) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Palettizer::yesno
|
||||
// Access: Private, Static
|
||||
// Description: A silly function to return "yes" or "no" based on a
|
||||
// bool flag for nicely formatted output.
|
||||
// Function: Palettizer::compute_statistics
|
||||
// Access: Private
|
||||
// Description: Determines how much memory, etc. is required by the
|
||||
// indicated set of texture placements, and reports this
|
||||
// to the indicated output stream.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const char *Palettizer::
|
||||
yesno(bool flag) {
|
||||
return flag ? "yes" : "no";
|
||||
void Palettizer::
|
||||
compute_statistics(ostream &out, int indent_level,
|
||||
const Palettizer::Placements &placements) const {
|
||||
TextureMemoryCounter counter;
|
||||
|
||||
Placements::const_iterator pi;
|
||||
for (pi = placements.begin(); pi != placements.end(); ++pi) {
|
||||
TexturePlacement *placement = (*pi);
|
||||
counter.add_placement(placement);
|
||||
}
|
||||
|
||||
counter.report(out, indent_level);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -20,6 +20,7 @@ class PNMFileType;
|
||||
class EggFile;
|
||||
class PaletteGroup;
|
||||
class TextureImage;
|
||||
class TexturePlacement;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : Palettizer
|
||||
@ -34,6 +35,8 @@ public:
|
||||
Palettizer();
|
||||
|
||||
void report_pi() const;
|
||||
void report_statistics() const;
|
||||
|
||||
void read_txa_file(const Filename &txa_filename);
|
||||
void all_params_set();
|
||||
void process_command_line_eggs(bool force_texture_read);
|
||||
@ -94,6 +97,10 @@ public:
|
||||
PNMFileType *_shadow_alpha_type;
|
||||
|
||||
private:
|
||||
typedef vector<TexturePlacement *> Placements;
|
||||
void compute_statistics(ostream &out, int indent_level,
|
||||
const Placements &placements) const;
|
||||
|
||||
typedef map<string, EggFile *> EggFiles;
|
||||
EggFiles _egg_files;
|
||||
|
||||
|
233
pandatool/src/egg-palettize/textureMemoryCounter.cxx
Normal file
233
pandatool/src/egg-palettize/textureMemoryCounter.cxx
Normal file
@ -0,0 +1,233 @@
|
||||
// Filename: textureMemoryCounter.cxx
|
||||
// Created by: drose (19Dec00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "textureMemoryCounter.h"
|
||||
#include "paletteImage.h"
|
||||
#include "textureImage.h"
|
||||
#include "destTextureImage.h"
|
||||
#include "omitReason.h"
|
||||
#include "texturePlacement.h"
|
||||
|
||||
#include <indent.h>
|
||||
#include <math.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextureMemoryCounter::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TextureMemoryCounter::
|
||||
TextureMemoryCounter() {
|
||||
reset();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextureMemoryCounter::reset
|
||||
// Access: Public
|
||||
// Description: Resets the count to zero.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TextureMemoryCounter::
|
||||
reset() {
|
||||
_num_textures = 0;
|
||||
_num_unplaced = 0;
|
||||
_num_placed = 0;
|
||||
_num_palettes = 0;
|
||||
|
||||
_bytes = 0;
|
||||
_unused_bytes = 0;
|
||||
_duplicate_bytes = 0;
|
||||
_textures.clear();
|
||||
_palettes.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextureMemoryCounter::add_placement
|
||||
// Access: Public
|
||||
// Description: Adds the indicated TexturePlacement to the counter.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TextureMemoryCounter::
|
||||
add_placement(TexturePlacement *placement) {
|
||||
TextureImage *texture = placement->get_texture();
|
||||
nassertv(texture != (TextureImage *)NULL);
|
||||
|
||||
if (placement->get_omit_reason() == OR_none) {
|
||||
PaletteImage *image = placement->get_image();
|
||||
nassertv(image != (PaletteImage *)NULL);
|
||||
add_palette(image);
|
||||
|
||||
int bytes = count_bytes(image, placement->get_placed_x_size(),
|
||||
placement->get_placed_y_size());
|
||||
add_texture(texture, bytes);
|
||||
_num_placed++;
|
||||
|
||||
} else {
|
||||
DestTextureImage *dest = placement->get_dest();
|
||||
nassertv(dest != (DestTextureImage *)NULL);
|
||||
|
||||
int bytes = count_bytes(dest);
|
||||
add_texture(texture, bytes);
|
||||
|
||||
_bytes += bytes;
|
||||
_num_unplaced++;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextureMemoryCounter::report
|
||||
// Access: Public
|
||||
// Description: Reports the measured texture memory usage.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TextureMemoryCounter::
|
||||
report(ostream &out, int indent_level) {
|
||||
indent(out, indent_level)
|
||||
<< _num_placed << " of " << _num_textures << " textures appear on "
|
||||
<< _num_palettes << " palette images with " << _num_unplaced
|
||||
<< " unplaced.\n";
|
||||
|
||||
indent(out, indent_level)
|
||||
<< (_bytes + 512) / 1024 << "k estimated texture memory required.\n";
|
||||
|
||||
if (_bytes != 0) {
|
||||
indent(out, indent_level + 2)
|
||||
<< "Of this, "
|
||||
<< floor(1000.0 * (double)_unused_bytes / (double)_bytes + 0.5) / 10.0
|
||||
<< "% is wasted because of unused palette space.\n";
|
||||
|
||||
if (_duplicate_bytes != 0) {
|
||||
indent(out, indent_level + 2)
|
||||
<< "And " << 100.0 * (double)_duplicate_bytes / (double)_bytes
|
||||
<< "% is wasted because of a texture appearing in multiple places.\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextureMemoryCounter::add_palette
|
||||
// Access: Private
|
||||
// Description: Adds the indicated PaletteImage to the count. If
|
||||
// this is called twice for a given PaletteImage it does
|
||||
// nothing.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TextureMemoryCounter::
|
||||
add_palette(PaletteImage *image) {
|
||||
bool inserted = _palettes.insert(image).second;
|
||||
if (!inserted) {
|
||||
// We've already added this palette image.
|
||||
return;
|
||||
}
|
||||
|
||||
int bytes = count_bytes(image);
|
||||
double wasted = 1.0 - image->count_utilization();
|
||||
|
||||
_bytes += bytes;
|
||||
_unused_bytes += (int)(wasted * bytes);
|
||||
_num_palettes++;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextureMemoryCounter::add_texture
|
||||
// Access: Private
|
||||
// Description: Adds the given TextureImage to the counter. If the
|
||||
// texture image has already been added, this counts the
|
||||
// smaller of the two as duplicate bytes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TextureMemoryCounter::
|
||||
add_texture(TextureImage *texture, int bytes) {
|
||||
pair<Textures::iterator, bool> result;
|
||||
result = _textures.insert(Textures::value_type(texture, bytes));
|
||||
if (result.second) {
|
||||
// If it was inserted, no problem--no duplicates.
|
||||
_num_textures++;
|
||||
return;
|
||||
}
|
||||
|
||||
// If it was not inserted, we have a duplicate.
|
||||
Textures::iterator ti = result.first;
|
||||
|
||||
_duplicate_bytes += min(bytes, (*ti).second);
|
||||
(*ti).second = max(bytes, (*ti).second);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextureMemoryCounter::count_bytes
|
||||
// Access: Private
|
||||
// Description: Attempts to estimate the number of bytes the given
|
||||
// image file will use in texture memory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int TextureMemoryCounter::
|
||||
count_bytes(ImageFile *image) {
|
||||
return count_bytes(image, image->get_x_size(), image->get_y_size());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextureMemoryCounter::count_bytes
|
||||
// Access: Private
|
||||
// Description: Attempts to estimate the number of bytes the given
|
||||
// image file will use in texture memory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int TextureMemoryCounter::
|
||||
count_bytes(ImageFile *image, int x_size, int y_size) {
|
||||
int pixels = x_size * y_size;
|
||||
|
||||
// Try to guess the number of bytes per pixel this texture will
|
||||
// consume in texture memory, based on its requested format. This
|
||||
// is only a loose guess, because this depends of course on the
|
||||
// pecularities of the particular rendering engine.
|
||||
int bpp = 0;
|
||||
switch (image->get_properties()._format) {
|
||||
case EggTexture::F_rgba12:
|
||||
bpp = 6;
|
||||
break;
|
||||
|
||||
case EggTexture::F_rgba:
|
||||
case EggTexture::F_rgbm:
|
||||
case EggTexture::F_rgba8:
|
||||
bpp = 4;
|
||||
break;
|
||||
|
||||
case EggTexture::F_rgb:
|
||||
case EggTexture::F_rgb12:
|
||||
bpp = 3;
|
||||
break;
|
||||
|
||||
case EggTexture::F_rgba4:
|
||||
case EggTexture::F_rgba5:
|
||||
case EggTexture::F_rgb8:
|
||||
case EggTexture::F_rgb5:
|
||||
case EggTexture::F_luminance_alpha:
|
||||
case EggTexture::F_luminance_alphamask:
|
||||
bpp = 2;
|
||||
break;
|
||||
|
||||
case EggTexture::F_rgb332:
|
||||
case EggTexture::F_red:
|
||||
case EggTexture::F_green:
|
||||
case EggTexture::F_blue:
|
||||
case EggTexture::F_alpha:
|
||||
case EggTexture::F_luminance:
|
||||
bpp = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
bpp = image->get_num_channels();
|
||||
}
|
||||
|
||||
int bytes = pixels * bpp;
|
||||
|
||||
// If we're mipmapping, it's worth 1/3 more bytes.
|
||||
switch (image->get_properties()._magfilter) {
|
||||
case EggTexture::FT_nearest_mipmap_nearest:
|
||||
case EggTexture::FT_linear_mipmap_nearest:
|
||||
case EggTexture::FT_nearest_mipmap_linear:
|
||||
case EggTexture::FT_linear_mipmap_linear:
|
||||
bytes = (bytes * 4) / 3;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
58
pandatool/src/egg-palettize/textureMemoryCounter.h
Normal file
58
pandatool/src/egg-palettize/textureMemoryCounter.h
Normal file
@ -0,0 +1,58 @@
|
||||
// Filename: textureMemoryCounter.h
|
||||
// Created by: drose (19Dec00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TEXTUREMEMORYCOUNTER_H
|
||||
#define TEXTUREMEMORYCOUNTER_H
|
||||
|
||||
#include <pandatoolbase.h>
|
||||
|
||||
class ImageFile;
|
||||
class PaletteImage;
|
||||
class TextureImage;
|
||||
class DestTextureImage;
|
||||
class TexturePlacement;
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : TextureMemoryCounter
|
||||
// Description : This class is used to gather statistics on texture
|
||||
// memory usage, etc. It adds up the total texture
|
||||
// memory required by a number of image files, and
|
||||
// reports it at the end.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class TextureMemoryCounter {
|
||||
public:
|
||||
TextureMemoryCounter();
|
||||
|
||||
void reset();
|
||||
void add_placement(TexturePlacement *placement);
|
||||
|
||||
void report(ostream &out, int indent_level);
|
||||
|
||||
private:
|
||||
void add_palette(PaletteImage *image);
|
||||
void add_texture(TextureImage *texture, int bytes);
|
||||
int count_bytes(ImageFile *image);
|
||||
int count_bytes(ImageFile *image, int x_size, int y_size);
|
||||
|
||||
int _num_textures;
|
||||
int _num_placed;
|
||||
int _num_unplaced;
|
||||
int _num_palettes;
|
||||
|
||||
int _bytes;
|
||||
int _unused_bytes;
|
||||
int _duplicate_bytes;
|
||||
|
||||
typedef map<TextureImage *, int> Textures;
|
||||
Textures _textures;
|
||||
|
||||
typedef set<PaletteImage *> Palettes;
|
||||
Palettes _palettes;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user