diff --git a/panda/src/display/config_display.cxx b/panda/src/display/config_display.cxx index f336b057f8..e8e4912d06 100644 --- a/panda/src/display/config_display.cxx +++ b/panda/src/display/config_display.cxx @@ -196,14 +196,6 @@ ConfigVariableString red_blue_stereo_colors "be a two-word string, where each word is one of 'red', 'blue', " "'green', or 'alpha'.")); -ConfigVariableBool auto_generate_mipmaps -("auto-generate-mipmaps", false, - PRC_DESC("Set this true to use the hardware to generate mipmaps " - "automatically in all cases, if supported. Set it false " - "to generate mipmaps in software when possible. This is " - "false by default because some drivers (Intel) seem to do a " - "poor job of generating mipmaps when needed.")); - ConfigVariableBool color_scale_via_lighting ("color-scale-via-lighting", true, PRC_DESC("When this is true, Panda will try to implement ColorAttribs and " diff --git a/panda/src/display/config_display.h b/panda/src/display/config_display.h index 27e6b219a1..81e8cc6756 100644 --- a/panda/src/display/config_display.h +++ b/panda/src/display/config_display.h @@ -57,7 +57,6 @@ extern EXPCL_PANDA_DISPLAY ConfigVariableBool copy_texture_inverted; extern EXPCL_PANDA_DISPLAY ConfigVariableBool window_inverted; extern EXPCL_PANDA_DISPLAY ConfigVariableBool red_blue_stereo; extern EXPCL_PANDA_DISPLAY ConfigVariableString red_blue_stereo_colors; -extern EXPCL_PANDA_DISPLAY ConfigVariableBool auto_generate_mipmaps; extern EXPCL_PANDA_DISPLAY ConfigVariableBool color_scale_via_lighting; extern EXPCL_PANDA_DISPLAY ConfigVariableBool alpha_scale_via_texture; extern EXPCL_PANDA_DISPLAY ConfigVariableBool allow_incomplete_render; diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index 05a31fa566..111ce54fc3 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -934,6 +934,21 @@ load_texture(TextureDef &def, EggTexture *egg_tex) { options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_preload_simple); } + if (!egg_ignore_filters && !egg_ignore_mipmaps) { + switch (egg_tex->get_minfilter()) { + case EggTexture::FT_nearest: + case EggTexture::FT_linear: + case EggTexture::FT_unspecified: + break; + + case EggTexture::FT_nearest_mipmap_nearest: + case EggTexture::FT_linear_mipmap_nearest: + case EggTexture::FT_nearest_mipmap_linear: + case EggTexture::FT_linear_mipmap_linear: + options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_generate_mipmaps); + } + } + PT(Texture) tex; switch (egg_tex->get_texture_type()) { case EggTexture::TT_unspecified: diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 58facda9f3..636b0fe984 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -660,11 +660,6 @@ reset() { _supports_generate_mipmap = has_extension("GL_SGIS_generate_mipmap") || is_at_least_version(1, 4); - // Temporary hack. There is an issue with auto-generating mipmaps - // for pre-compressed images, on certain drivers. Until I check in - // a fix, let's turn off this feature in general. - _supports_generate_mipmap = false; - _supports_multitexture = false; _supports_mesa_6 = false; @@ -7278,9 +7273,12 @@ upload_texture_image(CLP(TextureContext) *gtc, if (num_ram_mipmap_levels == 1) { // No RAM mipmap levels available. Should we generate some? - if (!_supports_generate_mipmap || - (!auto_generate_mipmaps && image_compression == Texture::CM_off)) { - // Yes, the GL won't generate them, so we need to. + if (!_supports_generate_mipmap || !driver_generate_mipmaps || + image_compression != Texture::CM_off) { + // Yes, the GL can't or won't generate them, so we need to. + // Note that some drivers (nVidia) will *corrupt memory* if + // you ask them to generate mipmaps for a pre-compressed + // texture. tex->generate_ram_mipmap_images(); num_ram_mipmap_levels = tex->get_num_ram_mipmap_images(); } diff --git a/panda/src/gobj/config_gobj.cxx b/panda/src/gobj/config_gobj.cxx index dbc0092ba6..93fb99db73 100644 --- a/panda/src/gobj/config_gobj.cxx +++ b/panda/src/gobj/config_gobj.cxx @@ -125,6 +125,15 @@ ConfigVariableBool driver_compress_textures "and will always be handed to the graphics driver, regardless " "of this setting.")); +ConfigVariableBool driver_generate_mipmaps +("driver-generate-mipmaps", false, + PRC_DESC("Set this true to use the hardware to generate mipmaps " + "automatically in all cases, if supported. Set it false " + "to generate mipmaps in software when possible. This is " + "false by default because some drivers (Intel) seem to do a " + "poor job of generating mipmaps when needed; also, generating " + "mipmaps in software may allow smoother texture loads.")); + ConfigVariableBool vertex_buffers ("vertex-buffers", true, PRC_DESC("Set this true to allow the use of vertex buffers (or buffer " diff --git a/panda/src/gobj/config_gobj.h b/panda/src/gobj/config_gobj.h index 9539973941..93fce7a909 100644 --- a/panda/src/gobj/config_gobj.h +++ b/panda/src/gobj/config_gobj.h @@ -56,6 +56,7 @@ extern EXPCL_PANDA_GOBJ ConfigVariableList exclude_texture_scale; extern EXPCL_PANDA_GOBJ ConfigVariableBool keep_texture_ram; extern EXPCL_PANDA_GOBJ ConfigVariableBool compressed_textures; extern EXPCL_PANDA_GOBJ ConfigVariableBool driver_compress_textures; +extern EXPCL_PANDA_GOBJ ConfigVariableBool driver_generate_mipmaps; extern EXPCL_PANDA_GOBJ ConfigVariableBool vertex_buffers; extern EXPCL_PANDA_GOBJ ConfigVariableBool vertex_arrays; extern EXPCL_PANDA_GOBJ ConfigVariableBool display_lists; diff --git a/panda/src/gobj/texture.I b/panda/src/gobj/texture.I index ab10e1db46..0530410a6c 100644 --- a/panda/src/gobj/texture.I +++ b/panda/src/gobj/texture.I @@ -254,7 +254,8 @@ load(const PNMImage &pnmimage, const LoaderOptions &options) { ++_properties_modified; ++_image_modified; if (do_load_one(pnmimage, get_name(), 0, 0, options)) { - consider_auto_compress_ram_image(); + bool generate_mipmaps = ((options.get_texture_flags() & LoaderOptions::TF_generate_mipmaps) != 0); + consider_auto_process_ram_image(generate_mipmaps || uses_mipmaps(), true); return true; } return false; @@ -272,7 +273,6 @@ load(const PNMImage &pnmimage, int z, int n, const LoaderOptions &options) { ++_properties_modified; ++_image_modified; if (do_load_one(pnmimage, get_name(), z, n, options)) { - consider_auto_compress_ram_image(); return true; } return false; @@ -1296,6 +1296,19 @@ has_ram_mipmap_image(int n) const { return do_has_ram_mipmap_image(n); } +//////////////////////////////////////////////////////////////////// +// Function: Texture::has_all_ram_mipmap_images +// Access: Published +// Description: Returns true if all expected mipmap levels have been +// defined and exist in the system RAM, or false if even +// one mipmap level is missing. +//////////////////////////////////////////////////////////////////// +INLINE bool Texture:: +has_all_ram_mipmap_images() const { + MutexHolder holder(_lock); + return do_has_all_ram_mipmap_images(); +} + //////////////////////////////////////////////////////////////////// // Function: Texture::get_ram_mipmap_image_size // Access: Published @@ -1403,6 +1416,26 @@ clear_ram_mipmap_images() { do_clear_ram_mipmap_images(); } +//////////////////////////////////////////////////////////////////// +// Function: Texture::generate_ram_mipmap_images +// Access: Published +// Description: Automatically fills in the n mipmap levels of the +// Texture, based on the texture's source image. This +// requires the texture's uncompressed ram image to be +// available in system memory. If it is not already, it +// will be fetched if possible. +// +// This call is not normally necessary, since the mipmap +// levels will be generated automatically if needed. +// But there may be certain cases in which you would +// like to call this explicitly. +//////////////////////////////////////////////////////////////////// +INLINE void Texture:: +generate_ram_mipmap_images() { + MutexHolder holder(_lock); + do_generate_ram_mipmap_images(); +} + //////////////////////////////////////////////////////////////////// // Function: Texture::get_simple_x_size // Access: Published diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index 51cac8dded..e2512fb22c 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -859,42 +859,6 @@ get_num_loadable_ram_mipmap_images() const { return n; } -//////////////////////////////////////////////////////////////////// -// Function: Texture::has_all_ram_mipmap_images -// Access: Published -// Description: Returns true if all expected mipmap levels have been -// defined and exist in the system RAM, or false if even -// one mipmap level is missing. -//////////////////////////////////////////////////////////////////// -bool Texture:: -has_all_ram_mipmap_images() const { - MutexHolder holder(_lock); - if (_ram_images.empty() || _ram_images[0]._image.empty()) { - // If we don't even have a base image, the answer is no. - return false; - } - if (!is_mipmap(_minfilter)) { - // If we have a base image and don't require mipmapping, the - // answer is yes. - return true; - } - - // Check that we have enough mipmap levels to meet the size - // requirements. - int size = max(_x_size, max(_y_size, _z_size)); - int n = 0; - int x = 1; - while (x < size) { - x = (x << 1); - ++n; - if (n >= (int)_ram_images.size() || _ram_images[n]._image.empty()) { - return false; - } - } - - return true; -} - //////////////////////////////////////////////////////////////////// // Function: Texture::get_ram_mipmap_image // Access: Published @@ -959,67 +923,6 @@ clear_ram_mipmap_image(int n) { _ram_images[n]._page_size = 0; } -//////////////////////////////////////////////////////////////////// -// Function: Texture::generate_ram_mipmap_images -// Access: Published -// Description: Automatically fills in the n mipmap levels of the -// Texture, based on the texture's source image. This -// requires the texture's uncompressed ram image to be -// available in system memory. If it is not already, it -// will be fetched if possible. -// -// This call is not normally necessary, since the mipmap -// levels will be generated automatically if needed. -// But there may be certain cases in which you would -// like to call this explicitly. -//////////////////////////////////////////////////////////////////// -void Texture:: -generate_ram_mipmap_images() { - MutexHolder holder(_lock); - - do_get_uncompressed_ram_image(); - nassertv(do_has_ram_image()); - nassertv(_ram_image_compression == CM_off); - nassertv(_component_type != T_float); - do_clear_ram_mipmap_images(); - - if (gobj_cat.is_debug()) { - gobj_cat.debug() - << "Generating mipmap levels for " << *this << "\n"; - } - - if (_texture_type == Texture::TT_3d_texture && _z_size != 1) { - // Eek, a 3-D texture. - int x_size = _x_size; - int y_size = _y_size; - int z_size = _z_size; - int n = 0; - while (x_size > 1 || y_size > 1 || z_size > 1) { - _ram_images.push_back(RamImage()); - filter_3d_mipmap_level(_ram_images[n + 1], _ram_images[n], - x_size, y_size, z_size); - x_size = max(x_size >> 1, 1); - y_size = max(y_size >> 1, 1); - z_size = max(z_size >> 1, 1); - ++n; - } - - } else { - // A 1-D, 2-D, or cube map texture. - int x_size = _x_size; - int y_size = _y_size; - int n = 0; - while (x_size > 1 || y_size > 1) { - _ram_images.push_back(RamImage()); - filter_2d_mipmap_pages(_ram_images[n + 1], _ram_images[n], - x_size, y_size); - x_size = max(x_size >> 1, 1); - y_size = max(y_size >> 1, 1); - ++n; - } - } -} - //////////////////////////////////////////////////////////////////// // Function: Texture::modify_simple_ram_image // Access: Published @@ -2097,8 +2000,9 @@ do_read(const Filename &fullpath, const Filename &alpha_fullpath, } else { if ((options.get_texture_flags() & LoaderOptions::TF_preload) != 0) { // If we intend to keep the ram image around, consider - // compressing it. - consider_auto_compress_ram_image(); + // compressing it etc. + bool generate_mipmaps = ((options.get_texture_flags() & LoaderOptions::TF_generate_mipmaps) != 0); + consider_auto_process_ram_image(generate_mipmaps || uses_mipmaps(), true); } } @@ -3029,8 +2933,11 @@ do_reload_ram_image(bool allow_compression) { _ram_images = tex->_ram_images; _loaded_from_image = true; - if (allow_compression && consider_auto_compress_ram_image()) { - if (cache->get_cache_compressed_textures()) { + bool was_compressed = (_ram_image_compression != CM_off); + if (consider_auto_process_ram_image(uses_mipmaps(), allow_compression)) { + bool is_compressed = (_ram_image_compression != CM_off); + if (!was_compressed && is_compressed && + cache->get_cache_compressed_textures()) { // We've re-compressed the image after loading it from the // cache. To keep the cache current, rewrite it to the // cache now, in its newly compressed form. @@ -3153,38 +3060,44 @@ do_make_ram_mipmap_image(int n) { } //////////////////////////////////////////////////////////////////// -// Function: Texture::consider_auto_compress_ram_image +// Function: Texture::consider_auto_process_ram_image // Access: Protected // Description: Should be called after a texture has been loaded into -// RAM, this considers compressing the RAM image, if -// cpu-compress-textures has been set and the default -// GSG has been set and supports it. - +// RAM, this considers generating mipmaps and/or +// compressing the RAM image. +// // Returns true if the image was modified by this // operation, false if it wasn't. //////////////////////////////////////////////////////////////////// bool Texture:: -consider_auto_compress_ram_image() { - if (!driver_compress_textures) { +consider_auto_process_ram_image(bool generate_mipmaps, bool allow_compression) { + bool modified = false; + + if (generate_mipmaps && !driver_generate_mipmaps && + _ram_images.size() == 1) { + do_generate_ram_mipmap_images(); + modified = true; + } + + if (allow_compression && !driver_compress_textures) { CompressionMode compression = _compression; - if (compression == CM_default) { - if (!compressed_textures) { - return false; - } + if (compression == CM_default && compressed_textures) { compression = CM_on; } if (compression != CM_off && _ram_image_compression == CM_off) { GraphicsStateGuardianBase *gsg = GraphicsStateGuardianBase::get_default_gsg(); if (do_compress_ram_image(compression, QL_default, gsg)) { - gobj_cat.info() - << "Compressed " << get_name() << " with " - << _ram_image_compression << "\n"; - return true; + if (gobj_cat.is_debug()) { + gobj_cat.debug() + << "Compressed " << get_name() << " with " + << _ram_image_compression << "\n"; + } + modified = true; } } } - return false; + return modified; } //////////////////////////////////////////////////////////////////// @@ -3324,6 +3237,39 @@ do_uncompress_ram_image() { return false; } +//////////////////////////////////////////////////////////////////// +// Function: Texture::do_has_all_ram_mipmap_images +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +bool Texture:: +do_has_all_ram_mipmap_images() const { + if (_ram_images.empty() || _ram_images[0]._image.empty()) { + // If we don't even have a base image, the answer is no. + return false; + } + if (!is_mipmap(_minfilter)) { + // If we have a base image and don't require mipmapping, the + // answer is yes. + return true; + } + + // Check that we have enough mipmap levels to meet the size + // requirements. + int size = max(_x_size, max(_y_size, _z_size)); + int n = 0; + int x = 1; + while (x < size) { + x = (x << 1); + ++n; + if (n >= (int)_ram_images.size() || _ram_images[n]._image.empty()) { + return false; + } + } + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: Texture::do_reconsider_z_size // Access: Protected @@ -3866,8 +3812,10 @@ do_get_uncompressed_ram_image() { // We have an image in-ram, but it's compressed. Try to // uncompress it first. if (do_uncompress_ram_image()) { - gobj_cat.info() - << "Uncompressed " << get_name() << "\n"; + if (gobj_cat.is_debug()) { + gobj_cat.debug() + << "Uncompressed " << get_name() << "\n"; + } return _ram_images[0]._image; } } @@ -4172,6 +4120,103 @@ do_clear_ram_mipmap_images() { } } +//////////////////////////////////////////////////////////////////// +// Function: Texture::do_generate_ram_mipmap_images +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +void Texture:: +do_generate_ram_mipmap_images() { + nassertv(do_has_ram_image()); + nassertv(_component_type != T_float); + if (do_get_expected_num_mipmap_levels() == 1) { + // Don't bother. + return; + } + + RamImage orig_compressed_image; + CompressionMode orig_compression_mode = CM_off; + + if (_ram_image_compression != CM_off) { + // The RAM image is compressed. This means we need to uncompress + // it in order to generate mipmap images. Save the original + // first, to avoid lossy recompression. + orig_compressed_image = _ram_images[0]; + orig_compression_mode = _ram_image_compression; + + // Now try to get the uncompressed source image. + do_get_uncompressed_ram_image(); + + nassertv(_ram_image_compression == CM_off); + } + + do_clear_ram_mipmap_images(); + + if (gobj_cat.is_debug()) { + gobj_cat.debug() + << "Generating mipmap levels for " << *this << "\n"; + } + + if (_texture_type == Texture::TT_3d_texture && _z_size != 1) { + // Eek, a 3-D texture. + int x_size = _x_size; + int y_size = _y_size; + int z_size = _z_size; + int n = 0; + while (x_size > 1 || y_size > 1 || z_size > 1) { + _ram_images.push_back(RamImage()); + filter_3d_mipmap_level(_ram_images[n + 1], _ram_images[n], + x_size, y_size, z_size); + x_size = max(x_size >> 1, 1); + y_size = max(y_size >> 1, 1); + z_size = max(z_size >> 1, 1); + ++n; + } + + } else { + // A 1-D, 2-D, or cube map texture. + int x_size = _x_size; + int y_size = _y_size; + int n = 0; + while (x_size > 1 || y_size > 1) { + _ram_images.push_back(RamImage()); + filter_2d_mipmap_pages(_ram_images[n + 1], _ram_images[n], + x_size, y_size); + x_size = max(x_size >> 1, 1); + y_size = max(y_size >> 1, 1); + ++n; + } + } + + if (orig_compression_mode != CM_off) { + // Now attempt to recompress the mipmap images according to the + // original compression mode. We don't need to bother compressing + // the first image (it was already compressed, after all), so + // temporarily remove it from the top of the mipmap stack, and + // compress all of the rest of them instead. + nassertv(_ram_images.size() > 1); + int l0_x_size = _x_size; + int l0_y_size = _y_size; + int l0_z_size = _z_size; + _x_size = do_get_expected_mipmap_x_size(1); + _y_size = do_get_expected_mipmap_y_size(1); + _z_size = do_get_expected_mipmap_z_size(1); + RamImage uncompressed_image = _ram_images[0]; + _ram_images.erase(_ram_images.begin()); + + bool success = do_compress_ram_image(orig_compression_mode, QL_default, NULL); + // Now restore the toplevel image. + if (success) { + _ram_images.insert(_ram_images.begin(), orig_compressed_image); + } else { + _ram_images.insert(_ram_images.begin(), uncompressed_image); + } + _x_size = l0_x_size; + _y_size = l0_y_size; + _z_size = l0_z_size; + } +} + //////////////////////////////////////////////////////////////////// // Function: Texture::do_set_pad_size // Access: Protected @@ -5328,6 +5373,13 @@ do_squish(Texture::CompressionMode compression, int squish_flags) { if (_ram_images.empty()) { return false; } + + if (!do_has_all_ram_mipmap_images()) { + // If we're about to compress the RAM image, we should ensure that + // we have all of the mipmap levels first. + do_generate_ram_mipmap_images(); + } + RamImages compressed_ram_images; compressed_ram_images.reserve(_ram_images.size()); for (size_t n = 0; n < _ram_images.size(); ++n) { @@ -5562,28 +5614,31 @@ make_from_bam(const FactoryParams ¶ms) { } } + LoaderOptions options = manager->get_loader_options(); + if (false) { // temporary hack standin + options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_generate_mipmaps); + } + switch (texture_type) { case TT_1d_texture: case TT_2d_texture: if (alpha_filename.empty()) { me = TexturePool::load_texture(filename, primary_file_num_channels, - false, manager->get_loader_options()); + false, options); } else { me = TexturePool::load_texture(filename, alpha_filename, primary_file_num_channels, alpha_file_channel, - false, manager->get_loader_options()); + false, options); } break; case TT_3d_texture: - me = TexturePool::load_3d_texture(filename, false, - manager->get_loader_options()); + me = TexturePool::load_3d_texture(filename, false, options); break; case TT_cube_map: - me = TexturePool::load_cube_map(filename, false, - manager->get_loader_options()); + me = TexturePool::load_cube_map(filename, false, options); break; } } @@ -5822,7 +5877,7 @@ write_datagram(BamWriter *manager, Datagram &me) { me.add_string(alpha_filename); me.add_uint8(_primary_file_num_channels); me.add_uint8(_alpha_file_channel); - me.add_uint8(has_rawdata); + me.add_bool(has_rawdata); me.add_uint8(_texture_type); // The data beginning at this point is handled by fillin(). diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index 4bf9ac48e9..655c7d6d52 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -321,7 +321,7 @@ PUBLISHED: INLINE int get_num_ram_mipmap_images() const; INLINE bool has_ram_mipmap_image(int n) const; int get_num_loadable_ram_mipmap_images() const; - bool has_all_ram_mipmap_images() const; + INLINE bool has_all_ram_mipmap_images() const; INLINE size_t get_ram_mipmap_image_size(int n) const; INLINE size_t get_ram_mipmap_page_size(int n) const; INLINE size_t get_expected_ram_mipmap_image_size(int n) const; @@ -332,7 +332,7 @@ PUBLISHED: void set_ram_mipmap_image(int n, PTA_uchar image, size_t page_size = 0); void clear_ram_mipmap_image(int n); INLINE void clear_ram_mipmap_images(); - void generate_ram_mipmap_images(); + INLINE void generate_ram_mipmap_images(); INLINE int get_simple_x_size() const; INLINE int get_simple_y_size() const; @@ -480,11 +480,13 @@ protected: PTA_uchar do_modify_ram_mipmap_image(int n); PTA_uchar do_make_ram_mipmap_image(int n); - bool consider_auto_compress_ram_image(); + bool consider_auto_process_ram_image(bool generate_mipmaps, + bool allow_compression); bool do_compress_ram_image(CompressionMode compression, QualityLevel quality_level, GraphicsStateGuardianBase *gsg); bool do_uncompress_ram_image(); + bool do_has_all_ram_mipmap_images() const; bool do_reconsider_z_size(int z); bool do_reconsider_image_properties(int x_size, int y_size, int num_components, @@ -533,6 +535,7 @@ protected: INLINE void do_clear_ram_image(); void do_clear_simple_ram_image(); void do_clear_ram_mipmap_images(); + void do_generate_ram_mipmap_images(); void do_set_pad_size(int x, int y, int z); // This nested class declaration is used below. diff --git a/panda/src/gobj/texturePool.cxx b/panda/src/gobj/texturePool.cxx index e4c9f0c964..122070695e 100644 --- a/panda/src/gobj/texturePool.cxx +++ b/panda/src/gobj/texturePool.cxx @@ -921,14 +921,20 @@ try_load_cache(PT(Texture) &tex, BamCache *cache, const Filename &filename, // But drop the RAM until we need it. tex->clear_ram_image(); - } else if (tex->consider_auto_compress_ram_image()) { - if (cache->get_cache_compressed_textures()) { - // We've re-compressed the image after loading it from the - // cache. To keep the cache current, rewrite it to the - // cache now, in its newly compressed form. - record->set_data(tex, false); - cache->store(record); - compressed_cache_record = true; + } else { + bool was_compressed = (tex->get_ram_image_compression() != Texture::CM_off); + if (tex->consider_auto_process_ram_image(tex->uses_mipmaps(), true)) { + bool is_compressed = (tex->get_ram_image_compression() != Texture::CM_off); + if (!was_compressed && is_compressed && + cache->get_cache_compressed_textures()) { + // We've re-compressed the image after loading it + // from the cache. To keep the cache current, + // rewrite it to the cache now, in its newly + // compressed form. + record->set_data(tex, false); + cache->store(record); + compressed_cache_record = true; + } } } tex->set_keep_ram_image(false); diff --git a/panda/src/putil/loaderOptions.cxx b/panda/src/putil/loaderOptions.cxx index 2303c0aba1..1c5230e0fc 100644 --- a/panda/src/putil/loaderOptions.cxx +++ b/panda/src/putil/loaderOptions.cxx @@ -57,6 +57,7 @@ output(ostream &out) const { write_flag(out, sep, "LF_no_disk_cache", LF_no_disk_cache); write_flag(out, sep, "LF_no_ram_cache", LF_no_ram_cache); } + write_flag(out, sep, "LF_allow_instance", LF_allow_instance); if (sep.empty()) { out << "0"; } @@ -66,6 +67,8 @@ output(ostream &out) const { sep = ""; write_texture_flag(out, sep, "TF_preload", TF_preload); write_texture_flag(out, sep, "TF_preload_simple", TF_preload_simple); + write_texture_flag(out, sep, "TF_allow_1d", TF_allow_1d); + write_texture_flag(out, sep, "TF_generate_mipmaps", TF_generate_mipmaps); if (sep.empty()) { out << "0"; } diff --git a/panda/src/putil/loaderOptions.h b/panda/src/putil/loaderOptions.h index f61c07bf92..c1f02f1114 100644 --- a/panda/src/putil/loaderOptions.h +++ b/panda/src/putil/loaderOptions.h @@ -43,6 +43,7 @@ PUBLISHED: TF_preload = 0x0004, // Texture will have RAM image TF_preload_simple = 0x0008, // Texture will have simple RAM image TF_allow_1d = 0x0010, // If texture is Nx1, make a 1-d texture + TF_generate_mipmaps = 0x0020, // Consider generating mipmaps }; LoaderOptions(int flags = LF_search | LF_report_errors);