mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 02:15:43 -04:00
better fixes for auto-compressed textures
This commit is contained in:
parent
2f47cbbb17
commit
32581604cf
@ -196,14 +196,6 @@ ConfigVariableString red_blue_stereo_colors
|
|||||||
"be a two-word string, where each word is one of 'red', 'blue', "
|
"be a two-word string, where each word is one of 'red', 'blue', "
|
||||||
"'green', or 'alpha'."));
|
"'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
|
ConfigVariableBool color_scale_via_lighting
|
||||||
("color-scale-via-lighting", true,
|
("color-scale-via-lighting", true,
|
||||||
PRC_DESC("When this is true, Panda will try to implement ColorAttribs and "
|
PRC_DESC("When this is true, Panda will try to implement ColorAttribs and "
|
||||||
|
@ -57,7 +57,6 @@ extern EXPCL_PANDA_DISPLAY ConfigVariableBool copy_texture_inverted;
|
|||||||
extern EXPCL_PANDA_DISPLAY ConfigVariableBool window_inverted;
|
extern EXPCL_PANDA_DISPLAY ConfigVariableBool window_inverted;
|
||||||
extern EXPCL_PANDA_DISPLAY ConfigVariableBool red_blue_stereo;
|
extern EXPCL_PANDA_DISPLAY ConfigVariableBool red_blue_stereo;
|
||||||
extern EXPCL_PANDA_DISPLAY ConfigVariableString red_blue_stereo_colors;
|
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 color_scale_via_lighting;
|
||||||
extern EXPCL_PANDA_DISPLAY ConfigVariableBool alpha_scale_via_texture;
|
extern EXPCL_PANDA_DISPLAY ConfigVariableBool alpha_scale_via_texture;
|
||||||
extern EXPCL_PANDA_DISPLAY ConfigVariableBool allow_incomplete_render;
|
extern EXPCL_PANDA_DISPLAY ConfigVariableBool allow_incomplete_render;
|
||||||
|
@ -934,6 +934,21 @@ load_texture(TextureDef &def, EggTexture *egg_tex) {
|
|||||||
options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_preload_simple);
|
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;
|
PT(Texture) tex;
|
||||||
switch (egg_tex->get_texture_type()) {
|
switch (egg_tex->get_texture_type()) {
|
||||||
case EggTexture::TT_unspecified:
|
case EggTexture::TT_unspecified:
|
||||||
|
@ -660,11 +660,6 @@ reset() {
|
|||||||
_supports_generate_mipmap =
|
_supports_generate_mipmap =
|
||||||
has_extension("GL_SGIS_generate_mipmap") || is_at_least_version(1, 4);
|
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_multitexture = false;
|
||||||
|
|
||||||
_supports_mesa_6 = false;
|
_supports_mesa_6 = false;
|
||||||
@ -7278,9 +7273,12 @@ upload_texture_image(CLP(TextureContext) *gtc,
|
|||||||
|
|
||||||
if (num_ram_mipmap_levels == 1) {
|
if (num_ram_mipmap_levels == 1) {
|
||||||
// No RAM mipmap levels available. Should we generate some?
|
// No RAM mipmap levels available. Should we generate some?
|
||||||
if (!_supports_generate_mipmap ||
|
if (!_supports_generate_mipmap || !driver_generate_mipmaps ||
|
||||||
(!auto_generate_mipmaps && image_compression == Texture::CM_off)) {
|
image_compression != Texture::CM_off) {
|
||||||
// Yes, the GL won't generate them, so we need to.
|
// 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();
|
tex->generate_ram_mipmap_images();
|
||||||
num_ram_mipmap_levels = tex->get_num_ram_mipmap_images();
|
num_ram_mipmap_levels = tex->get_num_ram_mipmap_images();
|
||||||
}
|
}
|
||||||
|
@ -125,6 +125,15 @@ ConfigVariableBool driver_compress_textures
|
|||||||
"and will always be handed to the graphics driver, regardless "
|
"and will always be handed to the graphics driver, regardless "
|
||||||
"of this setting."));
|
"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
|
ConfigVariableBool vertex_buffers
|
||||||
("vertex-buffers", true,
|
("vertex-buffers", true,
|
||||||
PRC_DESC("Set this true to allow the use of vertex buffers (or buffer "
|
PRC_DESC("Set this true to allow the use of vertex buffers (or buffer "
|
||||||
|
@ -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 keep_texture_ram;
|
||||||
extern EXPCL_PANDA_GOBJ ConfigVariableBool compressed_textures;
|
extern EXPCL_PANDA_GOBJ ConfigVariableBool compressed_textures;
|
||||||
extern EXPCL_PANDA_GOBJ ConfigVariableBool driver_compress_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_buffers;
|
||||||
extern EXPCL_PANDA_GOBJ ConfigVariableBool vertex_arrays;
|
extern EXPCL_PANDA_GOBJ ConfigVariableBool vertex_arrays;
|
||||||
extern EXPCL_PANDA_GOBJ ConfigVariableBool display_lists;
|
extern EXPCL_PANDA_GOBJ ConfigVariableBool display_lists;
|
||||||
|
@ -254,7 +254,8 @@ load(const PNMImage &pnmimage, const LoaderOptions &options) {
|
|||||||
++_properties_modified;
|
++_properties_modified;
|
||||||
++_image_modified;
|
++_image_modified;
|
||||||
if (do_load_one(pnmimage, get_name(), 0, 0, options)) {
|
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 true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -272,7 +273,6 @@ load(const PNMImage &pnmimage, int z, int n, const LoaderOptions &options) {
|
|||||||
++_properties_modified;
|
++_properties_modified;
|
||||||
++_image_modified;
|
++_image_modified;
|
||||||
if (do_load_one(pnmimage, get_name(), z, n, options)) {
|
if (do_load_one(pnmimage, get_name(), z, n, options)) {
|
||||||
consider_auto_compress_ram_image();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -1296,6 +1296,19 @@ has_ram_mipmap_image(int n) const {
|
|||||||
return do_has_ram_mipmap_image(n);
|
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
|
// Function: Texture::get_ram_mipmap_image_size
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -1403,6 +1416,26 @@ clear_ram_mipmap_images() {
|
|||||||
do_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
|
// Function: Texture::get_simple_x_size
|
||||||
// Access: Published
|
// Access: Published
|
||||||
|
@ -859,42 +859,6 @@ get_num_loadable_ram_mipmap_images() const {
|
|||||||
return n;
|
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
|
// Function: Texture::get_ram_mipmap_image
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -959,67 +923,6 @@ clear_ram_mipmap_image(int n) {
|
|||||||
_ram_images[n]._page_size = 0;
|
_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
|
// Function: Texture::modify_simple_ram_image
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -2097,8 +2000,9 @@ do_read(const Filename &fullpath, const Filename &alpha_fullpath,
|
|||||||
} else {
|
} else {
|
||||||
if ((options.get_texture_flags() & LoaderOptions::TF_preload) != 0) {
|
if ((options.get_texture_flags() & LoaderOptions::TF_preload) != 0) {
|
||||||
// If we intend to keep the ram image around, consider
|
// If we intend to keep the ram image around, consider
|
||||||
// compressing it.
|
// compressing it etc.
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3029,8 +2933,11 @@ do_reload_ram_image(bool allow_compression) {
|
|||||||
_ram_images = tex->_ram_images;
|
_ram_images = tex->_ram_images;
|
||||||
_loaded_from_image = true;
|
_loaded_from_image = true;
|
||||||
|
|
||||||
if (allow_compression && consider_auto_compress_ram_image()) {
|
bool was_compressed = (_ram_image_compression != CM_off);
|
||||||
if (cache->get_cache_compressed_textures()) {
|
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
|
// We've re-compressed the image after loading it from the
|
||||||
// cache. To keep the cache current, rewrite it to the
|
// cache. To keep the cache current, rewrite it to the
|
||||||
// cache now, in its newly compressed form.
|
// 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
|
// Access: Protected
|
||||||
// Description: Should be called after a texture has been loaded into
|
// Description: Should be called after a texture has been loaded into
|
||||||
// RAM, this considers compressing the RAM image, if
|
// RAM, this considers generating mipmaps and/or
|
||||||
// cpu-compress-textures has been set and the default
|
// compressing the RAM image.
|
||||||
// GSG has been set and supports it.
|
//
|
||||||
|
|
||||||
// Returns true if the image was modified by this
|
// Returns true if the image was modified by this
|
||||||
// operation, false if it wasn't.
|
// operation, false if it wasn't.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool Texture::
|
bool Texture::
|
||||||
consider_auto_compress_ram_image() {
|
consider_auto_process_ram_image(bool generate_mipmaps, bool allow_compression) {
|
||||||
if (!driver_compress_textures) {
|
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;
|
CompressionMode compression = _compression;
|
||||||
if (compression == CM_default) {
|
if (compression == CM_default && compressed_textures) {
|
||||||
if (!compressed_textures) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
compression = CM_on;
|
compression = CM_on;
|
||||||
}
|
}
|
||||||
if (compression != CM_off && _ram_image_compression == CM_off) {
|
if (compression != CM_off && _ram_image_compression == CM_off) {
|
||||||
GraphicsStateGuardianBase *gsg = GraphicsStateGuardianBase::get_default_gsg();
|
GraphicsStateGuardianBase *gsg = GraphicsStateGuardianBase::get_default_gsg();
|
||||||
if (do_compress_ram_image(compression, QL_default, gsg)) {
|
if (do_compress_ram_image(compression, QL_default, gsg)) {
|
||||||
gobj_cat.info()
|
if (gobj_cat.is_debug()) {
|
||||||
<< "Compressed " << get_name() << " with "
|
gobj_cat.debug()
|
||||||
<< _ram_image_compression << "\n";
|
<< "Compressed " << get_name() << " with "
|
||||||
return true;
|
<< _ram_image_compression << "\n";
|
||||||
|
}
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -3324,6 +3237,39 @@ do_uncompress_ram_image() {
|
|||||||
return false;
|
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
|
// Function: Texture::do_reconsider_z_size
|
||||||
// Access: Protected
|
// Access: Protected
|
||||||
@ -3866,8 +3812,10 @@ do_get_uncompressed_ram_image() {
|
|||||||
// We have an image in-ram, but it's compressed. Try to
|
// We have an image in-ram, but it's compressed. Try to
|
||||||
// uncompress it first.
|
// uncompress it first.
|
||||||
if (do_uncompress_ram_image()) {
|
if (do_uncompress_ram_image()) {
|
||||||
gobj_cat.info()
|
if (gobj_cat.is_debug()) {
|
||||||
<< "Uncompressed " << get_name() << "\n";
|
gobj_cat.debug()
|
||||||
|
<< "Uncompressed " << get_name() << "\n";
|
||||||
|
}
|
||||||
return _ram_images[0]._image;
|
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
|
// Function: Texture::do_set_pad_size
|
||||||
// Access: Protected
|
// Access: Protected
|
||||||
@ -5328,6 +5373,13 @@ do_squish(Texture::CompressionMode compression, int squish_flags) {
|
|||||||
if (_ram_images.empty()) {
|
if (_ram_images.empty()) {
|
||||||
return false;
|
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;
|
RamImages compressed_ram_images;
|
||||||
compressed_ram_images.reserve(_ram_images.size());
|
compressed_ram_images.reserve(_ram_images.size());
|
||||||
for (size_t n = 0; n < _ram_images.size(); ++n) {
|
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) {
|
switch (texture_type) {
|
||||||
case TT_1d_texture:
|
case TT_1d_texture:
|
||||||
case TT_2d_texture:
|
case TT_2d_texture:
|
||||||
if (alpha_filename.empty()) {
|
if (alpha_filename.empty()) {
|
||||||
me = TexturePool::load_texture(filename, primary_file_num_channels,
|
me = TexturePool::load_texture(filename, primary_file_num_channels,
|
||||||
false, manager->get_loader_options());
|
false, options);
|
||||||
} else {
|
} else {
|
||||||
me = TexturePool::load_texture(filename, alpha_filename,
|
me = TexturePool::load_texture(filename, alpha_filename,
|
||||||
primary_file_num_channels,
|
primary_file_num_channels,
|
||||||
alpha_file_channel,
|
alpha_file_channel,
|
||||||
false, manager->get_loader_options());
|
false, options);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TT_3d_texture:
|
case TT_3d_texture:
|
||||||
me = TexturePool::load_3d_texture(filename, false,
|
me = TexturePool::load_3d_texture(filename, false, options);
|
||||||
manager->get_loader_options());
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TT_cube_map:
|
case TT_cube_map:
|
||||||
me = TexturePool::load_cube_map(filename, false,
|
me = TexturePool::load_cube_map(filename, false, options);
|
||||||
manager->get_loader_options());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5822,7 +5877,7 @@ write_datagram(BamWriter *manager, Datagram &me) {
|
|||||||
me.add_string(alpha_filename);
|
me.add_string(alpha_filename);
|
||||||
me.add_uint8(_primary_file_num_channels);
|
me.add_uint8(_primary_file_num_channels);
|
||||||
me.add_uint8(_alpha_file_channel);
|
me.add_uint8(_alpha_file_channel);
|
||||||
me.add_uint8(has_rawdata);
|
me.add_bool(has_rawdata);
|
||||||
me.add_uint8(_texture_type);
|
me.add_uint8(_texture_type);
|
||||||
|
|
||||||
// The data beginning at this point is handled by fillin().
|
// The data beginning at this point is handled by fillin().
|
||||||
|
@ -321,7 +321,7 @@ PUBLISHED:
|
|||||||
INLINE int get_num_ram_mipmap_images() const;
|
INLINE int get_num_ram_mipmap_images() const;
|
||||||
INLINE bool has_ram_mipmap_image(int n) const;
|
INLINE bool has_ram_mipmap_image(int n) const;
|
||||||
int get_num_loadable_ram_mipmap_images() 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_image_size(int n) const;
|
||||||
INLINE size_t get_ram_mipmap_page_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;
|
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 set_ram_mipmap_image(int n, PTA_uchar image, size_t page_size = 0);
|
||||||
void clear_ram_mipmap_image(int n);
|
void clear_ram_mipmap_image(int n);
|
||||||
INLINE void clear_ram_mipmap_images();
|
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_x_size() const;
|
||||||
INLINE int get_simple_y_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_modify_ram_mipmap_image(int n);
|
||||||
PTA_uchar do_make_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,
|
bool do_compress_ram_image(CompressionMode compression,
|
||||||
QualityLevel quality_level,
|
QualityLevel quality_level,
|
||||||
GraphicsStateGuardianBase *gsg);
|
GraphicsStateGuardianBase *gsg);
|
||||||
bool do_uncompress_ram_image();
|
bool do_uncompress_ram_image();
|
||||||
|
bool do_has_all_ram_mipmap_images() const;
|
||||||
|
|
||||||
bool do_reconsider_z_size(int z);
|
bool do_reconsider_z_size(int z);
|
||||||
bool do_reconsider_image_properties(int x_size, int y_size, int num_components,
|
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();
|
INLINE void do_clear_ram_image();
|
||||||
void do_clear_simple_ram_image();
|
void do_clear_simple_ram_image();
|
||||||
void do_clear_ram_mipmap_images();
|
void do_clear_ram_mipmap_images();
|
||||||
|
void do_generate_ram_mipmap_images();
|
||||||
void do_set_pad_size(int x, int y, int z);
|
void do_set_pad_size(int x, int y, int z);
|
||||||
|
|
||||||
// This nested class declaration is used below.
|
// This nested class declaration is used below.
|
||||||
|
@ -921,14 +921,20 @@ try_load_cache(PT(Texture) &tex, BamCache *cache, const Filename &filename,
|
|||||||
// But drop the RAM until we need it.
|
// But drop the RAM until we need it.
|
||||||
tex->clear_ram_image();
|
tex->clear_ram_image();
|
||||||
|
|
||||||
} else if (tex->consider_auto_compress_ram_image()) {
|
} else {
|
||||||
if (cache->get_cache_compressed_textures()) {
|
bool was_compressed = (tex->get_ram_image_compression() != Texture::CM_off);
|
||||||
// We've re-compressed the image after loading it from the
|
if (tex->consider_auto_process_ram_image(tex->uses_mipmaps(), true)) {
|
||||||
// cache. To keep the cache current, rewrite it to the
|
bool is_compressed = (tex->get_ram_image_compression() != Texture::CM_off);
|
||||||
// cache now, in its newly compressed form.
|
if (!was_compressed && is_compressed &&
|
||||||
record->set_data(tex, false);
|
cache->get_cache_compressed_textures()) {
|
||||||
cache->store(record);
|
// We've re-compressed the image after loading it
|
||||||
compressed_cache_record = true;
|
// 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);
|
tex->set_keep_ram_image(false);
|
||||||
|
@ -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_disk_cache", LF_no_disk_cache);
|
||||||
write_flag(out, sep, "LF_no_ram_cache", LF_no_ram_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()) {
|
if (sep.empty()) {
|
||||||
out << "0";
|
out << "0";
|
||||||
}
|
}
|
||||||
@ -66,6 +67,8 @@ output(ostream &out) const {
|
|||||||
sep = "";
|
sep = "";
|
||||||
write_texture_flag(out, sep, "TF_preload", TF_preload);
|
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_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()) {
|
if (sep.empty()) {
|
||||||
out << "0";
|
out << "0";
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ PUBLISHED:
|
|||||||
TF_preload = 0x0004, // Texture will have RAM image
|
TF_preload = 0x0004, // Texture will have RAM image
|
||||||
TF_preload_simple = 0x0008, // Texture will have simple 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_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);
|
LoaderOptions(int flags = LF_search | LF_report_errors);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user