16 #include "pandabase.h" 18 #include "config_gobj.h" 19 #include "config_util.h" 20 #include "texturePool.h" 21 #include "textureContext.h" 23 #include "bamCacheRecord.h" 25 #include "datagramIterator.h" 26 #include "bamReader.h" 27 #include "bamWriter.h" 28 #include "string_utils.h" 29 #include "preparedGraphicsObjects.h" 31 #include "pnmReader.h" 33 #include "virtualFileSystem.h" 34 #include "datagramInputFile.h" 35 #include "datagramOutputFile.h" 40 #include "pStatTimer.h" 42 #include "streamReader.h" 43 #include "texturePeeker.h" 44 #include "convert_srgb.h" 53 (
"texture-quality-level", Texture::QL_normal,
54 PRC_DESC(
"This specifies a global quality level for all textures. You " 55 "may specify either fastest, normal, or best. This actually " 56 "affects the meaning of Texture::set_quality_level(QL_default), " 57 "so it may be overridden on a per-texture basis. This generally " 58 "only has an effect when using the tinydisplay software renderer; " 59 "it has little or no effect on normal, hardware-accelerated " 60 "renderers. See Texture::set_quality_level()."));
62 PStatCollector Texture::_texture_read_pcollector(
"*:Texture:Read");
65 AutoTextureScale Texture::_textures_power_2 = ATS_unspecified;
70 #define DDS_MAGIC 0x20534444 74 #define DDSD_CAPS 0x00000001 75 #define DDSD_HEIGHT 0x00000002 76 #define DDSD_WIDTH 0x00000004 77 #define DDSD_PITCH 0x00000008 78 #define DDSD_PIXELFORMAT 0x00001000 79 #define DDSD_MIPMAPCOUNT 0x00020000 80 #define DDSD_LINEARSIZE 0x00080000 81 #define DDSD_DEPTH 0x00800000 84 #define DDPF_ALPHAPIXELS 0x00000001 85 #define DDPF_FOURCC 0x00000004 86 #define DDPF_INDEXED 0x00000020 87 #define DDPF_RGB 0x00000040 90 #define DDSCAPS_COMPLEX 0x00000008 91 #define DDSCAPS_TEXTURE 0x00001000 92 #define DDSCAPS_MIPMAP 0x00400000 95 #define DDSCAPS2_CUBEMAP 0x00000200 96 #define DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400 97 #define DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800 98 #define DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000 99 #define DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000 100 #define DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000 101 #define DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000 102 #define DDSCAPS2_VOLUME 0x00200000 105 unsigned int pf_size;
106 unsigned int pf_flags;
107 unsigned int four_cc;
108 unsigned int rgb_bitcount;
122 unsigned int dds_magic;
123 unsigned int dds_size;
124 unsigned int dds_flags;
129 unsigned int num_levels;
152 do_set_format(cdata, F_rgb);
153 do_set_component_type(cdata, T_unsigned_byte);
165 _cycler(copy._cycler),
166 _lock(copy.get_name()),
179 operator = (
const Texture ©) {
180 Namable::operator = (copy);
181 _cycler = copy._cycler;
192 nassertv(!_reloading);
208 do_setup_texture(cdata, TT_cube_map, size, size, 6, T_unsigned_byte, F_rgb);
209 PTA_uchar image = do_make_ram_image(cdata);
210 cdata->_keep_ram_image =
true;
212 cdata->inc_image_modified();
213 cdata->inc_properties_modified();
215 PN_stdfloat half_size = (PN_stdfloat)size * 0.5f;
216 PN_stdfloat center = half_size - 0.5f;
219 (127.5f, 0.0f, 0.0f, 0.0f,
220 0.0f, 127.5f, 0.0f, 0.0f,
221 0.0f, 0.0f, 127.5f, 0.0f,
222 127.5f, 127.5f, 127.5f, 1.0f);
224 unsigned char *p = image;
228 for (yi = 0; yi < size; ++yi) {
229 for (xi = 0; xi < size; ++xi) {
230 LVector3 vec(half_size, center - yi, center - xi);
234 *p++ = (
unsigned char)vec[2];
235 *p++ = (
unsigned char)vec[1];
236 *p++ = (
unsigned char)vec[0];
241 for (yi = 0; yi < size; ++yi) {
242 for (xi = 0; xi < size; ++xi) {
243 LVector3 vec(-half_size, center - yi, xi - center);
246 *p++ = (
unsigned char)vec[2];
247 *p++ = (
unsigned char)vec[1];
248 *p++ = (
unsigned char)vec[0];
253 for (yi = 0; yi < size; ++yi) {
254 for (xi = 0; xi < size; ++xi) {
255 LVector3 vec(xi - center, half_size, yi - center);
258 *p++ = (
unsigned char)vec[2];
259 *p++ = (
unsigned char)vec[1];
260 *p++ = (
unsigned char)vec[0];
265 for (yi = 0; yi < size; ++yi) {
266 for (xi = 0; xi < size; ++xi) {
267 LVector3 vec(xi - center, -half_size, center - yi);
270 *p++ = (
unsigned char)vec[2];
271 *p++ = (
unsigned char)vec[1];
272 *p++ = (
unsigned char)vec[0];
277 for (yi = 0; yi < size; ++yi) {
278 for (xi = 0; xi < size; ++xi) {
279 LVector3 vec(xi - center, center - yi, half_size);
282 *p++ = (
unsigned char)vec[2];
283 *p++ = (
unsigned char)vec[1];
284 *p++ = (
unsigned char)vec[0];
289 for (yi = 0; yi < size; ++yi) {
290 for (xi = 0; xi < size; ++xi) {
291 LVector3 vec(center - xi, center - yi, -half_size);
294 *p++ = (
unsigned char)vec[2];
295 *p++ = (
unsigned char)vec[1];
296 *p++ = (
unsigned char)vec[0];
313 do_setup_texture(cdata, TT_1d_texture, 256, 1, 1, T_unsigned_byte, F_alpha);
314 cdata->_default_sampler.set_wrap_u(SamplerState::WM_clamp);
315 cdata->_default_sampler.set_minfilter(SamplerState::FT_nearest);
316 cdata->_default_sampler.set_magfilter(SamplerState::FT_nearest);
318 cdata->_compression = CM_off;
320 cdata->inc_image_modified();
321 cdata->inc_properties_modified();
323 PTA_uchar image = do_make_ram_image(cdata);
324 cdata->_keep_ram_image =
true;
326 unsigned char *p = image;
327 for (
int xi = 0; xi < 256; ++xi) {
341 cdata->inc_properties_modified();
342 cdata->inc_image_modified();
343 return do_read(cdata, fullpath,
Filename(), 0, 0, 0, 0,
false,
false,
360 int primary_file_num_channels,
int alpha_file_channel,
364 cdata->inc_properties_modified();
365 cdata->inc_image_modified();
366 return do_read(cdata, fullpath, alpha_fullpath, primary_file_num_channels,
367 alpha_file_channel, 0, 0,
false,
false,
383 bool read_pages,
bool read_mipmaps,
386 cdata->inc_properties_modified();
387 cdata->inc_image_modified();
388 return do_read(cdata, fullpath,
Filename(), 0, 0, z, n, read_pages, read_mipmaps,
463 int primary_file_num_channels,
int alpha_file_channel,
464 int z,
int n,
bool read_pages,
bool read_mipmaps,
468 cdata->inc_properties_modified();
469 cdata->inc_image_modified();
470 return do_read(cdata, fullpath, alpha_fullpath, primary_file_num_channels,
471 alpha_file_channel, z, n, read_pages, read_mipmaps,
492 size_t pixels = cdata->_x_size * cdata->_y_size * cdata->_z_size;
495 switch (cdata->_format) {
496 case Texture::F_rgb332:
500 case Texture::F_alpha:
502 case Texture::F_green:
503 case Texture::F_blue:
504 case Texture::F_luminance:
505 case Texture::F_sluminance:
510 case Texture::F_luminance_alpha:
511 case Texture::F_luminance_alphamask:
512 case Texture::F_sluminance_alpha:
513 case Texture::F_rgba4:
514 case Texture::F_rgb5:
515 case Texture::F_rgba5:
519 case Texture::F_rgba:
520 case Texture::F_rgbm:
522 case Texture::F_srgb:
528 case Texture::F_color_index:
529 case Texture::F_rgb8:
530 case Texture::F_rgba8:
531 case Texture::F_srgb_alpha:
532 case Texture::F_rgb8i:
533 case Texture::F_rgba8i:
537 case Texture::F_depth_stencil:
541 case Texture::F_depth_component:
542 case Texture::F_depth_component16:
546 case Texture::F_depth_component24:
547 case Texture::F_depth_component32:
551 case Texture::F_rgba12:
552 case Texture::F_rgb12:
556 case Texture::F_rgba16:
559 case Texture::F_rgba32:
564 case Texture::F_rg8i:
567 case Texture::F_rg16:
570 case Texture::F_rgb16:
574 case Texture::F_r32i:
579 case Texture::F_rg32:
583 case Texture::F_rgb32:
591 size_t bytes = pixels * bpp;
593 bytes = (bytes * 4) / 3;
613 _aux_data[key] = aux_data;
625 _aux_data.erase(key);
638 AuxData::const_iterator di;
639 di = _aux_data.find(key);
640 if (di != _aux_data.end()) {
662 cdata->inc_properties_modified();
663 cdata->inc_image_modified();
664 return do_read_txo(cdata, in, filename);
680 make_from_txo(istream &in,
const string &filename) {
683 if (!din.
open(in, filename)) {
685 <<
"Could not read texture object: " << filename <<
"\n";
692 << filename <<
" is not a texture object file.\n";
696 if (head != _bam_header) {
698 << filename <<
" is not a texture object file.\n";
703 if (!reader.
init()) {
720 <<
"Texture object " << filename <<
" is empty.\n";
723 }
else if (!object->
is_of_type(Texture::get_class_type())) {
725 <<
"Texture object " << filename <<
" contains a " 726 <<
object->get_type() <<
", not a Texture.\n";
733 <<
"Unable to fully resolve texture object file.\n";
752 return do_write_txo(cdata, out, filename);
768 read_dds(istream &in,
const string &filename,
bool header_only) {
770 cdata->inc_properties_modified();
771 cdata->inc_image_modified();
772 return do_read_dds(cdata, in, filename, header_only);
788 RelatedTextures::const_iterator ti;
789 ti = _related_textures.find(suffix);
790 if (ti != _related_textures.end()) {
793 if (cdata->_fullpath.empty()) {
800 if (!cdata->_alpha_fullpath.empty()) {
801 Filename alph = cdata->_alpha_fullpath;
809 cdata->_primary_file_num_channels,
810 cdata->_alpha_file_channel,
false);
825 ((
Texture *)
this)->_related_textures.insert(RelatedTextures::value_type(suffix, res));
843 string format = upcase(supplied_format);
846 int imgsize = cdata->_x_size * cdata->_y_size;
847 nassertv(image.size() == (size_t)(cdata->_component_width * format.size() * imgsize));
850 if ((cdata->_num_components == 1 && format.size() == 1) ||
851 (cdata->_num_components == 2 && format.size() == 2 && format.at(1) ==
'A' && format.at(0) !=
'A') ||
852 (cdata->_num_components == 3 && format ==
"BGR") ||
853 (cdata->_num_components == 4 && format ==
"BGRA")) {
855 do_set_ram_image(cdata, image);
860 PTA_uchar newdata = PTA_uchar::empty_array(imgsize * cdata->_num_components * cdata->_component_width, get_class_type());
863 if (cdata->_component_width == 1) {
864 if (format ==
"RGBA" && cdata->_num_components == 4) {
866 for (
int p = 0; p < imgsize; p += 4) {
867 newdata[p + 2] = image[p ];
868 newdata[p + 1] = image[p + 1];
869 newdata[p ] = image[p + 2];
870 newdata[p + 3] = image[p + 3];
872 do_set_ram_image(cdata, newdata);
875 if (format ==
"RGB" && cdata->_num_components == 3) {
877 for (
int p = 0; p < imgsize; p += 3) {
878 newdata[p + 2] = image[p ];
879 newdata[p + 1] = image[p + 1];
880 newdata[p ] = image[p + 2];
882 do_set_ram_image(cdata, newdata);
885 if (format ==
"A" && cdata->_num_components != 3) {
887 int component = cdata->_num_components - 1;
888 for (
int p = 0; p < imgsize; ++p) {
889 newdata[component] = image[p];
891 do_set_ram_image(cdata, newdata);
894 for (
int p = 0; p < imgsize; ++p) {
895 for (uchar s = 0; s < format.size(); ++s) {
896 signed char component = -1;
897 if (format.at(s) ==
'B' || (cdata->_num_components <= 2 && format.at(s) !=
'A')) {
899 }
else if (format.at(s) ==
'G') {
901 }
else if (format.at(s) ==
'R') {
903 }
else if (format.at(s) ==
'A') {
904 nassertv(cdata->_num_components != 3);
905 component = cdata->_num_components - 1;
906 }
else if (format.at(s) ==
'0') {
908 }
else if (format.at(s) ==
'1') {
911 gobj_cat.error() <<
"Unexpected component character '" 912 << format.at(s) <<
"', expected one of RGBA!\n";
915 if (component >= 0) {
916 newdata[p * cdata->_num_components + component] = image[p * format.size() + s];
920 do_set_ram_image(cdata, newdata);
923 for (
int p = 0; p < imgsize; ++p) {
924 for (uchar s = 0; s < format.size(); ++s) {
925 signed char component = -1;
926 if (format.at(s) ==
'B' || (cdata->_num_components <= 2 && format.at(s) !=
'A')) {
928 }
else if (format.at(s) ==
'G') {
930 }
else if (format.at(s) ==
'R') {
932 }
else if (format.at(s) ==
'A') {
933 nassertv(cdata->_num_components != 3);
934 component = cdata->_num_components - 1;
935 }
else if (format.at(s) ==
'0') {
937 }
else if (format.at(s) ==
'1') {
940 gobj_cat.error() <<
"Unexpected component character '" 941 << format.at(s) <<
"', expected one of RGBA!\n";
944 if (component >= 0) {
945 memcpy((
void*)(newdata + (p * cdata->_num_components + component) * cdata->_component_width),
946 (
void*)(image + (p * format.size() + s) * cdata->_component_width),
947 cdata->_component_width);
951 do_set_ram_image(cdata, newdata);
966 return cdata->_keep_ram_image;
980 return do_has_bam_rawdata(cdata);
1004 if (cdata->_ram_images.empty() || cdata->_ram_images[0]._image.empty()) {
1016 int size = max(cdata->_x_size, max(cdata->_y_size, cdata->_z_size));
1022 if (n >= (
int)cdata->_ram_images.size() || cdata->_ram_images[n]._image.empty()) {
1041 if (n < (
int)cdata->_ram_images.size() && !cdata->_ram_images[n]._image.empty()) {
1042 return cdata->_ram_images[n]._image;
1058 if (n < (
int)cdata->_ram_images.size()) {
1059 return cdata->_ram_images[n]._pointer_image;
1081 nassertv(cdata->_ram_image_compression != CM_off || do_get_expected_ram_mipmap_image_size(cdata, n));
1083 while (n >= (
int)cdata->_ram_images.size()) {
1084 cdata->_ram_images.push_back(RamImage());
1087 cdata->_ram_images[n]._page_size = page_size;
1089 cdata->_ram_images[n]._pointer_image = image;
1090 cdata->inc_image_modified();
1118 if (n >= (
int)cdata->_ram_images.size()) {
1121 cdata->_ram_images[n]._page_size = 0;
1122 cdata->_ram_images[n]._image.clear();
1123 cdata->_ram_images[n]._pointer_image = NULL;
1135 cdata->_simple_image_date_generated = (PN_int32)time(NULL);
1136 return cdata->_simple_ram_image._image;
1149 nassertr(cdata->_texture_type == TT_2d_texture, PTA_uchar());
1150 size_t expected_page_size = (size_t)(x_size * y_size * 4);
1152 cdata->_simple_x_size = x_size;
1153 cdata->_simple_y_size = y_size;
1154 cdata->_simple_ram_image._image = PTA_uchar::empty_array(expected_page_size);
1155 cdata->_simple_ram_image._page_size = expected_page_size;
1156 cdata->_simple_image_date_generated = (PN_int32)time(NULL);
1157 cdata->inc_simple_image_modified();
1159 return cdata->_simple_ram_image._image;
1174 if (cdata->_texture_type != TT_2d_texture ||
1175 cdata->_ram_image_compression != CM_off) {
1180 if (!do_store_one(cdata, pnmimage, 0, 0)) {
1185 int x_size = simple_image_size.
get_word(0);
1186 int y_size = simple_image_size.
get_word(1);
1198 if (!scaled.has_alpha()) {
1200 scaled.alpha_fill(1.0);
1202 scaled.set_num_channels(4);
1207 did_anything =
false;
1211 int new_x_size = (x_size >> 1);
1212 PNMImage smaller(new_x_size, y_size, 4);
1214 PNMImage bigger(x_size, y_size, 4);
1217 if (compare_images(scaled, bigger)) {
1218 scaled.take_from(smaller);
1219 x_size = new_x_size;
1220 did_anything =
true;
1226 int new_y_size = (y_size >> 1);
1227 PNMImage smaller(x_size, new_y_size, 4);
1229 PNMImage bigger(x_size, y_size, 4);
1232 if (compare_images(scaled, bigger)) {
1233 scaled.take_from(smaller);
1234 y_size = new_y_size;
1235 did_anything =
true;
1238 }
while (did_anything);
1240 size_t expected_page_size = (size_t)(x_size * y_size * 4);
1241 PTA_uchar image = PTA_uchar::empty_array(expected_page_size, get_class_type());
1242 convert_from_pnmimage(image, expected_page_size, x_size, 0, 0, 0, scaled, 4, 1);
1244 do_set_simple_ram_image(cdata, image, x_size, y_size);
1245 cdata->_simple_image_date_generated = (PN_int32)time(NULL);
1266 CDWriter cdata(_cycler, unlocked_ensure_ram_image(
true));
1269 if (peeker->is_valid()) {
1303 PreparedViews::const_iterator pvi;
1304 pvi = _prepared_views.find(prepared_objects);
1305 if (pvi != _prepared_views.end()) {
1324 PreparedViews::const_iterator pvi;
1325 pvi = _prepared_views.find(prepared_objects);
1326 if (pvi != _prepared_views.end()) {
1327 const Contexts &contexts = (*pvi).second;
1328 for (
int view = 0; view < cdata->_num_views; ++view) {
1329 Contexts::const_iterator ci;
1330 ci = contexts.find(view);
1331 if (ci == contexts.end()) {
1360 PreparedViews::const_iterator pvi;
1361 size_t total_size = 0;
1362 pvi = _prepared_views.find(prepared_objects);
1363 if (pvi != _prepared_views.end()) {
1364 const Contexts &contexts = (*pvi).second;
1365 for (
int view = 0; view < cdata->_num_views; ++view) {
1366 Contexts::const_iterator ci;
1367 ci = contexts.find(view);
1368 if (ci != contexts.end()) {
1389 PreparedViews::const_iterator pvi;
1390 pvi = _prepared_views.find(prepared_objects);
1391 if (pvi != _prepared_views.end()) {
1392 const Contexts &contexts = (*pvi).second;
1393 for (
int view = 0; view < cdata->_num_views; ++view) {
1394 Contexts::const_iterator ci;
1395 ci = contexts.find(view);
1396 if (ci != contexts.end()) {
1419 PreparedViews::const_iterator pvi;
1420 pvi = _prepared_views.find(prepared_objects);
1421 if (pvi != _prepared_views.end()) {
1422 const Contexts &contexts = (*pvi).second;
1423 for (
int view = 0; view < cdata->_num_views; ++view) {
1424 Contexts::const_iterator ci;
1425 ci = contexts.find(view);
1426 if (ci != contexts.end()) {
1447 PreparedViews::iterator pvi;
1448 pvi = _prepared_views.find(prepared_objects);
1449 if (pvi != _prepared_views.end()) {
1451 temp.swap((*pvi).second);
1452 Contexts::iterator ci;
1453 for (ci = temp.begin(); ci != temp.end(); ++ci) {
1459 _prepared_views.erase(pvi);
1482 temp.swap(_prepared_views);
1483 int num_freed = (int)temp.size();
1485 PreparedViews::iterator pvi;
1486 for (pvi = temp.begin(); pvi != temp.end(); ++pvi) {
1489 temp.swap((*pvi).second);
1490 Contexts::iterator ci;
1491 for (ci = temp.begin(); ci != temp.end(); ++ci) {
1509 write(ostream &out,
int indent_level)
const {
1511 indent(out, indent_level)
1512 << cdata->_texture_type <<
" " << get_name();
1513 if (!cdata->_filename.empty()) {
1514 out <<
" (from " << cdata->_filename <<
")";
1518 indent(out, indent_level + 2);
1520 switch (cdata->_texture_type) {
1522 out <<
"1-d, " << cdata->_x_size;
1526 out <<
"2-d, " << cdata->_x_size <<
" x " << cdata->_y_size;
1530 out <<
"3-d, " << cdata->_x_size <<
" x " << cdata->_y_size <<
" x " << cdata->_z_size;
1533 case TT_2d_texture_array:
1534 out <<
"2-d array, " << cdata->_x_size <<
" x " << cdata->_y_size <<
" x " << cdata->_z_size;
1538 out <<
"cube map, " << cdata->_x_size <<
" x " << cdata->_y_size;
1542 if (cdata->_num_views > 1) {
1543 out <<
" (x " << cdata->_num_views <<
" views)";
1546 out <<
" pixels, each " << cdata->_num_components;
1548 switch (cdata->_component_type) {
1549 case T_unsigned_byte:
1553 case T_unsigned_short:
1561 case T_unsigned_int_24_8:
1571 switch (cdata->_format) {
1573 out <<
"color_index";
1575 case F_depth_stencil:
1576 out <<
"depth_stencil";
1578 case F_depth_component:
1579 out <<
"depth_component";
1581 case F_depth_component16:
1582 out <<
"depth_component16";
1584 case F_depth_component24:
1585 out <<
"depth_component24";
1587 case F_depth_component32:
1588 out <<
"depth_component32";
1647 case F_luminance_alpha:
1648 out <<
"luminance_alpha";
1650 case F_luminance_alphamask:
1651 out <<
"luminance_alphamask";
1668 out <<
"srgb_alpha";
1671 out <<
"sluminance";
1673 case F_sluminance_alpha:
1674 out <<
"sluminance_alpha";
1705 if (cdata->_compression != CM_default) {
1706 out <<
", compression " << cdata->_compression;
1710 indent(out, indent_level + 2);
1712 cdata->_default_sampler.output(out);
1714 if (do_has_ram_image(cdata)) {
1715 indent(out, indent_level + 2)
1716 << do_get_ram_image_size(cdata) <<
" bytes in ram, compression " 1717 << cdata->_ram_image_compression <<
"\n";
1719 if (cdata->_ram_images.size() > 1) {
1721 size_t total_size = 0;
1722 for (
size_t n = 1; n < cdata->_ram_images.size(); ++n) {
1723 if (!cdata->_ram_images[n]._image.empty()) {
1725 total_size += cdata->_ram_images[n]._image.size();
1731 indent(out, indent_level + 2)
1733 <<
" mipmap levels also present in ram (" << total_size
1738 indent(out, indent_level + 2)
1739 <<
"no ram image\n";
1742 if (!cdata->_simple_ram_image._image.empty()) {
1743 indent(out, indent_level + 2)
1744 <<
"simple image: " << cdata->_simple_x_size <<
" x " 1745 << cdata->_simple_y_size <<
", " 1746 << cdata->_simple_ram_image._image.size() <<
" bytes\n";
1761 if (do_get_auto_texture_scale(cdata) != ATS_none) {
1765 if (cdata->_texture_type == TT_3d_texture) {
1770 do_set_z_size(cdata, z);
1773 do_set_x_size(cdata, x);
1774 do_set_y_size(cdata, y);
1775 do_set_z_size(cdata, z);
1777 do_set_pad_size(cdata,
1780 cdata->_z_size - z);
1792 cdata->_orig_file_x_size = x;
1793 cdata->_orig_file_y_size = y;
1795 nassertv(z == cdata->_z_size);
1822 view = max(min(view, cdata->_num_views - 1), 0);
1825 Contexts &contexts = _prepared_views[prepared_objects];
1826 Contexts::const_iterator pvi;
1827 pvi = contexts.find(view);
1828 if (pvi != contexts.end()) {
1829 return (*pvi).second;
1833 contexts[view] = tc;
1849 int bit = get_next_higher_bit(((
unsigned int)value) - 1);
1864 int bit = get_next_higher_bit(((
unsigned int)value) >> 1);
1905 if (
adjust_size(new_x_size, new_y_size, name,
false, auto_texture_scale)) {
1931 return "1d_texture";
1933 return "2d_texture";
1935 return "3d_texture";
1936 case TT_2d_texture_array:
1937 return "2d_texture_array";
1941 return "**invalid**";
1952 if (cmp_nocase(str,
"1d_texture") == 0) {
1953 return TT_1d_texture;
1954 }
else if (cmp_nocase(str,
"2d_texture") == 0) {
1955 return TT_2d_texture;
1956 }
else if (cmp_nocase(str,
"3d_texture") == 0) {
1957 return TT_3d_texture;
1958 }
else if (cmp_nocase(str,
"2d_texture_array") == 0) {
1959 return TT_2d_texture_array;
1960 }
else if (cmp_nocase(str,
"cube_map") == 0) {
1965 <<
"Invalid Texture::TextureType value: " << str <<
"\n";
1966 return TT_2d_texture;
1978 case T_unsigned_byte:
1979 return "unsigned_byte";
1980 case T_unsigned_short:
1981 return "unsigned_short";
1984 case T_unsigned_int_24_8:
1985 return "unsigned_int_24_8";
1990 return "**invalid**";
2001 if (cmp_nocase(str,
"unsigned_byte") == 0) {
2002 return T_unsigned_byte;
2003 }
else if (cmp_nocase(str,
"unsigned_short") == 0) {
2004 return T_unsigned_short;
2005 }
else if (cmp_nocase(str,
"float") == 0) {
2007 }
else if (cmp_nocase(str,
"unsigned_int_24_8") == 0) {
2008 return T_unsigned_int_24_8;
2009 }
else if (cmp_nocase(str,
"int") == 0) {
2014 <<
"Invalid Texture::ComponentType value: " << str <<
"\n";
2015 return T_unsigned_byte;
2027 case F_depth_stencil:
2028 return "depth_stencil";
2029 case F_depth_component:
2030 return "depth_component";
2031 case F_depth_component16:
2032 return "depth_component16";
2033 case F_depth_component24:
2034 return "depth_component24";
2035 case F_depth_component32:
2036 return "depth_component32";
2038 return "color_index";
2071 case F_luminance_alpha:
2072 return "luminance_alpha";
2073 case F_luminance_alphamask:
2074 return "luminance_alphamask";
2088 return "srgb_alpha";
2090 return "sluminance";
2091 case F_sluminance_alpha:
2092 return "sluminance_alpha";
2110 return "**invalid**";
2121 if (cmp_nocase(str,
"depth_stencil") == 0) {
2122 return F_depth_stencil;
2123 }
else if (cmp_nocase(str,
"depth_component") == 0) {
2124 return F_depth_component;
2125 }
else if (cmp_nocase(str,
"depth_component16") == 0 || cmp_nocase(str,
"d16") == 0) {
2126 return F_depth_component16;
2127 }
else if (cmp_nocase(str,
"depth_component24") == 0 || cmp_nocase(str,
"d24") == 0) {
2128 return F_depth_component24;
2129 }
else if (cmp_nocase(str,
"depth_component32") == 0 || cmp_nocase(str,
"d32") == 0) {
2130 return F_depth_component32;
2131 }
else if (cmp_nocase(str,
"color_index") == 0) {
2132 return F_color_index;
2133 }
else if (cmp_nocase(str,
"red") == 0) {
2135 }
else if (cmp_nocase(str,
"green") == 0) {
2137 }
else if (cmp_nocase(str,
"blue") == 0) {
2139 }
else if (cmp_nocase(str,
"alpha") == 0) {
2141 }
else if (cmp_nocase(str,
"rgb") == 0) {
2143 }
else if (cmp_nocase(str,
"rgb5") == 0) {
2145 }
else if (cmp_nocase(str,
"rgb8") == 0 || cmp_nocase(str,
"r8g8b8") == 0) {
2147 }
else if (cmp_nocase(str,
"rgb12") == 0) {
2149 }
else if (cmp_nocase(str,
"rgb332") == 0 || cmp_nocase(str,
"r3g3b2") == 0) {
2151 }
else if (cmp_nocase(str,
"rgba") == 0) {
2153 }
else if (cmp_nocase(str,
"rgbm") == 0) {
2155 }
else if (cmp_nocase(str,
"rgba4") == 0) {
2157 }
else if (cmp_nocase(str,
"rgba5") == 0) {
2159 }
else if (cmp_nocase(str,
"rgba8") == 0 || cmp_nocase(str,
"r8g8b8a8") == 0) {
2161 }
else if (cmp_nocase(str,
"rgba12") == 0) {
2163 }
else if (cmp_nocase(str,
"luminance") == 0) {
2165 }
else if (cmp_nocase(str,
"luminance_alpha") == 0) {
2166 return F_luminance_alpha;
2167 }
else if (cmp_nocase(str,
"luminance_alphamask") == 0) {
2168 return F_luminance_alphamask;
2169 }
else if (cmp_nocase(str,
"rgba16") == 0 || cmp_nocase(str,
"r16g16b16a16") == 0) {
2171 }
else if (cmp_nocase(str,
"rgba32") == 0 || cmp_nocase(str,
"r32g32b32a32") == 0) {
2173 }
else if (cmp_nocase(str,
"r16") == 0 || cmp_nocase(str,
"red16") == 0) {
2175 }
else if (cmp_nocase(str,
"rg16") == 0 || cmp_nocase(str,
"r16g16") == 0) {
2177 }
else if (cmp_nocase(str,
"rgb16") == 0 || cmp_nocase(str,
"r16g16b16") == 0) {
2179 }
else if (cmp_nocase(str,
"srgb") == 0) {
2181 }
else if (cmp_nocase(str,
"srgb_alpha") == 0) {
2182 return F_srgb_alpha;
2183 }
else if (cmp_nocase(str,
"sluminance") == 0) {
2184 return F_sluminance;
2185 }
else if (cmp_nocase(str,
"sluminance_alpha") == 0) {
2186 return F_sluminance_alpha;
2187 }
else if (cmp_nocase(str,
"r32i") == 0) {
2189 }
else if (cmp_nocase(str,
"r32") == 0 || cmp_nocase(str,
"red32") == 0) {
2191 }
else if (cmp_nocase(str,
"rg32") == 0 || cmp_nocase(str,
"r32g32") == 0) {
2193 }
else if (cmp_nocase(str,
"rgb32") == 0 || cmp_nocase(str,
"r32g32b32") == 0) {
2198 <<
"Invalid Texture::Format value: " << str <<
"\n";
2235 return "**invalid**";
2246 if (cmp_nocase_uh(str,
"default") == 0) {
2248 }
else if (cmp_nocase_uh(str,
"off") == 0) {
2250 }
else if (cmp_nocase_uh(str,
"on") == 0) {
2252 }
else if (cmp_nocase_uh(str,
"fxt1") == 0) {
2254 }
else if (cmp_nocase_uh(str,
"dxt1") == 0) {
2256 }
else if (cmp_nocase_uh(str,
"dxt2") == 0) {
2258 }
else if (cmp_nocase_uh(str,
"dxt3") == 0) {
2260 }
else if (cmp_nocase_uh(str,
"dxt4") == 0) {
2262 }
else if (cmp_nocase_uh(str,
"dxt5") == 0) {
2264 }
else if (cmp_nocase_uh(str,
"pvr1_2bpp") == 0) {
2265 return CM_pvr1_2bpp;
2266 }
else if (cmp_nocase_uh(str,
"pvr1_4bpp") == 0) {
2267 return CM_pvr1_4bpp;
2271 <<
"Invalid Texture::CompressionMode value: " << str <<
"\n";
2295 return "**invalid**";
2306 if (cmp_nocase(str,
"default") == 0) {
2308 }
else if (cmp_nocase(str,
"fastest") == 0) {
2310 }
else if (cmp_nocase(str,
"normal") == 0) {
2312 }
else if (cmp_nocase(str,
"best") == 0) {
2317 <<
"Invalid Texture::QualityLevel value: " << str <<
"\n";
2337 if (!keep_texture_ram && !cdata->_keep_ram_image) {
2342 CDWriter cdataw(_cycler, cdata,
false);
2343 if (gobj_cat.is_debug()) {
2345 <<
"Dumping RAM for texture " << get_name() <<
"\n";
2347 do_clear_ram_image(cdataw);
2402 switch (compression) {
2431 case F_luminance_alpha:
2432 case F_luminance_alphamask:
2434 case F_sluminance_alpha:
2471 case F_sluminance_alpha:
2494 bool for_padding, AutoTextureScale auto_texture_scale) {
2495 bool exclude =
false;
2497 for (
int i = 0; i < num_excludes && !exclude; ++i) {
2499 if (pat.matches(name)) {
2504 int new_x_size = x_size;
2505 int new_y_size = y_size;
2508 new_x_size = (int)cfloor(new_x_size * texture_scale + 0.5);
2509 new_y_size = (int)cfloor(new_y_size * texture_scale + 0.5);
2513 new_x_size = min(max(new_x_size, (
int)texture_scale_limit), x_size);
2514 new_y_size = min(max(new_y_size, (
int)texture_scale_limit), y_size);
2517 AutoTextureScale ats = auto_texture_scale;
2518 if (ats == ATS_unspecified) {
2521 if (!for_padding && ats == ATS_pad) {
2541 case ATS_unspecified:
2545 ats = textures_square.get_value();
2546 if (!for_padding && ats == ATS_pad) {
2551 new_x_size = new_y_size = min(new_x_size, new_y_size);
2556 new_x_size = new_y_size = max(new_x_size, new_y_size);
2560 case ATS_unspecified:
2565 int max_dimension = max_texture_dimension;
2567 if (max_dimension < 0) {
2570 max_dimension = gsg->get_max_texture_dimension();
2574 if (max_dimension > 0) {
2575 new_x_size = min(new_x_size, (
int)max_dimension);
2576 new_y_size = min(new_y_size, (
int)max_dimension);
2580 if (x_size != new_x_size || y_size != new_y_size) {
2581 x_size = new_x_size;
2582 y_size = new_y_size;
2618 reconsider_dirty() {
2629 do_adjust_this_size(
const CData *cdata,
int &x_size,
int &y_size,
const string &name,
2630 bool for_padding)
const {
2631 return adjust_size(x_size, y_size, name, for_padding, cdata->_auto_texture_scale);
2641 do_read(CData *cdata,
const Filename &fullpath,
const Filename &alpha_fullpath,
2642 int primary_file_num_channels,
int alpha_file_channel,
2643 int z,
int n,
bool read_pages,
bool read_mipmaps,
2651 bool header_only = ((options.get_texture_flags() & (LoaderOptions::TF_preload | LoaderOptions::TF_preload_simple)) == 0);
2653 header_only =
false;
2656 if ((z == 0 || read_pages) && (n == 0 || read_mipmaps)) {
2659 do_clear_ram_image(cdata);
2662 if (is_txo_filename(fullpath)) {
2666 return do_read_txo_file(cdata, fullpath);
2669 if (is_dds_filename(fullpath)) {
2673 return do_read_dds_file(cdata, fullpath, header_only);
2686 switch (cdata->_texture_type) {
2702 if (options.get_texture_flags() & LoaderOptions::TF_multiview) {
2707 do_set_num_views(cdata, num_views);
2713 if (read_pages && read_mipmaps) {
2717 do_set_z_size(cdata, z_size);
2725 z_size = do_get_expected_mipmap_z_size(cdata, n);
2735 <<
"Filename requires two different hash sequences: " << fullpath
2743 if ((n_size == 0 && (vfs->
exists(file) || n == 0)) ||
2744 (n_size != 0 && n < n_size)) {
2751 int num_pages = z_size * num_views;
2752 while ((num_pages == 0 && (vfs->
exists(file) || z == 0)) ||
2753 (num_pages != 0 && z < num_pages)) {
2754 if (!do_read_one(cdata, file, alpha_file, z, n, primary_file_num_channels,
2755 alpha_file_channel, options, header_only, record)) {
2765 if (n == 0 && n_size == 0) {
2769 n_size = do_get_expected_num_mipmap_levels(cdata);
2773 cdata->_fullpath = fullpath_pattern;
2774 cdata->_alpha_fullpath = alpha_fullpath_pattern;
2776 }
else if (read_pages) {
2780 if (!fullpath_pattern.
has_hash()) {
2782 <<
"Filename requires a hash mark: " << fullpath
2787 do_set_z_size(cdata, z_size);
2792 int num_pages = z_size * num_views;
2793 while ((num_pages == 0 && (vfs->
exists(file) || z == 0)) ||
2794 (num_pages != 0 && z < num_pages)) {
2795 if (!do_read_one(cdata, file, alpha_file, z, 0, primary_file_num_channels,
2796 alpha_file_channel, options, header_only, record)) {
2804 cdata->_fullpath = fullpath_pattern;
2805 cdata->_alpha_fullpath = alpha_fullpath_pattern;
2807 }
else if (read_mipmaps) {
2811 if (!fullpath_pattern.
has_hash()) {
2813 <<
"Filename requires a hash mark: " << fullpath
2822 while ((n_size == 0 && (vfs->
exists(file) || n == 0)) ||
2823 (n_size != 0 && n < n_size)) {
2824 if (!do_read_one(cdata, file, alpha_file, z, n,
2825 primary_file_num_channels, alpha_file_channel,
2826 options, header_only, record)) {
2831 if (n_size == 0 && n >= do_get_expected_num_mipmap_levels(cdata)) {
2840 cdata->_fullpath = fullpath_pattern;
2841 cdata->_alpha_fullpath = alpha_fullpath_pattern;
2845 if (!do_read_one(cdata, fullpath, alpha_fullpath, z, n,
2846 primary_file_num_channels, alpha_file_channel,
2847 options, header_only, record)) {
2852 cdata->_has_read_pages = read_pages;
2853 cdata->_has_read_mipmaps = read_mipmaps;
2854 cdata->_num_mipmap_levels_read = cdata->_ram_images.size();
2860 do_clear_ram_image(cdata);
2862 if ((options.get_texture_flags() & LoaderOptions::TF_preload) != 0) {
2865 bool generate_mipmaps = ((options.get_texture_flags() & LoaderOptions::TF_generate_mipmaps) != 0);
2866 do_consider_auto_process_ram_image(cdata, generate_mipmaps ||
uses_mipmaps(),
true);
2881 do_read_one(CData *cdata,
const Filename &fullpath,
const Filename &alpha_fullpath,
2882 int z,
int n,
int primary_file_num_channels,
int alpha_file_channel,
2885 nassertr(!header_only,
false);
2892 if (image_reader == NULL) {
2894 <<
"Texture::read() - couldn't read: " << fullpath << endl;
2899 AutoTextureScale auto_texture_scale = do_get_auto_texture_scale(cdata);
2903 bool read_floating_point;
2904 int texture_load_type = (options.get_texture_flags() & (LoaderOptions::TF_integer | LoaderOptions::TF_float));
2905 switch (texture_load_type) {
2906 case LoaderOptions::TF_integer:
2907 read_floating_point =
false;
2910 case LoaderOptions::TF_float:
2911 read_floating_point =
true;
2918 if (!alpha_fullpath.empty()) {
2919 read_floating_point =
false;
2923 if (header_only || textures_header_only) {
2926 if (z == 0 && n == 0) {
2927 cdata->_orig_file_x_size = x_size;
2928 cdata->_orig_file_y_size = y_size;
2931 if (textures_header_only) {
2941 if (read_floating_point) {
2947 image.
fill(0.2, 0.3, 1.0);
2952 delete image_reader;
2955 if (z == 0 && n == 0) {
2959 cdata->_orig_file_x_size = x_size;
2960 cdata->_orig_file_y_size = y_size;
2966 image.
set_read_size(do_get_expected_mipmap_x_size(cdata, n),
2967 do_get_expected_mipmap_y_size(cdata, n));
2973 <<
"Implicitly rescaling " << fullpath.
get_basename() <<
" from " 2980 if (read_floating_point) {
2981 success = pfm.
read(image_reader);
2983 success = image.
read(image_reader);
2988 <<
"Texture::read() - couldn't read: " << fullpath << endl;
2995 if (!alpha_fullpath.empty()) {
2997 if (alpha_image_reader == NULL) {
2999 <<
"Texture::read() - couldn't read: " << alpha_fullpath << endl;
3008 if (header_only || textures_header_only) {
3014 alpha_image.
fill(1.0);
3018 delete alpha_image_reader;
3024 <<
"Implicitly rescaling " << alpha_fullpath.
get_basename()
3025 <<
" from " << alpha_image.
get_x_size() <<
" by " 3031 if (!alpha_image.
read(alpha_image_reader)) {
3033 <<
"Texture::read() - couldn't read (alpha): " << alpha_fullpath << endl;
3040 if (z == 0 && n == 0) {
3044 if (cdata->_filename.empty()) {
3045 cdata->_filename = fullpath;
3046 cdata->_alpha_filename = alpha_fullpath;
3051 cdata->_keep_ram_image =
false;
3054 cdata->_fullpath = fullpath;
3055 cdata->_alpha_fullpath = alpha_fullpath;
3058 if (!alpha_fullpath.empty()) {
3065 <<
"Automatically rescaling " << alpha_fullpath.
get_basename()
3066 <<
" from " << alpha_image.
get_x_size() <<
" by " 3076 alpha_image = scaled;
3081 consider_downgrade(image, primary_file_num_channels, get_name());
3083 cdata->_alpha_file_channel = 0;
3086 if (!alpha_fullpath.empty()) {
3091 if (alpha_file_channel == 4 ||
3096 << alpha_fullpath.
get_basename() <<
" has no channel " << alpha_file_channel <<
".\n";
3099 for (
int x = 0; x < image.
get_x_size(); x++) {
3100 for (
int y = 0; y < image.
get_y_size(); y++) {
3107 }
else if (alpha_file_channel >= 1 && alpha_file_channel <= 3 &&
3110 for (
int x = 0; x < image.
get_x_size(); x++) {
3111 for (
int y = 0; y < image.
get_y_size(); y++) {
3115 cdata->_alpha_file_channel = alpha_file_channel;
3119 for (
int x = 0; x < image.
get_x_size(); x++) {
3120 for (
int y = 0; y < image.
get_y_size(); y++) {
3124 cdata->_alpha_file_channel = 0;
3128 if (read_floating_point) {
3129 if (!do_load_one(cdata, pfm, fullpath.
get_basename(), z, n, options)) {
3137 if (do_get_auto_texture_scale(cdata) == ATS_pad) {
3140 if (do_adjust_this_size(cdata, new_x_size, new_y_size, fullpath.
get_basename(),
true)) {
3141 pad_x_size = new_x_size - image.
get_x_size();
3142 pad_y_size = new_y_size - image.
get_y_size();
3151 if (!do_load_one(cdata, image, fullpath.
get_basename(), z, n, options)) {
3155 do_set_pad_size(cdata, pad_x_size, pad_y_size, 0);
3167 do_load_one(CData *cdata,
const PNMImage &pnmimage,
const string &name,
int z,
int n,
3169 if (cdata->_ram_images.size() <= 1 && n == 0) {
3173 if (!do_reconsider_z_size(cdata, z, options)) {
3176 nassertr(z >= 0 && z < cdata->_z_size * cdata->_num_views,
false);
3179 ComponentType component_type = T_unsigned_byte;
3182 component_type = T_unsigned_short;
3192 do_modify_ram_image(cdata);
3193 cdata->_loaded_from_image =
true;
3196 do_modify_ram_mipmap_image(cdata, n);
3199 int x_size = do_get_expected_mipmap_x_size(cdata, n);
3200 int y_size = do_get_expected_mipmap_y_size(cdata, n);
3204 <<
"Automatically rescaling " << name;
3206 gobj_cat.info(
false)
3207 <<
" mipmap level " << n;
3209 gobj_cat.info(
false)
3210 <<
" from " << pnmimage.
get_x_size() <<
" by " 3211 << pnmimage.
get_y_size() <<
" to " << x_size <<
" by " 3220 convert_from_pnmimage(cdata->_ram_images[n]._image,
3221 do_get_expected_ram_mipmap_page_size(cdata, n),
3222 x_size, 0, 0, z, scaled,
3223 cdata->_num_components, cdata->_component_width);
3227 convert_from_pnmimage(cdata->_ram_images[n]._image,
3228 do_get_expected_ram_mipmap_page_size(cdata, n),
3229 x_size, 0, 0, z, pnmimage,
3230 cdata->_num_components, cdata->_component_width);
3244 do_load_one(CData *cdata,
const PfmFile &pfm,
const string &name,
int z,
int n,
3246 if (cdata->_ram_images.size() <= 1 && n == 0) {
3250 if (!do_reconsider_z_size(cdata, z, options)) {
3253 nassertr(z >= 0 && z < cdata->_z_size * cdata->_num_views,
false);
3256 ComponentType component_type = T_float;
3264 do_modify_ram_image(cdata);
3265 cdata->_loaded_from_image =
true;
3268 do_modify_ram_mipmap_image(cdata, n);
3271 int x_size = do_get_expected_mipmap_x_size(cdata, n);
3272 int y_size = do_get_expected_mipmap_y_size(cdata, n);
3276 <<
"Automatically rescaling " << name;
3278 gobj_cat.info(
false)
3279 <<
" mipmap level " << n;
3281 gobj_cat.info(
false)
3283 << pfm.
get_y_size() <<
" to " << x_size <<
" by " 3287 scaled.
resize(x_size, y_size);
3290 convert_from_pfm(cdata->_ram_images[n]._image,
3291 do_get_expected_ram_mipmap_page_size(cdata, n), z,
3292 scaled, cdata->_num_components, cdata->_component_width);
3296 convert_from_pfm(cdata->_ram_images[n]._image,
3297 do_get_expected_ram_mipmap_page_size(cdata, n), z,
3298 pfm, cdata->_num_components, cdata->_component_width);
3312 do_load_sub_image(CData *cdata,
const PNMImage &image,
int x,
int y,
int z,
int n) {
3313 nassertr(n >= 0 && (
size_t)n < cdata->_ram_images.size(),
false);
3315 int tex_x_size = do_get_expected_mipmap_x_size(cdata, n);
3316 int tex_y_size = do_get_expected_mipmap_y_size(cdata, n);
3317 int tex_z_size = do_get_expected_mipmap_z_size(cdata, n);
3319 nassertr(x >= 0 && x < tex_x_size,
false);
3320 nassertr(y >= 0 && y < tex_y_size,
false);
3321 nassertr(z >= 0 && z < tex_z_size,
false);
3323 nassertr(image.
get_x_size() + x <= tex_x_size,
false);
3324 nassertr(image.
get_y_size() + y <= tex_y_size,
false);
3327 y = cdata->_y_size - (image.
get_y_size() + y);
3329 cdata->inc_image_modified();
3330 do_modify_ram_mipmap_image(cdata, n);
3331 convert_from_pnmimage(cdata->_ram_images[n]._image,
3332 do_get_expected_ram_mipmap_page_size(cdata, n),
3333 tex_x_size, x, y, z, image,
3334 cdata->_num_components, cdata->_component_width);
3346 do_read_txo_file(CData *cdata,
const Filename &fullpath) {
3349 Filename filename = Filename::binary_filename(fullpath);
3354 <<
"Could not find " << fullpath <<
"\n";
3358 if (gobj_cat.is_debug()) {
3360 <<
"Reading texture object " << filename <<
"\n";
3363 istream *in = file->open_read_file(
true);
3364 bool success = do_read_txo(cdata, *in, fullpath);
3367 cdata->_fullpath = fullpath;
3368 cdata->_alpha_fullpath =
Filename();
3369 cdata->_keep_ram_image =
false;
3380 do_read_txo(CData *cdata, istream &in,
const string &filename) {
3381 PT(
Texture) other = make_from_txo(in, filename);
3382 if (other == (
Texture *)NULL) {
3386 CDReader cdata_other(other->_cycler);
3387 Namable::operator = (*other);
3388 do_assign(cdata, other, cdata_other);
3390 cdata->_loaded_from_image =
true;
3391 cdata->_loaded_from_txo =
true;
3392 cdata->_has_read_pages =
false;
3393 cdata->_has_read_mipmaps =
false;
3394 cdata->_num_mipmap_levels_read = 0;
3405 do_read_dds_file(CData *cdata,
const Filename &fullpath,
bool header_only) {
3408 Filename filename = Filename::binary_filename(fullpath);
3413 <<
"Could not find " << fullpath <<
"\n";
3417 if (gobj_cat.is_debug()) {
3419 <<
"Reading DDS file " << filename <<
"\n";
3422 istream *in = file->open_read_file(
true);
3423 bool success = do_read_dds(cdata, *in, fullpath, header_only);
3430 cdata->_fullpath = fullpath;
3431 cdata->_alpha_fullpath =
Filename();
3432 cdata->_keep_ram_image =
false;
3443 do_read_dds(CData *cdata, istream &in,
const string &filename,
bool header_only) {
3477 if (header.dds_magic != DDS_MAGIC || (in.fail() || in.eof())) {
3479 << filename <<
" is not a DDS file.\n";
3483 if ((header.dds_flags & DDSD_MIPMAPCOUNT) == 0) {
3485 header.num_levels = 1;
3487 }
else if (header.num_levels == 0) {
3490 header.num_levels = 1;
3493 TextureType texture_type;
3494 if (header.caps.caps2 & DDSCAPS2_CUBEMAP) {
3495 static const unsigned int all_faces =
3496 (DDSCAPS2_CUBEMAP_POSITIVEX |
3497 DDSCAPS2_CUBEMAP_POSITIVEY |
3498 DDSCAPS2_CUBEMAP_POSITIVEZ |
3499 DDSCAPS2_CUBEMAP_NEGATIVEX |
3500 DDSCAPS2_CUBEMAP_NEGATIVEY |
3501 DDSCAPS2_CUBEMAP_NEGATIVEZ);
3502 if ((header.caps.caps2 & all_faces) != all_faces) {
3504 << filename <<
" is missing some cube map faces; cannot load.\n";
3508 texture_type = TT_cube_map;
3510 }
else if (header.caps.caps2 & DDSCAPS2_VOLUME) {
3511 texture_type = TT_3d_texture;
3514 texture_type = TT_2d_texture;
3519 typedef PTA_uchar (*ReadDDSLevelFunc)(
Texture *tex, Texture::CData *cdata,
3520 const DDSHeader &header,
int n, istream &in);
3521 ReadDDSLevelFunc func = NULL;
3523 Format format = F_rgb;
3525 do_clear_ram_image(cdata);
3526 CompressionMode compression = CM_off;
3528 if (header.pf.pf_flags & DDPF_FOURCC) {
3530 if (texture_type == TT_3d_texture) {
3532 << filename <<
": unsupported compression on 3-d texture.\n";
3536 if (header.pf.four_cc == 0x31545844) {
3537 compression = CM_dxt1;
3538 func = read_dds_level_dxt1;
3539 }
else if (header.pf.four_cc == 0x32545844) {
3540 compression = CM_dxt2;
3541 func = read_dds_level_dxt23;
3542 }
else if (header.pf.four_cc == 0x33545844) {
3543 compression = CM_dxt3;
3544 func = read_dds_level_dxt23;
3545 }
else if (header.pf.four_cc == 0x34545844) {
3546 compression = CM_dxt4;
3547 func = read_dds_level_dxt45;
3548 }
else if (header.pf.four_cc == 0x35545844) {
3549 compression = CM_dxt5;
3550 func = read_dds_level_dxt45;
3553 << filename <<
": unsupported texture compression.\n";
3563 func = read_dds_level_generic_uncompressed;
3565 if (header.pf.pf_flags & DDPF_ALPHAPIXELS) {
3568 if (header.pf.rgb_bitcount == 32 &&
3569 header.pf.r_mask == 0x000000ff &&
3570 header.pf.g_mask == 0x0000ff00 &&
3571 header.pf.b_mask == 0x00ff0000 &&
3572 header.pf.a_mask == 0xff000000U) {
3573 func = read_dds_level_abgr8;
3574 }
else if (header.pf.rgb_bitcount == 32 &&
3575 header.pf.r_mask == 0x00ff0000 &&
3576 header.pf.g_mask == 0x0000ff00 &&
3577 header.pf.b_mask == 0x000000ff &&
3578 header.pf.a_mask == 0xff000000U) {
3579 func = read_dds_level_rgba8;
3581 }
else if (header.pf.r_mask != 0 &&
3582 header.pf.g_mask == 0 &&
3583 header.pf.b_mask == 0) {
3584 func = read_dds_level_luminance_uncompressed;
3585 format = F_luminance_alpha;
3589 if (header.pf.rgb_bitcount == 24 &&
3590 header.pf.r_mask == 0x00ff0000 &&
3591 header.pf.g_mask == 0x0000ff00 &&
3592 header.pf.b_mask == 0x000000ff) {
3593 func = read_dds_level_bgr8;
3594 }
else if (header.pf.rgb_bitcount == 24 &&
3595 header.pf.r_mask == 0x000000ff &&
3596 header.pf.g_mask == 0x0000ff00 &&
3597 header.pf.b_mask == 0x00ff0000) {
3598 func = read_dds_level_rgb8;
3600 }
else if (header.pf.r_mask != 0 &&
3601 header.pf.g_mask == 0 &&
3602 header.pf.b_mask == 0) {
3603 func = read_dds_level_luminance_uncompressed;
3604 format = F_luminance;
3609 do_setup_texture(cdata, texture_type, header.width, header.height, header.depth,
3610 T_unsigned_byte, format);
3612 cdata->_orig_file_x_size = cdata->_x_size;
3613 cdata->_orig_file_y_size = cdata->_y_size;
3614 cdata->_compression = compression;
3615 cdata->_ram_image_compression = compression;
3618 switch (texture_type) {
3623 for (
int n = 0; n < (int)header.num_levels; ++n) {
3624 int z_size = do_get_expected_mipmap_z_size(cdata, n);
3626 size_t page_size = 0;
3628 for (z = 0; z < z_size; ++z) {
3629 PTA_uchar page = func(
this, cdata, header, n, in);
3630 if (page.is_null()) {
3633 nassertr(page_size == 0 || page_size == page.size(),
false);
3634 page_size = page.size();
3635 pages.push_back(page);
3640 PTA_uchar image = PTA_uchar::empty_array(page_size * z_size);
3641 unsigned char *imagep = (
unsigned char *)image.p();
3642 for (z = 0; z < z_size; ++z) {
3643 int fz = z_size - 1 - z;
3644 memcpy(imagep + z * page_size, pages[fz].p(), page_size);
3647 do_set_ram_mipmap_image(cdata, n, image, page_size);
3659 for (z = 0; z < 6; ++z) {
3662 levels.reserve(header.num_levels);
3664 for (n = 0; n < (int)header.num_levels; ++n) {
3665 PTA_uchar image = func(
this, cdata, header, n, in);
3666 if (image.is_null()) {
3669 levels.push_back(image);
3676 static const int level_remap[6] = {
3679 for (n = 0; n < (int)header.num_levels; ++n) {
3680 size_t page_size = pages[0][n].size();
3681 PTA_uchar image = PTA_uchar::empty_array(page_size * 6);
3682 unsigned char *imagep = (
unsigned char *)image.p();
3683 for (z = 0; z < 6; ++z) {
3684 int fz = level_remap[z];
3685 nassertr(pages[fz][n].size() == page_size,
false);
3686 memcpy(imagep + z * page_size, pages[fz][n].p(), page_size);
3689 do_set_ram_mipmap_image(cdata, n, image, page_size);
3697 for (
int n = 0; n < (int)header.num_levels; ++n) {
3698 PTA_uchar image = func(
this, cdata, header, n, in);
3699 if (image.is_null()) {
3702 do_set_ram_mipmap_image(cdata, n, image, 0);
3706 cdata->_has_read_pages =
true;
3707 cdata->_has_read_mipmaps =
true;
3708 cdata->_num_mipmap_levels_read = cdata->_ram_images.size();
3711 if (in.fail() || in.eof()) {
3713 << filename <<
": truncated DDS file.\n";
3717 cdata->_loaded_from_image =
true;
3718 cdata->_loaded_from_txo =
true;
3730 do_write(CData *cdata,
3731 const Filename &fullpath,
int z,
int n,
bool write_pages,
bool write_mipmaps) {
3732 if (is_txo_filename(fullpath)) {
3733 if (!do_has_bam_rawdata(cdata)) {
3734 do_get_bam_rawdata(cdata);
3736 nassertr(do_has_bam_rawdata(cdata),
false);
3737 return do_write_txo_file(cdata, fullpath);
3740 if (!do_has_uncompressed_ram_image(cdata)) {
3741 do_get_uncompressed_ram_image(cdata);
3744 nassertr(do_has_ram_mipmap_image(cdata, n),
false);
3745 nassertr(cdata->_ram_image_compression == CM_off,
false);
3747 if (write_pages && write_mipmaps) {
3750 int num_levels = cdata->_ram_images.size();
3752 for (
int n = 0; n < num_levels; ++n) {
3753 int num_pages = do_get_expected_mipmap_num_pages(cdata, n);
3755 for (z = 0; z < num_pages; ++z) {
3760 <<
"Filename requires two different hash sequences: " << fullpath
3771 }
else if (write_pages) {
3774 if (!fullpath_pattern.
has_hash()) {
3776 <<
"Filename requires a hash mark: " << fullpath
3781 int num_pages = cdata->_z_size * cdata->_num_views;
3782 for (z = 0; z < num_pages; ++z) {
3788 }
else if (write_mipmaps) {
3791 if (!fullpath_pattern.
has_hash()) {
3793 <<
"Filename requires a hash mark: " << fullpath
3798 int num_levels = cdata->_ram_images.size();
3799 for (
int n = 0; n < num_levels; ++n) {
3807 if (!do_write_one(cdata, fullpath, z, n)) {
3822 do_write_one(CData *cdata,
const Filename &fullpath,
int z,
int n) {
3823 if (!do_has_ram_mipmap_image(cdata, n)) {
3827 nassertr(cdata->_ram_image_compression == CM_off,
false);
3830 if (cdata->_component_type == T_float) {
3833 if (!do_store_one(cdata, pfm, z, n)) {
3836 success = pfm.
write(fullpath);
3840 if (!do_store_one(cdata, pnmimage, z, n)) {
3843 success = pnmimage.
write(fullpath);
3848 <<
"Texture::write() - couldn't write: " << fullpath << endl;
3862 do_store_one(CData *cdata,
PNMImage &pnmimage,
int z,
int n) {
3864 do_get_uncompressed_ram_image(cdata);
3866 if (!do_has_ram_mipmap_image(cdata, n)) {
3870 nassertr(z >= 0 && z < do_get_expected_mipmap_num_pages(cdata, n),
false);
3871 nassertr(cdata->_ram_image_compression == CM_off,
false);
3873 if (cdata->_component_type == T_float) {
3876 bool success = convert_to_pfm(pfm,
3877 do_get_expected_mipmap_x_size(cdata, n),
3878 do_get_expected_mipmap_y_size(cdata, n),
3879 cdata->_num_components, cdata->_component_width,
3880 cdata->_ram_images[n]._image,
3881 do_get_ram_mipmap_page_size(cdata, n), z);
3885 return pfm.
store(pnmimage);
3888 return convert_to_pnmimage(pnmimage,
3889 do_get_expected_mipmap_x_size(cdata, n),
3890 do_get_expected_mipmap_y_size(cdata, n),
3891 cdata->_num_components, cdata->_component_width,
3892 cdata->_ram_images[n]._image,
3893 do_get_ram_mipmap_page_size(cdata, n), z);
3903 do_store_one(CData *cdata,
PfmFile &pfm,
int z,
int n) {
3905 do_get_uncompressed_ram_image(cdata);
3907 if (!do_has_ram_mipmap_image(cdata, n)) {
3911 nassertr(z >= 0 && z < do_get_expected_mipmap_num_pages(cdata, n),
false);
3912 nassertr(cdata->_ram_image_compression == CM_off,
false);
3914 if (cdata->_component_type != T_float) {
3917 bool success = convert_to_pnmimage(pnmimage,
3918 do_get_expected_mipmap_x_size(cdata, n),
3919 do_get_expected_mipmap_y_size(cdata, n),
3920 cdata->_num_components, cdata->_component_width,
3921 cdata->_ram_images[n]._image,
3922 do_get_ram_mipmap_page_size(cdata, n), z);
3926 return pfm.
load(pnmimage);
3929 return convert_to_pfm(pfm,
3930 do_get_expected_mipmap_x_size(cdata, n),
3931 do_get_expected_mipmap_y_size(cdata, n),
3932 cdata->_num_components, cdata->_component_width,
3933 cdata->_ram_images[n]._image,
3934 do_get_ram_mipmap_page_size(cdata, n), z);
3944 do_write_txo_file(
const CData *cdata,
const Filename &fullpath)
const {
3946 Filename filename = Filename::binary_filename(fullpath);
3950 <<
"Unable to open " << filename <<
"\n";
3954 bool success = do_write_txo(cdata, *out, fullpath);
3965 do_write_txo(
const CData *cdata, ostream &out,
const string &filename)
const {
3968 if (!dout.
open(out, filename)) {
3970 <<
"Could not write texture object: " << filename <<
"\n";
3976 <<
"Unable to write to " << filename <<
"\n";
3981 if (!writer.
init()) {
3991 if (!do_has_bam_rawdata(cdata)) {
3993 << get_name() <<
" does not have ram image\n";
4020 Texture::CData *Texture::
4021 unlocked_ensure_ram_image(
bool allow_compression) {
4027 while (_reloading) {
4032 const CData *cdata = _cycler.
read(current_thread);
4034 if (has_ram_image && !allow_compression && cdata->_ram_image_compression != Texture::CM_off) {
4037 has_ram_image =
false;
4039 if (has_ram_image || !do_can_reload(cdata)) {
4046 nassertr(!_reloading, NULL);
4049 PT(
Texture) tex = do_make_copy(cdata);
4055 CDWriter cdata_tex(tex->_cycler,
true);
4056 tex->do_reload_ram_image(cdata_tex, allow_compression);
4068 cdataw->_orig_file_x_size = cdata_tex->_orig_file_x_size;
4069 cdataw->_orig_file_y_size = cdata_tex->_orig_file_y_size;
4073 if (cdata_tex->_x_size != cdataw->_x_size ||
4074 cdata_tex->_y_size != cdataw->_y_size ||
4075 cdata_tex->_z_size != cdataw->_z_size ||
4076 cdata_tex->_num_views != cdataw->_num_views ||
4077 cdata_tex->_num_components != cdataw->_num_components ||
4078 cdata_tex->_component_width != cdataw->_component_width ||
4079 cdata_tex->_texture_type != cdataw->_texture_type ||
4080 cdata_tex->_component_type != cdataw->_component_type) {
4082 cdataw->_x_size = cdata_tex->_x_size;
4083 cdataw->_y_size = cdata_tex->_y_size;
4084 cdataw->_z_size = cdata_tex->_z_size;
4085 cdataw->_num_views = cdata_tex->_num_views;
4087 cdataw->_num_components = cdata_tex->_num_components;
4088 cdataw->_component_width = cdata_tex->_component_width;
4089 cdataw->_texture_type = cdata_tex->_texture_type;
4090 cdataw->_format = cdata_tex->_format;
4091 cdataw->_component_type = cdata_tex->_component_type;
4093 cdataw->inc_properties_modified();
4094 cdataw->inc_image_modified();
4097 cdataw->_keep_ram_image = cdata_tex->_keep_ram_image;
4098 cdataw->_ram_image_compression = cdata_tex->_ram_image_compression;
4099 cdataw->_ram_images = cdata_tex->_ram_images;
4101 nassertr(_reloading, NULL);
4126 do_reload_ram_image(CData *cdata,
bool allow_compression) {
4130 if (!do_has_compression(cdata)) {
4131 allow_compression =
false;
4138 record = cache->lookup(cdata->_fullpath,
"txo");
4140 record->has_data()) {
4145 int x_size = cdata->_orig_file_x_size;
4146 int y_size = cdata->_orig_file_y_size;
4147 do_adjust_this_size(cdata, x_size, y_size, cdata->_filename.get_basename(),
true);
4149 if (gobj_cat.is_debug()) {
4151 <<
"Cached texture " << *
this <<
" has size " 4153 <<
" instead of " << x_size <<
" x " << y_size
4154 <<
"; ignoring cache.\n";
4160 if (gobj_cat.is_debug()) {
4162 <<
"Cached texture " << *
this 4163 <<
" is compressed in cache; ignoring cache.\n";
4167 <<
"Texture " << get_name() <<
" reloaded from disk cache\n";
4173 cdata->_x_size = cdata_tex->_x_size;
4174 cdata->_y_size = cdata_tex->_y_size;
4175 if (cdata->_num_components != cdata_tex->_num_components) {
4176 cdata->_num_components = cdata_tex->_num_components;
4177 cdata->_format = cdata_tex->_format;
4179 cdata->_component_type = cdata_tex->_component_type;
4180 cdata->_compression = cdata_tex->_compression;
4181 cdata->_ram_image_compression = cdata_tex->_ram_image_compression;
4182 cdata->_ram_images = cdata_tex->_ram_images;
4183 cdata->_loaded_from_image =
true;
4185 bool was_compressed = (cdata->_ram_image_compression != CM_off);
4186 if (do_consider_auto_process_ram_image(cdata,
uses_mipmaps(), allow_compression)) {
4187 bool is_compressed = (cdata->_ram_image_compression != CM_off);
4188 if (!was_compressed && is_compressed &&
4194 cache->
store(record);
4205 <<
"Reloading texture " << get_name() <<
"\n";
4210 if (cdata->_has_read_pages) {
4213 if (cdata->_has_read_mipmaps) {
4214 n = cdata->_num_mipmap_levels_read;
4217 cdata->_loaded_from_image =
false;
4218 Format orig_format = cdata->_format;
4219 int orig_num_components = cdata->_num_components;
4222 options.set_texture_flags(LoaderOptions::TF_preload);
4223 do_read(cdata, cdata->_fullpath, cdata->_alpha_fullpath,
4224 cdata->_primary_file_num_channels, cdata->_alpha_file_channel,
4225 z, n, cdata->_has_read_pages, cdata->_has_read_mipmaps, options, NULL);
4227 if (orig_num_components == cdata->_num_components) {
4230 cdata->_format = orig_format;
4233 if (do_has_ram_image(cdata) && record != (
BamCacheRecord *)NULL) {
4240 cache->
store(record);
4252 do_modify_ram_image(CData *cdata) {
4253 if (cdata->_ram_images.empty() || cdata->_ram_images[0]._image.empty() ||
4254 cdata->_ram_image_compression != CM_off) {
4255 do_make_ram_image(cdata);
4257 do_clear_ram_mipmap_images(cdata);
4259 return cdata->_ram_images[0]._image;
4269 do_make_ram_image(CData *cdata) {
4270 int image_size = do_get_expected_ram_image_size(cdata);
4271 cdata->_ram_images.clear();
4272 cdata->_ram_images.push_back(RamImage());
4273 cdata->_ram_images[0]._page_size = do_get_expected_ram_page_size(cdata);
4274 cdata->_ram_images[0]._image = PTA_uchar::empty_array(image_size, get_class_type());
4275 cdata->_ram_images[0]._pointer_image = NULL;
4276 cdata->_ram_image_compression = CM_off;
4278 if (cdata->_has_clear_color) {
4280 unsigned char pixel[16];
4281 const int pixel_size = do_get_clear_data(cdata, pixel);
4282 nassertr(pixel_size > 0, cdata->_ram_images[0]._image);
4284 unsigned char *image_data = cdata->_ram_images[0]._image;
4285 for (
int i = 0; i < image_size; i += pixel_size) {
4286 memcpy(image_data + i, pixel, pixel_size);
4290 return cdata->_ram_images[0]._image;
4304 do_set_ram_image(CData *cdata,
CPTA_uchar image, Texture::CompressionMode compression,
4306 nassertv(compression != CM_default);
4307 nassertv(compression != CM_off || image.size() == do_get_expected_ram_image_size(cdata));
4308 if (cdata->_ram_images.empty()) {
4309 cdata->_ram_images.push_back(RamImage());
4311 do_clear_ram_mipmap_images(cdata);
4313 if (page_size == 0) {
4314 page_size = image.size();
4316 if (cdata->_ram_images[0]._image != image ||
4317 cdata->_ram_images[0]._page_size != page_size ||
4318 cdata->_ram_image_compression != compression) {
4320 cdata->_ram_images[0]._page_size = page_size;
4321 cdata->_ram_images[0]._pointer_image = NULL;
4322 cdata->_ram_image_compression = compression;
4323 cdata->inc_image_modified();
4334 do_modify_ram_mipmap_image(CData *cdata,
int n) {
4335 nassertr(cdata->_ram_image_compression == CM_off, PTA_uchar());
4337 if (n >= (
int)cdata->_ram_images.size() ||
4338 cdata->_ram_images[n]._image.empty()) {
4339 do_make_ram_mipmap_image(cdata, n);
4341 return cdata->_ram_images[n]._image;
4350 do_make_ram_mipmap_image(CData *cdata,
int n) {
4351 nassertr(cdata->_ram_image_compression == CM_off, PTA_uchar(get_class_type()));
4353 while (n >= (
int)cdata->_ram_images.size()) {
4354 cdata->_ram_images.push_back(RamImage());
4357 size_t image_size = do_get_expected_ram_mipmap_image_size(cdata, n);
4358 cdata->_ram_images[n]._image = PTA_uchar::empty_array(image_size, get_class_type());
4359 cdata->_ram_images[n]._pointer_image = NULL;
4360 cdata->_ram_images[n]._page_size = do_get_expected_ram_mipmap_page_size(cdata, n);
4362 if (cdata->_has_clear_color) {
4364 unsigned char pixel[16];
4365 const size_t pixel_size = (size_t)do_get_clear_data(cdata, pixel);
4366 nassertr(pixel_size > 0, cdata->_ram_images[n]._image);
4368 unsigned char *image_data = cdata->_ram_images[n]._image;
4369 for (
size_t i = 0; i < image_size; i += pixel_size) {
4370 memcpy(image_data + i, pixel, pixel_size);
4374 return cdata->_ram_images[n]._image;
4383 do_set_ram_mipmap_image(CData *cdata,
int n,
CPTA_uchar image,
size_t page_size) {
4384 nassertv(cdata->_ram_image_compression != CM_off || image.size() == do_get_expected_ram_mipmap_image_size(cdata, n));
4386 while (n >= (
int)cdata->_ram_images.size()) {
4387 cdata->_ram_images.push_back(RamImage());
4389 if (page_size == 0) {
4390 page_size = image.size();
4393 if (cdata->_ram_images[n]._image != image ||
4394 cdata->_ram_images[n]._page_size != page_size) {
4396 cdata->_ram_images[n]._pointer_image = NULL;
4397 cdata->_ram_images[n]._page_size = page_size;
4398 cdata->inc_image_modified();
4415 do_get_clear_data(
const CData *cdata,
unsigned char *into)
const {
4416 nassertr(cdata->_has_clear_color, 0);
4417 nassertr(cdata->_num_components <= 4, 0);
4420 switch (cdata->_component_type) {
4421 case T_unsigned_byte:
4425 switch (cdata->_num_components) {
4427 into[1] = (
unsigned char)scaled[1];
4429 into[0] = (
unsigned char)scaled[0];
4432 into[3] = (
unsigned char)scaled[3];
4434 into[0] = (
unsigned char)scaled[2];
4435 into[1] = (
unsigned char)scaled[1];
4436 into[2] = (
unsigned char)scaled[0];
4442 case T_unsigned_short:
4446 switch (cdata->_num_components) {
4448 ((
unsigned short *)into)[1] = (
unsigned short)scaled[1];
4450 ((
unsigned short *)into)[0] = (
unsigned short)scaled[0];
4453 ((
unsigned short *)into)[3] = (
unsigned short)scaled[3];
4455 ((
unsigned short *)into)[0] = (
unsigned short)scaled[2];
4456 ((
unsigned short *)into)[1] = (
unsigned short)scaled[1];
4457 ((
unsigned short *)into)[2] = (
unsigned short)scaled[0];
4464 switch (cdata->_num_components) {
4466 ((
float *)into)[1] = cdata->_clear_color[1];
4468 ((
float *)into)[0] = cdata->_clear_color[0];
4471 ((
float *)into)[3] = cdata->_clear_color[3];
4473 ((
float *)into)[0] = cdata->_clear_color[2];
4474 ((
float *)into)[1] = cdata->_clear_color[1];
4475 ((
float *)into)[2] = cdata->_clear_color[0];
4480 case T_unsigned_int_24_8:
4481 nassertr(cdata->_num_components == 1, 0);
4482 *((
unsigned int *)into) =
4483 ((
unsigned int)(cdata->_clear_color[0] * 16777215) << 8) +
4484 (
unsigned int)max(min(cdata->_clear_color[1], (PN_stdfloat)255), (PN_stdfloat)0);
4491 switch (cdata->_num_components) {
4493 ((
int *)into)[1] = (int)cdata->_clear_color[1];
4495 ((
int *)into)[0] = (
int)cdata->_clear_color[0];
4498 ((
int *)into)[3] = (int)cdata->_clear_color[3];
4500 ((
int *)into)[0] = (
int)cdata->_clear_color[2];
4501 ((
int *)into)[1] = (int)cdata->_clear_color[1];
4502 ((
int *)into)[2] = (
int)cdata->_clear_color[0];
4509 return cdata->_num_components * cdata->_component_width;
4523 consider_auto_process_ram_image(
bool generate_mipmaps,
bool allow_compression) {
4525 return do_consider_auto_process_ram_image(cdata, generate_mipmaps, allow_compression);
4539 do_consider_auto_process_ram_image(CData *cdata,
bool generate_mipmaps,
4540 bool allow_compression) {
4541 bool modified =
false;
4543 if (generate_mipmaps && !driver_generate_mipmaps &&
4544 cdata->_ram_images.
size() == 1) {
4545 do_generate_ram_mipmap_images(cdata);
4549 if (allow_compression && !driver_compress_textures) {
4550 CompressionMode compression = cdata->_compression;
4551 if (compression == CM_default && compressed_textures) {
4552 compression = CM_on;
4554 if (compression != CM_off && cdata->_ram_image_compression == CM_off) {
4556 if (do_compress_ram_image(cdata, compression, QL_default, gsg)) {
4557 if (gobj_cat.is_debug()) {
4559 <<
"Compressed " << get_name() <<
" with " 4560 << cdata->_ram_image_compression <<
"\n";
4576 do_compress_ram_image(CData *cdata, Texture::CompressionMode compression,
4577 Texture::QualityLevel quality_level,
4579 nassertr(compression != CM_off,
false);
4581 if (compression == CM_on) {
4583 switch (cdata->_format) {
4584 case Texture::F_rgbm:
4585 case Texture::F_rgb:
4586 case Texture::F_rgb5:
4587 case Texture::F_rgba5:
4588 case Texture::F_rgb8:
4589 case Texture::F_rgb12:
4590 case Texture::F_rgb332:
4591 case Texture::F_rgb16:
4592 case Texture::F_rgb32:
4593 if (gsg == NULL || gsg->get_supports_compressed_texture_format(CM_dxt1)) {
4594 compression = CM_dxt1;
4595 }
else if (gsg == NULL || gsg->get_supports_compressed_texture_format(CM_dxt3)) {
4596 compression = CM_dxt3;
4597 }
else if (gsg == NULL || gsg->get_supports_compressed_texture_format(CM_dxt5)) {
4598 compression = CM_dxt5;
4602 case Texture::F_rgba4:
4603 if (gsg == NULL || gsg->get_supports_compressed_texture_format(CM_dxt3)) {
4604 compression = CM_dxt3;
4605 }
else if (gsg == NULL || gsg->get_supports_compressed_texture_format(CM_dxt5)) {
4606 compression = CM_dxt5;
4610 case Texture::F_rgba:
4611 case Texture::F_rgba8:
4612 case Texture::F_rgba12:
4613 case Texture::F_rgba16:
4614 case Texture::F_rgba32:
4615 if (gsg == NULL || gsg->get_supports_compressed_texture_format(CM_dxt5)) {
4616 compression = CM_dxt5;
4626 if (quality_level == Texture::QL_default) {
4627 quality_level = cdata->_quality_level;
4629 if (quality_level == Texture::QL_default) {
4630 quality_level = texture_quality_level;
4634 if (cdata->_texture_type != TT_3d_texture &&
4635 cdata->_texture_type != TT_2d_texture_array &&
4636 cdata->_component_type == T_unsigned_byte) {
4637 int squish_flags = 0;
4638 switch (compression) {
4640 squish_flags |= squish::kDxt1;
4644 squish_flags |= squish::kDxt3;
4648 squish_flags |= squish::kDxt5;
4655 if (squish_flags != 0) {
4657 switch (quality_level) {
4659 squish_flags |= squish::kColourRangeFit;
4664 squish_flags |= squish::kColourRangeFit;
4669 squish_flags |= squish::kColourIterativeClusterFit;
4676 if (do_squish(cdata, compression, squish_flags)) {
4681 #endif // HAVE_SQUISH 4692 do_uncompress_ram_image(CData *cdata) {
4695 if (cdata->_texture_type != TT_3d_texture &&
4696 cdata->_texture_type != TT_2d_texture_array &&
4697 cdata->_component_type == T_unsigned_byte) {
4698 int squish_flags = 0;
4699 switch (cdata->_ram_image_compression) {
4701 squish_flags |= squish::kDxt1;
4705 squish_flags |= squish::kDxt3;
4709 squish_flags |= squish::kDxt5;
4716 if (squish_flags != 0) {
4718 if (do_unsquish(cdata, squish_flags)) {
4723 #endif // HAVE_SQUISH 4733 do_has_all_ram_mipmap_images(
const CData *cdata)
const {
4734 if (cdata->_ram_images.empty() || cdata->_ram_images[0]._image.empty()) {
4746 int size = max(cdata->_x_size, max(cdata->_y_size, cdata->_z_size));
4752 if (n >= (
int)cdata->_ram_images.size() || cdata->_ram_images[n]._image.empty()) {
4771 do_reconsider_z_size(CData *cdata,
int z,
const LoaderOptions &options) {
4772 if (z >= cdata->_z_size * cdata->_num_views) {
4773 bool num_views_specified =
true;
4774 if (options.get_texture_flags() & LoaderOptions::TF_multiview) {
4782 if (num_views_specified &&
4783 (cdata->_texture_type == Texture::TT_3d_texture ||
4784 cdata->_texture_type == Texture::TT_2d_texture_array)) {
4789 nassertr(cdata->_num_views != 0,
false);
4790 cdata->_z_size = (z / cdata->_num_views) + 1;
4792 }
else if (cdata->_z_size != 0) {
4796 cdata->_num_views = (z / cdata->_z_size) + 1;
4805 do_allocate_pages(cdata);
4821 do_allocate_pages(CData *cdata) {
4822 size_t new_size = do_get_expected_ram_image_size(cdata);
4823 if (!cdata->_ram_images.empty() &&
4824 !cdata->_ram_images[0]._image.empty() &&
4825 new_size > cdata->_ram_images[0]._image.size()) {
4826 cdata->_ram_images[0]._image.insert(cdata->_ram_images[0]._image.end(), new_size - cdata->_ram_images[0]._image.size(), 0);
4827 nassertv(cdata->_ram_images[0]._image.size() == new_size);
4841 do_reconsider_image_properties(CData *cdata,
int x_size,
int y_size,
int num_components,
4842 Texture::ComponentType component_type,
int z,
4844 if (!cdata->_loaded_from_image || num_components != cdata->_num_components || component_type != cdata->_component_type) {
4850 switch (num_components) {
4852 cdata->_format = F_luminance;
4856 cdata->_format = F_luminance_alpha;
4860 cdata->_format = F_rgb;
4864 cdata->_format = F_rgba;
4869 nassertr(
false,
false);
4870 cdata->_format = F_rgb;
4874 if (!cdata->_loaded_from_image) {
4875 if ((options.get_texture_flags() & LoaderOptions::TF_allow_1d) &&
4876 cdata->_texture_type == TT_2d_texture && x_size != 1 && y_size == 1) {
4878 cdata->_texture_type = TT_1d_texture;
4882 if (cdata->_texture_type == TT_1d_texture) {
4883 nassertr(y_size == 1,
false);
4884 }
else if (cdata->_texture_type == TT_cube_map) {
4885 nassertr(x_size == y_size,
false);
4888 if ((cdata->_x_size != x_size)||(cdata->_y_size != y_size)) {
4889 do_set_pad_size(cdata, 0, 0, 0);
4891 cdata->_x_size = x_size;
4892 cdata->_y_size = y_size;
4893 cdata->_num_components = num_components;
4894 do_set_component_type(cdata, component_type);
4897 if (cdata->_x_size != x_size ||
4898 cdata->_y_size != y_size ||
4899 cdata->_num_components != num_components ||
4900 cdata->_component_type != component_type) {
4902 <<
"Texture properties have changed for texture " << get_name()
4903 <<
" page " << z <<
".\n";
4917 do_rescale_texture(CData *cdata) {
4918 int new_x_size = cdata->_x_size;
4919 int new_y_size = cdata->_y_size;
4920 if (cdata->_z_size * cdata->_num_views != 1) {
4921 nassert_raise(
"rescale_texture() doesn't support 3-d or multiview textures.");
4925 if (do_adjust_this_size(cdata, new_x_size, new_y_size, get_name(),
false)) {
4928 if (!do_store_one(cdata, orig_image, 0, 0)) {
4930 <<
"Couldn't get image in rescale_texture()\n";
4935 <<
"Resizing " << get_name() <<
" to " << new_x_size <<
" x " 4936 << new_y_size <<
"\n";
4942 do_clear_ram_image(cdata);
4943 cdata->inc_image_modified();
4944 cdata->_x_size = new_x_size;
4945 cdata->_y_size = new_y_size;
4946 if (!do_load_one(cdata, new_image, get_name(), 0, 0,
LoaderOptions())) {
4956 if (do_get_auto_texture_scale(cdata) == ATS_pad) {
4957 new_x_size = cdata->_x_size;
4958 new_y_size = cdata->_y_size;
4959 if (do_adjust_this_size(cdata, new_x_size, new_y_size, get_name(),
true)) {
4960 pad_x_size = new_x_size - cdata->_x_size;
4961 pad_y_size = new_y_size - cdata->_y_size;
4964 if (!do_store_one(cdata, orig_image, 0, 0)) {
4966 <<
"Couldn't get image in rescale_texture()\n";
4974 do_clear_ram_image(cdata);
4975 cdata->_loaded_from_image =
false;
4976 cdata->inc_image_modified();
4977 if (!do_load_one(cdata, new_image, get_name(), 0, 0,
LoaderOptions())) {
4981 do_set_pad_size(cdata, pad_x_size, pad_y_size, 0);
4996 make_copy_impl()
const {
4998 return do_make_copy(cdata);
5007 do_make_copy(
const CData *cdata)
const {
5009 CDWriter cdata_tex(tex->_cycler,
true);
5010 tex->do_assign(cdata_tex,
this, cdata);
5021 do_assign(CData *cdata,
const Texture *copy,
const CData *cdata_copy) {
5022 cdata->do_assign(cdata_copy);
5032 do_clear(CData *cdata) {
5036 do_assign(cdata, &tex, cdata_tex);
5038 cdata->inc_properties_modified();
5039 cdata->inc_image_modified();
5040 cdata->inc_simple_image_modified();
5049 do_setup_texture(CData *cdata, Texture::TextureType texture_type,
5050 int x_size,
int y_size,
int z_size,
5051 Texture::ComponentType component_type,
5052 Texture::Format format) {
5053 switch (texture_type) {
5055 nassertv(y_size == 1 && z_size == 1);
5059 nassertv(z_size == 1);
5065 case TT_2d_texture_array:
5070 nassertv(x_size == y_size && z_size == 6);
5075 cdata->_default_sampler.set_wrap_u(SamplerState::WM_clamp);
5076 cdata->_default_sampler.set_wrap_v(SamplerState::WM_clamp);
5077 cdata->_default_sampler.set_wrap_w(SamplerState::WM_clamp);
5081 if (texture_type != TT_2d_texture) {
5082 do_clear_simple_ram_image(cdata);
5085 cdata->_texture_type = texture_type;
5086 cdata->_x_size = x_size;
5087 cdata->_y_size = y_size;
5088 cdata->_z_size = z_size;
5089 cdata->_num_views = 1;
5090 do_set_component_type(cdata, component_type);
5091 do_set_format(cdata, format);
5093 do_clear_ram_image(cdata);
5094 do_set_pad_size(cdata, 0, 0, 0);
5095 cdata->_orig_file_x_size = 0;
5096 cdata->_orig_file_y_size = 0;
5097 cdata->_loaded_from_image =
false;
5098 cdata->_loaded_from_txo =
false;
5099 cdata->_has_read_pages =
false;
5100 cdata->_has_read_mipmaps =
false;
5109 do_set_format(CData *cdata, Texture::Format format) {
5110 if (format == cdata->_format) {
5113 cdata->_format = format;
5114 cdata->inc_properties_modified();
5116 switch (cdata->_format) {
5118 case F_depth_stencil:
5119 case F_depth_component:
5120 case F_depth_component16:
5121 case F_depth_component24:
5122 case F_depth_component32:
5133 cdata->_num_components = 1;
5136 case F_luminance_alpha:
5137 case F_luminance_alphamask:
5139 case F_sluminance_alpha:
5142 cdata->_num_components = 2;
5154 cdata->_num_components = 3;
5167 cdata->_num_components = 4;
5178 do_set_component_type(CData *cdata, Texture::ComponentType component_type) {
5179 cdata->_component_type = component_type;
5181 switch (component_type) {
5182 case T_unsigned_byte:
5183 cdata->_component_width = 1;
5186 case T_unsigned_short:
5187 cdata->_component_width = 2;
5191 cdata->_component_width = 4;
5194 case T_unsigned_int_24_8:
5195 cdata->_component_width = 4;
5199 cdata->_component_width = 4;
5210 do_set_x_size(CData *cdata,
int x_size) {
5211 if (cdata->_x_size != x_size) {
5212 cdata->_x_size = x_size;
5213 cdata->inc_image_modified();
5214 do_clear_ram_image(cdata);
5215 do_set_pad_size(cdata, 0, 0, 0);
5225 do_set_y_size(CData *cdata,
int y_size) {
5226 if (cdata->_y_size != y_size) {
5227 nassertv(cdata->_texture_type != Texture::TT_1d_texture || y_size == 1);
5228 cdata->_y_size = y_size;
5229 cdata->inc_image_modified();
5230 do_clear_ram_image(cdata);
5231 do_set_pad_size(cdata, 0, 0, 0);
5243 do_set_z_size(CData *cdata,
int z_size) {
5244 if (cdata->_z_size != z_size) {
5245 nassertv((cdata->_texture_type == Texture::TT_3d_texture) ||
5246 (cdata->_texture_type == Texture::TT_cube_map && z_size == 6) ||
5247 (cdata->_texture_type == Texture::TT_2d_texture_array) || (z_size == 1));
5248 cdata->_z_size = z_size;
5249 cdata->inc_image_modified();
5250 do_clear_ram_image(cdata);
5251 do_set_pad_size(cdata, 0, 0, 0);
5261 do_set_num_views(CData *cdata,
int num_views) {
5262 nassertv(num_views >= 1);
5263 if (cdata->_num_views != num_views) {
5264 cdata->_num_views = num_views;
5265 if (do_has_ram_image(cdata)) {
5266 cdata->inc_image_modified();
5267 do_clear_ram_image(cdata);
5269 do_set_pad_size(cdata, 0, 0, 0);
5279 do_set_wrap_u(CData *cdata, SamplerState::WrapMode wrap) {
5280 if (cdata->_default_sampler.get_wrap_u() != wrap) {
5281 cdata->inc_properties_modified();
5282 cdata->_default_sampler.set_wrap_u(wrap);
5292 do_set_wrap_v(CData *cdata, SamplerState::WrapMode wrap) {
5293 if (cdata->_default_sampler.get_wrap_v() != wrap) {
5294 cdata->inc_properties_modified();
5295 cdata->_default_sampler.set_wrap_v(wrap);
5305 do_set_wrap_w(CData *cdata, SamplerState::WrapMode wrap) {
5306 if (cdata->_default_sampler.get_wrap_w() != wrap) {
5307 cdata->inc_properties_modified();
5308 cdata->_default_sampler.set_wrap_w(wrap);
5318 do_set_minfilter(CData *cdata, SamplerState::FilterType filter) {
5319 if (cdata->_default_sampler.get_minfilter() != filter) {
5320 cdata->inc_properties_modified();
5321 cdata->_default_sampler.set_minfilter(filter);
5331 do_set_magfilter(CData *cdata, SamplerState::FilterType filter) {
5332 if (cdata->_default_sampler.get_magfilter() != filter) {
5333 cdata->inc_properties_modified();
5334 cdata->_default_sampler.set_magfilter(filter);
5344 do_set_anisotropic_degree(CData *cdata,
int anisotropic_degree) {
5345 if (cdata->_default_sampler.get_anisotropic_degree() != anisotropic_degree) {
5346 cdata->inc_properties_modified();
5347 cdata->_default_sampler.set_anisotropic_degree(anisotropic_degree);
5357 do_set_border_color(CData *cdata,
const LColor &color) {
5358 if (cdata->_default_sampler.get_border_color() != color) {
5359 cdata->inc_properties_modified();
5360 cdata->_default_sampler.set_border_color(color);
5370 do_set_compression(CData *cdata, Texture::CompressionMode compression) {
5371 if (cdata->_compression != compression) {
5372 cdata->inc_properties_modified();
5373 cdata->_compression = compression;
5375 if (do_has_ram_image(cdata)) {
5377 bool has_ram_image_compression = (cdata->_ram_image_compression != CM_off);
5378 if (has_compression != has_ram_image_compression ||
5395 do_set_quality_level(CData *cdata, Texture::QualityLevel quality_level) {
5396 if (cdata->_quality_level != quality_level) {
5397 cdata->inc_properties_modified();
5398 cdata->_quality_level = quality_level;
5408 do_has_compression(
const CData *cdata)
const {
5409 if (cdata->_compression == CM_default) {
5410 return compressed_textures;
5412 return (cdata->_compression != CM_off);
5423 do_has_ram_image(
const CData *cdata)
const {
5424 return !cdata->_ram_images.empty() && !cdata->_ram_images[0]._image.empty();
5435 do_has_uncompressed_ram_image(
const CData *cdata)
const {
5436 return !cdata->_ram_images.empty() && !cdata->_ram_images[0]._image.empty() && cdata->_ram_image_compression == CM_off;
5445 do_get_ram_image(CData *cdata) {
5446 if (!do_has_ram_image(cdata) && do_can_reload(cdata)) {
5447 do_reload_ram_image(cdata,
true);
5449 if (do_has_ram_image(cdata)) {
5454 cdata->inc_image_modified();
5455 cdata->inc_properties_modified();
5459 if (cdata->_ram_images.empty()) {
5463 return cdata->_ram_images[0]._image;
5472 do_get_uncompressed_ram_image(CData *cdata) {
5473 if (!cdata->_ram_images.empty() && cdata->_ram_image_compression != CM_off) {
5476 if (do_uncompress_ram_image(cdata)) {
5477 if (gobj_cat.is_debug()) {
5479 <<
"Uncompressed " << get_name() <<
"\n";
5481 return cdata->_ram_images[0]._image;
5486 if ((!do_has_ram_image(cdata) || cdata->_ram_image_compression != CM_off) && do_can_reload(cdata)) {
5487 do_reload_ram_image(cdata,
false);
5490 if (!cdata->_ram_images.empty() && cdata->_ram_image_compression != CM_off) {
5492 if (do_uncompress_ram_image(cdata)) {
5494 <<
"Uncompressed " << get_name() <<
"\n";
5495 return cdata->_ram_images[0]._image;
5499 if (cdata->_ram_images.empty() || cdata->_ram_image_compression != CM_off) {
5503 return cdata->_ram_images[0]._image;
5537 string format = upcase(requested_format);
5540 CPTA_uchar data = do_get_uncompressed_ram_image(cdata);
5542 gobj_cat.error() <<
"Couldn't find an uncompressed RAM image!\n";
5545 int imgsize = cdata->_x_size * cdata->_y_size;
5546 nassertr(cdata->_num_components > 0 && cdata->_num_components <= 4,
CPTA_uchar(get_class_type()));
5547 nassertr(data.size() == (size_t)(cdata->_component_width * cdata->_num_components * imgsize),
CPTA_uchar(get_class_type()));
5550 if ((cdata->_num_components == 1 && format.size() == 1) ||
5551 (cdata->_num_components == 2 && format.size() == 2 && format.at(1) ==
'A' && format.at(0) !=
'A') ||
5552 (cdata->_num_components == 3 && format ==
"BGR") ||
5553 (cdata->_num_components == 4 && format ==
"BGRA")) {
5559 PTA_uchar newdata = PTA_uchar::empty_array(imgsize * format.size() * cdata->_component_width, get_class_type());
5562 if (format ==
"RGBA" && cdata->_num_components == 4 && cdata->_component_width == 1) {
5564 for (
int p = 0; p < imgsize; p += 4) {
5565 newdata[p ] = data[p + 2];
5566 newdata[p + 1] = data[p + 1];
5567 newdata[p + 2] = data[p ];
5568 newdata[p + 3] = data[p + 3];
5572 if (format ==
"RGB" && cdata->_num_components == 3 && cdata->_component_width == 1) {
5574 for (
int p = 0; p < imgsize; p += 3) {
5575 newdata[p ] = data[p + 2];
5576 newdata[p + 1] = data[p + 1];
5577 newdata[p + 2] = data[p ];
5581 if (format ==
"A" && cdata->_component_width == 1 && cdata->_num_components != 3) {
5583 int component = cdata->_num_components - 1;
5584 for (
int p = 0; p < imgsize; ++p) {
5585 newdata[p] = data[component];
5589 if (cdata->_component_width == 1) {
5590 for (
int p = 0; p < imgsize; ++p) {
5591 for (uchar s = 0; s < format.size(); ++s) {
5592 signed char component = -1;
5593 if (format.at(s) ==
'B' || (cdata->_num_components <= 2 && format.at(s) !=
'A')) {
5595 }
else if (format.at(s) ==
'G') {
5597 }
else if (format.at(s) ==
'R') {
5599 }
else if (format.at(s) ==
'A') {
5600 nassertr(cdata->_num_components != 3,
CPTA_uchar(get_class_type()));
5601 component = cdata->_num_components - 1;
5602 }
else if (format.at(s) ==
'0') {
5603 newdata[p * format.size() + s] = 0x00;
5604 }
else if (format.at(s) ==
'1') {
5605 newdata[p * format.size() + s] = 0xff;
5607 gobj_cat.error() <<
"Unexpected component character '" 5608 << format.at(s) <<
"', expected one of RGBA!\n";
5611 if (component >= 0) {
5612 newdata[p * format.size() + s] = data[p * cdata->_num_components + component];
5618 for (
int p = 0; p < imgsize; ++p) {
5619 for (uchar s = 0; s < format.size(); ++s) {
5620 signed char component = -1;
5621 if (format.at(s) ==
'B' || (cdata->_num_components <= 2 && format.at(s) !=
'A')) {
5623 }
else if (format.at(s) ==
'G') {
5625 }
else if (format.at(s) ==
'R') {
5627 }
else if (format.at(s) ==
'A') {
5628 nassertr(cdata->_num_components != 3,
CPTA_uchar(get_class_type()));
5629 component = cdata->_num_components - 1;
5630 }
else if (format.at(s) ==
'0') {
5631 memset((
void*)(newdata + (p * format.size() + s) * cdata->_component_width), 0, cdata->_component_width);
5632 }
else if (format.at(s) ==
'1') {
5633 memset((
void*)(newdata + (p * format.size() + s) * cdata->_component_width), -1, cdata->_component_width);
5635 gobj_cat.error() <<
"Unexpected component character '" 5636 << format.at(s) <<
"', expected one of RGBA!\n";
5639 if (component >= 0) {
5640 memcpy((
void*)(newdata + (p * format.size() + s) * cdata->_component_width),
5641 (
void*)(data + (p * cdata->_num_components + component) * cdata->_component_width),
5642 cdata->_component_width);
5655 do_set_simple_ram_image(CData *cdata,
CPTA_uchar image,
int x_size,
int y_size) {
5656 nassertv(cdata->_texture_type == TT_2d_texture);
5657 size_t expected_page_size = (size_t)(x_size * y_size * 4);
5658 nassertv(image.size() == expected_page_size);
5660 cdata->_simple_x_size = x_size;
5661 cdata->_simple_y_size = y_size;
5663 cdata->_simple_ram_image._page_size = image.size();
5664 cdata->_simple_image_date_generated = (PN_int32)time(NULL);
5665 cdata->inc_simple_image_modified();
5674 do_get_expected_num_mipmap_levels(
const CData *cdata)
const {
5675 int size = max(cdata->_x_size, cdata->_y_size);
5676 if (cdata->_texture_type == Texture::TT_3d_texture) {
5677 size = max(size, cdata->_z_size);
5693 do_get_ram_mipmap_page_size(
const CData *cdata,
int n)
const {
5694 if (cdata->_ram_image_compression != CM_off) {
5695 if (n >= 0 && n < (
int)cdata->_ram_images.size()) {
5696 return cdata->_ram_images[n]._page_size;
5700 return do_get_expected_ram_mipmap_page_size(cdata, n);
5710 do_get_expected_mipmap_x_size(
const CData *cdata,
int n)
const {
5711 int size = max(cdata->_x_size, 1);
5712 while (n > 0 && size > 1) {
5725 do_get_expected_mipmap_y_size(
const CData *cdata,
int n)
const {
5726 int size = max(cdata->_y_size, 1);
5727 while (n > 0 && size > 1) {
5740 do_get_expected_mipmap_z_size(
const CData *cdata,
int n)
const {
5744 if (cdata->_texture_type == Texture::TT_3d_texture) {
5745 int size = max(cdata->_z_size, 1);
5746 while (n > 0 && size > 1) {
5753 return cdata->_z_size;
5763 do_clear_simple_ram_image(CData *cdata) {
5764 cdata->_simple_x_size = 0;
5765 cdata->_simple_y_size = 0;
5766 cdata->_simple_ram_image._image.clear();
5767 cdata->_simple_ram_image._page_size = 0;
5768 cdata->_simple_image_date_generated = 0;
5773 cdata->inc_simple_image_modified();
5782 do_clear_ram_mipmap_images(CData *cdata) {
5783 if (!cdata->_ram_images.empty()) {
5784 cdata->_ram_images.erase(cdata->_ram_images.begin() + 1, cdata->_ram_images.end());
5794 do_generate_ram_mipmap_images(CData *cdata) {
5795 nassertv(do_has_ram_image(cdata));
5797 if (do_get_expected_num_mipmap_levels(cdata) == 1) {
5802 RamImage orig_compressed_image;
5803 CompressionMode orig_compression_mode = CM_off;
5805 if (cdata->_ram_image_compression != CM_off) {
5809 orig_compressed_image = cdata->_ram_images[0];
5810 orig_compression_mode = cdata->_ram_image_compression;
5813 do_get_uncompressed_ram_image(cdata);
5815 nassertv(cdata->_ram_image_compression == CM_off);
5818 do_clear_ram_mipmap_images(cdata);
5820 if (gobj_cat.is_debug()) {
5822 <<
"Generating mipmap levels for " << *
this <<
"\n";
5825 if (cdata->_texture_type == Texture::TT_3d_texture && cdata->_z_size != 1) {
5827 int x_size = cdata->_x_size;
5828 int y_size = cdata->_y_size;
5829 int z_size = cdata->_z_size;
5831 while (x_size > 1 || y_size > 1 || z_size > 1) {
5832 cdata->_ram_images.push_back(RamImage());
5833 do_filter_3d_mipmap_level(cdata, cdata->_ram_images[n + 1], cdata->_ram_images[n],
5834 x_size, y_size, z_size);
5835 x_size = max(x_size >> 1, 1);
5836 y_size = max(y_size >> 1, 1);
5837 z_size = max(z_size >> 1, 1);
5843 int x_size = cdata->_x_size;
5844 int y_size = cdata->_y_size;
5846 while (x_size > 1 || y_size > 1) {
5847 cdata->_ram_images.push_back(RamImage());
5848 do_filter_2d_mipmap_pages(cdata, cdata->_ram_images[n + 1], cdata->_ram_images[n],
5850 x_size = max(x_size >> 1, 1);
5851 y_size = max(y_size >> 1, 1);
5856 if (orig_compression_mode != CM_off) {
5862 nassertv(cdata->_ram_images.size() > 1);
5863 int l0_x_size = cdata->_x_size;
5864 int l0_y_size = cdata->_y_size;
5865 int l0_z_size = cdata->_z_size;
5866 cdata->_x_size = do_get_expected_mipmap_x_size(cdata, 1);
5867 cdata->_y_size = do_get_expected_mipmap_y_size(cdata, 1);
5868 cdata->_z_size = do_get_expected_mipmap_z_size(cdata, 1);
5869 RamImage uncompressed_image = cdata->_ram_images[0];
5870 cdata->_ram_images.erase(cdata->_ram_images.begin());
5872 bool success = do_compress_ram_image(cdata, orig_compression_mode, QL_default, NULL);
5875 cdata->_ram_images.insert(cdata->_ram_images.begin(), orig_compressed_image);
5877 cdata->_ram_images.insert(cdata->_ram_images.begin(), uncompressed_image);
5879 cdata->_x_size = l0_x_size;
5880 cdata->_y_size = l0_y_size;
5881 cdata->_z_size = l0_z_size;
5891 do_set_pad_size(CData *cdata,
int x,
int y,
int z) {
5892 if (x > cdata->_x_size) {
5895 if (y > cdata->_y_size) {
5898 if (z > cdata->_z_size) {
5902 cdata->_pad_x_size = x;
5903 cdata->_pad_y_size = y;
5904 cdata->_pad_z_size = z;
5917 do_can_reload(
const CData *cdata)
const {
5918 return (cdata->_loaded_from_image && !cdata->_fullpath.empty());
5927 do_reload(CData *cdata) {
5928 if (do_can_reload(cdata)) {
5929 do_clear_ram_image(cdata);
5930 do_reload_ram_image(cdata,
true);
5931 if (do_has_ram_image(cdata)) {
5933 cdata->inc_image_modified();
5953 do_has_bam_rawdata(
const CData *cdata)
const {
5954 return do_has_ram_image(cdata);
5964 do_get_bam_rawdata(CData *cdata) {
5965 do_get_ram_image(cdata);
5975 convert_from_pnmimage(PTA_uchar &image,
size_t page_size,
5976 int row_stride,
int x,
int y,
int z,
5977 const PNMImage &pnmimage,
int num_components,
5978 int component_width) {
5982 int pixel_size = num_components * component_width;
5985 if (row_stride == 0) {
5986 row_stride = x_size;
5988 row_skip = (row_stride - x_size) * pixel_size;
5989 nassertv(row_skip >= 0);
5992 bool is_grayscale = (num_components == 1 || num_components == 2);
5993 bool has_alpha = (num_components == 2 || num_components == 4);
5994 bool img_has_alpha = pnmimage.
has_alpha();
5996 int idx = page_size * z;
5997 nassertv(idx + page_size <= image.size());
5998 unsigned char *p = &image[idx];
6000 if (x != 0 || y != 0) {
6001 p += (row_stride * y + x) * pixel_size;
6004 if (maxval == 255 && component_width == 1) {
6009 switch (num_components) {
6011 for (
int j = y_size-1; j >= 0; j--) {
6012 const xel *row = array + j * x_size;
6013 for (
int i = 0; i < x_size; i++) {
6014 *p++ = (uchar)PPM_GETB(row[i]);
6021 if (img_has_alpha) {
6023 for (
int j = y_size-1; j >= 0; j--) {
6024 const xel *row = array + j * x_size;
6025 const xelval *alpha_row = alpha + j * x_size;
6026 for (
int i = 0; i < x_size; i++) {
6027 *p++ = (uchar)PPM_GETB(row[i]);
6028 *p++ = (uchar)alpha_row[i];
6033 for (
int j = y_size-1; j >= 0; j--) {
6034 const xel *row = array + j * x_size;
6035 for (
int i = 0; i < x_size; i++) {
6036 *p++ = (uchar)PPM_GETB(row[i]);
6045 for (
int j = y_size-1; j >= 0; j--) {
6046 const xel *row = array + j * x_size;
6047 for (
int i = 0; i < x_size; i++) {
6048 *p++ = (uchar)PPM_GETB(row[i]);
6049 *p++ = (uchar)PPM_GETG(row[i]);
6050 *p++ = (uchar)PPM_GETR(row[i]);
6057 if (img_has_alpha) {
6059 for (
int j = y_size-1; j >= 0; j--) {
6060 const xel *row = array + j * x_size;
6061 const xelval *alpha_row = alpha + j * x_size;
6062 for (
int i = 0; i < x_size; i++) {
6063 *p++ = (uchar)PPM_GETB(row[i]);
6064 *p++ = (uchar)PPM_GETG(row[i]);
6065 *p++ = (uchar)PPM_GETR(row[i]);
6066 *p++ = (uchar)alpha_row[i];
6071 for (
int j = y_size-1; j >= 0; j--) {
6072 const xel *row = array + j * x_size;
6073 for (
int i = 0; i < x_size; i++) {
6074 *p++ = (uchar)PPM_GETB(row[i]);
6075 *p++ = (uchar)PPM_GETG(row[i]);
6076 *p++ = (uchar)PPM_GETR(row[i]);
6085 nassertv(num_components >= 1 && num_components <= 4);
6089 }
else if (maxval == 65535 && component_width == 2) {
6092 for (
int j = y_size-1; j >= 0; j--) {
6093 for (
int i = 0; i < x_size; i++) {
6099 store_unscaled_short(p, pnmimage.
get_red_val(i, j));
6102 if (img_has_alpha) {
6105 store_unscaled_short(p, 65535);
6112 }
else if (component_width == 1) {
6116 double scale = 255.0 / (double)maxval;
6118 for (
int j = y_size-1; j >= 0; j--) {
6119 for (
int i = 0; i < x_size; i++) {
6121 store_scaled_byte(p, pnmimage.
get_gray_val(i, j), scale);
6123 store_scaled_byte(p, pnmimage.
get_blue_val(i, j), scale);
6125 store_scaled_byte(p, pnmimage.
get_red_val(i, j), scale);
6128 if (img_has_alpha) {
6131 store_unscaled_byte(p, 255);
6142 double scale = 65535.0 / (double)maxval;
6144 for (
int j = y_size-1; j >= 0; j--) {
6145 for (
int i = 0; i < x_size; i++) {
6147 store_scaled_short(p, pnmimage.
get_gray_val(i, j), scale);
6149 store_scaled_short(p, pnmimage.
get_blue_val(i, j), scale);
6151 store_scaled_short(p, pnmimage.
get_red_val(i, j), scale);
6154 if (img_has_alpha) {
6157 store_unscaled_short(p, 65535);
6173 convert_from_pfm(PTA_uchar &image,
size_t page_size,
int z,
6174 const PfmFile &pfm,
int num_components,
int component_width) {
6175 nassertv(component_width == 4);
6179 int idx = page_size * z;
6180 nassertv(idx + page_size <= image.size());
6181 PN_float32 *p = (PN_float32 *)&image[idx];
6183 switch (num_components) {
6186 for (
int j = y_size-1; j >= 0; j--) {
6187 for (
int i = 0; i < x_size; i++) {
6197 for (
int j = y_size-1; j >= 0; j--) {
6198 for (
int i = 0; i < x_size; i++) {
6210 for (
int j = y_size-1; j >= 0; j--) {
6211 for (
int i = 0; i < x_size; i++) {
6224 for (
int j = y_size-1; j >= 0; j--) {
6225 for (
int i = 0; i < x_size; i++) {
6240 nassertv((
unsigned char *)p == &image[idx] + page_size);
6250 convert_to_pnmimage(
PNMImage &pnmimage,
int x_size,
int y_size,
6251 int num_components,
int component_width,
6253 xelval maxval = 0xff;
6254 if (component_width > 1) {
6257 pnmimage.
clear(x_size, y_size, num_components, maxval);
6261 int idx = page_size * z;
6262 nassertr(idx + page_size <= image.size(),
false);
6263 const unsigned char *p = &image[idx];
6265 if (component_width == 1) {
6270 for (
int j = y_size-1; j >= 0; j--) {
6271 xel *row = array + j * x_size;
6272 xelval *alpha_row = alpha + j * x_size;
6273 for (
int i = 0; i < x_size; i++) {
6274 PPM_PUTB(row[i], *p++);
6275 alpha_row[i] = *p++;
6279 for (
int j = y_size-1; j >= 0; j--) {
6280 xel *row = array + j * x_size;
6281 for (
int i = 0; i < x_size; i++) {
6282 PPM_PUTB(row[i], *p++);
6289 for (
int j = y_size-1; j >= 0; j--) {
6290 xel *row = array + j * x_size;
6291 xelval *alpha_row = alpha + j * x_size;
6292 for (
int i = 0; i < x_size; i++) {
6293 PPM_PUTB(row[i], *p++);
6294 PPM_PUTG(row[i], *p++);
6295 PPM_PUTR(row[i], *p++);
6296 alpha_row[i] = *p++;
6300 for (
int j = y_size-1; j >= 0; j--) {
6301 xel *row = array + j * x_size;
6302 for (
int i = 0; i < x_size; i++) {
6303 PPM_PUTB(row[i], *p++);
6304 PPM_PUTG(row[i], *p++);
6305 PPM_PUTR(row[i], *p++);
6311 }
else if (component_width == 2) {
6312 for (
int j = y_size-1; j >= 0; j--) {
6313 for (
int i = 0; i < x_size; i++) {
6315 pnmimage.
set_gray(i, j, get_unsigned_short(p));
6317 pnmimage.
set_blue(i, j, get_unsigned_short(p));
6318 pnmimage.
set_green(i, j, get_unsigned_short(p));
6319 pnmimage.
set_red(i, j, get_unsigned_short(p));
6322 pnmimage.
set_alpha(i, j, get_unsigned_short(p));
6331 nassertr(p == &image[idx] + page_size,
false);
6342 convert_to_pfm(
PfmFile &pfm,
int x_size,
int y_size,
6343 int num_components,
int component_width,
6345 nassertr(component_width == 4,
false);
6346 pfm.
clear(x_size, y_size, num_components);
6348 int idx = page_size * z;
6349 nassertr(idx + page_size <= image.size(),
false);
6350 const PN_float32 *p = (
const PN_float32 *)&image[idx];
6352 switch (num_components) {
6354 for (
int j = y_size-1; j >= 0; j--) {
6355 for (
int i = 0; i < x_size; i++) {
6363 for (
int j = y_size-1; j >= 0; j--) {
6364 for (
int i = 0; i < x_size; i++) {
6374 for (
int j = y_size-1; j >= 0; j--) {
6375 for (
int i = 0; i < x_size; i++) {
6386 for (
int j = y_size-1; j >= 0; j--) {
6387 for (
int i = 0; i < x_size; i++) {
6398 nassertr(
false,
false);
6401 nassertr((
unsigned char *)p == &image[idx] + page_size,
false);
6411 read_dds_level_bgr8(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
6413 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
6414 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
6416 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
6417 size_t row_bytes = x_size * 3;
6418 PTA_uchar image = PTA_uchar::empty_array(size);
6419 for (
int y = y_size - 1; y >= 0; --y) {
6420 unsigned char *p = image.p() + y * row_bytes;
6421 nassertr(p + row_bytes <= image.p() + size, PTA_uchar());
6422 in.read((
char *)p, row_bytes);
6434 read_dds_level_rgb8(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
6436 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
6437 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
6439 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
6440 size_t row_bytes = x_size * 3;
6441 PTA_uchar image = PTA_uchar::empty_array(size);
6442 for (
int y = y_size - 1; y >= 0; --y) {
6443 unsigned char *p = image.p() + y * row_bytes;
6444 nassertr(p + row_bytes <= image.p() + size, PTA_uchar());
6445 in.read((
char *)p, row_bytes);
6448 for (
int x = 0; x < x_size; ++x) {
6449 unsigned char r = p[0];
6454 nassertr(p <= image.p() + size, PTA_uchar());
6466 read_dds_level_abgr8(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
6468 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
6469 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
6471 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
6472 size_t row_bytes = x_size * 4;
6473 PTA_uchar image = PTA_uchar::empty_array(size);
6474 for (
int y = y_size - 1; y >= 0; --y) {
6475 unsigned char *p = image.p() + y * row_bytes;
6476 in.read((
char *)p, row_bytes);
6478 PN_uint32 *pw = (PN_uint32 *)p;
6479 for (
int x = 0; x < x_size; ++x) {
6481 #ifdef WORDS_BIGENDIAN 6483 w = ((w & 0xff00) << 16) | ((w & 0xff000000U) >> 16) | (w & 0xff00ff);
6486 w = ((w & 0xff) << 16) | ((w & 0xff0000) >> 16) | (w & 0xff00ff00U);
6491 nassertr((
unsigned char *)pw <= image.p() + size, PTA_uchar());
6503 read_dds_level_rgba8(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
6505 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
6506 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
6508 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
6509 size_t row_bytes = x_size * 4;
6510 PTA_uchar image = PTA_uchar::empty_array(size);
6511 for (
int y = y_size - 1; y >= 0; --y) {
6512 unsigned char *p = image.p() + y * row_bytes;
6513 nassertr(p + row_bytes <= image.p() + size, PTA_uchar());
6514 in.read((
char *)p, row_bytes);
6527 read_dds_level_generic_uncompressed(
Texture *tex, CData *cdata,
const DDSHeader &header,
6528 int n, istream &in) {
6529 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
6530 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
6532 int pitch = (x_size * header.pf.rgb_bitcount) / 8;
6540 pitch = ((pitch + 3) / 4) * 4;
6541 if (header.dds_flags & DDSD_PITCH) {
6542 pitch = header.pitch;
6546 int bpp = header.pf.rgb_bitcount / 8;
6547 int skip_bytes = pitch - (bpp * x_size);
6548 nassertr(skip_bytes >= 0, PTA_uchar());
6550 unsigned int r_mask = header.pf.r_mask;
6551 unsigned int g_mask = header.pf.g_mask;
6552 unsigned int b_mask = header.pf.b_mask;
6553 unsigned int a_mask = header.pf.a_mask;
6557 int r_shift = get_lowest_on_bit(r_mask);
6558 int g_shift = get_lowest_on_bit(g_mask);
6559 int b_shift = get_lowest_on_bit(b_mask);
6560 int a_shift = get_lowest_on_bit(a_mask);
6564 unsigned int r_scale = 0;
6566 r_scale = 0xff000000 / (r_mask >> r_shift);
6568 unsigned int g_scale = 0;
6570 g_scale = 0xff000000 / (g_mask >> g_shift);
6572 unsigned int b_scale = 0;
6574 b_scale = 0xff000000 / (b_mask >> b_shift);
6576 unsigned int a_scale = 0;
6578 a_scale = 0xff000000 / (a_mask >> a_shift);
6581 bool add_alpha =
has_alpha(cdata->_format);
6583 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
6584 size_t row_bytes = x_size * cdata->_num_components;
6585 PTA_uchar image = PTA_uchar::empty_array(size);
6586 for (
int y = y_size - 1; y >= 0; --y) {
6587 unsigned char *p = image.p() + y * row_bytes;
6588 for (
int x = 0; x < x_size; ++x) {
6591 unsigned int pixel = 0;
6593 for (
int bi = 0; bi < bpp; ++bi) {
6594 unsigned int ch = (
unsigned char)in.get();
6595 pixel |= (ch << shift);
6601 unsigned int r = (((pixel & r_mask) >> r_shift) * r_scale) >> 24;
6602 unsigned int g = (((pixel & g_mask) >> g_shift) * g_scale) >> 24;
6603 unsigned int b = (((pixel & b_mask) >> b_shift) * b_scale) >> 24;
6606 store_unscaled_byte(p, b);
6607 store_unscaled_byte(p, g);
6608 store_unscaled_byte(p, r);
6610 unsigned int a = (((pixel & a_mask) >> a_shift) * a_scale) >> 24;
6611 store_unscaled_byte(p, a);
6614 nassertr(p <= image.p() + size, PTA_uchar());
6615 for (
int bi = 0; bi < skip_bytes; ++bi) {
6630 read_dds_level_luminance_uncompressed(
Texture *tex, CData *cdata,
const DDSHeader &header,
6631 int n, istream &in) {
6632 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
6633 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
6635 int pitch = (x_size * header.pf.rgb_bitcount) / 8;
6643 pitch = ((pitch + 3) / 4) * 4;
6644 if (header.dds_flags & DDSD_PITCH) {
6645 pitch = header.pitch;
6649 int bpp = header.pf.rgb_bitcount / 8;
6650 int skip_bytes = pitch - (bpp * x_size);
6651 nassertr(skip_bytes >= 0, PTA_uchar());
6653 unsigned int r_mask = header.pf.r_mask;
6654 unsigned int a_mask = header.pf.a_mask;
6658 int r_shift = get_lowest_on_bit(r_mask);
6659 int a_shift = get_lowest_on_bit(a_mask);
6663 unsigned int r_scale = 0;
6665 r_scale = 0xff000000 / (r_mask >> r_shift);
6667 unsigned int a_scale = 0;
6669 a_scale = 0xff000000 / (a_mask >> a_shift);
6672 bool add_alpha =
has_alpha(cdata->_format);
6674 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
6675 size_t row_bytes = x_size * cdata->_num_components;
6676 PTA_uchar image = PTA_uchar::empty_array(size);
6677 for (
int y = y_size - 1; y >= 0; --y) {
6678 unsigned char *p = image.p() + y * row_bytes;
6679 for (
int x = 0; x < x_size; ++x) {
6682 unsigned int pixel = 0;
6684 for (
int bi = 0; bi < bpp; ++bi) {
6685 unsigned int ch = (
unsigned char)in.get();
6686 pixel |= (ch << shift);
6690 unsigned int r = (((pixel & r_mask) >> r_shift) * r_scale) >> 24;
6693 store_unscaled_byte(p, r);
6695 unsigned int a = (((pixel & a_mask) >> a_shift) * a_scale) >> 24;
6696 store_unscaled_byte(p, a);
6699 nassertr(p <= image.p() + size, PTA_uchar());
6700 for (
int bi = 0; bi < skip_bytes; ++bi) {
6714 read_dds_level_dxt1(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
6715 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
6716 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
6718 static const int div = 4;
6719 static const int block_bytes = 8;
6723 int num_cols = max(div, x_size) / div;
6724 int num_rows = max(div, y_size) / div;
6725 int row_length = num_cols * block_bytes;
6726 int linear_size = row_length * num_rows;
6729 if (header.dds_flags & DDSD_LINEARSIZE) {
6730 nassertr(linear_size == (
int)header.pitch, PTA_uchar());
6734 PTA_uchar image = PTA_uchar::empty_array(linear_size);
6740 for (
int ri = num_rows - 1; ri >= 0; --ri) {
6741 unsigned char *p = image.p() + row_length * ri;
6742 in.read((
char *)p, row_length);
6744 for (
int ci = 0; ci < num_cols; ++ci) {
6747 PN_uint32 *cells = (PN_uint32 *)p;
6748 PN_uint32 w = cells[1];
6749 w = ((w & 0xff) << 24) | ((w & 0xff00) << 8) | ((w & 0xff0000) >> 8) | ((w & 0xff000000U) >> 24);
6756 }
else if (y_size >= 2) {
6758 unsigned char *p = image.p();
6759 in.read((
char *)p, row_length);
6761 for (
int ci = 0; ci < num_cols; ++ci) {
6762 PN_uint32 *cells = (PN_uint32 *)p;
6763 PN_uint32 w = cells[1];
6764 w = ((w & 0xff) << 8) | ((w & 0xff00) >> 8);
6770 }
else if (y_size >= 1) {
6772 unsigned char *p = image.p();
6773 in.read((
char *)p, row_length);
6785 read_dds_level_dxt23(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
6786 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
6787 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
6789 static const int div = 4;
6790 static const int block_bytes = 16;
6796 int num_cols = max(div, x_size) / div;
6797 int num_rows = max(div, y_size) / div;
6798 int row_length = num_cols * block_bytes;
6799 int linear_size = row_length * num_rows;
6802 if (header.dds_flags & DDSD_LINEARSIZE) {
6803 nassertr(linear_size == (
int)header.pitch, PTA_uchar());
6807 PTA_uchar image = PTA_uchar::empty_array(linear_size);
6813 for (
int ri = num_rows - 1; ri >= 0; --ri) {
6814 unsigned char *p = image.p() + row_length * ri;
6815 in.read((
char *)p, row_length);
6817 for (
int ci = 0; ci < num_cols; ++ci) {
6820 PN_uint32 *cells = (PN_uint32 *)p;
6823 PN_uint32 w0 = cells[0];
6824 PN_uint32 w1 = cells[1];
6825 w0 = ((w0 & 0xffff) << 16) | ((w0 & 0xffff0000U) >> 16);
6826 w1 = ((w1 & 0xffff) << 16) | ((w1 & 0xffff0000U) >> 16);
6832 PN_uint32 w = cells[3];
6833 w = ((w & 0xff) << 24) | ((w & 0xff00) << 8) | ((w & 0xff0000) >> 8) | ((w & 0xff000000U) >> 24);
6840 }
else if (y_size >= 2) {
6842 unsigned char *p = image.p();
6843 in.read((
char *)p, row_length);
6845 for (
int ci = 0; ci < num_cols; ++ci) {
6846 PN_uint32 *cells = (PN_uint32 *)p;
6848 PN_uint32 w0 = cells[0];
6849 w0 = ((w0 & 0xffff) << 16) | ((w0 & 0xffff0000U) >> 16);
6852 PN_uint32 w = cells[3];
6853 w = ((w & 0xff) << 8) | ((w & 0xff00) >> 8);
6859 }
else if (y_size >= 1) {
6861 unsigned char *p = image.p();
6862 in.read((
char *)p, row_length);
6874 read_dds_level_dxt45(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
6875 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
6876 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
6878 static const int div = 4;
6879 static const int block_bytes = 16;
6884 int num_cols = max(div, x_size) / div;
6885 int num_rows = max(div, y_size) / div;
6886 int row_length = num_cols * block_bytes;
6887 int linear_size = row_length * num_rows;
6890 if (header.dds_flags & DDSD_LINEARSIZE) {
6891 nassertr(linear_size == (
int)header.pitch, PTA_uchar());
6895 PTA_uchar image = PTA_uchar::empty_array(linear_size);
6901 for (
int ri = num_rows - 1; ri >= 0; --ri) {
6902 unsigned char *p = image.p() + row_length * ri;
6903 in.read((
char *)p, row_length);
6905 for (
int ci = 0; ci < num_cols; ++ci) {
6908 PN_uint32 *cells = (PN_uint32 *)p;
6913 unsigned char p2 = p[2];
6914 unsigned char p3 = p[3];
6915 unsigned char p4 = p[4];
6916 unsigned char p5 = p[5];
6917 unsigned char p6 = p[6];
6918 unsigned char p7 = p[7];
6920 p[2] = ((p7 & 0xf) << 4) | ((p6 & 0xf0) >> 4);
6921 p[3] = ((p5 & 0xf) << 4) | ((p7 & 0xf0) >> 4);
6922 p[4] = ((p6 & 0xf) << 4) | ((p5 & 0xf0) >> 4);
6923 p[5] = ((p4 & 0xf) << 4) | ((p3 & 0xf0) >> 4);
6924 p[6] = ((p2 & 0xf) << 4) | ((p4 & 0xf0) >> 4);
6925 p[7] = ((p3 & 0xf) << 4) | ((p2 & 0xf0) >> 4);
6929 PN_uint32 w = cells[3];
6930 w = ((w & 0xff) << 24) | ((w & 0xff00) << 8) | ((w & 0xff0000) >> 8) | ((w & 0xff000000U) >> 24);
6937 }
else if (y_size >= 2) {
6939 unsigned char *p = image.p();
6940 in.read((
char *)p, row_length);
6942 for (
int ci = 0; ci < num_cols; ++ci) {
6943 PN_uint32 *cells = (PN_uint32 *)p;
6945 unsigned char p2 = p[2];
6946 unsigned char p3 = p[3];
6947 unsigned char p4 = p[4];
6949 p[2] = ((p4 & 0xf) << 4) | ((p3 & 0xf0) >> 4);
6950 p[3] = ((p2 & 0xf) << 4) | ((p4 & 0xf0) >> 4);
6951 p[4] = ((p3 & 0xf) << 4) | ((p2 & 0xf0) >> 4);
6953 PN_uint32 w0 = cells[0];
6954 w0 = ((w0 & 0xffff) << 16) | ((w0 & 0xffff0000U) >> 16);
6957 PN_uint32 w = cells[3];
6958 w = ((w & 0xff) << 8) | ((w & 0xff00) >> 8);
6964 }
else if (y_size >= 1) {
6966 unsigned char *p = image.p();
6967 in.read((
char *)p, row_length);
6984 PreparedViews::iterator pvi;
6985 pvi = _prepared_views.find(prepared_objects);
6986 if (pvi != _prepared_views.end()) {
6987 Contexts &contexts = (*pvi).second;
6988 Contexts::iterator ci;
6989 ci = contexts.find(view);
6990 if (ci != contexts.end()) {
6994 if (contexts.empty()) {
6995 _prepared_views.erase(pvi);
7007 consider_downgrade(
PNMImage &pnmimage,
int num_channels,
const string &name) {
7016 <<
"Downgrading " << name <<
" from " 7018 << num_channels <<
".\n";
7045 for (
int yi = 0; yi < a.
get_y_size(); ++yi) {
7046 const xel *a_row = a_array + yi * x_size;
7047 const xel *b_row = b_array + yi * x_size;
7048 const xelval *a_alpha_row = a_alpha + yi * x_size;
7049 const xelval *b_alpha_row = b_alpha + yi * x_size;
7050 for (
int xi = 0; xi < x_size; ++xi) {
7051 delta += abs(PPM_GETR(a_row[xi]) - PPM_GETR(b_row[xi]));
7052 delta += abs(PPM_GETG(a_row[xi]) - PPM_GETG(b_row[xi]));
7053 delta += abs(PPM_GETB(a_row[xi]) - PPM_GETB(b_row[xi]));
7054 delta += abs(a_alpha_row[xi] - b_alpha_row[xi]);
7059 return (average_delta <= simple_image_threshold);
7076 do_filter_2d_mipmap_pages(
const CData *cdata,
7077 Texture::RamImage &to,
const Texture::RamImage &from,
7078 int x_size,
int y_size)
const {
7079 Filter2DComponent *filter_component;
7080 Filter2DComponent *filter_alpha;
7082 if (
is_srgb(cdata->_format)) {
7085 nassertv(cdata->_component_type == T_unsigned_byte);
7087 if (has_sse2_sRGB_encode()) {
7088 filter_component = &filter_2d_unsigned_byte_srgb_sse2;
7090 filter_component = &filter_2d_unsigned_byte_srgb;
7094 filter_alpha = &filter_2d_unsigned_byte;
7097 switch (cdata->_component_type) {
7098 case T_unsigned_byte:
7099 filter_component = &filter_2d_unsigned_byte;
7102 case T_unsigned_short:
7103 filter_component = &filter_2d_unsigned_short;
7107 filter_component = &filter_2d_float;
7112 <<
"Unable to generate mipmaps for 2D texture with component type " 7113 << cdata->_component_type <<
"!";
7116 filter_alpha = filter_component;
7119 size_t pixel_size = cdata->_num_components * cdata->_component_width;
7120 size_t row_size = (size_t)x_size * pixel_size;
7122 int to_x_size = max(x_size >> 1, 1);
7123 int to_y_size = max(y_size >> 1, 1);
7125 size_t to_row_size = (size_t)to_x_size * pixel_size;
7126 to._page_size = (size_t)to_y_size * to_row_size;
7127 to._image = PTA_uchar::empty_array(to._page_size * cdata->_z_size * cdata->_num_views, get_class_type());
7130 int num_color_components = cdata->_num_components;
7132 --num_color_components;
7135 int num_pages = cdata->_z_size * cdata->_num_views;
7136 for (
int z = 0; z < num_pages; ++z) {
7138 unsigned char *p = to._image.p() + z * to._page_size;
7139 nassertv(p <= to._image.p() + to._image.size() + to._page_size);
7140 const unsigned char *q = from._image.p() + z * from._page_size;
7141 nassertv(q <= from._image.p() + from._image.size() + from._page_size);
7144 for (y = 0; y < y_size - 1; y += 2) {
7146 nassertv(p == to._image.p() + z * to._page_size + (y / 2) * to_row_size);
7147 nassertv(q == from._image.p() + z * from._page_size + y * row_size);
7150 for (x = 0; x < x_size - 1; x += 2) {
7152 for (
int c = 0; c < num_color_components; ++c) {
7154 filter_component(p, q, pixel_size, row_size);
7157 filter_alpha(p, q, pixel_size, row_size);
7167 for (
int c = 0; c < num_color_components; ++c) {
7169 filter_component(p, q, 0, row_size);
7172 filter_alpha(p, q, 0, row_size);
7186 for (x = 0; x < x_size - 1; x += 2) {
7188 for (
int c = 0; c < num_color_components; ++c) {
7190 filter_component(p, q, pixel_size, 0);
7193 filter_alpha(p, q, pixel_size, 0);
7203 for (
int c = 0; c < num_color_components; ++c) {
7205 filter_component(p, q, 0, 0);
7208 filter_alpha(p, q, pixel_size, 0);
7213 nassertv(p == to._image.p() + (z + 1) * to._page_size);
7214 nassertv(q == from._image.p() + (z + 1) * from._page_size);
7232 do_filter_3d_mipmap_level(
const CData *cdata,
7233 Texture::RamImage &to,
const Texture::RamImage &from,
7234 int x_size,
int y_size,
int z_size)
const {
7235 Filter3DComponent *filter_component;
7236 Filter3DComponent *filter_alpha;
7238 if (
is_srgb(cdata->_format)) {
7241 nassertv(cdata->_component_type == T_unsigned_byte);
7243 if (has_sse2_sRGB_encode()) {
7244 filter_component = &filter_3d_unsigned_byte_srgb_sse2;
7246 filter_component = &filter_3d_unsigned_byte_srgb;
7250 filter_alpha = &filter_3d_unsigned_byte;
7253 switch (cdata->_component_type) {
7254 case T_unsigned_byte:
7255 filter_component = &filter_3d_unsigned_byte;
7258 case T_unsigned_short:
7259 filter_component = &filter_3d_unsigned_short;
7263 filter_component = &filter_3d_float;
7268 <<
"Unable to generate mipmaps for 3D texture with component type " 7269 << cdata->_component_type <<
"!";
7272 filter_alpha = filter_component;
7275 size_t pixel_size = cdata->_num_components * cdata->_component_width;
7276 size_t row_size = (size_t)x_size * pixel_size;
7277 size_t page_size = (size_t)y_size * row_size;
7278 size_t view_size = (size_t)z_size * page_size;
7280 int to_x_size = max(x_size >> 1, 1);
7281 int to_y_size = max(y_size >> 1, 1);
7282 int to_z_size = max(z_size >> 1, 1);
7284 size_t to_row_size = (size_t)to_x_size * pixel_size;
7285 size_t to_page_size = (size_t)to_y_size * to_row_size;
7286 size_t to_view_size = (size_t)to_z_size * to_page_size;
7287 to._page_size = to_page_size;
7288 to._image = PTA_uchar::empty_array(to_page_size * to_z_size * cdata->_num_views, get_class_type());
7291 int num_color_components = cdata->_num_components;
7293 --num_color_components;
7296 for (
int view = 0; view < cdata->_num_views; ++view) {
7297 unsigned char *start_to = to._image.p() + view * to_view_size;
7298 const unsigned char *start_from = from._image.p() + view * view_size;
7299 nassertv(start_to + to_view_size <= to._image.p() + to._image.size());
7300 nassertv(start_from + view_size <= from._image.p() + from._image.size());
7301 unsigned char *p = start_to;
7302 const unsigned char *q = start_from;
7305 for (z = 0; z < z_size - 1; z += 2) {
7307 nassertv(p == start_to + (z / 2) * to_page_size);
7308 nassertv(q == start_from + z * page_size);
7311 for (y = 0; y < y_size - 1; y += 2) {
7313 nassertv(p == start_to + (z / 2) * to_page_size + (y / 2) * to_row_size);
7314 nassertv(q == start_from + z * page_size + y * row_size);
7317 for (x = 0; x < x_size - 1; x += 2) {
7319 for (
int c = 0; c < num_color_components; ++c) {
7321 filter_component(p, q, pixel_size, row_size, page_size);
7324 filter_alpha(p, q, pixel_size, row_size, page_size);
7334 for (
int c = 0; c < num_color_components; ++c) {
7336 filter_component(p, q, 0, row_size, page_size);
7339 filter_alpha(p, q, 0, row_size, page_size);
7353 for (x = 0; x < x_size - 1; x += 2) {
7355 for (
int c = 0; c < num_color_components; ++c) {
7357 filter_component(p, q, pixel_size, 0, page_size);
7360 filter_alpha(p, q, pixel_size, 0, page_size);
7370 for (
int c = 0; c < num_color_components; ++c) {
7372 filter_component(p, q, 0, 0, page_size);
7375 filter_alpha(p, q, 0, 0, page_size);
7389 for (y = 0; y < y_size - 1; y += 2) {
7391 nassertv(p == start_to + (y / 2) * to_row_size);
7392 nassertv(q == start_from + y * row_size);
7395 for (x = 0; x < x_size - 1; x += 2) {
7397 for (
int c = 0; c < num_color_components; ++c) {
7399 filter_component(p, q, pixel_size, row_size, 0);
7402 filter_alpha(p, q, pixel_size, row_size, 0);
7412 for (
int c = 0; c < num_color_components; ++c) {
7414 filter_component(p, q, 0, row_size, 0);
7417 filter_alpha(p, q, 0, row_size, 0);
7431 for (x = 0; x < x_size - 1; x += 2) {
7433 for (
int c = 0; c < num_color_components; ++c) {
7435 filter_component(p, q, pixel_size, 0, 0);
7438 filter_alpha(p, q, pixel_size, 0, 0);
7448 for (
int c = 0; c < num_color_components; ++c) {
7450 filter_component(p, q, 0, 0, 0);
7453 filter_alpha(p, q, 0, 0, 0);
7459 nassertv(p == start_to + to_z_size * to_page_size);
7460 nassertv(q == start_from + z_size * page_size);
7472 filter_2d_unsigned_byte(
unsigned char *&p,
const unsigned char *&q,
7473 size_t pixel_size,
size_t row_size) {
7474 unsigned int result = ((
unsigned int)q[0] +
7475 (
unsigned int)q[pixel_size] +
7476 (
unsigned int)q[row_size] +
7477 (
unsigned int)q[pixel_size + row_size]) >> 2;
7478 *p = (
unsigned char)result;
7491 filter_2d_unsigned_byte_srgb(
unsigned char *&p,
const unsigned char *&q,
7492 size_t pixel_size,
size_t row_size) {
7493 float result = (decode_sRGB_float(q[0]) +
7494 decode_sRGB_float(q[pixel_size]) +
7495 decode_sRGB_float(q[row_size]) +
7496 decode_sRGB_float(q[pixel_size + row_size]));
7498 *p = encode_sRGB_uchar(result * 0.25f);
7511 filter_2d_unsigned_byte_srgb_sse2(
unsigned char *&p,
const unsigned char *&q,
7512 size_t pixel_size,
size_t row_size) {
7513 float result = (decode_sRGB_float(q[0]) +
7514 decode_sRGB_float(q[pixel_size]) +
7515 decode_sRGB_float(q[row_size]) +
7516 decode_sRGB_float(q[pixel_size + row_size]));
7518 *p = encode_sRGB_uchar_sse2(result * 0.25f);
7531 filter_2d_unsigned_short(
unsigned char *&p,
const unsigned char *&q,
7532 size_t pixel_size,
size_t row_size) {
7533 unsigned int result = ((
unsigned int)*(
unsigned short *)&q[0] +
7534 (
unsigned int)*(
unsigned short *)&q[pixel_size] +
7535 (
unsigned int)*(
unsigned short *)&q[row_size] +
7536 (
unsigned int)*(
unsigned short *)&q[pixel_size + row_size]) >> 2;
7537 store_unscaled_short(p, result);
7549 filter_2d_float(
unsigned char *&p,
const unsigned char *&q,
7550 size_t pixel_size,
size_t row_size) {
7551 *(
float *)p = (*(
float *)&q[0] +
7552 *(
float *)&q[pixel_size] +
7553 *(
float *)&q[row_size] +
7554 *(
float *)&q[pixel_size + row_size]) / 4.0f;
7567 filter_3d_unsigned_byte(
unsigned char *&p,
const unsigned char *&q,
7568 size_t pixel_size,
size_t row_size,
size_t page_size) {
7569 unsigned int result = ((
unsigned int)q[0] +
7570 (
unsigned int)q[pixel_size] +
7571 (
unsigned int)q[row_size] +
7572 (
unsigned int)q[pixel_size + row_size] +
7573 (
unsigned int)q[page_size] +
7574 (
unsigned int)q[pixel_size + page_size] +
7575 (
unsigned int)q[row_size + page_size] +
7576 (
unsigned int)q[pixel_size + row_size + page_size]) >> 3;
7577 *p = (
unsigned char)result;
7590 filter_3d_unsigned_byte_srgb(
unsigned char *&p,
const unsigned char *&q,
7591 size_t pixel_size,
size_t row_size,
size_t page_size) {
7592 float result = (decode_sRGB_float(q[0]) +
7593 decode_sRGB_float(q[pixel_size]) +
7594 decode_sRGB_float(q[row_size]) +
7595 decode_sRGB_float(q[pixel_size + row_size]) +
7596 decode_sRGB_float(q[page_size]) +
7597 decode_sRGB_float(q[pixel_size + page_size]) +
7598 decode_sRGB_float(q[row_size + page_size]) +
7599 decode_sRGB_float(q[pixel_size + row_size + page_size]));
7601 *p = encode_sRGB_uchar(result * 0.125f);
7614 filter_3d_unsigned_byte_srgb_sse2(
unsigned char *&p,
const unsigned char *&q,
7615 size_t pixel_size,
size_t row_size,
size_t page_size) {
7616 float result = (decode_sRGB_float(q[0]) +
7617 decode_sRGB_float(q[pixel_size]) +
7618 decode_sRGB_float(q[row_size]) +
7619 decode_sRGB_float(q[pixel_size + row_size]) +
7620 decode_sRGB_float(q[page_size]) +
7621 decode_sRGB_float(q[pixel_size + page_size]) +
7622 decode_sRGB_float(q[row_size + page_size]) +
7623 decode_sRGB_float(q[pixel_size + row_size + page_size]));
7625 *p = encode_sRGB_uchar_sse2(result * 0.125f);
7638 filter_3d_unsigned_short(
unsigned char *&p,
const unsigned char *&q,
7639 size_t pixel_size,
size_t row_size,
7641 unsigned int result = ((
unsigned int)*(
unsigned short *)&q[0] +
7642 (
unsigned int)*(
unsigned short *)&q[pixel_size] +
7643 (
unsigned int)*(
unsigned short *)&q[row_size] +
7644 (
unsigned int)*(
unsigned short *)&q[pixel_size + row_size] +
7645 (
unsigned int)*(
unsigned short *)&q[page_size] +
7646 (
unsigned int)*(
unsigned short *)&q[pixel_size + page_size] +
7647 (
unsigned int)*(
unsigned short *)&q[row_size + page_size] +
7648 (
unsigned int)*(
unsigned short *)&q[pixel_size + row_size + page_size]) >> 3;
7649 store_unscaled_short(p, result);
7661 filter_3d_float(
unsigned char *&p,
const unsigned char *&q,
7662 size_t pixel_size,
size_t row_size,
size_t page_size) {
7663 *(
float *)p = (*(
float *)&q[0] +
7664 *(
float *)&q[pixel_size] +
7665 *(
float *)&q[row_size] +
7666 *(
float *)&q[pixel_size + row_size] +
7667 *(
float *)&q[page_size] +
7668 *(
float *)&q[pixel_size + page_size] +
7669 *(
float *)&q[row_size + page_size] +
7670 *(
float *)&q[pixel_size + row_size + page_size]) / 8.0f;
7682 do_squish(CData *cdata, Texture::CompressionMode compression,
int squish_flags) {
7684 if (cdata->_ram_images.empty() || cdata->_ram_image_compression != CM_off) {
7688 if (!do_has_all_ram_mipmap_images(cdata)) {
7691 do_generate_ram_mipmap_images(cdata);
7695 compressed_ram_images.reserve(cdata->_ram_images.size());
7696 for (
size_t n = 0; n < cdata->_ram_images.size(); ++n) {
7697 RamImage compressed_image;
7698 int x_size = do_get_expected_mipmap_x_size(cdata, n);
7699 int y_size = do_get_expected_mipmap_y_size(cdata, n);
7700 int num_pages = do_get_expected_mipmap_num_pages(cdata, n);
7701 int page_size = squish::GetStorageRequirements(x_size, y_size, squish_flags);
7702 int cell_size = squish::GetStorageRequirements(4, 4, squish_flags);
7704 compressed_image._page_size = page_size;
7705 compressed_image._image = PTA_uchar::empty_array(page_size * num_pages);
7706 for (
int z = 0; z < num_pages; ++z) {
7707 unsigned char *dest_page = compressed_image._image.p() + z * page_size;
7708 unsigned const char *source_page = cdata->_ram_images[n]._image.p() + z * cdata->_ram_images[n]._page_size;
7709 unsigned const char *source_page_end = source_page + cdata->_ram_images[n]._page_size;
7711 unsigned char *d = dest_page;
7712 for (
int y = 0; y < y_size; y += 4) {
7713 for (
int x = 0; x < x_size; x += 4) {
7714 unsigned char tb[16 * 4];
7716 unsigned char *t = tb;
7717 for (
int i = 0; i < 16; ++i) {
7720 unsigned const char *s = source_page + (yi * x_size + xi) * cdata->_num_components;
7721 if (s < source_page_end) {
7722 switch (cdata->_num_components) {
7755 squish::CompressMasked(tb, mask, d, squish_flags);
7761 compressed_ram_images.push_back(compressed_image);
7763 cdata->_ram_images.swap(compressed_ram_images);
7764 cdata->_ram_image_compression = compression;
7767 #else // HAVE_SQUISH 7770 #endif // HAVE_SQUISH 7780 do_unsquish(CData *cdata,
int squish_flags) {
7782 if (cdata->_ram_images.empty()) {
7786 uncompressed_ram_images.reserve(cdata->_ram_images.size());
7787 for (
size_t n = 0; n < cdata->_ram_images.size(); ++n) {
7788 RamImage uncompressed_image;
7789 int x_size = do_get_expected_mipmap_x_size(cdata, n);
7790 int y_size = do_get_expected_mipmap_y_size(cdata, n);
7791 int num_pages = do_get_expected_mipmap_num_pages(cdata, n);
7792 int page_size = squish::GetStorageRequirements(x_size, y_size, squish_flags);
7793 int cell_size = squish::GetStorageRequirements(4, 4, squish_flags);
7795 uncompressed_image._page_size = do_get_expected_ram_mipmap_page_size(cdata, n);
7796 uncompressed_image._image = PTA_uchar::empty_array(uncompressed_image._page_size * num_pages);
7797 for (
int z = 0; z < num_pages; ++z) {
7798 unsigned char *dest_page = uncompressed_image._image.p() + z * uncompressed_image._page_size;
7799 unsigned char *dest_page_end = dest_page + uncompressed_image._page_size;
7800 unsigned const char *source_page = cdata->_ram_images[n]._image.p() + z * page_size;
7802 unsigned const char *s = source_page;
7803 for (
int y = 0; y < y_size; y += 4) {
7804 for (
int x = 0; x < x_size; x += 4) {
7805 unsigned char tb[16 * 4];
7806 squish::Decompress(tb, s, squish_flags);
7809 unsigned char *t = tb;
7810 for (
int i = 0; i < 16; ++i) {
7813 unsigned char *d = dest_page + (yi * x_size + xi) * cdata->_num_components;
7814 if (d < dest_page_end) {
7815 switch (cdata->_num_components) {
7845 uncompressed_ram_images.push_back(uncompressed_image);
7847 cdata->_ram_images.swap(uncompressed_ram_images);
7848 cdata->_ram_image_compression = CM_off;
7851 #else // HAVE_SQUISH 7854 #endif // HAVE_SQUISH 7877 bool has_rawdata =
false;
7878 do_write_datagram_header(cdata, manager, me, has_rawdata);
7879 do_write_datagram_body(cdata, manager, me);
7884 do_write_datagram_rawdata(cdata, manager, me);
7930 do_write_datagram_header(CData *cdata,
BamWriter *manager,
Datagram &me,
bool &has_rawdata) {
7940 has_rawdata = (file_texture_mode == BamWriter::BTM_rawdata ||
7941 (cdata->_filename.empty() && do_has_bam_rawdata(cdata)));
7942 if (has_rawdata && !do_has_bam_rawdata(cdata)) {
7943 do_get_bam_rawdata(cdata);
7944 if (!do_has_bam_rawdata(cdata)) {
7946 has_rawdata =
false;
7952 Filename filename = cdata->_filename;
7953 Filename alpha_filename = cdata->_alpha_filename;
7957 switch (file_texture_mode) {
7958 case BamWriter::BTM_unchanged:
7959 case BamWriter::BTM_rawdata:
7962 case BamWriter::BTM_fullpath:
7963 filename = cdata->_fullpath;
7964 alpha_filename = cdata->_alpha_fullpath;
7967 case BamWriter::BTM_relative:
7968 filename = cdata->_fullpath;
7969 alpha_filename = cdata->_alpha_fullpath;
7974 if (gobj_cat.is_debug()) {
7976 <<
"Texture file " << cdata->_fullpath
7977 <<
" found as " << filename <<
"\n";
7982 if (gobj_cat.is_debug()) {
7984 <<
"Alpha image " << cdata->_alpha_fullpath
7985 <<
" found as " << alpha_filename <<
"\n";
7989 case BamWriter::BTM_basename:
7991 alpha_filename = cdata->_alpha_fullpath.
get_basename();
7996 <<
"Unsupported bam-texture-mode: " << (int)file_texture_mode <<
"\n";
7999 if (filename.empty() && do_has_bam_rawdata(cdata)) {
8007 me.
add_uint8(cdata->_primary_file_num_channels);
8008 me.
add_uint8(cdata->_alpha_file_channel);
8011 me.
add_bool(cdata->_has_read_mipmaps);
8023 cdata->_default_sampler.write_datagram(me);
8031 me.
add_uint8(cdata->_auto_texture_scale);
8039 if (has_simple_ram_image) {
8042 me.
add_int32(cdata->_simple_image_date_generated);
8043 me.
add_uint32(cdata->_simple_ram_image._image.size());
8044 me.
append_data(cdata->_simple_ram_image._image, cdata->_simple_ram_image._image.size());
8067 me.
add_uint8(cdata->_ram_image_compression);
8068 me.
add_uint8(cdata->_ram_images.size());
8069 for (
size_t n = 0; n < cdata->_ram_images.size(); ++n) {
8070 me.
add_uint32(cdata->_ram_images[n]._page_size);
8071 me.
add_uint32(cdata->_ram_images[n]._image.size());
8072 me.
append_data(cdata->_ram_images[n]._image, cdata->_ram_images[n]._image.size());
8084 return dummy->make_this_from_bam(params);
8108 parse_params(params, scan, manager);
8116 int primary_file_num_channels = scan.
get_uint8();
8117 int alpha_file_channel = scan.
get_uint8();
8118 bool has_rawdata = scan.
get_bool();
8119 TextureType texture_type = (TextureType)scan.
get_uint8();
8124 if (texture_type == TT_2d_texture_array) {
8125 texture_type = TT_cube_map;
8128 bool has_read_mipmaps =
false;
8130 has_read_mipmaps = scan.
get_bool();
8141 CDWriter cdata_me(me->_cycler,
true);
8142 cdata_me->_filename = filename;
8143 cdata_me->_alpha_filename = alpha_filename;
8144 cdata_me->_primary_file_num_channels = primary_file_num_channels;
8145 cdata_me->_alpha_file_channel = alpha_file_channel;
8146 cdata_me->_texture_type = texture_type;
8147 cdata_me->_has_read_mipmaps = has_read_mipmaps;
8150 me->do_fillin_body(cdata_me, scan, manager);
8151 me->do_fillin_rawdata(cdata_me, scan, manager);
8164 AutoTextureScale auto_texture_scale = ATS_unspecified;
8166 CDWriter cdata_dummy(dummy->_cycler,
true);
8167 dummy->do_fillin_body(cdata_dummy, scan, manager);
8168 auto_texture_scale = cdata_dummy->_auto_texture_scale;
8171 if (filename.empty()) {
8175 <<
"Cannot create texture '" << name <<
"' with no filename.\n";
8185 if (!alpha_filename.empty()) {
8192 options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_generate_mipmaps);
8196 switch (texture_type) {
8199 if (alpha_filename.empty()) {
8201 has_read_mipmaps, options);
8204 primary_file_num_channels,
8206 has_read_mipmaps, options);
8214 case TT_2d_texture_array:
8226 CDWriter cdata_me(me->_cycler,
true);
8227 me->do_fillin_from(cdata_me, dummy);
8246 cdata->_default_sampler.read_datagram(scan, manager);
8249 cdata->_compression = (CompressionMode)scan.
get_uint8();
8252 cdata->_quality_level = (QualityLevel)scan.
get_uint8();
8255 cdata->_format = (Format)scan.
get_uint8();
8256 cdata->_num_components = scan.
get_uint8();
8258 if ((
int)cdata->_texture_type == 5) {
8263 <<
"Buffer textures are not supported in this version of Panda3D.\n";
8266 cdata->inc_properties_modified();
8268 cdata->_auto_texture_scale = ATS_unspecified;
8270 cdata->_auto_texture_scale = (AutoTextureScale)scan.
get_uint8();
8275 cdata->_orig_file_x_size = scan.
get_uint32();
8276 cdata->_orig_file_y_size = scan.
get_uint32();
8278 has_simple_ram_image = scan.
get_bool();
8281 if (has_simple_ram_image) {
8284 cdata->_simple_image_date_generated = scan.
get_int32();
8291 <<
"simple RAM image extends past end of datagram, is texture corrupt?\n";
8295 PTA_uchar image = PTA_uchar::empty_array(u_size, get_class_type());
8298 cdata->_simple_ram_image._image = image;
8299 cdata->_simple_ram_image._page_size = u_size;
8300 cdata->inc_simple_image_modified();
8321 do_set_pad_size(cdata, 0, 0, 0);
8324 cdata->_num_views = 1;
8328 cdata->_component_type = (ComponentType)scan.
get_uint8();
8329 cdata->_component_width = scan.
get_uint8();
8330 cdata->_ram_image_compression = CM_off;
8332 cdata->_ram_image_compression = (CompressionMode)scan.
get_uint8();
8335 int num_ram_images = 1;
8340 cdata->_ram_images.clear();
8341 cdata->_ram_images.reserve(num_ram_images);
8342 for (
int n = 0; n < num_ram_images; ++n) {
8343 cdata->_ram_images.push_back(RamImage());
8346 cdata->_ram_images[n]._page_size = scan.
get_uint32();
8355 <<
"RAM image " << n <<
" extends past end of datagram, is texture corrupt?\n";
8359 PTA_uchar image = PTA_uchar::empty_array(u_size, get_class_type());
8362 cdata->_ram_images[n]._image = image;
8364 cdata->_loaded_from_image =
true;
8365 cdata->inc_image_modified();
8377 do_fillin_from(CData *cdata,
const Texture *dummy) {
8385 CDReader cdata_dummy(dummy->_cycler);
8387 do_set_wrap_u(cdata, cdata_dummy->_default_sampler.get_wrap_u());
8388 do_set_wrap_v(cdata, cdata_dummy->_default_sampler.get_wrap_v());
8389 do_set_wrap_w(cdata, cdata_dummy->_default_sampler.get_wrap_w());
8390 do_set_border_color(cdata, cdata_dummy->_default_sampler.get_border_color());
8392 if (cdata_dummy->_default_sampler.get_minfilter() != SamplerState::FT_default) {
8393 do_set_minfilter(cdata, cdata_dummy->_default_sampler.get_minfilter());
8395 if (cdata_dummy->_default_sampler.get_magfilter() != SamplerState::FT_default) {
8396 do_set_magfilter(cdata, cdata_dummy->_default_sampler.get_magfilter());
8398 if (cdata_dummy->_default_sampler.get_anisotropic_degree() != 0) {
8399 do_set_anisotropic_degree(cdata, cdata_dummy->_default_sampler.get_anisotropic_degree());
8401 if (cdata_dummy->_compression != CM_default) {
8402 do_set_compression(cdata, cdata_dummy->_compression);
8404 if (cdata_dummy->_quality_level != QL_default) {
8405 do_set_quality_level(cdata, cdata_dummy->_quality_level);
8408 Format format = cdata_dummy->_format;
8409 int num_components = cdata_dummy->_num_components;
8411 if (num_components == cdata->_num_components) {
8416 do_set_format(cdata, format);
8419 if (!cdata_dummy->_simple_ram_image._image.empty()) {
8422 if (cdata->_simple_ram_image._image.empty() ||
8423 cdata_dummy->_simple_image_date_generated > cdata->_simple_image_date_generated) {
8424 do_set_simple_ram_image(cdata,
8425 cdata_dummy->_simple_ram_image._image,
8426 cdata_dummy->_simple_x_size,
8427 cdata_dummy->_simple_y_size);
8428 cdata->_simple_image_date_generated = cdata_dummy->_simple_image_date_generated;
8440 _primary_file_num_channels = 0;
8441 _alpha_file_channel = 0;
8442 _keep_ram_image =
true;
8443 _compression = CM_default;
8444 _auto_texture_scale = ATS_unspecified;
8445 _ram_image_compression = CM_off;
8446 _render_to_texture =
false;
8447 _match_framebuffer_format =
false;
8448 _post_load_store_cache =
false;
8449 _quality_level = QL_default;
8451 _texture_type = TT_2d_texture;
8466 _orig_file_x_size = 0;
8467 _orig_file_y_size = 0;
8469 _loaded_from_image =
false;
8470 _loaded_from_txo =
false;
8471 _has_read_pages =
false;
8472 _has_read_mipmaps =
false;
8473 _num_mipmap_levels_read = 0;
8477 _simple_ram_image._page_size = 0;
8479 _has_clear_color =
false;
8488 CData(
const Texture::CData ©) {
8489 _num_mipmap_levels_read = 0;
8493 _properties_modified = copy._properties_modified;
8494 _image_modified = copy._image_modified;
8495 _simple_image_modified = copy._simple_image_modified;
8505 return new CData(*
this);
8513 void Texture::CData::
8514 do_assign(
const Texture::CData *copy) {
8515 _filename = copy->_filename;
8516 _alpha_filename = copy->_alpha_filename;
8517 if (!copy->_fullpath.empty()) {
8520 _fullpath = copy->_fullpath;
8521 _alpha_fullpath = copy->_alpha_fullpath;
8523 _primary_file_num_channels = copy->_primary_file_num_channels;
8524 _alpha_file_channel = copy->_alpha_file_channel;
8525 _x_size = copy->_x_size;
8526 _y_size = copy->_y_size;
8527 _z_size = copy->_z_size;
8528 _num_views = copy->_num_views;
8529 _pad_x_size = copy->_pad_x_size;
8530 _pad_y_size = copy->_pad_y_size;
8531 _pad_z_size = copy->_pad_z_size;
8532 _orig_file_x_size = copy->_orig_file_x_size;
8533 _orig_file_y_size = copy->_orig_file_y_size;
8534 _num_components = copy->_num_components;
8535 _component_width = copy->_component_width;
8536 _texture_type = copy->_texture_type;
8537 _format = copy->_format;
8538 _component_type = copy->_component_type;
8539 _loaded_from_image = copy->_loaded_from_image;
8540 _loaded_from_txo = copy->_loaded_from_txo;
8541 _has_read_pages = copy->_has_read_pages;
8542 _has_read_mipmaps = copy->_has_read_mipmaps;
8543 _num_mipmap_levels_read = copy->_num_mipmap_levels_read;
8544 _default_sampler = copy->_default_sampler;
8545 _keep_ram_image = copy->_keep_ram_image;
8546 _compression = copy->_compression;
8547 _match_framebuffer_format = copy->_match_framebuffer_format;
8548 _quality_level = copy->_quality_level;
8549 _auto_texture_scale = copy->_auto_texture_scale;
8550 _ram_image_compression = copy->_ram_image_compression;
8551 _ram_images = copy->_ram_images;
8552 _simple_x_size = copy->_simple_x_size;
8553 _simple_y_size = copy->_simple_y_size;
8554 _simple_ram_image = copy->_simple_ram_image;
8563 void Texture::CData::
8574 int Texture::CData::
8586 void Texture::CData::
8595 operator << (ostream &out, Texture::TextureType tt) {
8604 operator << (ostream &out, Texture::ComponentType ct) {
8613 operator << (ostream &out, Texture::Format f) {
8622 operator << (ostream &out, Texture::CompressionMode cm) {
8631 operator << (ostream &out, Texture::QualityLevel tql) {
8640 operator >> (istream &in, Texture::QualityLevel &tql) {
Filename get_filename_index(int index) const
If the pattern flag is set for this Filename and the filename string actually includes a sequence of ...
string get_dirname() const
Returns the directory part of the filename.
void set_data(TypedWritable *ptr, ReferenceCount *ref_ptr)
Stores a new data object on the record.
virtual void ensure_loader_type(const Filename &filename)
May be called prior to calling read_txo() or any bam-related Texture-creating callback, to ensure that the proper dynamic libraries for a Texture of the current class type, and the indicated filename, have been already loaded.
static bool is_srgb(Format format)
Returns true if the indicated format is in the sRGB color space, false otherwise. ...
string get_basename() const
Returns the basename part of the filename.
static string format_quality_level(QualityLevel tql)
Returns the indicated QualityLevel converted to a string word.
bool was_image_modified() const
Returns true if the texture image has been modified since the last time mark_loaded() was called...
const Filename & get_filename() const
If a BAM is a file, then the BamWriter should contain the name of the file.
void add_uint8(PN_uint8 value)
Adds an unsigned 8-bit integer to the datagram.
void set_green(int x, int y, float g)
Sets the green component color only at the indicated pixel.
void enqueue_texture(Texture *tex)
Indicates that a texture would like to be put on the list to be prepared when the GSG is next ready t...
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
This is our own Panda specialization on the default STL map.
static string format_component_type(ComponentType ct)
Returns the indicated ComponentType converted to a string word.
bool resolve_filename(Filename &filename, const DSearchPath &searchpath, const string &default_extension=string()) const
Searches the given search path for the filename.
void copy_sub_image(const PNMImage ©, int xto, int yto, int xfrom=0, int yfrom=0, int x_size=-1, int y_size=-1)
Copies a rectangular area of another image into a rectangular area of this image. ...
xelval get_channel_val(int x, int y, int channel) const
Returns the nth component color at the indicated pixel.
bool get_bool()
Extracts a boolean value.
void add_string(const string &str)
Adds a variable-length string to the datagram.
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
static Texture * load_cube_map(const Filename &filename_pattern, bool read_mipmaps=false, const LoaderOptions &options=LoaderOptions())
Loads a cube map texture that is specified with a series of 6 pages, numbered 0 through 5...
ColorSpace get_color_space() const
Returns the color space in which the image is encoded.
void release_texture(TextureContext *tc)
Indicates that a texture context, created by a previous call to prepare_texture(), is no longer needed.
TypedWritable * get_data() const
Returns a pointer to the data stored in the record, or NULL if there is no data.
static bool adjust_size(int &x_size, int &y_size, const string &name, bool for_padding, AutoTextureScale auto_texture_scale=ATS_unspecified)
Computes the proper size of the texture, based on the original size, the filename, and the resizing whims of the config file.
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
virtual bool is_cacheable() const
Returns true if there is enough information in this Texture object to write it to the bam cache succe...
xelval get_gray_val(int x, int y) const
Returns the gray component color at the indicated pixel.
void wait()
Waits on the condition.
static string format_format(Format f)
Returns the indicated Format converted to a string word.
void append_data(const void *data, size_t size)
Appends some more raw data to the end of the datagram.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
bool get_resident(PreparedGraphicsObjects *prepared_objects) const
Returns true if this Texture is reported to be resident within graphics memory for the indicated GSG...
bool resolve()
This may be called at any time during processing of the Bam file to resolve all the known pointers so...
void alpha_fill(float alpha=0.0)
Sets the entire alpha channel to the given level.
void set_ram_mipmap_pointer_from_int(long long pointer, int n, int page_size)
Accepts a raw pointer cast as an int, which is then passed to set_ram_mipmap_pointer(); see the docum...
AutoTextureScale get_auto_texture_scale() const
Returns the power-of-2 texture-scaling mode that will be applied to this particular texture when it i...
Specifies parameters that may be passed to the loader.
This class maintains a cache of Bam and/or Txo objects generated from model files and texture images ...
A hierarchy of directories and files that appears to be one continuous file system, even though the files may originate from several different sources that may not be related to the actual OS's file system.
bool dequeue_texture(Texture *tex)
Removes a texture from the queued list of textures to be prepared.
static Filename pattern_filename(const string &filename)
Constructs a filename that represents a sequence of numbered files.
TypedWritable * read_object()
Reads a single object from the Bam file.
int release_all()
Frees the context allocated on all objects for which the texture has been declared.
float get_gray(int x, int y) const
Returns the gray component color at the indicated pixel.
static void register_with_read_factory()
Factory method to generate a Texture object.
bool read(const Filename &filename, PNMFileType *type=NULL, bool report_unknown_type=true)
Reads the indicated image filename.
A single page of data maintained by a PipelineCycler.
static Format string_format(const string &str)
Returns the Format corresponding to the indicated string word.
bool was_image_modified(PreparedGraphicsObjects *prepared_objects) const
Returns true if the texture needs to be re-loaded onto the indicated GSG, either because its image da...
virtual bool is_floating_point()
Returns true if this PNMFileType represents a floating-point image type, false if it is a normal...
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
void set_ram_image_as(CPTA_uchar image, const string &provided_format)
Replaces the current system-RAM image with the new data, converting it first if necessary from the in...
Base class for objects that can be written to and read from Bam files.
PN_uint32 get_uint32()
Extracts an unsigned 32-bit integer.
bool write_header(const string &header)
Writes a sequence of bytes to the beginning of the datagram file.
size_t estimate_texture_memory() const
Estimates the amount of texture memory that will be consumed by loading this texture.
void set_orig_file_size(int x, int y, int z=1)
Specifies the size of the texture as it exists in its original disk file, before any Panda scaling...
static bool is_specific(CompressionMode compression)
Returns true if the indicated compression mode is one of the specific compression types...
bool get_active(PreparedGraphicsObjects *prepared_objects) const
Returns true if this Texture was rendered in the most recent frame within the indicated GSG...
This is a special class object that holds all the information returned by a particular GSG to indicat...
This collects together the pieces of data that are accumulated for each node while walking the scene ...
bool read_txo(istream &in, const string &filename="")
Reads the texture from a Panda texture object.
A base class for things which need to inherit from both TypedObject and from ReferenceCount.
virtual void write_datagram(BamWriter *manager, Datagram &me)
Function to write the important information in the particular object to a Datagram.
PTA_uchar modify_simple_ram_image()
Returns a modifiable pointer to the internal "simple" texture image.
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
xel * get_array()
Directly access the underlying PNMImage array.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
bool get_cache_textures() const
Returns whether texture files (e.g.
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
void set_basename_wo_extension(const string &s)
Replaces the basename part of the filename, without the file extension.
PN_int32 get_int32()
Extracts a signed 32-bit integer.
void set_red(int x, int y, float r)
Sets the red component color only at the indicated pixel.
PN_uint8 get_uint8()
Extracts an unsigned 8-bit integer.
int get_texture_num_views() const
See set_texture_num_views().
PN_uint32 get_uint32()
Extracts an unsigned 32-bit integer.
static void consider_yield()
Possibly suspends the current thread for the rest of the current epoch, if it has run for enough this...
CPTA_uchar get_ram_image_as(const string &requested_format)
Returns the uncompressed system-RAM image data associated with the texture.
The abstract base class for a file or directory within the VirtualFileSystem.
A table of objects that are saved within the graphics context for reference by handle later...
bool has_ram_image() const
Returns true if the Texture has its image contents available in main RAM, false if it exists only in ...
Texture(const string &name=string())
Constructs an empty texture.
static void close_read_file(istream *stream)
Closes a file opened by a previous call to open_read_file().
string get_string()
Extracts a variable-length string.
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
int size() const
Returns the number of unique words in the variable.
static CompressionMode string_compression_mode(const string &str)
Returns the CompressionMode value associated with the given string representation.
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
void quick_filter_from(const PNMImage ©, int xborder=0, int yborder=0)
Resizes from the given image, with a fixed radius of 0.5.
TypedReferenceCount * get_aux_data(const string &key) const
Returns a record previously recorded via set_aux_data().
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
bool open(const FileReference *file)
Opens the indicated filename for writing.
static QualityLevel string_quality_level(const string &str)
Returns the QualityLevel value associated with the given string representation.
void resize(int new_x_size, int new_y_size)
Applies a simple filter to resample the pfm file in-place to the indicated size.
bool is_valid() const
Returns true if the image has been read in or correctly initialized with a height and width...
This is our own Panda specialization on the default STL vector.
void notify_all()
Informs all of the other threads who are currently blocked on wait() that the relevant condition has ...
void clear_aux_data(const string &key)
Removes a record previously recorded via set_aux_data().
CPTA_uchar get_ram_mipmap_image(int n) const
Returns the system-RAM image data associated with the nth mipmap level, if present.
void set_file_texture_mode(BamTextureMode file_texture_mode)
Changes the BamTextureMode preference for the Bam file currently being written.
bool release(PreparedGraphicsObjects *prepared_objects)
Frees the texture context only on the indicated object, if it exists there.
void consider_rescale(PNMImage &pnmimage)
Asks the PNMImage to change its scale when it reads the image, according to the whims of the Config...
void set_size_padded(int x=1, int y=1, int z=1)
Changes the size of the texture, padding if necessary, and setting the pad region as well...
bool store(BamCacheRecord *record)
Flushes a cache entry to disk.
bool read(const Filename &fullpath)
Reads the PFM data from the indicated file, returning true on success, false on failure.
A lightweight class that represents a single element that may be timed and/or counted via stats...
static AutoTextureScale get_textures_power_2()
This flag returns ATS_none, ATS_up, or ATS_down and controls the scaling of textures in general...
bool write(const Filename &fullpath)
Writes the PFM data to the indicated file, returning true on success, false on failure.
virtual bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const
If has_cull_callback() returns true, this function will be called during the cull traversal to perfor...
string extract_bytes(size_t size)
Extracts the indicated number of bytes in the datagram and returns them as a string.
void generate_alpha_scale_map()
Generates a special 256x1 1-d texture that can be used to apply an arbitrary alpha scale to objects b...
void add_bool(bool value)
Adds a boolean value to the datagram.
A base class for all things which can have a name.
void acquire() const
Grabs the mutex if it is available.
bool uses_mipmaps() const
Returns true if the minfilter settings on this texture indicate the use of mipmapping, false otherwise.
bool exists(const Filename &filename) const
Convenience function; returns true if the named file exists.
bool init()
Initializes the BamReader prior to reading any objects from its source.
int get_read_y_size() const
Returns the requested y_size of the image if set_read_size() has been called, or the image y_size oth...
bool get_resident() const
Returns the resident flag associated with this object.
void set_auto_texture_scale(AutoTextureScale scale)
Set this flag to ATS_none, ATS_up, ATS_down, or ATS_pad to control how a texture is scaled from disk ...
bool get_cache_compressed_textures() const
Returns whether compressed texture files will be stored in the cache, as compressed txo files...
The name of a file, such as a texture file or an Egg file.
PointerToArray< Element > cast_non_const() const
Casts away the constness of the CPTA(Element), and returns an equivalent PTA(Element).
Defines a pfm file, a 2-d table of floating-point numbers, either 3-component or 1-component, or with a special extension, 2- or 4-component.
LVecBase3f xform_point(const LVecBase3f &v) const
The matrix transforms a 3-component point (including translation component) and returns the result...
int get_num_loadable_ram_mipmap_images() const
Returns the number of contiguous mipmap levels that exist in RAM, up until the first gap in the seque...
int get_remaining_size() const
Return the bytes left in the datagram.
const LoaderOptions & get_loader_options() const
Returns the LoaderOptions passed to the loader when the model was requested, if any.
This is a 4-by-4 transform matrix.
An instance of this class is written to the front of a Bam or Txo file to make the file a cached inst...
static bool has_alpha(Format format)
Returns true if the indicated format includes alpha, false otherwise.
void set_gray(int x, int y, float gray)
Sets the gray component color at the indicated pixel.
void copy_header_from(const PNMImageHeader &header)
Copies just the header information into this image.
string get_unique_value(int n) const
Returns the nth unique value of the variable.
xelval get_blue_val(int x, int y) const
Returns the blue component color at the indicated pixel.
bool get_active() const
Returns the active flag associated with this object.
void set_blue(int x, int y, float b)
Sets the blue component color only at the indicated pixel.
bool has_simple_ram_image() const
Returns true if the Texture has a "simple" image available in main RAM.
This template class calls PipelineCycler::read() in the constructor and PipelineCycler::release_read(...
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
static GraphicsStateGuardianBase * get_default_gsg()
Returns a pointer to the "default" GSG.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
PN_float32 get_channel(int x, int y, int c) const
Returns the cth channel of the point value at the indicated point.
Texture * load_related(const InternalName *suffix) const
Loads a texture whose filename is derived by concatenating a suffix to the filename of this texture...
void set_aux_data(const string &key, TypedReferenceCount *aux_data)
Records an arbitrary object in the Texture, associated with a specified key.
This class specializes ConfigVariable as an enumerated type.
int get_word(int n) const
Returns the variable's nth value.
bool write_object(const TypedWritable *obj)
Writes a single object to the Bam file, so that the BamReader::read_object() can later correctly rest...
PointerTo< VirtualFile > get_file(const Filename &filename, bool status_only=false) const
Looks up the file by the indicated name in the file system.
bool read_dds(istream &in, const string &filename="", bool header_only=false)
Reads the texture from a DDS file object.
size_t get_data_size_bytes() const
Returns the number of bytes previously reported for the data object.
bool write(const Filename &filename, PNMFileType *type=NULL) const
Writes the image to the indicated filename.
void register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
static Texture * load_texture(const Filename &filename, int primary_file_num_channels=0, bool read_mipmaps=false, const LoaderOptions &options=LoaderOptions())
Loads the given filename up into a texture, if it has not already been loaded, and returns the new te...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
xelval * get_alpha_array()
Directly access the underlying PNMImage array of alpha values.
string get_basename_wo_extension() const
Returns the basename part of the filename, without the file extension.
size_t get_data_size_bytes(PreparedGraphicsObjects *prepared_objects) const
Returns the number of bytes which the texture is reported to consume within graphics memory...
This is an abstract base class that defines the interface for reading image files of various types...
void ref() const
Explicitly increments the reference count.
bool make_relative_to(Filename directory, bool allow_backups=true)
Adjusts this filename, which must be a fully-specified pathname beginning with a slash, to make it a relative filename, relative to the fully-specified directory indicated (which must also begin with, and may or may not end with, a slash–a terminating slash is ignored).
void register_factory(TypeHandle handle, CreateFunc *func)
Registers a new kind of thing the Factory will be able to create.
bool is_texture_queued(const Texture *tex) const
Returns true if the texture has been queued on this GSG, false otherwise.
int get_ref_count() const
Returns the current reference count.
An instance of this object is returned by Texture::peek().
void set_channel(int x, int y, int c, PN_float32 value)
Replaces the cth channel of the point value at the indicated point.
static TextureType string_texture_type(const string &str)
Returns the TextureType corresponding to the indicated string word.
void local_object()
This function should be called, once, immediately after creating a new instance of some ReferenceCoun...
TextureContext * prepare_now(int view, PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg)
Creates a context for the texture on the particular GSG, if it does not already exist.
bool load(const PNMImage &pnmimage)
Fills the PfmFile with the data from the indicated PNMImage, converted to floating-point values...
This is the base class for all three-component vectors and points.
This class can be used to write a binary file that consists of an arbitrary header followed by a numb...
CompressionMode get_ram_image_compression() const
Returns the compression mode in which the ram image is already stored pre-compressed.
void add_alpha()
Adds an alpha channel to the image, if it does not already have one.
void make_absolute()
Converts the filename to a fully-qualified pathname from the root (if it is a relative pathname)...
void generate_simple_ram_image()
Computes the "simple" ram image by loading the main RAM image, if it is not already available...
ostream * open_write_file(const Filename &filename, bool auto_wrap, bool truncate)
Convenience function; returns a newly allocated ostream if the file exists and can be written...
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
CycleDataType * elevate_read_upstream(const CycleDataType *pointer, bool force_to_0, Thread *current_thread)
See PipelineCyclerBase::elevate_read_upstream().
void clear()
Frees all memory allocated for the image, and clears all its parameters (size, color, type, etc).
static int up_to_power_2(int value)
Returns the smallest power of 2 greater than or equal to value.
void set_alpha(int x, int y, float a)
Sets the alpha component color only at the indicated pixel.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
AutoTextureScale get_auto_texture_scale() const
See set_auto_texture_scale().
PTA_uchar new_simple_ram_image(int x_size, int y_size)
Creates an empty array for the simple ram image of the indicated size, and returns a modifiable point...
A thread; that is, a lightweight process.
void take_from(PNMImage &orig)
Move the contents of the other image into this one, and empty the other image.
TextureContext * prepare_texture_now(Texture *tex, int view, GraphicsStateGuardianBase *gsg)
Immediately creates a new TextureContext for the indicated texture and returns it.
bool write_txo(ostream &out, const string &filename="") const
Writes the texture to a Panda texture object.
void prepare(PreparedGraphicsObjects *prepared_objects)
Indicates that the texture should be enqueued to be prepared in the indicated prepared_objects at the...
int find_on_searchpath(const DSearchPath &searchpath)
Performs the reverse of the resolve_filename() operation: assuming that the current filename is fully...
void add_uint32(PN_uint32 value)
Adds an unsigned 32-bit integer to the datagram.
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const
Returns true if the texture has already been prepared or enqueued for preparation on the indicated GS...
int get_y_size() const
Returns the height of the texture image in texels.
CycleDataType * write_upstream(bool force_to_0, Thread *current_thread)
See PipelineCyclerBase::write_upstream().
static string format_texture_type(TextureType tt)
Returns the indicated TextureType converted to a string word.
static int down_to_power_2(int value)
Returns the largest power of 2 less than or equal to value.
int get_num_unique_values() const
Returns the number of unique values in the variable.
void generate_normalization_cube_map(int size)
Generates a special cube map image in the texture that can be used to apply bump mapping effects: for...
bool read(const Filename &fullpath, const LoaderOptions &options=LoaderOptions())
Reads the named filename into the texture.
BamTextureMode get_file_texture_mode() const
Returns the BamTextureMode preference indicated by the Bam file currently being written.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Filename get_cwd() const
Returns the current directory name.
void clear_ram_mipmap_image(int n)
Discards the current system-RAM image for the nth mipmap level.
void add_dependent_file(const Filename &pathname)
Adds the indicated file to the list of files that will be loaded to generate the data in this record...
void add_int32(PN_int32 value)
Adds a signed 32-bit integer to the datagram.
A class to retrieve the individual data elements previously stored in a Datagram. ...
void texture_uploaded()
This method is called by the GraphicsEngine at the beginning of the frame *after* a texture has been ...
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
void release() const
Releases the mutex.
static Texture * load_3d_texture(const Filename &filename_pattern, bool read_mipmaps=false, const LoaderOptions &options=LoaderOptions())
Loads a 3-D texture that is specified with a series of n pages, all numbered in sequence, and beginning with index 0.
static Texture * load_2d_texture_array(const Filename &filename_pattern, bool read_mipmaps=false, const LoaderOptions &options=LoaderOptions())
Loads a 2-D texture array that is specified with a series of n pages, all numbered in sequence...
xelval get_alpha_val(int x, int y) const
Returns the alpha component color at the indicated pixel.
TypeHandle is the identifier used to differentiate C++ class types.
static void close_write_file(ostream *stream)
Closes a file opened by a previous call to open_write_file().
void fill(float red, float green, float blue)
Sets the entire image (except the alpha channel) to the given color.
bool store(PNMImage &pnmimage) const
Copies the data to the indicated PNMImage, converting to RGB values.
bool has_compression() const
Returns true if the texture indicates it wants to be compressed, either with CM_on or higher...
void set_num_channels(int num_channels)
Changes the number of channels associated with the image.
A class to read sequential binary data directly from an istream.
virtual bool get_keep_ram_image() const
Returns the flag that indicates whether this Texture is eligible to have its main RAM copy of the tex...
void set_read_size(int x_size, int y_size)
Specifies the size to we'd like to scale the image upon reading it.
bool has_hash() const
Returns true if the filename is indicated to be a filename pattern (that is, set_pattern(true) was ca...
const CycleDataType * read(Thread *current_thread) const
See PipelineCyclerBase::read().
bool normalize()
Normalizes the vector in place.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
static bool has_binary_alpha(Format format)
Returns true if the indicated format includes a binary alpha only, false otherwise.
bool init()
Initializes the BamWriter prior to writing any objects to its output stream.
void release_read(const CycleData *pointer) const
Releases a pointer previously obtained via a call to read().
const Filename & get_filename() const
If a BAM is a file, then the BamReader should contain the name of the file.
static string format_compression_mode(CompressionMode cm)
Returns the indicated CompressionMode converted to a string word.
static ComponentType string_component_type(const string &str)
Returns the ComponentType corresponding to the indicated string word.
xelval get_green_val(int x, int y) const
Returns the green component color at the indicated pixel.
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling...
xelval get_red_val(int x, int y) const
Returns the red component color at the indicated pixel.
static BamCache * get_global_ptr()
Returns a pointer to the global BamCache object, which is used automatically by the ModelPool and Tex...
void clear()
Eliminates all data in the file.
virtual bool has_cull_callback() const
Should be overridden by derived classes to return true if cull_callback() has been defined...
size_t get_expected_ram_page_size() const
Returns the number of bytes that should be used per each Z page of the 3-d texture.
bool write(const Filename &fullpath)
Writes the texture to the named filename.
This class can be used to test for string matches against standard Unix-shell filename globbing conve...
int get_x_size() const
Returns the width of the texture image in texels.
virtual bool unref() const
Explicitly decrements the reference count.
void skip_bytes(size_t size)
Skips over the indicated number of bytes in the stream.
static const LVecBase4f & zero()
Returns a zero-length vector.
float get_alpha(int x, int y) const
Returns the alpha component color at the indicated pixel.
int get_read_x_size() const
Returns the requested x_size of the image if set_read_size() has been called, or the image x_size oth...
void set_ram_mipmap_pointer(int n, void *image, size_t page_size=0)
Sets an explicit void pointer as the texture's mipmap image for the indicated level.
void * get_ram_mipmap_pointer(int n) const
Similiar to get_ram_mipmap_image(), however, in this case the void pointer for the given ram image is...