Panda3D
Loading...
Searching...
No Matches
textureMemoryCounter.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file textureMemoryCounter.cxx
10 * @author drose
11 * @date 2000-12-19
12 */
13
15#include "paletteImage.h"
16#include "textureImage.h"
17#include "destTextureImage.h"
18#include "omitReason.h"
19#include "texturePlacement.h"
20
21#include "indent.h"
22#include <math.h>
23
24/**
25 *
26 */
27TextureMemoryCounter::
28TextureMemoryCounter() {
29 reset();
30}
31
32/**
33 * Resets the count to zero.
34 */
36reset() {
37 _num_textures = 0;
38 _num_unplaced = 0;
39 _num_placed = 0;
40 _num_palettes = 0;
41
42 _bytes = 0;
43 _unused_bytes = 0;
44 _duplicate_bytes = 0;
45 _coverage_bytes = 0;
46 _textures.clear();
47 _palettes.clear();
48}
49
50/**
51 * Adds the indicated TexturePlacement to the counter.
52 */
55 TextureImage *texture = placement->get_texture();
56 nassertv(texture != nullptr);
57
58 if (placement->get_omit_reason() == OR_none) {
59 PaletteImage *image = placement->get_image();
60 nassertv(image != nullptr);
61 add_palette(image);
62
63 int bytes = count_bytes(image, placement->get_placed_x_size(),
64 placement->get_placed_y_size());
65 add_texture(texture, bytes);
66 _num_placed++;
67
68 } else {
69 DestTextureImage *dest = placement->get_dest();
70 if (dest != nullptr) {
71 int bytes = count_bytes(dest);
72 add_texture(texture, bytes);
73
74 _bytes += bytes;
75 _num_unplaced++;
76 }
77 }
78}
79
80/**
81 * Reports the measured texture memory usage.
82 */
84report(std::ostream &out, int indent_level) {
85 indent(out, indent_level)
86 << _num_placed << " of " << _num_textures << " textures appear on "
87 << _num_palettes << " palette images with " << _num_unplaced
88 << " unplaced.\n";
89
90 indent(out, indent_level)
91 << (_bytes + 512) / 1024 << "k estimated texture memory required.\n";
92
93 if (_bytes != 0) {
94 if (_unused_bytes != 0) {
95 indent(out, indent_level + 2);
96 format_memory_fraction(out, _unused_bytes, _bytes)
97 << " is wasted because of unused palette space.\n";
98 }
99
100 if (_coverage_bytes > 0) {
101 indent(out, indent_level + 2);
102 format_memory_fraction(out, _coverage_bytes, _bytes)
103 << " is wasted for repeating textures and margins.\n";
104
105 } else if (_coverage_bytes < 0) {
106 indent(out, indent_level + 2);
107 format_memory_fraction(out, -_coverage_bytes, _bytes)
108 << " is *saved* for palettizing partial textures.\n";
109 }
110
111 if (_duplicate_bytes != 0) {
112 indent(out, indent_level + 2);
113 format_memory_fraction(out, _duplicate_bytes, _bytes)
114 << " is wasted because of a texture appearing in multiple groups.\n";
115 }
116 }
117}
118
119/**
120 * Writes to the indicated ostream an indication of the fraction of the total
121 * memory usage that is represented by fraction_bytes.
122 */
123std::ostream &TextureMemoryCounter::
124format_memory_fraction(std::ostream &out, int fraction_bytes, int palette_bytes) {
125 out << floor(1000.0 * (double)fraction_bytes / (double)palette_bytes + 0.5) / 10.0
126 << "% (" << (fraction_bytes + 512) / 1024 << "k)";
127 return out;
128}
129
130/**
131 * Adds the indicated PaletteImage to the count. If this is called twice for
132 * a given PaletteImage it does nothing.
133 */
134void TextureMemoryCounter::
135add_palette(PaletteImage *image) {
136 bool inserted = _palettes.insert(image).second;
137 if (!inserted) {
138 // We've already added this palette image.
139 return;
140 }
141
142 int bytes = count_bytes(image);
143 double unused = 1.0 - image->count_utilization();
144 double coverage = image->count_coverage();
145
146 _bytes += bytes;
147 _unused_bytes += (int)(unused * bytes);
148 _coverage_bytes += (int)(coverage * bytes);
149
150 _num_palettes++;
151}
152
153/**
154 * Adds the given TextureImage to the counter. If the texture image has
155 * already been added, this counts the smaller of the two as duplicate bytes.
156 */
157void TextureMemoryCounter::
158add_texture(TextureImage *texture, int bytes) {
159 std::pair<Textures::iterator, bool> result;
160 result = _textures.insert(Textures::value_type(texture, bytes));
161 if (result.second) {
162 // If it was inserted, no problem--no duplicates.
163 _num_textures++;
164 return;
165 }
166
167 // If it was not inserted, we have a duplicate.
168 Textures::iterator ti = result.first;
169
170 _duplicate_bytes += std::min(bytes, (*ti).second);
171 (*ti).second = std::max(bytes, (*ti).second);
172}
173
174/**
175 * Attempts to estimate the number of bytes the given image file will use in
176 * texture memory.
177 */
178int TextureMemoryCounter::
179count_bytes(ImageFile *image) {
180 return count_bytes(image, image->get_x_size(), image->get_y_size());
181}
182
183/**
184 * Attempts to estimate the number of bytes the given image file will use in
185 * texture memory.
186 */
187int TextureMemoryCounter::
188count_bytes(ImageFile *image, int x_size, int y_size) {
189 int pixels = x_size * y_size;
190
191 // Try to guess the number of bytes per pixel this texture will consume in
192 // texture memory, based on its requested format. This is only a loose
193 // guess, because this depends of course on the pecularities of the
194 // particular rendering engine.
195 int bpp = 0;
196 switch (image->get_properties()._format) {
197 case EggTexture::F_rgba12:
198 bpp = 6;
199 break;
200
201 case EggTexture::F_rgba:
202 case EggTexture::F_rgbm:
203 case EggTexture::F_rgba8:
204 bpp = 4;
205 break;
206
207 case EggTexture::F_rgb:
208 case EggTexture::F_rgb12:
209 bpp = 3;
210 break;
211
212 case EggTexture::F_rgba4:
213 case EggTexture::F_rgba5:
214 case EggTexture::F_rgb8:
215 case EggTexture::F_rgb5:
216 case EggTexture::F_luminance_alpha:
217 case EggTexture::F_luminance_alphamask:
218 bpp = 2;
219 break;
220
221 case EggTexture::F_rgb332:
222 case EggTexture::F_red:
223 case EggTexture::F_green:
224 case EggTexture::F_blue:
225 case EggTexture::F_alpha:
226 case EggTexture::F_luminance:
227 bpp = 1;
228 break;
229
230 default:
231 bpp = image->get_num_channels();
232 }
233
234 int bytes = pixels * bpp;
235
236 // If we're mipmapping, it's worth 13 more bytes.
237 switch (image->get_properties()._minfilter) {
238 case EggTexture::FT_nearest_mipmap_nearest:
239 case EggTexture::FT_linear_mipmap_nearest:
240 case EggTexture::FT_nearest_mipmap_linear:
241 case EggTexture::FT_linear_mipmap_linear:
242 bytes = (bytes * 4) / 3;
243 break;
244
245 default:
246 break;
247 }
248
249 return bytes;
250}
This represents a texture filename as it has been resized and copied to the map directory (e....
This is the base class of both TextureImage and PaletteImage.
Definition imageFile.h:33
int get_num_channels() const
Returns the number of channels of the image.
int get_x_size() const
Returns the size of the image file in pixels in the X direction.
Definition imageFile.cxx:82
const TextureProperties & get_properties() const
Returns the grouping properties of the image.
int get_y_size() const
Returns the size of the image file in pixels in the Y direction.
Definition imageFile.cxx:92
This is a single palette image, one of several within a PalettePage, which is in turn one of several ...
double count_utilization() const
Returns the fraction of the PaletteImage that is actually used by any textures.
double count_coverage() const
Returns the a weighted average of the fraction of coverage represented by all of the textures placed ...
This represents a single source texture that is referenced by one or more egg files.
void add_placement(TexturePlacement *placement)
Adds the indicated TexturePlacement to the counter.
void report(std::ostream &out, int indent_level)
Reports the measured texture memory usage.
void reset()
Resets the count to zero.
This corresponds to a particular assignment of a TextureImage with a PaletteGroup,...
OmitReason get_omit_reason() const
Returns the reason the texture has been omitted from a palette image, or OR_none if it has not.
DestTextureImage * get_dest() const
Returns the DestTextureImage that corresponds to this texture as it was copied to the install directo...
int get_placed_x_size() const
Returns the size in the X dimension, in pixels, of the texture image as it has been placed within the...
PaletteImage * get_image() const
Returns the particular PaletteImage on which the texture has been placed.
TextureImage * get_texture() const
Returns the texture that this placement represents.
int get_placed_y_size() const
Returns the size in the Y dimension, in pixels, of the texture image as it has been placed within the...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition indent.cxx:20
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.