16 #include "texturePool.h"
17 #include "config_gobj.h"
18 #include "config_util.h"
19 #include "config_express.h"
20 #include "string_utils.h"
21 #include "virtualFileSystem.h"
23 #include "bamCacheRecord.h"
24 #include "pnmFileTypeRegistry.h"
25 #include "texturePoolFilter.h"
26 #include "configVariableList.h"
28 #include "mutexHolder.h"
59 extract_words(downcase(extensions), words);
61 vector_string::const_iterator wi;
62 for (wi = words.begin(); wi != words.end(); ++wi) {
63 _type_registry[*wi] = func;
78 <<
"Registering Texture filter " << *filter <<
"\n";
79 _filter_registry.push_back(filter);
94 string c = downcase(extension);
95 TypeRegistry::const_iterator ti;
96 ti = _type_registry.find(c);
97 if (ti != _type_registry.end()) {
106 ((
TexturePool *)
this)->_type_registry[c] = Texture::make_texture;
107 return Texture::make_texture;
127 pnm_reg->
write(out, indent_level);
131 TypeRegistry::const_iterator ti;
132 for (ti = _type_registry.begin(); ti != _type_registry.end(); ++ti) {
133 string extension = (*ti).first;
134 MakeTextureFunc *func = (*ti).second;
138 string name = tex->get_type().get_name();
139 indent(out, indent_level) << name;
140 indent(out, max(30 - (
int)name.length(), 0))
141 <<
" ." << extension <<
"\n";
160 _global_ptr->load_filters();
175 (
"fake-texture-image",
"",
176 PRC_DESC(
"Set this to enable a speedy-load mode in which you don't care "
177 "what the world looks like, you just want it to load in minimal "
178 "time. This causes all texture loads via the TexturePool to use "
179 "the same texture file, which will presumably only be loaded "
181 _fake_texture_image = fake_texture_image;
190 ns_has_texture(
const Filename &orig_filename) {
194 resolve_filename(filename, orig_filename,
false,
LoaderOptions());
196 Textures::const_iterator ti;
197 ti = _textures.find(filename);
198 if (ti != _textures.end()) {
212 ns_load_texture(
const Filename &orig_filename,
int primary_file_num_channels,
218 resolve_filename(filename, orig_filename, read_mipmaps, options);
219 Textures::const_iterator ti;
220 ti = _textures.find(filename);
221 if (ti != _textures.end()) {
232 bool store_record = false;
235 tex = pre_load(orig_filename,
Filename(), primary_file_num_channels, 0,
236 read_mipmaps, options);
239 bool compressed_cache_record = false;
240 try_load_cache(tex, cache, filename, record, compressed_cache_record,
247 <<
"Loading texture " << filename <<
"\n";
249 string ext = downcase(filename.get_extension());
250 if (ext ==
"txo" || ext ==
"bam") {
256 filename.set_binary();
261 <<
"Could not find " << filename <<
"\n";
265 if (gobj_cat.is_debug()) {
267 <<
"Reading texture object " << filename <<
"\n";
271 tex = Texture::make_from_txo(*in, filename);
277 tex->set_fullpath(filename);
278 tex->clear_alpha_fullpath();
279 tex->set_keep_ram_image(
false);
283 tex = ns_make_texture(ext);
284 if (!tex->read(filename, Filename(), primary_file_num_channels, 0,
285 0, 0,
false, read_mipmaps, record, options)) {
287 report_texture_unreadable(filename);
292 if (options.get_texture_flags() & LoaderOptions::TF_preload_simple) {
293 tex->generate_simple_ram_image();
299 if (cache->get_cache_compressed_textures() && tex->has_compression()) {
301 bool needs_driver_compression =
true;
303 bool needs_driver_compression = driver_compress_textures;
304 #endif // HAVE_SQUISH
305 if (needs_driver_compression) {
308 store_record =
false;
309 if (!compressed_cache_record) {
310 tex->set_post_load_store_cache(
true);
314 }
else if (!cache->get_cache_textures()) {
316 store_record =
false;
320 nassertr(tex != (
Texture *)NULL, NULL);
321 tex->set_filename(orig_filename);
322 tex->set_fullpath(filename);
323 tex->_texture_pool_key = filename;
330 Textures::const_iterator ti;
331 ti = _textures.find(filename);
332 if (ti != _textures.end()) {
339 _textures[filename] = tex;
344 record->set_data(tex, tex);
345 cache->
store(record);
348 if (!(options.get_texture_flags() & LoaderOptions::TF_preload)) {
356 tex = post_load(tex);
367 ns_load_texture(
const Filename &orig_filename,
368 const Filename &orig_alpha_filename,
369 int primary_file_num_channels,
370 int alpha_file_channel,
372 if (!_fake_texture_image.empty()) {
373 return ns_load_texture(_fake_texture_image, primary_file_num_channels,
374 read_mipmaps, options);
378 Filename alpha_filename;
382 resolve_filename(filename, orig_filename, read_mipmaps, options);
383 resolve_filename(alpha_filename, orig_alpha_filename, read_mipmaps, options);
385 Textures::const_iterator ti;
386 ti = _textures.find(filename);
387 if (ti != _textures.end()) {
397 bool store_record = false;
400 tex = pre_load(orig_filename, alpha_filename, primary_file_num_channels,
401 alpha_file_channel, read_mipmaps, options);
404 bool compressed_cache_record = false;
405 try_load_cache(tex, cache, filename, record, compressed_cache_record,
412 <<
"Loading texture " << filename <<
" and alpha component "
413 << alpha_filename << endl;
414 tex = ns_make_texture(filename.get_extension());
415 if (!tex->read(filename, alpha_filename, primary_file_num_channels,
416 alpha_file_channel, 0, 0,
false, read_mipmaps, NULL,
419 report_texture_unreadable(filename);
423 if (options.get_texture_flags() & LoaderOptions::TF_preload_simple) {
424 tex->generate_simple_ram_image();
430 if (cache->get_cache_compressed_textures() && tex->has_compression()) {
432 bool needs_driver_compression =
true;
434 bool needs_driver_compression = driver_compress_textures;
435 #endif // HAVE_SQUISH
436 if (needs_driver_compression) {
439 store_record =
false;
440 if (!compressed_cache_record) {
441 tex->set_post_load_store_cache(
true);
445 }
else if (!cache->get_cache_textures()) {
447 store_record =
false;
451 nassertr(tex != (
Texture *)NULL, NULL);
452 tex->set_filename(orig_filename);
453 tex->set_fullpath(filename);
454 tex->set_alpha_filename(orig_alpha_filename);
455 tex->set_alpha_fullpath(alpha_filename);
456 tex->_texture_pool_key = filename;
462 Textures::const_iterator ti;
463 ti = _textures.find(filename);
464 if (ti != _textures.end()) {
471 _textures[filename] = tex;
476 record->set_data(tex, tex);
477 cache->
store(record);
480 if (!(options.get_texture_flags() & LoaderOptions::TF_preload)) {
488 tex = post_load(tex);
499 ns_load_3d_texture(
const Filename &filename_pattern,
501 Filename orig_filename(filename_pattern);
502 orig_filename.set_pattern(
true);
507 resolve_filename(filename, orig_filename, read_mipmaps, options);
509 Textures::const_iterator ti;
510 ti = _textures.find(filename);
511 if (ti != _textures.end()) {
512 if ((*ti).second->get_texture_type() == Texture::TT_3d_texture) {
521 bool store_record = false;
524 bool compressed_cache_record = false;
525 try_load_cache(tex, cache, filename, record, compressed_cache_record,
533 <<
"Loading 3-d texture " << filename <<
"\n";
534 tex = ns_make_texture(filename.get_extension());
535 tex->setup_3d_texture();
536 if (!tex->read(filename, 0, 0,
true, read_mipmaps, options)) {
538 report_texture_unreadable(filename);
544 if (cache->get_cache_compressed_textures() && tex->has_compression()) {
546 bool needs_driver_compression =
true;
548 bool needs_driver_compression = driver_compress_textures;
549 #endif // HAVE_SQUISH
550 if (needs_driver_compression) {
553 store_record =
false;
554 if (!compressed_cache_record) {
555 tex->set_post_load_store_cache(
true);
559 }
else if (!cache->get_cache_textures()) {
561 store_record =
false;
565 nassertr(tex != (
Texture *)NULL, NULL);
566 tex->set_filename(filename_pattern);
567 tex->set_fullpath(filename);
568 tex->_texture_pool_key = filename;
574 Textures::const_iterator ti;
575 ti = _textures.find(filename);
576 if (ti != _textures.end()) {
577 if ((*ti).second->get_texture_type() == Texture::TT_3d_texture) {
583 _textures[filename] = tex;
586 if (store_record && tex->is_cacheable()) {
588 record->set_data(tex, tex);
589 cache->store(record);
592 nassertr(!tex->get_fullpath().empty(), tex);
602 ns_load_2d_texture_array(
const Filename &filename_pattern,
604 Filename orig_filename(filename_pattern);
605 orig_filename.set_pattern(
true);
608 Filename unique_filename;
611 resolve_filename(filename, orig_filename, read_mipmaps, options);
613 unique_filename = filename +
".2DARRAY";
615 Textures::const_iterator ti;
616 ti = _textures.find(unique_filename);
617 if (ti != _textures.end()) {
618 if ((*ti).second->get_texture_type() == Texture::TT_2d_texture_array) {
627 bool store_record = false;
630 bool compressed_cache_record = false;
631 try_load_cache(tex, cache, filename, record, compressed_cache_record,
639 <<
"Loading 2-d texture array " << filename <<
"\n";
640 tex = ns_make_texture(filename.get_extension());
641 tex->setup_2d_texture_array();
642 if (!tex->read(filename, 0, 0,
true, read_mipmaps, options)) {
644 report_texture_unreadable(filename);
650 if (cache->get_cache_compressed_textures() && tex->has_compression()) {
652 bool needs_driver_compression =
true;
654 bool needs_driver_compression = driver_compress_textures;
655 #endif // HAVE_SQUISH
656 if (needs_driver_compression) {
659 store_record =
false;
660 if (!compressed_cache_record) {
661 tex->set_post_load_store_cache(
true);
665 }
else if (!cache->get_cache_textures()) {
667 store_record =
false;
671 nassertr(tex != (
Texture *)NULL, NULL);
672 tex->set_filename(filename_pattern);
673 tex->set_fullpath(filename);
674 tex->_texture_pool_key = filename;
680 Textures::const_iterator ti;
681 ti = _textures.find(unique_filename);
682 if (ti != _textures.end()) {
683 if ((*ti).second->get_texture_type() == Texture::TT_2d_texture_array) {
689 _textures[unique_filename] = tex;
692 if (store_record && tex->is_cacheable()) {
694 record->set_data(tex, tex);
695 cache->store(record);
698 nassertr(!tex->get_fullpath().empty(), tex);
708 ns_load_cube_map(
const Filename &filename_pattern,
bool read_mipmaps,
710 Filename orig_filename(filename_pattern);
711 orig_filename.set_pattern(
true);
716 resolve_filename(filename, orig_filename, read_mipmaps, options);
718 Textures::const_iterator ti;
719 ti = _textures.find(filename);
720 if (ti != _textures.end()) {
728 bool store_record = false;
731 bool compressed_cache_record = false;
732 try_load_cache(tex, cache, filename, record, compressed_cache_record,
740 <<
"Loading cube map texture " << filename <<
"\n";
741 tex = ns_make_texture(filename.get_extension());
742 tex->setup_cube_map();
743 if (!tex->read(filename, 0, 0,
true, read_mipmaps, options)) {
745 report_texture_unreadable(filename);
751 if (cache->get_cache_compressed_textures() && tex->has_compression()) {
753 bool needs_driver_compression =
true;
755 bool needs_driver_compression = driver_compress_textures;
756 #endif // HAVE_SQUISH
757 if (needs_driver_compression) {
760 store_record =
false;
761 if (!compressed_cache_record) {
762 tex->set_post_load_store_cache(
true);
766 }
else if (!cache->get_cache_textures()) {
768 store_record =
false;
772 nassertr(tex != (
Texture *)NULL, NULL);
773 tex->set_filename(filename_pattern);
774 tex->set_fullpath(filename);
775 tex->_texture_pool_key = filename;
781 Textures::const_iterator ti;
782 ti = _textures.find(filename);
783 if (ti != _textures.end()) {
788 _textures[filename] = tex;
791 if (store_record && tex->is_cacheable()) {
793 record->set_data(tex, tex);
794 cache->store(record);
797 nassertr(!tex->get_fullpath().empty(), tex);
807 ns_get_normalization_cube_map(
int size) {
810 if (_normalization_cube_map == (
Texture *)NULL) {
811 _normalization_cube_map =
new Texture(
"normalization_cube_map");
813 if (_normalization_cube_map->get_x_size() < size ||
814 _normalization_cube_map->get_texture_type() != Texture::TT_cube_map) {
815 _normalization_cube_map->generate_normalization_cube_map(size);
818 return _normalization_cube_map;
827 ns_get_alpha_scale_map() {
830 if (_alpha_scale_map == (
Texture *)NULL) {
831 _alpha_scale_map =
new Texture(
"alpha_scale_map");
832 _alpha_scale_map->generate_alpha_scale_map();
835 return _alpha_scale_map;
848 if (!tex->_texture_pool_key.empty()) {
849 ns_release_texture(tex);
852 if (filename.empty()) {
853 gobj_cat.error() <<
"Attempt to call add_texture() on an unnamed texture.\n";
857 tex->_texture_pool_key = filename;
858 _textures[filename] = tex;
868 ns_release_texture(
Texture *tex) {
871 if (!tex->_texture_pool_key.empty()) {
872 Textures::iterator ti;
873 ti = _textures.find(tex->_texture_pool_key);
874 if (ti != _textures.end() && (*ti).second == tex) {
877 tex->_texture_pool_key = string();
881 _relpath_lookup.clear();
890 ns_release_all_textures() {
893 Textures::iterator ti;
894 for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
896 tex->_texture_pool_key = string();
900 _normalization_cube_map = NULL;
903 _relpath_lookup.clear();
912 ns_garbage_collect() {
915 int num_released = 0;
918 Textures::iterator ti;
919 for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
922 if (gobj_cat.is_debug()) {
924 <<
"Releasing " << (*ti).first <<
"\n";
927 tex->_texture_pool_key = string();
929 new_set.insert(new_set.end(), *ti);
933 _textures.swap(new_set);
935 if (_normalization_cube_map != (
Texture *)NULL &&
936 _normalization_cube_map->get_ref_count() == 1) {
937 if (gobj_cat.is_debug()) {
939 <<
"Releasing normalization cube map\n";
942 _normalization_cube_map = NULL;
954 ns_list_contents(ostream &out)
const {
959 Textures::const_iterator ti;
961 out <<
"texture pool contents:\n";
965 for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
967 out << (*ti).first <<
"\n";
974 nassertv(tex->_texture_pool_key == (*ti).first);
979 out <<
"total number of textures: " << _textures.size() <<
"\n";
980 out <<
"texture pool ram : " << total_ram_size <<
"\n";
981 out <<
"texture pool size: " << total_size <<
"\n";
982 out <<
"texture pool size - texture pool ram: " << total_size - total_ram_size <<
"\n";
991 ns_find_texture(
const string &name)
const {
995 Textures::const_iterator ti;
996 for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
998 if (glob.matches(tex->get_name())) {
1012 ns_find_all_textures(
const string &name)
const {
1017 Textures::const_iterator ti;
1018 for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
1020 if (glob.matches(tex->get_name())) {
1037 ns_make_texture(const
string &extension)
const {
1057 resolve_filename(Filename &new_filename,
const Filename &orig_filename,
1059 if (!_fake_texture_image.empty()) {
1060 new_filename = _fake_texture_image;
1064 RelpathLookup::iterator rpi = _relpath_lookup.find(orig_filename);
1065 if (rpi != _relpath_lookup.end()) {
1066 new_filename = (*rpi).second;
1070 new_filename = orig_filename;
1071 if (read_mipmaps || (options.get_texture_flags() & LoaderOptions::TF_multiview)) {
1078 _relpath_lookup[orig_filename] = new_filename;
1087 try_load_cache(PT(
Texture) &tex,
BamCache *cache,
const Filename &filename,
1101 PT(
Texture) dummy = ns_make_texture(ext);
1105 record = cache->lookup(filename, "txo");
1116 if (gobj_cat.is_debug()) {
1118 <<
"Not caching uncompressed texture " << *tex <<
"\n";
1129 if (gobj_cat.is_debug()) {
1131 <<
"Cached texture " << *tex <<
" has size "
1133 <<
" instead of " << x_size <<
" x " << y_size
1134 <<
"; dropping cache.\n";
1141 if (gobj_cat.is_debug()) {
1143 <<
"Cached texture " << *tex
1144 <<
" is compressed in cache; dropping cache.\n";
1150 <<
"Texture " << filename <<
" found in disk cache.\n";
1151 if ((options.get_texture_flags() & LoaderOptions::TF_preload_simple) &&
1155 if (!(options.get_texture_flags() & LoaderOptions::TF_preload)) {
1161 if (tex->consider_auto_process_ram_image(tex->
uses_mipmaps(),
true)) {
1163 if (!was_compressed && is_compressed &&
1170 cache->
store(record);
1171 compressed_cache_record =
true;
1182 if (gobj_cat.is_debug()) {
1184 <<
"Not caching uncompressed texture\n";
1201 report_texture_unreadable(
const Filename &filename)
const {
1203 bool has_hash = (filename.
get_fullpath().find(
'#') != string::npos);
1204 if (!has_hash && !vfs->
exists(filename)) {
1210 <<
"Unable to find texture \"" << filename <<
"\""
1211 <<
" on model-path " << get_model_path() <<
"\n";
1216 <<
"Texture \"" << filename <<
"\" does not exist.\n";
1223 <<
"Texture \"" << filename <<
"\" exists but cannot be read.\n";
1228 <<
"Texture \"" << filename <<
"\" cannot be read.\n";
1233 if (func == (MakeTextureFunc *)NULL) {
1236 <<
"\" is unknown. Supported texture types:\n";
1251 pre_load(const Filename &orig_filename, const Filename &orig_alpha_filename,
1252 int primary_file_num_channels,
int alpha_file_channel,
1258 FilterRegistry::iterator fi;
1259 for (fi = _filter_registry.begin();
1260 fi != _filter_registry.end();
1262 tex = (*fi)->pre_load(orig_filename, orig_alpha_filename,
1263 primary_file_num_channels, alpha_file_channel,
1264 read_mipmaps, options);
1284 FilterRegistry::iterator fi;
1285 for (fi = _filter_registry.begin();
1286 fi != _filter_registry.end();
1288 result = (*fi)->post_load(result);
1305 PRC_DESC(
"Names one or more external libraries that should be loaded for the "
1306 "purposes of performing texture filtering. This variable may be repeated several "
1307 "times. As in load-display, the actual library filename is derived by "
1308 "prefixing 'lib' to the specified name."));
1310 int num_aux = texture_filter.get_num_unique_values();
1311 for (
int i = 0; i < num_aux; i++) {
1312 string name = texture_filter.get_unique_value(i);
1314 Filename dlname = Filename::dso_filename(
"lib" + name +
".so");
1316 <<
"loading texture filter: " << dlname.
to_os_specific() << endl;
1317 void *tmp = load_dso(get_plugin_path().get_value(), dlname);
1318 if (tmp == (
void *)NULL) {
1320 <<
"Unable to load: " << load_dso_error() << endl;
void set_data(TypedWritable *ptr, ReferenceCount *ref_ptr)
Stores a new data object on the record.
MakeTextureFunc * get_texture_type(const string &extension) const
Returns the factory function to construct a new texture of the type appropriate for the indicated fil...
size_t get_ram_page_size() const
Returns the number of bytes used by the in-memory image per page, or 0 if there is no in-memory image...
virtual void ensure_loader_type(const Filename &filename)
May be called prior to calling read_txo() or any bam-related Texture-creating callback, to ensure that the proper dynamic libraries for a Texture of the current class type, and the indicated filename, have been already loaded.
string get_fullpath() const
Returns the entire filename: directory, basename, extension.
PNMFileType * get_type_from_extension(const string &filename) const
Tries to determine what the PNMFileType is likely to be for a particular image file based on its exte...
void clear()
Reinitializes the texture to its default, empty state (except for the name).
size_t get_ram_image_size() const
Returns the total number of bytes used by the in-memory image, across all pages and views...
Specifies parameters that may be passed to the loader.
This class maintains a cache of Bam and/or Txo objects generated from model files and texture images ...
This is a convenience class to specialize ConfigVariable as a Filename type.
A hierarchy of directories and files that appears to be one continuous file system, even though the files may originate from several different sources that may not be related to the actual OS's file system.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
This is the base class of a family of classes that represent particular image file types that PNMImag...
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
void add_texture(Texture *texture)
Adds a new Texture to the collection.
The abstract base class for a file or directory within the VirtualFileSystem.
This class is similar to ConfigVariable, but it reports its value as a list of strings.
void register_filter(TexturePoolFilter *filter)
Records a TexturePoolFilter object that may operate on texture images as they are loaded from disk...
bool is_local() const
Returns true if the filename is local, e.g.
Texture(const string &name=string())
Constructs an empty texture.
static void close_read_file(istream *stream)
Closes a file opened by a previous call to open_read_file().
bool uses_mipmaps() const
Returns true if the minfilter settings on this texture indicate the use of mipmapping, false otherwise.
bool has_data() const
Returns true if this cache record has an in-memory data object associated–that is, the object stored in the cache.
static PNMFileTypeRegistry * get_global_ptr()
Returns a pointer to the global PNMFileTypeRegistry object.
bool store(BamCacheRecord *record)
Flushes a cache entry to disk.
bool get_cache_textures() const
Returns whether texture files (e.g.
void register_texture_type(MakeTextureFunc *func, const string &extensions)
Records a factory function that makes a Texture object of the appropriate type for one or more partic...
The name of a file, such as a texture file or an Egg file.
An instance of this class is written to the front of a Bam or Txo file to make the file a cached inst...
CompressionMode get_ram_image_compression() const
Returns the compression mode in which the ram image is already stored pre-compressed.
void set_keep_ram_image(bool keep_ram_image)
Sets the flag that indicates whether this Texture is eligible to have its main RAM copy of the textur...
virtual bool is_cacheable() const
Returns true if there is enough information in this Texture object to write it to the bam cache succe...
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
Manages a list of Texture objects, as returned by TexturePool::find_all_textures().
bool resolve_filename(Filename &filename, const DSearchPath &searchpath, const string &default_extension=string()) const
Searches the given search path for the filename.
int get_orig_file_y_size() const
Returns the Y size of the original disk image that this Texture was loaded from (if it came from a di...
TypedWritable * get_data() const
Returns a pointer to the data stored in the record, or NULL if there is no data.
istream * open_read_file(const Filename &filename, bool auto_unwrap) const
Convenience function; returns a newly allocated istream if the file exists and can be read...
bool adjust_this_size(int &x_size, int &y_size, const string &name, bool for_padding) const
Works like adjust_size, but also considers the texture class.
bool has_compression() const
Returns true if the texture indicates it wants to be compressed, either with CM_on or higher...
bool get_cache_compressed_textures() const
Returns whether compressed texture files will be stored in the cache, as compressed txo files...
TextureType get_texture_type() const
Returns the overall interpretation of the texture.
bool store(PNMImage &pnmimage) const
Saves the texture to the indicated PNMImage, but does not write it to disk.
string to_os_specific() const
Converts the filename from our generic Unix-like convention (forward slashes starting with the root a...
bool has_simple_ram_image() const
Returns true if the Texture has a "simple" image available in main RAM.
static TexturePool * get_global_ptr()
Initializes and/or returns the global pointer to the one TexturePool object in the system...
void clear_ram_image()
Discards the current system-RAM image.
static void write(ostream &out)
Lists the contents of the texture pool to the indicated output stream.
bool exists(const Filename &filename) const
Convenience function; returns true if the named file exists.
This class maintains the set of all known PNMFileTypes in the universe.
void generate_simple_ram_image()
Computes the "simple" ram image by loading the main RAM image, if it is not already available...
void write_texture_types(ostream &out, int indent_level) const
Outputs a list of the available texture types to the indicated output stream.
int get_orig_file_x_size() const
Returns the X size of the original disk image that this Texture was loaded from (if it came from a di...
This is an abstract base class, a placeholder for any number of different classes that may wish to im...
This is the preferred interface for loading textures from image files.
int get_ref_count() const
Returns the current reference count.
string get_extension() const
Returns the file extension.
int get_y_size() const
Returns the height of the texture image in texels.
int get_x_size() const
Returns the width of the texture image in texels.
void set_pattern(bool pattern)
Sets the flag indicating whether this is a filename pattern.
This class can be used to test for string matches against standard Unix-shell filename globbing conve...
void write(ostream &out, int indent_level=0) const
Writes a list of supported image file types to the indicated output stream, one per line...
const Filename & get_fullpath() const
Returns the fullpath that has been set.