mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 02:15:43 -04:00
add support for libsquish
This commit is contained in:
parent
6954933382
commit
b37a30fe63
@ -470,6 +470,13 @@
|
||||
// drfftw instead of rfftw.
|
||||
#defer HAVE_DRFFTW_H $[libtest $[FFTW_LPATH],drfftw]
|
||||
|
||||
// Is libsquish installed, and where?
|
||||
#define SQUISH_IPATH /usr/local/include
|
||||
#define SQUISH_LPATH /usr/local/lib
|
||||
#define SQUISH_LIBS squish
|
||||
#defer HAVE_SQUISH $[libtest $[SQUISH_LPATH],$[SQUISH_LIBS]]
|
||||
|
||||
|
||||
// Is Berkeley DB installed, and where? Presently, this is only used
|
||||
// for some applications (egg-optchar in particular) in Pandatool, and
|
||||
// it is completely optional there. If available, egg-optchar takes
|
||||
|
@ -41,6 +41,11 @@
|
||||
#else
|
||||
#print - Did not find fftw
|
||||
#endif
|
||||
#if $[HAVE_SQUISH]
|
||||
#print + squish
|
||||
#else
|
||||
#print - Did not find squish
|
||||
#endif
|
||||
#if $[HAVE_CG]
|
||||
#print + Nvidia Cg High Level Shading Language
|
||||
#else
|
||||
@ -232,6 +237,9 @@ $[cdefine HAVE_TAR]
|
||||
/* Define if we have libfftw installed. */
|
||||
$[cdefine HAVE_FFTW]
|
||||
|
||||
/* Define if we have libsquish installed. */
|
||||
$[cdefine HAVE_SQUISH]
|
||||
|
||||
/* Define if we have Berkeley DB installed. */
|
||||
$[cdefine HAVE_BDB]
|
||||
|
||||
|
@ -145,6 +145,11 @@
|
||||
#set FFTW_LIBS $[FFTW_LIBS]
|
||||
#set HAVE_FFTW $[HAVE_FFTW]
|
||||
|
||||
#set SQUISH_IPATH $[unixfilename $[SQUISH_IPATH]]
|
||||
#set SQUISH_LPATH $[unixfilename $[SQUISH_LPATH]]
|
||||
#set SQUISH_LIBS $[SQUISH_LIBS]
|
||||
#set HAVE_SQUISH $[HAVE_SQUISH]
|
||||
|
||||
#set BDB_IPATH $[unixfilename $[BDB_IPATH]]
|
||||
#set BDB_LPATH $[unixfilename $[BDB_LPATH]]
|
||||
#set BDB_LIBS $[BDB_LIBS]
|
||||
|
@ -241,6 +241,13 @@
|
||||
#define fftw_libs $[FFTW_LIBS]
|
||||
#endif
|
||||
|
||||
#if $[HAVE_SQUISH]
|
||||
#define squish_ipath $[wildcard $[SQUISH_IPATH]]
|
||||
#define squish_lpath $[wildcard $[SQUISH_LPATH]]
|
||||
#define squish_cflags $[SQUISH_CFLAGS]
|
||||
#define squish_libs $[SQUISH_LIBS]
|
||||
#endif
|
||||
|
||||
#if $[HAVE_BDB]
|
||||
#define bdb_ipath $[wildcard $[BDB_IPATH]]
|
||||
#define bdb_lpath $[wildcard $[BDB_LPATH]]
|
||||
|
@ -419,13 +419,15 @@ get_supports_compressed_texture() const {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::get_supports_compressed_texture_format
|
||||
// Access: Published
|
||||
// Access: Published, Virtual
|
||||
// Description: Returns true if this GSG can accept textures
|
||||
// pre-compressed in the indicated format.
|
||||
// compression_mode may be any of the
|
||||
// Texture::CompressionMode enums.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool GraphicsStateGuardian::
|
||||
get_supports_compressed_texture_format(Texture::CompressionMode compression) const {
|
||||
return _compressed_texture_formats.get_bit(compression);
|
||||
get_supports_compressed_texture_format(int compression_mode) const {
|
||||
return _compressed_texture_formats.get_bit(compression_mode);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -122,7 +122,7 @@ PUBLISHED:
|
||||
INLINE bool get_supports_tex_non_pow2() const;
|
||||
|
||||
INLINE bool get_supports_compressed_texture() const;
|
||||
INLINE bool get_supports_compressed_texture_format(Texture::CompressionMode compression) const;
|
||||
virtual INLINE bool get_supports_compressed_texture_format(int compression_mode) const;
|
||||
|
||||
INLINE int get_max_lights() const;
|
||||
INLINE int get_max_clip_planes() const;
|
||||
|
@ -1,7 +1,7 @@
|
||||
#define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
|
||||
dtoolutil:c dtoolbase:c dtool:m prc:c
|
||||
//#define OSX_SYS_LIBS mx
|
||||
#define USE_PACKAGES zlib cg
|
||||
#define USE_PACKAGES zlib cg squish
|
||||
|
||||
#begin lib_target
|
||||
#define TARGET gobj
|
||||
|
@ -106,6 +106,17 @@ ConfigVariableBool compressed_textures
|
||||
"changes the meaning of set_compression(Texture::CM_default) to "
|
||||
"Texture::CM_on."));
|
||||
|
||||
ConfigVariableBool cpu_compress_textures
|
||||
("cpu-compress-textures", false,
|
||||
PRC_DESC("Set this true to use the squish library to compress textures on "
|
||||
"the CPU, as they are loaded, rather than to hand them off to "
|
||||
"the graphics driver to compress them. This will be done "
|
||||
"only if the graphics window is already open and is the default "
|
||||
"graphics context, and it claims to support DXT1/3/5 "
|
||||
"compression. If any of this is not true, the texture will "
|
||||
"not be automatically compressed via squish, but it may still "
|
||||
"be compressed by the graphics driver."));
|
||||
|
||||
ConfigVariableBool vertex_buffers
|
||||
("vertex-buffers", true,
|
||||
PRC_DESC("Set this true to allow the use of vertex buffers (or buffer "
|
||||
|
@ -54,6 +54,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 cpu_compress_textures;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableBool vertex_buffers;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableBool vertex_arrays;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableBool display_lists;
|
||||
|
@ -253,7 +253,11 @@ load(const PNMImage &pnmimage, const LoaderOptions &options) {
|
||||
do_clear();
|
||||
++_properties_modified;
|
||||
++_image_modified;
|
||||
return do_load_one(pnmimage, get_name(), 0, 0, options);
|
||||
if (do_load_one(pnmimage, get_name(), 0, 0, options)) {
|
||||
consider_auto_compress_ram_image();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -267,7 +271,11 @@ load(const PNMImage &pnmimage, int z, int n, const LoaderOptions &options) {
|
||||
MutexHolder holder(_lock);
|
||||
++_properties_modified;
|
||||
++_image_modified;
|
||||
return 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 false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1205,6 +1213,56 @@ set_keep_ram_image(bool keep_ram_image) {
|
||||
_keep_ram_image = keep_ram_image;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::compress_ram_image
|
||||
// Access: Published
|
||||
// Description: Attempts to compress the texture's RAM image
|
||||
// internally, to a format supported by the indicated
|
||||
// GSG. In order for this to work, the squish library
|
||||
// must have been compiled into Panda.
|
||||
//
|
||||
// If compression is CM_on, then an appropriate
|
||||
// compression method that is supported by the indicated
|
||||
// GSG is automatically chosen. If the GSG pointer is
|
||||
// NULL, any of the standard DXT1/3/5 compression
|
||||
// methods will be used, regardless of whether it is
|
||||
// supported.
|
||||
//
|
||||
// If compression is any specific compression method,
|
||||
// that method is used regardless of whether the GSG
|
||||
// supports it.
|
||||
//
|
||||
// quality_level determines the speed/quality tradeoff
|
||||
// of the compression. If it is QL_default, the
|
||||
// texture's own quality_level parameter is used.
|
||||
//
|
||||
// Returns true if successful, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool Texture::
|
||||
compress_ram_image(Texture::CompressionMode compression,
|
||||
Texture::QualityLevel quality_level,
|
||||
GraphicsStateGuardianBase *gsg) {
|
||||
MutexHolder holder(_lock);
|
||||
return do_compress_ram_image(compression, quality_level, gsg);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::uncompress_ram_image
|
||||
// Access: Published
|
||||
// Description: Attempts to uncompress the texture's RAM image
|
||||
// internally. In order for this to work, the squish
|
||||
// library must have been compiled into Panda, and the
|
||||
// ram image must be compressed in a format supported by
|
||||
// squish.
|
||||
//
|
||||
// Returns true if successful, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool Texture::
|
||||
uncompress_ram_image() {
|
||||
MutexHolder holder(_lock);
|
||||
return do_uncompress_ram_image();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::get_num_ram_mipmap_images
|
||||
// Access: Published
|
||||
|
@ -39,13 +39,17 @@
|
||||
#include "streamReader.h"
|
||||
#include "texturePeeker.h"
|
||||
|
||||
#ifdef HAVE_SQUISH
|
||||
#include <squish.h>
|
||||
#endif // HAVE_SQUISH
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
ConfigVariableEnum<Texture::QualityLevel> texture_quality_level
|
||||
("texture-quality-level", Texture::QL_normal,
|
||||
PRC_DESC("This specifies a global quality level for all textures. You "
|
||||
"may specify either fastest, normal, or best. This actually "
|
||||
"affects the meaning of Texture::set_quality_level(TQL_default), "
|
||||
"affects the meaning of Texture::set_quality_level(QL_default), "
|
||||
"so it may be overridden on a per-texture basis. This generally "
|
||||
"only has an effect when using the tinydisplay software renderer; "
|
||||
"it has little or no effect on normal, hardware-accelerated "
|
||||
@ -2082,6 +2086,12 @@ do_read(const Filename &fullpath, const Filename &alpha_fullpath,
|
||||
// information, don't let the Texture think that it's got the
|
||||
// image now.
|
||||
do_clear_ram_image();
|
||||
} 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();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -2472,6 +2482,7 @@ do_read_txo(istream &in, const string &filename) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Namable::operator = (*other);
|
||||
do_assign(*other);
|
||||
_loaded_from_image = true;
|
||||
_loaded_from_txo = true;
|
||||
@ -2798,7 +2809,7 @@ do_write_one(const Filename &fullpath, int z, int n) const {
|
||||
bool Texture::
|
||||
do_store_one(PNMImage &pnmimage, int z, int n) const {
|
||||
// First, reload the ram image if necessary.
|
||||
((Texture *)this)->do_get_ram_image();
|
||||
((Texture *)this)->do_get_uncompressed_ram_image();
|
||||
|
||||
nassertr(do_has_ram_mipmap_image(n), false);
|
||||
nassertr(z >= 0 && z < do_get_expected_mipmap_z_size(n), false);
|
||||
@ -3009,6 +3020,17 @@ do_reload_ram_image(bool allow_compression) {
|
||||
_ram_image_compression = tex->_ram_image_compression;
|
||||
_ram_images = tex->_ram_images;
|
||||
_loaded_from_image = true;
|
||||
|
||||
if (allow_compression && 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(this, false);
|
||||
cache->store(record);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -3122,6 +3144,180 @@ do_make_ram_mipmap_image(int n) {
|
||||
return _ram_images[n]._image;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::consider_auto_compress_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.
|
||||
|
||||
// Returns true if the image was modified by this
|
||||
// operation, false if it wasn't.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Texture::
|
||||
consider_auto_compress_ram_image() {
|
||||
if (cpu_compress_textures) {
|
||||
CompressionMode compression = _compression;
|
||||
if (compression == CM_default) {
|
||||
if (!compressed_textures) {
|
||||
return false;
|
||||
}
|
||||
compression = CM_on;
|
||||
}
|
||||
if (compression != CM_off && _ram_image_compression == CM_off) {
|
||||
GraphicsStateGuardianBase *gsg = GraphicsStateGuardianBase::get_default_gsg();
|
||||
if (gsg != (GraphicsStateGuardianBase *)NULL) {
|
||||
if (do_compress_ram_image(compression, QL_default, gsg)) {
|
||||
gobj_cat.info()
|
||||
<< "Compressed " << get_name() << " with "
|
||||
<< _ram_image_compression << "\n";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::do_compress_ram_image
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Texture::
|
||||
do_compress_ram_image(Texture::CompressionMode compression,
|
||||
Texture::QualityLevel quality_level,
|
||||
GraphicsStateGuardianBase *gsg) {
|
||||
nassertr(compression != CM_off, false);
|
||||
|
||||
if (compression == CM_on) {
|
||||
// Select an appropriate compression mode automatically.
|
||||
switch (_format) {
|
||||
case Texture::F_rgbm:
|
||||
case Texture::F_rgb:
|
||||
case Texture::F_rgb5:
|
||||
case Texture::F_rgba5:
|
||||
case Texture::F_rgb8:
|
||||
case Texture::F_rgb12:
|
||||
case Texture::F_rgb332:
|
||||
if (gsg == NULL || gsg->get_supports_compressed_texture_format(CM_dxt1)) {
|
||||
compression = CM_dxt1;
|
||||
} else if (gsg == NULL || gsg->get_supports_compressed_texture_format(CM_dxt3)) {
|
||||
compression = CM_dxt3;
|
||||
} else if (gsg == NULL || gsg->get_supports_compressed_texture_format(CM_dxt5)) {
|
||||
compression = CM_dxt5;
|
||||
}
|
||||
break;
|
||||
|
||||
case Texture::F_rgba4:
|
||||
if (gsg == NULL || gsg->get_supports_compressed_texture_format(CM_dxt3)) {
|
||||
compression = CM_dxt3;
|
||||
} else if (gsg == NULL || gsg->get_supports_compressed_texture_format(CM_dxt5)) {
|
||||
compression = CM_dxt5;
|
||||
}
|
||||
break;
|
||||
|
||||
case Texture::F_rgba:
|
||||
case Texture::F_rgba8:
|
||||
case Texture::F_rgba12:
|
||||
if (gsg == NULL || gsg->get_supports_compressed_texture_format(CM_dxt5)) {
|
||||
compression = CM_dxt5;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Choose an appropriate quality level.
|
||||
if (quality_level == Texture::QL_default) {
|
||||
quality_level = _quality_level;
|
||||
}
|
||||
if (quality_level == Texture::QL_default) {
|
||||
quality_level = texture_quality_level;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SQUISH
|
||||
if (_texture_type != TT_3d_texture && _component_type == T_unsigned_byte) {
|
||||
int squish_flags = 0;
|
||||
switch (compression) {
|
||||
case CM_dxt1:
|
||||
squish_flags |= squish::kDxt1;
|
||||
break;
|
||||
|
||||
case CM_dxt3:
|
||||
squish_flags |= squish::kDxt3;
|
||||
break;
|
||||
|
||||
case CM_dxt5:
|
||||
squish_flags |= squish::kDxt5;
|
||||
break;
|
||||
}
|
||||
|
||||
if (squish_flags != 0) {
|
||||
// This compression mode is supported by squish; use it.
|
||||
switch (quality_level) {
|
||||
case QL_fastest:
|
||||
squish_flags |= squish::kColourRangeFit;
|
||||
break;
|
||||
|
||||
case QL_normal:
|
||||
// ColourClusterFit is just too slow for everyday use.
|
||||
squish_flags |= squish::kColourRangeFit;
|
||||
// squish_flags |= squish::kColourClusterFit;
|
||||
break;
|
||||
|
||||
case QL_best:
|
||||
squish_flags |= squish::kColourIterativeClusterFit;
|
||||
break;
|
||||
}
|
||||
|
||||
if (do_squish(compression, squish_flags)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // HAVE_SQUISH
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::do_uncompress_ram_image
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Texture::
|
||||
do_uncompress_ram_image() {
|
||||
|
||||
#ifdef HAVE_SQUISH
|
||||
if (_texture_type != TT_3d_texture && _component_type == T_unsigned_byte) {
|
||||
int squish_flags = 0;
|
||||
switch (_ram_image_compression) {
|
||||
case CM_dxt1:
|
||||
squish_flags |= squish::kDxt1;
|
||||
break;
|
||||
|
||||
case CM_dxt3:
|
||||
squish_flags |= squish::kDxt3;
|
||||
break;
|
||||
|
||||
case CM_dxt5:
|
||||
squish_flags |= squish::kDxt5;
|
||||
break;
|
||||
}
|
||||
|
||||
if (squish_flags != 0) {
|
||||
// This compression mode is supported by squish; use it.
|
||||
if (do_unsquish(squish_flags)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // HAVE_SQUISH
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::do_reconsider_z_size
|
||||
// Access: Protected
|
||||
@ -3660,6 +3856,17 @@ do_get_ram_image() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPTA_uchar Texture::
|
||||
do_get_uncompressed_ram_image() {
|
||||
if (!_ram_images.empty() && _ram_image_compression != CM_off) {
|
||||
// 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";
|
||||
return _ram_images[0]._image;
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't uncompress the existing image. Try to reload it.
|
||||
if (_loaded_from_image && (!do_has_ram_image() || _ram_image_compression != CM_off) && !_fullpath.empty()) {
|
||||
do_unlock_and_reload_ram_image(false);
|
||||
}
|
||||
@ -5094,6 +5301,183 @@ filter_3d_unsigned_short(unsigned char *&p, const unsigned char *&q,
|
||||
q += 2;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::do_squish
|
||||
// Access: Private
|
||||
// Description: Invokes the squish library to compress the RAM
|
||||
// image(s).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Texture::
|
||||
do_squish(Texture::CompressionMode compression, int squish_flags) {
|
||||
#ifdef HAVE_SQUISH
|
||||
if (_ram_images.empty()) {
|
||||
return false;
|
||||
}
|
||||
RamImages compressed_ram_images;
|
||||
compressed_ram_images.reserve(_ram_images.size());
|
||||
for (size_t n = 0; n < _ram_images.size(); ++n) {
|
||||
RamImage compressed_image;
|
||||
int x_size = do_get_expected_mipmap_x_size(n);
|
||||
int y_size = do_get_expected_mipmap_y_size(n);
|
||||
int z_size = do_get_expected_mipmap_z_size(n);
|
||||
int page_size = squish::GetStorageRequirements(x_size, y_size, squish_flags);
|
||||
int cell_size = squish::GetStorageRequirements(4, 4, squish_flags);
|
||||
|
||||
compressed_image._page_size = page_size;
|
||||
compressed_image._image = PTA_uchar::empty_array(page_size * z_size);
|
||||
for (int z = 0; z < z_size; ++z) {
|
||||
unsigned char *dest_page = compressed_image._image.p() + z * page_size;
|
||||
unsigned const char *source_page = _ram_images[n]._image.p() + z * _ram_images[n]._page_size;
|
||||
unsigned const char *source_page_end = source_page + _ram_images[n]._page_size;
|
||||
// Convert one 4 x 4 cell at a time.
|
||||
unsigned char *d = dest_page;
|
||||
for (int y = 0; y < y_size; y += 4) {
|
||||
for (int x = 0; x < x_size; x += 4) {
|
||||
unsigned char tb[16 * 4];
|
||||
int mask = 0;
|
||||
unsigned char *t = tb;
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
int xi = x + i % 4;
|
||||
int yi = y + i / 4;
|
||||
unsigned const char *s = source_page + (yi * x_size + xi) * _num_components;
|
||||
if (s < source_page_end) {
|
||||
switch (_num_components) {
|
||||
case 1:
|
||||
t[0] = s[0]; // r
|
||||
t[1] = s[0]; // g
|
||||
t[2] = s[0]; // b
|
||||
t[3] = 255; // a
|
||||
break;
|
||||
|
||||
case 2:
|
||||
t[0] = s[0]; // r
|
||||
t[1] = s[0]; // g
|
||||
t[2] = s[0]; // b
|
||||
t[3] = s[1]; // a
|
||||
break;
|
||||
|
||||
case 3:
|
||||
t[0] = s[2]; // r
|
||||
t[1] = s[1]; // g
|
||||
t[2] = s[0]; // b
|
||||
t[3] = 255; // a
|
||||
break;
|
||||
|
||||
case 4:
|
||||
t[0] = s[2]; // r
|
||||
t[1] = s[1]; // g
|
||||
t[2] = s[0]; // b
|
||||
t[3] = s[3]; // a
|
||||
break;
|
||||
}
|
||||
mask |= (1 << i);
|
||||
}
|
||||
t += 4;
|
||||
}
|
||||
squish::CompressMasked(tb, mask, d, squish_flags);
|
||||
d += cell_size;
|
||||
Thread::consider_yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
compressed_ram_images.push_back(compressed_image);
|
||||
}
|
||||
_ram_images.swap(compressed_ram_images);
|
||||
_ram_image_compression = compression;
|
||||
++_image_modified;
|
||||
return true;
|
||||
|
||||
#else // HAVE_SQUISH
|
||||
return false;
|
||||
|
||||
#endif // HAVE_SQUISH
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::do_unsquish
|
||||
// Access: Private
|
||||
// Description: Invokes the squish library to uncompress the RAM
|
||||
// image(s).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Texture::
|
||||
do_unsquish(int squish_flags) {
|
||||
#ifdef HAVE_SQUISH
|
||||
if (_ram_images.empty()) {
|
||||
return false;
|
||||
}
|
||||
RamImages uncompressed_ram_images;
|
||||
uncompressed_ram_images.reserve(_ram_images.size());
|
||||
for (size_t n = 0; n < _ram_images.size(); ++n) {
|
||||
RamImage uncompressed_image;
|
||||
int x_size = do_get_expected_mipmap_x_size(n);
|
||||
int y_size = do_get_expected_mipmap_y_size(n);
|
||||
int z_size = do_get_expected_mipmap_z_size(n);
|
||||
int page_size = squish::GetStorageRequirements(x_size, y_size, squish_flags);
|
||||
int cell_size = squish::GetStorageRequirements(4, 4, squish_flags);
|
||||
|
||||
uncompressed_image._page_size = do_get_expected_ram_mipmap_page_size(n);
|
||||
uncompressed_image._image = PTA_uchar::empty_array(uncompressed_image._page_size * z_size);
|
||||
for (int z = 0; z < z_size; ++z) {
|
||||
unsigned char *dest_page = uncompressed_image._image.p() + z * uncompressed_image._page_size;
|
||||
unsigned char *dest_page_end = dest_page + uncompressed_image._page_size;
|
||||
unsigned const char *source_page = _ram_images[n]._image.p() + z * page_size;
|
||||
// Unconvert one 4 x 4 cell at a time.
|
||||
unsigned const char *s = source_page;
|
||||
for (int y = 0; y < y_size; y += 4) {
|
||||
for (int x = 0; x < x_size; x += 4) {
|
||||
unsigned char tb[16 * 4];
|
||||
squish::Decompress(tb, s, squish_flags);
|
||||
s += cell_size;
|
||||
|
||||
unsigned char *t = tb;
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
int xi = x + i % 4;
|
||||
int yi = y + i / 4;
|
||||
unsigned char *d = dest_page + (yi * x_size + xi) * _num_components;
|
||||
if (d < dest_page_end) {
|
||||
switch (_num_components) {
|
||||
case 1:
|
||||
d[0] = t[1]; // g
|
||||
break;
|
||||
|
||||
case 2:
|
||||
d[0] = t[1]; // g
|
||||
d[1] = t[3]; // a
|
||||
break;
|
||||
|
||||
case 3:
|
||||
d[2] = t[0]; // r
|
||||
d[1] = t[1]; // g
|
||||
d[0] = t[2]; // b
|
||||
break;
|
||||
|
||||
case 4:
|
||||
d[2] = t[0]; // r
|
||||
d[1] = t[1]; // g
|
||||
d[0] = t[2]; // b
|
||||
d[3] = t[3]; // a
|
||||
break;
|
||||
}
|
||||
}
|
||||
t += 4;
|
||||
}
|
||||
}
|
||||
Thread::consider_yield();
|
||||
}
|
||||
}
|
||||
uncompressed_ram_images.push_back(uncompressed_image);
|
||||
}
|
||||
_ram_images.swap(uncompressed_ram_images);
|
||||
_ram_image_compression = CM_off;
|
||||
++_image_modified;
|
||||
return true;
|
||||
|
||||
#else // HAVE_SQUISH
|
||||
return false;
|
||||
|
||||
#endif // HAVE_SQUISH
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::register_with_read_factory
|
||||
// Access: Public, Static
|
||||
|
@ -313,6 +313,11 @@ PUBLISHED:
|
||||
INLINE void set_keep_ram_image(bool keep_ram_image);
|
||||
virtual bool get_keep_ram_image() const;
|
||||
|
||||
INLINE bool compress_ram_image(CompressionMode compression = CM_on,
|
||||
QualityLevel quality_level = QL_default,
|
||||
GraphicsStateGuardianBase *gsg = NULL);
|
||||
INLINE bool uncompress_ram_image();
|
||||
|
||||
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;
|
||||
@ -475,6 +480,12 @@ 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 do_compress_ram_image(CompressionMode compression,
|
||||
QualityLevel quality_level,
|
||||
GraphicsStateGuardianBase *gsg);
|
||||
bool do_uncompress_ram_image();
|
||||
|
||||
bool do_reconsider_z_size(int z);
|
||||
bool do_reconsider_image_properties(int x_size, int y_size, int num_components,
|
||||
ComponentType component_type, int z,
|
||||
@ -607,6 +618,9 @@ private:
|
||||
const unsigned char *&q,
|
||||
size_t pixel_size, size_t row_size,
|
||||
size_t page_size);
|
||||
|
||||
bool do_squish(CompressionMode compression, int squish_flags);
|
||||
bool do_unsquish(int squish_flags);
|
||||
|
||||
protected:
|
||||
// Protects all of the members of this class.
|
||||
|
@ -920,6 +920,16 @@ try_load_cache(PT(Texture) &tex, BamCache *cache, const Filename &filename,
|
||||
if (!(options.get_texture_flags() & LoaderOptions::TF_preload)) {
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
tex->set_keep_ram_image(false);
|
||||
}
|
||||
|
@ -115,6 +115,7 @@ PUBLISHED:
|
||||
virtual int get_max_vertices_per_primitive() const=0;
|
||||
|
||||
virtual int get_max_texture_dimension() const=0;
|
||||
virtual bool get_supports_compressed_texture_format(int compression_mode) const=0;
|
||||
|
||||
virtual bool get_supports_multisample() const=0;
|
||||
virtual int get_supported_geom_rendering() const=0;
|
||||
|
@ -101,8 +101,9 @@ get_cache_textures() const {
|
||||
// Access: Published
|
||||
// Description: Indicates whether compressed texture files will be
|
||||
// stored in the cache, as compressed txo files. The
|
||||
// compression data is extracted from the GSG after the
|
||||
// texture has been loaded.
|
||||
// compressed data may either be generated in-CPU, via
|
||||
// the squish library, or it may be extracted from the
|
||||
// GSG after the texture has been loaded.
|
||||
//
|
||||
// This may be set in conjunction with
|
||||
// set_cache_textures(), or independently of it. If
|
||||
|
@ -1597,17 +1597,22 @@ prepare_texture(Texture *tex) {
|
||||
default:
|
||||
// Anything else is not supported.
|
||||
tinydisplay_cat.info()
|
||||
<< "not loading texture " << tex->get_name() << ": "
|
||||
<< "Not loading texture " << tex->get_name() << ": "
|
||||
<< tex->get_texture_type() << "\n";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Even though the texture might be compressed now, it might have an
|
||||
// available uncompressed version that we can load. So don't reject
|
||||
// it out-of-hand just because it's compressed.
|
||||
/*
|
||||
if (tex->get_ram_image_compression() != Texture::CM_off) {
|
||||
tinydisplay_cat.info()
|
||||
<< "not loading texture " << tex->get_name() << ": "
|
||||
<< "Not loading texture " << tex->get_name() << ": "
|
||||
<< tex->get_ram_image_compression() << "\n";
|
||||
return NULL;
|
||||
}
|
||||
*/
|
||||
|
||||
TinyTextureContext *gtc = new TinyTextureContext(_prepared_objects, tex);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user