diff --git a/panda/src/gobj/config_gobj.cxx b/panda/src/gobj/config_gobj.cxx index dbbc1f20ec..e437f20743 100644 --- a/panda/src/gobj/config_gobj.cxx +++ b/panda/src/gobj/config_gobj.cxx @@ -83,6 +83,16 @@ ConfigVariableBool keep_texture_ram "texture image from disk; but it will consume memory somewhat " "wastefully.")); +ConfigVariableBool preload_textures +("preload-textures", true, + PRC_DESC("When this is true, texture images are loaded from disk as soon " + "as the Texture is created from the TexturePool. When this is " + "false, the Texture is created immediately, but the image data " + "is not loaded from disk until the Texture is actually rendered " + "(or otherwise prepared) on the GSG. This can help reduce " + "wasted memory from Textures that are created but never used " + "to render.")); + ConfigVariableBool compressed_textures ("compressed-textures", false, PRC_DESC("Set this to true to compress textures as they are loaded into " diff --git a/panda/src/gobj/config_gobj.h b/panda/src/gobj/config_gobj.h index a14ec15084..0de4b81c12 100644 --- a/panda/src/gobj/config_gobj.h +++ b/panda/src/gobj/config_gobj.h @@ -39,6 +39,7 @@ EXPCL_PANDA istream &operator >> (istream &in, AutoTextureScale &ats); // Configure variables for gobj package. extern EXPCL_PANDA ConfigVariableInt max_texture_dimension; extern EXPCL_PANDA ConfigVariableBool keep_texture_ram; +extern EXPCL_PANDA ConfigVariableBool preload_textures; extern EXPCL_PANDA ConfigVariableBool compressed_textures; extern EXPCL_PANDA ConfigVariableBool vertex_buffers; extern EXPCL_PANDA ConfigVariableBool vertex_arrays; diff --git a/panda/src/gobj/texture.I b/panda/src/gobj/texture.I index 5d9f34a7f1..87a05a1c83 100644 --- a/panda/src/gobj/texture.I +++ b/panda/src/gobj/texture.I @@ -134,7 +134,8 @@ setup_cube_map(int size, ComponentType component_type, INLINE bool Texture:: read(const Filename &fullpath) { clear(); - return do_read(fullpath, Filename(), 0, 0, 0, 0, false, false, NULL); + return do_read(fullpath, Filename(), 0, 0, 0, 0, false, false, + !preload_textures, NULL); } //////////////////////////////////////////////////////////////////// @@ -153,7 +154,8 @@ read(const Filename &fullpath, const Filename &alpha_fullpath, int primary_file_num_channels, int alpha_file_channel) { clear(); return do_read(fullpath, alpha_fullpath, primary_file_num_channels, - alpha_file_channel, 0, 0, false, false, NULL); + alpha_file_channel, 0, 0, false, false, !preload_textures, + NULL); } //////////////////////////////////////////////////////////////////// @@ -172,7 +174,7 @@ read(const Filename &fullpath, int z, int n, ++_properties_modified; ++_image_modified; return do_read(fullpath, Filename(), 0, 0, z, n, read_pages, read_mipmaps, - NULL); + !preload_textures, NULL); } //////////////////////////////////////////////////////////////////// @@ -253,7 +255,7 @@ read(const Filename &fullpath, const Filename &alpha_fullpath, ++_image_modified; return do_read(fullpath, alpha_fullpath, primary_file_num_channels, alpha_file_channel, z, n, read_pages, read_mipmaps, - record); + !preload_textures, record); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index be5d218ba3..f084a3b2db 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -1747,7 +1747,11 @@ bool Texture:: do_read(const Filename &fullpath, const Filename &alpha_fullpath, int primary_file_num_channels, int alpha_file_channel, int z, int n, bool read_pages, bool read_mipmaps, - BamCacheRecord *record) { + bool header_only, BamCacheRecord *record) { + if (record != (BamCacheRecord *)NULL) { + header_only = false; + } + if ((z == 0 || read_pages) && (n == 0 || read_mipmaps)) { // When we re-read the page 0 of the base image, we clear // everything and start over. @@ -1829,7 +1833,7 @@ do_read(const Filename &fullpath, const Filename &alpha_fullpath, while ((z_size == 0 && (vfs->exists(file) || z == 0)) || (z_size != 0 && z < z_size)) { if (!do_read_one(file, alpha_file, z, n, primary_file_num_channels, - alpha_file_channel, record)) { + alpha_file_channel, header_only, record)) { return false; } ++z; @@ -1866,7 +1870,7 @@ do_read(const Filename &fullpath, const Filename &alpha_fullpath, while ((z_size == 0 && (vfs->exists(file) || z == 0)) || (z_size != 0 && z < z_size)) { if (!do_read_one(file, alpha_file, z, 0, primary_file_num_channels, - alpha_file_channel, record)) { + alpha_file_channel, header_only, record)) { return false; } ++z; @@ -1894,7 +1898,7 @@ do_read(const Filename &fullpath, const Filename &alpha_fullpath, (n_size != 0 && n < n_size)) { if (!do_read_one(file, alpha_file, z, n, primary_file_num_channels, alpha_file_channel, - record)) { + header_only, record)) { return false; } ++n; @@ -1913,7 +1917,7 @@ do_read(const Filename &fullpath, const Filename &alpha_fullpath, // Just an ordinary read of one file. if (!do_read_one(fullpath, alpha_fullpath, z, n, primary_file_num_channels, alpha_file_channel, - record)) { + header_only, record)) { return false; } } @@ -1922,6 +1926,13 @@ do_read(const Filename &fullpath, const Filename &alpha_fullpath, _has_read_mipmaps = read_mipmaps; _num_mipmap_levels_read = _ram_images.size(); + if (header_only) { + // If we were only supposed to be checking the image header + // information, don't let the Texture think that it's got the + // image now. + clear_ram_image(); + } + return true; } @@ -1935,20 +1946,29 @@ do_read(const Filename &fullpath, const Filename &alpha_fullpath, bool Texture:: do_read_one(const Filename &fullpath, const Filename &alpha_fullpath, int z, int n, int primary_file_num_channels, int alpha_file_channel, - BamCacheRecord *record) { + bool header_only, BamCacheRecord *record) { if (record != (BamCacheRecord *)NULL) { + nassertr(!header_only, false); record->add_dependent_file(fullpath); } PNMImage image; - if (textures_header_only) { + if (header_only || textures_header_only) { if (!image.read_header(fullpath)) { gobj_cat.error() << "Texture::read() - couldn't read: " << fullpath << endl; return false; } - image = PNMImage(1, 1, image.get_num_channels(), image.get_maxval(), - image.get_type()); + int x_size = image.get_x_size(); + int y_size = image.get_y_size(); + if (textures_header_only) { + // In this mode, we never intend to load the actual texture + // image anyway, so we don't even need to make the size right. + x_size = 1; + y_size = 1; + } + image = PNMImage(x_size, y_size, image.get_num_channels(), + image.get_maxval(), image.get_type()); image.fill(0.2, 0.3, 1.0); if (image.has_alpha()) { image.alpha_fill(1.0); @@ -1968,13 +1988,19 @@ do_read_one(const Filename &fullpath, const Filename &alpha_fullpath, record->add_dependent_file(alpha_fullpath); } - if (textures_header_only) { + if (header_only || textures_header_only) { if (!alpha_image.read_header(alpha_fullpath)) { gobj_cat.error() << "Texture::read() - couldn't read: " << alpha_fullpath << endl; return false; } - alpha_image = PNMImage(1, 1, alpha_image.get_num_channels(), + int x_size = alpha_image.get_x_size(); + int y_size = alpha_image.get_y_size(); + if (textures_header_only) { + x_size = 1; + y_size = 1; + } + alpha_image = PNMImage(x_size, y_size, alpha_image.get_num_channels(), alpha_image.get_maxval(), alpha_image.get_type()); alpha_image.fill(1.0); @@ -2333,7 +2359,7 @@ reload_ram_image() { do_read(get_fullpath(), get_alpha_fullpath(), _primary_file_num_channels, _alpha_file_channel, - z, n, _has_read_pages, _has_read_mipmaps, NULL); + z, n, _has_read_pages, _has_read_mipmaps, false, NULL); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index 65ef9941de..b2cfce2a6e 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -29,6 +29,7 @@ #include "updateSeq.h" #include "pStatCollectorForward.h" #include "pmap.h" +#include "config_gobj.h" class PNMImage; class TextureContext; @@ -377,10 +378,10 @@ protected: virtual bool do_read(const Filename &fullpath, const Filename &alpha_fullpath, int primary_file_num_channels, int alpha_file_channel, int z, int n, bool read_pages, bool read_mipmaps, - BamCacheRecord *record); + bool header_only, BamCacheRecord *record); virtual bool do_read_one(const Filename &fullpath, const Filename &alpha_fullpath, int z, int n, int primary_file_num_channels, int alpha_file_channel, - BamCacheRecord *record); + bool header_only, BamCacheRecord *record); bool do_write(const Filename &fullpath, int z, int n, bool write_pages, bool write_mipmaps) const; bool do_write_one(const Filename &fullpath, int z, int n) const;