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;
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:
509 case Texture::F_luminance_alpha:
510 case Texture::F_luminance_alphamask:
511 case Texture::F_sluminance_alpha:
515 case Texture::F_rgba:
516 case Texture::F_rgba4:
517 case Texture::F_rgbm:
519 case Texture::F_rgb5:
520 case Texture::F_rgba5:
521 case Texture::F_srgb:
525 case Texture::F_color_index:
526 case Texture::F_rgb8:
527 case Texture::F_rgba8:
528 case Texture::F_srgb_alpha:
529 case Texture::F_rgb8i:
530 case Texture::F_rgba8i:
534 case Texture::F_depth_stencil:
538 case Texture::F_depth_component:
542 case Texture::F_rgba12:
543 case Texture::F_rgb12:
547 case Texture::F_rgba16:
550 case Texture::F_rgba32:
556 case Texture::F_rg8i:
559 case Texture::F_rg16:
562 case Texture::F_rgb16:
566 case Texture::F_r32i:
573 case Texture::F_rg32:
576 case Texture::F_rgb32:
584 size_t bytes = pixels * bpp;
586 bytes = (bytes * 4) / 3;
606 _aux_data[key] = aux_data;
618 _aux_data.erase(key);
631 AuxData::const_iterator di;
632 di = _aux_data.find(key);
633 if (di != _aux_data.end()) {
655 cdata->inc_properties_modified();
656 cdata->inc_image_modified();
657 return do_read_txo(cdata, in, filename);
673 make_from_txo(istream &in, const
string &filename) {
676 if (!din.
open(in, filename)) {
678 <<
"Could not read texture object: " << filename <<
"\n";
685 << filename <<
" is not a texture object file.\n";
689 if (head != _bam_header) {
691 << filename <<
" is not a texture object file.\n";
696 if (!reader.init()) {
708 object = reader.read_object();
713 <<
"Texture object " << filename <<
" is empty.\n";
716 }
else if (!object->
is_of_type(Texture::get_class_type())) {
718 <<
"Texture object " << filename <<
" contains a "
719 <<
object->get_type() <<
", not a Texture.\n";
724 if (!reader.resolve()) {
726 <<
"Unable to fully resolve texture object file.\n";
745 return do_write_txo(cdata, out, filename);
761 read_dds(istream &in,
const string &filename,
bool header_only) {
763 cdata->inc_properties_modified();
764 cdata->inc_image_modified();
765 return do_read_dds(cdata, in, filename, header_only);
781 RelatedTextures::const_iterator ti;
782 ti = _related_textures.find(suffix);
783 if (ti != _related_textures.end()) {
786 if (cdata->_fullpath.empty()) {
793 if (!cdata->_alpha_fullpath.empty()) {
794 Filename alph = cdata->_alpha_fullpath;
802 cdata->_primary_file_num_channels,
803 cdata->_alpha_file_channel,
false);
818 ((
Texture *)
this)->_related_textures.insert(RelatedTextures::value_type(suffix, res));
836 string format = upcase(supplied_format);
839 int imgsize = cdata->_x_size * cdata->_y_size;
840 nassertv(image.size() == (size_t)(cdata->_component_width * format.size() * imgsize));
843 if ((cdata->_num_components == 1 && format.size() == 1) ||
844 (cdata->_num_components == 2 && format.size() == 2 && format.at(1) ==
'A' && format.at(0) !=
'A') ||
845 (cdata->_num_components == 3 && format ==
"BGR") ||
846 (cdata->_num_components == 4 && format ==
"BGRA")) {
848 do_set_ram_image(cdata, image);
853 PTA_uchar newdata = PTA_uchar::empty_array(imgsize * cdata->_num_components * cdata->_component_width, get_class_type());
856 if (cdata->_component_width == 1) {
857 if (format ==
"RGBA" && cdata->_num_components == 4) {
859 for (
int p = 0; p < imgsize; p += 4) {
860 newdata[p + 2] = image[p ];
861 newdata[p + 1] = image[p + 1];
862 newdata[p ] = image[p + 2];
863 newdata[p + 3] = image[p + 3];
865 do_set_ram_image(cdata, newdata);
868 if (format ==
"RGB" && cdata->_num_components == 3) {
870 for (
int p = 0; p < imgsize; p += 3) {
871 newdata[p + 2] = image[p ];
872 newdata[p + 1] = image[p + 1];
873 newdata[p ] = image[p + 2];
875 do_set_ram_image(cdata, newdata);
878 if (format ==
"A" && cdata->_num_components != 3) {
880 int component = cdata->_num_components - 1;
881 for (
int p = 0; p < imgsize; ++p) {
882 newdata[component] = image[p];
884 do_set_ram_image(cdata, newdata);
887 for (
int p = 0; p < imgsize; ++p) {
888 for (uchar s = 0; s < format.size(); ++s) {
889 signed char component = -1;
890 if (format.at(s) ==
'B' || (cdata->_num_components <= 2 && format.at(s) !=
'A')) {
892 }
else if (format.at(s) ==
'G') {
894 }
else if (format.at(s) ==
'R') {
896 }
else if (format.at(s) ==
'A') {
897 nassertv(cdata->_num_components != 3);
898 component = cdata->_num_components - 1;
899 }
else if (format.at(s) ==
'0') {
901 }
else if (format.at(s) ==
'1') {
904 gobj_cat.error() <<
"Unexpected component character '"
905 << format.at(s) <<
"', expected one of RGBA!\n";
908 if (component >= 0) {
909 newdata[p * cdata->_num_components + component] = image[p * format.
size() + s];
913 do_set_ram_image(cdata, newdata);
916 for (
int p = 0; p < imgsize; ++p) {
917 for (uchar s = 0; s < format.size(); ++s) {
918 signed char component = -1;
919 if (format.at(s) ==
'B' || (cdata->_num_components <= 2 && format.at(s) !=
'A')) {
921 }
else if (format.at(s) ==
'G') {
923 }
else if (format.at(s) ==
'R') {
925 }
else if (format.at(s) ==
'A') {
926 nassertv(cdata->_num_components != 3);
927 component = cdata->_num_components - 1;
928 }
else if (format.at(s) ==
'0') {
930 }
else if (format.at(s) ==
'1') {
933 gobj_cat.error() <<
"Unexpected component character '"
934 << format.at(s) <<
"', expected one of RGBA!\n";
937 if (component >= 0) {
938 memcpy((
void*)(newdata + (p * cdata->_num_components + component) * cdata->_component_width),
939 (
void*)(image + (p * format.
size() + s) * cdata->_component_width),
940 cdata->_component_width);
944 do_set_ram_image(cdata, newdata);
959 return cdata->_keep_ram_image;
973 return do_has_bam_rawdata(cdata);
997 if (cdata->_ram_images.empty() || cdata->_ram_images[0]._image.empty()) {
1009 int size = max(cdata->_x_size, max(cdata->_y_size, cdata->_z_size));
1015 if (n >= (
int)cdata->_ram_images.size() || cdata->_ram_images[n]._image.empty()) {
1034 if (n < (
int)cdata->_ram_images.size() && !cdata->_ram_images[n]._image.empty()) {
1035 return cdata->_ram_images[n]._image;
1051 if (n < (
int)cdata->_ram_images.size()) {
1052 return cdata->_ram_images[n]._pointer_image;
1074 nassertv(cdata->_ram_image_compression != CM_off || do_get_expected_ram_mipmap_image_size(cdata, n));
1076 while (n >= (
int)cdata->_ram_images.size()) {
1077 cdata->_ram_images.push_back(RamImage());
1080 cdata->_ram_images[n]._page_size = page_size;
1082 cdata->_ram_images[n]._pointer_image = image;
1083 cdata->inc_image_modified();
1111 if (n >= (
int)cdata->_ram_images.size()) {
1114 cdata->_ram_images[n]._page_size = 0;
1115 cdata->_ram_images[n]._image.clear();
1116 cdata->_ram_images[n]._pointer_image = NULL;
1128 cdata->_simple_image_date_generated = (PN_int32)time(NULL);
1129 return cdata->_simple_ram_image._image;
1142 nassertr(cdata->_texture_type == TT_2d_texture, PTA_uchar());
1143 size_t expected_page_size = (size_t)(x_size * y_size * 4);
1145 cdata->_simple_x_size = x_size;
1146 cdata->_simple_y_size = y_size;
1147 cdata->_simple_ram_image._image = PTA_uchar::empty_array(expected_page_size);
1148 cdata->_simple_ram_image._page_size = expected_page_size;
1149 cdata->_simple_image_date_generated = (PN_int32)time(NULL);
1150 cdata->inc_simple_image_modified();
1152 return cdata->_simple_ram_image._image;
1167 if (cdata->_texture_type != TT_2d_texture ||
1168 cdata->_ram_image_compression != CM_off) {
1173 if (!do_store_one(cdata, pnmimage, 0, 0)) {
1178 int x_size = simple_image_size.
get_word(0);
1179 int y_size = simple_image_size.
get_word(1);
1191 if (!scaled.has_alpha()) {
1193 scaled.alpha_fill(1.0);
1195 scaled.set_num_channels(4);
1200 did_anything =
false;
1204 int new_x_size = (x_size >> 1);
1205 PNMImage smaller(new_x_size, y_size, 4);
1207 PNMImage bigger(x_size, y_size, 4);
1210 if (compare_images(scaled, bigger)) {
1211 scaled.take_from(smaller);
1212 x_size = new_x_size;
1213 did_anything =
true;
1219 int new_y_size = (y_size >> 1);
1220 PNMImage smaller(x_size, new_y_size, 4);
1222 PNMImage bigger(x_size, y_size, 4);
1225 if (compare_images(scaled, bigger)) {
1226 scaled.take_from(smaller);
1227 y_size = new_y_size;
1228 did_anything =
true;
1231 }
while (did_anything);
1233 size_t expected_page_size = (size_t)(x_size * y_size * 4);
1234 PTA_uchar image = PTA_uchar::empty_array(expected_page_size, get_class_type());
1235 convert_from_pnmimage(image, expected_page_size, x_size, 0, 0, 0, scaled, 4, 1);
1237 do_set_simple_ram_image(cdata, image, x_size, y_size);
1238 cdata->_simple_image_date_generated = (PN_int32)time(NULL);
1259 CDWriter cdata(_cycler, unlocked_ensure_ram_image(
true));
1262 if (peeker->is_valid()) {
1296 PreparedViews::const_iterator pvi;
1297 pvi = _prepared_views.find(prepared_objects);
1298 if (pvi != _prepared_views.end()) {
1317 PreparedViews::const_iterator pvi;
1318 pvi = _prepared_views.find(prepared_objects);
1319 if (pvi != _prepared_views.end()) {
1320 const Contexts &contexts = (*pvi).second;
1321 for (
int view = 0; view < cdata->_num_views; ++view) {
1322 Contexts::const_iterator ci;
1323 ci = contexts.find(view);
1324 if (ci == contexts.end()) {
1353 PreparedViews::const_iterator pvi;
1354 size_t total_size = 0;
1355 pvi = _prepared_views.find(prepared_objects);
1356 if (pvi != _prepared_views.end()) {
1357 const Contexts &contexts = (*pvi).second;
1358 for (
int view = 0; view < cdata->_num_views; ++view) {
1359 Contexts::const_iterator ci;
1360 ci = contexts.find(view);
1361 if (ci != contexts.end()) {
1382 PreparedViews::const_iterator pvi;
1383 pvi = _prepared_views.find(prepared_objects);
1384 if (pvi != _prepared_views.end()) {
1385 const Contexts &contexts = (*pvi).second;
1386 for (
int view = 0; view < cdata->_num_views; ++view) {
1387 Contexts::const_iterator ci;
1388 ci = contexts.find(view);
1389 if (ci != contexts.end()) {
1412 PreparedViews::const_iterator pvi;
1413 pvi = _prepared_views.find(prepared_objects);
1414 if (pvi != _prepared_views.end()) {
1415 const Contexts &contexts = (*pvi).second;
1416 for (
int view = 0; view < cdata->_num_views; ++view) {
1417 Contexts::const_iterator ci;
1418 ci = contexts.find(view);
1419 if (ci != contexts.end()) {
1440 PreparedViews::iterator pvi;
1441 pvi = _prepared_views.find(prepared_objects);
1442 if (pvi != _prepared_views.end()) {
1444 temp.swap((*pvi).second);
1445 Contexts::iterator ci;
1446 for (ci = temp.begin(); ci != temp.end(); ++ci) {
1452 _prepared_views.erase(pvi);
1475 temp.swap(_prepared_views);
1476 int num_freed = (int)temp.size();
1478 PreparedViews::iterator pvi;
1479 for (pvi = temp.begin(); pvi != temp.end(); ++pvi) {
1482 temp.swap((*pvi).second);
1483 Contexts::iterator ci;
1484 for (ci = temp.begin(); ci != temp.end(); ++ci) {
1502 write(ostream &out,
int indent_level)
const {
1504 indent(out, indent_level)
1505 << cdata->_texture_type <<
" " << get_name();
1506 if (!cdata->_filename.empty()) {
1507 out <<
" (from " << cdata->_filename <<
")";
1511 indent(out, indent_level + 2);
1513 switch (cdata->_texture_type) {
1515 out <<
"1-d, " << cdata->_x_size;
1519 out <<
"2-d, " << cdata->_x_size <<
" x " << cdata->_y_size;
1523 out <<
"3-d, " << cdata->_x_size <<
" x " << cdata->_y_size <<
" x " << cdata->_z_size;
1526 case TT_2d_texture_array:
1527 out <<
"2-d array, " << cdata->_x_size <<
" x " << cdata->_y_size <<
" x " << cdata->_z_size;
1531 out <<
"cube map, " << cdata->_x_size <<
" x " << cdata->_y_size;
1535 if (cdata->_num_views > 1) {
1536 out <<
" (x " << cdata->_num_views <<
" views)";
1539 out <<
" pixels, each " << cdata->_num_components;
1541 switch (cdata->_component_type) {
1542 case T_unsigned_byte:
1546 case T_unsigned_short:
1554 case T_unsigned_int_24_8:
1564 switch (cdata->_format) {
1566 out <<
"color_index";
1568 case F_depth_stencil:
1569 out <<
"depth_stencil";
1571 case F_depth_component:
1572 out <<
"depth_component";
1574 case F_depth_component16:
1575 out <<
"depth_component16";
1577 case F_depth_component24:
1578 out <<
"depth_component24";
1580 case F_depth_component32:
1581 out <<
"depth_component32";
1640 case F_luminance_alpha:
1641 out <<
"luminance_alpha";
1643 case F_luminance_alphamask:
1644 out <<
"luminance_alphamask";
1661 out <<
"srgb_alpha";
1664 out <<
"sluminance";
1666 case F_sluminance_alpha:
1667 out <<
"sluminance_alpha";
1698 if (cdata->_compression != CM_default) {
1699 out <<
", compression " << cdata->_compression;
1703 indent(out, indent_level + 2);
1705 cdata->_default_sampler.output(out);
1707 if (do_has_ram_image(cdata)) {
1708 indent(out, indent_level + 2)
1709 << do_get_ram_image_size(cdata) <<
" bytes in ram, compression "
1710 << cdata->_ram_image_compression <<
"\n";
1712 if (cdata->_ram_images.size() > 1) {
1714 size_t total_size = 0;
1715 for (
size_t n = 1; n < cdata->_ram_images.size(); ++n) {
1716 if (!cdata->_ram_images[n]._image.empty()) {
1718 total_size += cdata->_ram_images[n]._image.size();
1724 indent(out, indent_level + 2)
1726 <<
" mipmap levels also present in ram (" << total_size
1731 indent(out, indent_level + 2)
1732 <<
"no ram image\n";
1735 if (!cdata->_simple_ram_image._image.empty()) {
1736 indent(out, indent_level + 2)
1737 <<
"simple image: " << cdata->_simple_x_size <<
" x "
1738 << cdata->_simple_y_size <<
", "
1739 << cdata->_simple_ram_image._image.size() <<
" bytes\n";
1754 if (do_get_auto_texture_scale(cdata) != ATS_none) {
1758 if (cdata->_texture_type == TT_3d_texture) {
1763 do_set_z_size(cdata, z);
1766 do_set_x_size(cdata, x);
1767 do_set_y_size(cdata, y);
1768 do_set_z_size(cdata, z);
1770 do_set_pad_size(cdata,
1773 cdata->_z_size - z);
1785 cdata->_orig_file_x_size = x;
1786 cdata->_orig_file_y_size = y;
1788 nassertv(z == cdata->_z_size);
1815 view = max(min(view, cdata->_num_views - 1), 0);
1818 Contexts &contexts = _prepared_views[prepared_objects];
1819 Contexts::const_iterator pvi;
1820 pvi = contexts.find(view);
1821 if (pvi != contexts.end()) {
1822 return (*pvi).second;
1826 contexts[view] = tc;
1842 int bit = get_next_higher_bit(((
unsigned int)value) - 1);
1857 int bit = get_next_higher_bit(((
unsigned int)value) >> 1);
1898 if (
adjust_size(new_x_size, new_y_size, name,
false, auto_texture_scale)) {
1924 return "1d_texture";
1926 return "2d_texture";
1928 return "3d_texture";
1929 case TT_2d_texture_array:
1930 return "2d_texture_array";
1934 return "**invalid**";
1945 if (cmp_nocase(str,
"1d_texture") == 0) {
1946 return TT_1d_texture;
1947 }
else if (cmp_nocase(str,
"2d_texture") == 0) {
1948 return TT_2d_texture;
1949 }
else if (cmp_nocase(str,
"3d_texture") == 0) {
1950 return TT_3d_texture;
1951 }
else if (cmp_nocase(str,
"2d_texture_array") == 0) {
1952 return TT_2d_texture_array;
1953 }
else if (cmp_nocase(str,
"cube_map") == 0) {
1958 <<
"Invalid Texture::TextureType value: " << str <<
"\n";
1959 return TT_2d_texture;
1971 case T_unsigned_byte:
1972 return "unsigned_byte";
1973 case T_unsigned_short:
1974 return "unsigned_short";
1977 case T_unsigned_int_24_8:
1978 return "unsigned_int_24_8";
1983 return "**invalid**";
1994 if (cmp_nocase(str,
"unsigned_byte") == 0) {
1995 return T_unsigned_byte;
1996 }
else if (cmp_nocase(str,
"unsigned_short") == 0) {
1997 return T_unsigned_short;
1998 }
else if (cmp_nocase(str,
"float") == 0) {
2000 }
else if (cmp_nocase(str,
"unsigned_int_24_8") == 0) {
2001 return T_unsigned_int_24_8;
2002 }
else if (cmp_nocase(str,
"int") == 0) {
2007 <<
"Invalid Texture::ComponentType value: " << str <<
"\n";
2008 return T_unsigned_byte;
2020 case F_depth_stencil:
2021 return "depth_stencil";
2022 case F_depth_component:
2023 return "depth_component";
2024 case F_depth_component16:
2025 return "depth_component16";
2026 case F_depth_component24:
2027 return "depth_component24";
2028 case F_depth_component32:
2029 return "depth_component32";
2031 return "color_index";
2064 case F_luminance_alpha:
2065 return "luminance_alpha";
2066 case F_luminance_alphamask:
2067 return "luminance_alphamask";
2081 return "srgb_alpha";
2083 return "sluminance";
2084 case F_sluminance_alpha:
2085 return "sluminance_alpha";
2103 return "**invalid**";
2114 if (cmp_nocase(str,
"depth_stencil") == 0) {
2115 return F_depth_stencil;
2116 }
else if (cmp_nocase(str,
"depth_component") == 0) {
2117 return F_depth_component;
2118 }
else if (cmp_nocase(str,
"depth_component16") == 0 || cmp_nocase(str,
"d16") == 0) {
2119 return F_depth_component16;
2120 }
else if (cmp_nocase(str,
"depth_component24") == 0 || cmp_nocase(str,
"d24") == 0) {
2121 return F_depth_component24;
2122 }
else if (cmp_nocase(str,
"depth_component32") == 0 || cmp_nocase(str,
"d32") == 0) {
2123 return F_depth_component32;
2124 }
else if (cmp_nocase(str,
"color_index") == 0) {
2125 return F_color_index;
2126 }
else if (cmp_nocase(str,
"red") == 0) {
2128 }
else if (cmp_nocase(str,
"green") == 0) {
2130 }
else if (cmp_nocase(str,
"blue") == 0) {
2132 }
else if (cmp_nocase(str,
"alpha") == 0) {
2134 }
else if (cmp_nocase(str,
"rgb") == 0) {
2136 }
else if (cmp_nocase(str,
"rgb5") == 0) {
2138 }
else if (cmp_nocase(str,
"rgb8") == 0 || cmp_nocase(str,
"r8g8b8") == 0) {
2140 }
else if (cmp_nocase(str,
"rgb12") == 0) {
2142 }
else if (cmp_nocase(str,
"rgb332") == 0 || cmp_nocase(str,
"r3g3b2") == 0) {
2144 }
else if (cmp_nocase(str,
"rgba") == 0) {
2146 }
else if (cmp_nocase(str,
"rgbm") == 0) {
2148 }
else if (cmp_nocase(str,
"rgba4") == 0) {
2150 }
else if (cmp_nocase(str,
"rgba5") == 0) {
2152 }
else if (cmp_nocase(str,
"rgba8") == 0 || cmp_nocase(str,
"r8g8b8a8") == 0) {
2154 }
else if (cmp_nocase(str,
"rgba12") == 0) {
2156 }
else if (cmp_nocase(str,
"luminance") == 0) {
2158 }
else if (cmp_nocase(str,
"luminance_alpha") == 0) {
2159 return F_luminance_alpha;
2160 }
else if (cmp_nocase(str,
"luminance_alphamask") == 0) {
2161 return F_luminance_alphamask;
2162 }
else if (cmp_nocase(str,
"rgba16") == 0 || cmp_nocase(str,
"r16g16b16a16") == 0) {
2164 }
else if (cmp_nocase(str,
"rgba32") == 0 || cmp_nocase(str,
"r32g32b32a32") == 0) {
2166 }
else if (cmp_nocase(str,
"r16") == 0 || cmp_nocase(str,
"red16") == 0) {
2168 }
else if (cmp_nocase(str,
"rg16") == 0 || cmp_nocase(str,
"r16g16") == 0) {
2170 }
else if (cmp_nocase(str,
"rgb16") == 0 || cmp_nocase(str,
"r16g16b16") == 0) {
2172 }
else if (cmp_nocase(str,
"srgb") == 0) {
2174 }
else if (cmp_nocase(str,
"srgb_alpha") == 0) {
2175 return F_srgb_alpha;
2176 }
else if (cmp_nocase(str,
"sluminance") == 0) {
2177 return F_sluminance;
2178 }
else if (cmp_nocase(str,
"sluminance_alpha") == 0) {
2179 return F_sluminance_alpha;
2180 }
else if (cmp_nocase(str,
"r32i") == 0) {
2182 }
else if (cmp_nocase(str,
"r32") == 0 || cmp_nocase(str,
"red32") == 0) {
2184 }
else if (cmp_nocase(str,
"rg32") == 0 || cmp_nocase(str,
"r32g32") == 0) {
2186 }
else if (cmp_nocase(str,
"rgb32") == 0 || cmp_nocase(str,
"r32g32b32") == 0) {
2191 <<
"Invalid Texture::Format value: " << str <<
"\n";
2228 return "**invalid**";
2239 if (cmp_nocase_uh(str,
"default") == 0) {
2241 }
else if (cmp_nocase_uh(str,
"off") == 0) {
2243 }
else if (cmp_nocase_uh(str,
"on") == 0) {
2245 }
else if (cmp_nocase_uh(str,
"fxt1") == 0) {
2247 }
else if (cmp_nocase_uh(str,
"dxt1") == 0) {
2249 }
else if (cmp_nocase_uh(str,
"dxt2") == 0) {
2251 }
else if (cmp_nocase_uh(str,
"dxt3") == 0) {
2253 }
else if (cmp_nocase_uh(str,
"dxt4") == 0) {
2255 }
else if (cmp_nocase_uh(str,
"dxt5") == 0) {
2257 }
else if (cmp_nocase_uh(str,
"pvr1_2bpp") == 0) {
2258 return CM_pvr1_2bpp;
2259 }
else if (cmp_nocase_uh(str,
"pvr1_4bpp") == 0) {
2260 return CM_pvr1_4bpp;
2264 <<
"Invalid Texture::CompressionMode value: " << str <<
"\n";
2288 return "**invalid**";
2299 if (cmp_nocase(str,
"default") == 0) {
2301 }
else if (cmp_nocase(str,
"fastest") == 0) {
2303 }
else if (cmp_nocase(str,
"normal") == 0) {
2305 }
else if (cmp_nocase(str,
"best") == 0) {
2310 <<
"Invalid Texture::QualityLevel value: " << str <<
"\n";
2330 if (!keep_texture_ram && !cdata->_keep_ram_image) {
2335 CDWriter cdataw(_cycler, cdata,
false);
2336 if (gobj_cat.is_debug()) {
2338 <<
"Dumping RAM for texture " << get_name() <<
"\n";
2340 do_clear_ram_image(cdataw);
2395 switch (compression) {
2424 case F_luminance_alpha:
2425 case F_luminance_alphamask:
2427 case F_sluminance_alpha:
2464 case F_sluminance_alpha:
2487 bool for_padding, AutoTextureScale auto_texture_scale) {
2488 bool exclude =
false;
2490 for (
int i = 0; i < num_excludes && !exclude; ++i) {
2492 if (pat.matches(name)) {
2497 int new_x_size = x_size;
2498 int new_y_size = y_size;
2501 new_x_size = (int)cfloor(new_x_size * texture_scale + 0.5);
2502 new_y_size = (int)cfloor(new_y_size * texture_scale + 0.5);
2506 new_x_size = min(max(new_x_size, (
int)texture_scale_limit), x_size);
2507 new_y_size = min(max(new_y_size, (
int)texture_scale_limit), y_size);
2510 AutoTextureScale ats = auto_texture_scale;
2511 if (ats == ATS_unspecified) {
2514 if (!for_padding && ats == ATS_pad) {
2534 case ATS_unspecified:
2538 ats = textures_square.get_value();
2539 if (!for_padding && ats == ATS_pad) {
2544 new_x_size = new_y_size = min(new_x_size, new_y_size);
2549 new_x_size = new_y_size = max(new_x_size, new_y_size);
2553 case ATS_unspecified:
2558 int max_dimension = max_texture_dimension;
2560 if (max_dimension < 0) {
2563 max_dimension = gsg->get_max_texture_dimension();
2567 if (max_dimension > 0) {
2568 new_x_size = min(new_x_size, (
int)max_dimension);
2569 new_y_size = min(new_y_size, (
int)max_dimension);
2573 if (x_size != new_x_size || y_size != new_y_size) {
2574 x_size = new_x_size;
2575 y_size = new_y_size;
2611 reconsider_dirty() {
2622 do_adjust_this_size(
const CData *cdata,
int &x_size,
int &y_size,
const string &name,
2623 bool for_padding)
const {
2624 return adjust_size(x_size, y_size, name, for_padding, cdata->_auto_texture_scale);
2634 do_read(CData *cdata,
const Filename &fullpath,
const Filename &alpha_fullpath,
2635 int primary_file_num_channels,
int alpha_file_channel,
2636 int z,
int n,
bool read_pages,
bool read_mipmaps,
2644 bool header_only = ((options.get_texture_flags() & (LoaderOptions::TF_preload | LoaderOptions::TF_preload_simple)) == 0);
2646 header_only =
false;
2649 if ((z == 0 || read_pages) && (n == 0 || read_mipmaps)) {
2652 do_clear_ram_image(cdata);
2655 if (is_txo_filename(fullpath)) {
2659 return do_read_txo_file(cdata, fullpath);
2662 if (is_dds_filename(fullpath)) {
2666 return do_read_dds_file(cdata, fullpath, header_only);
2679 switch (cdata->_texture_type) {
2695 if (options.get_texture_flags() & LoaderOptions::TF_multiview) {
2700 do_set_num_views(cdata, num_views);
2706 if (read_pages && read_mipmaps) {
2710 do_set_z_size(cdata, z_size);
2718 z_size = do_get_expected_mipmap_z_size(cdata, n);
2728 <<
"Filename requires two different hash sequences: " << fullpath
2736 if ((n_size == 0 && (vfs->
exists(file) || n == 0)) ||
2737 (n_size != 0 && n < n_size)) {
2744 int num_pages = z_size * num_views;
2745 while ((num_pages == 0 && (vfs->
exists(file) || z == 0)) ||
2746 (num_pages != 0 && z < num_pages)) {
2747 if (!do_read_one(cdata, file, alpha_file, z, n, primary_file_num_channels,
2748 alpha_file_channel, options, header_only, record)) {
2758 if (n == 0 && n_size == 0) {
2762 n_size = do_get_expected_num_mipmap_levels(cdata);
2766 cdata->_fullpath = fullpath_pattern;
2767 cdata->_alpha_fullpath = alpha_fullpath_pattern;
2769 }
else if (read_pages) {
2773 if (!fullpath_pattern.
has_hash()) {
2775 <<
"Filename requires a hash mark: " << fullpath
2780 do_set_z_size(cdata, z_size);
2785 int num_pages = z_size * num_views;
2786 while ((num_pages == 0 && (vfs->
exists(file) || z == 0)) ||
2787 (num_pages != 0 && z < num_pages)) {
2788 if (!do_read_one(cdata, file, alpha_file, z, 0, primary_file_num_channels,
2789 alpha_file_channel, options, header_only, record)) {
2797 cdata->_fullpath = fullpath_pattern;
2798 cdata->_alpha_fullpath = alpha_fullpath_pattern;
2800 }
else if (read_mipmaps) {
2804 if (!fullpath_pattern.
has_hash()) {
2806 <<
"Filename requires a hash mark: " << fullpath
2815 while ((n_size == 0 && (vfs->
exists(file) || n == 0)) ||
2816 (n_size != 0 && n < n_size)) {
2817 if (!do_read_one(cdata, file, alpha_file, z, n,
2818 primary_file_num_channels, alpha_file_channel,
2819 options, header_only, record)) {
2824 if (n_size == 0 && n >= do_get_expected_num_mipmap_levels(cdata)) {
2833 cdata->_fullpath = fullpath_pattern;
2834 cdata->_alpha_fullpath = alpha_fullpath_pattern;
2838 if (!do_read_one(cdata, fullpath, alpha_fullpath, z, n,
2839 primary_file_num_channels, alpha_file_channel,
2840 options, header_only, record)) {
2845 cdata->_has_read_pages = read_pages;
2846 cdata->_has_read_mipmaps = read_mipmaps;
2847 cdata->_num_mipmap_levels_read = cdata->_ram_images.size();
2853 do_clear_ram_image(cdata);
2855 if ((options.get_texture_flags() & LoaderOptions::TF_preload) != 0) {
2858 bool generate_mipmaps = ((options.get_texture_flags() & LoaderOptions::TF_generate_mipmaps) != 0);
2859 do_consider_auto_process_ram_image(cdata, generate_mipmaps ||
uses_mipmaps(),
true);
2874 do_read_one(CData *cdata,
const Filename &fullpath,
const Filename &alpha_fullpath,
2875 int z,
int n,
int primary_file_num_channels,
int alpha_file_channel,
2878 nassertr(!header_only,
false);
2885 if (image_reader == NULL) {
2887 <<
"Texture::read() - couldn't read: " << fullpath << endl;
2892 AutoTextureScale auto_texture_scale = do_get_auto_texture_scale(cdata);
2896 bool read_floating_point;
2897 int texture_load_type = (options.get_texture_flags() & (LoaderOptions::TF_integer | LoaderOptions::TF_float));
2898 switch (texture_load_type) {
2899 case LoaderOptions::TF_integer:
2900 read_floating_point =
false;
2903 case LoaderOptions::TF_float:
2904 read_floating_point =
true;
2911 if (!alpha_fullpath.empty()) {
2912 read_floating_point =
false;
2916 if (header_only || textures_header_only) {
2919 if (z == 0 && n == 0) {
2920 cdata->_orig_file_x_size = x_size;
2921 cdata->_orig_file_y_size = y_size;
2924 if (textures_header_only) {
2934 if (read_floating_point) {
2940 image.
fill(0.2, 0.3, 1.0);
2945 delete image_reader;
2948 if (z == 0 && n == 0) {
2952 cdata->_orig_file_x_size = x_size;
2953 cdata->_orig_file_y_size = y_size;
2959 image.
set_read_size(do_get_expected_mipmap_x_size(cdata, n),
2960 do_get_expected_mipmap_y_size(cdata, n));
2966 <<
"Implicitly rescaling " << fullpath.
get_basename() <<
" from "
2973 if (read_floating_point) {
2974 success = pfm.
read(image_reader);
2976 success = image.
read(image_reader);
2981 <<
"Texture::read() - couldn't read: " << fullpath << endl;
2988 if (!alpha_fullpath.empty()) {
2990 if (alpha_image_reader == NULL) {
2992 <<
"Texture::read() - couldn't read: " << alpha_fullpath << endl;
3001 if (header_only || textures_header_only) {
3007 alpha_image.
fill(1.0);
3011 delete alpha_image_reader;
3017 <<
"Implicitly rescaling " << alpha_fullpath.
get_basename()
3018 <<
" from " << alpha_image.
get_x_size() <<
" by "
3024 if (!alpha_image.
read(alpha_image_reader)) {
3026 <<
"Texture::read() - couldn't read (alpha): " << alpha_fullpath << endl;
3033 if (z == 0 && n == 0) {
3037 if (cdata->_filename.empty()) {
3038 cdata->_filename = fullpath;
3039 cdata->_alpha_filename = alpha_fullpath;
3044 cdata->_keep_ram_image =
false;
3047 cdata->_fullpath = fullpath;
3048 cdata->_alpha_fullpath = alpha_fullpath;
3051 if (!alpha_fullpath.empty()) {
3058 <<
"Automatically rescaling " << alpha_fullpath.
get_basename()
3059 <<
" from " << alpha_image.
get_x_size() <<
" by "
3069 alpha_image = scaled;
3074 consider_downgrade(image, primary_file_num_channels, get_name());
3076 cdata->_alpha_file_channel = 0;
3079 if (!alpha_fullpath.empty()) {
3084 if (alpha_file_channel == 4 ||
3089 << alpha_fullpath.
get_basename() <<
" has no channel " << alpha_file_channel <<
".\n";
3092 for (
int x = 0; x < image.
get_x_size(); x++) {
3093 for (
int y = 0; y < image.
get_y_size(); y++) {
3100 }
else if (alpha_file_channel >= 1 && alpha_file_channel <= 3 &&
3103 for (
int x = 0; x < image.
get_x_size(); x++) {
3104 for (
int y = 0; y < image.
get_y_size(); y++) {
3108 cdata->_alpha_file_channel = alpha_file_channel;
3112 for (
int x = 0; x < image.
get_x_size(); x++) {
3113 for (
int y = 0; y < image.
get_y_size(); y++) {
3117 cdata->_alpha_file_channel = 0;
3121 if (read_floating_point) {
3122 if (!do_load_one(cdata, pfm, fullpath.
get_basename(), z, n, options)) {
3130 if (do_get_auto_texture_scale(cdata) == ATS_pad) {
3133 if (do_adjust_this_size(cdata, new_x_size, new_y_size, fullpath.
get_basename(),
true)) {
3134 pad_x_size = new_x_size - image.
get_x_size();
3135 pad_y_size = new_y_size - image.
get_y_size();
3144 if (!do_load_one(cdata, image, fullpath.
get_basename(), z, n, options)) {
3148 do_set_pad_size(cdata, pad_x_size, pad_y_size, 0);
3160 do_load_one(CData *cdata,
const PNMImage &pnmimage,
const string &name,
int z,
int n,
3162 if (cdata->_ram_images.size() <= 1 && n == 0) {
3166 if (!do_reconsider_z_size(cdata, z, options)) {
3169 nassertr(z >= 0 && z < cdata->_z_size * cdata->_num_views,
false);
3172 ComponentType component_type = T_unsigned_byte;
3175 component_type = T_unsigned_short;
3185 do_modify_ram_image(cdata);
3186 cdata->_loaded_from_image =
true;
3189 do_modify_ram_mipmap_image(cdata, n);
3192 int x_size = do_get_expected_mipmap_x_size(cdata, n);
3193 int y_size = do_get_expected_mipmap_y_size(cdata, n);
3197 <<
"Automatically rescaling " << name;
3199 gobj_cat.info(
false)
3200 <<
" mipmap level " << n;
3202 gobj_cat.info(
false)
3203 <<
" from " << pnmimage.
get_x_size() <<
" by "
3204 << pnmimage.
get_y_size() <<
" to " << x_size <<
" by "
3213 convert_from_pnmimage(cdata->_ram_images[n]._image,
3214 do_get_expected_ram_mipmap_page_size(cdata, n),
3215 x_size, 0, 0, z, scaled,
3216 cdata->_num_components, cdata->_component_width);
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, pnmimage,
3223 cdata->_num_components, cdata->_component_width);
3237 do_load_one(CData *cdata,
const PfmFile &pfm,
const string &name,
int z,
int n,
3239 if (cdata->_ram_images.size() <= 1 && n == 0) {
3243 if (!do_reconsider_z_size(cdata, z, options)) {
3246 nassertr(z >= 0 && z < cdata->_z_size * cdata->_num_views,
false);
3249 ComponentType component_type = T_float;
3257 do_modify_ram_image(cdata);
3258 cdata->_loaded_from_image =
true;
3261 do_modify_ram_mipmap_image(cdata, n);
3264 int x_size = do_get_expected_mipmap_x_size(cdata, n);
3265 int y_size = do_get_expected_mipmap_y_size(cdata, n);
3269 <<
"Automatically rescaling " << name;
3271 gobj_cat.info(
false)
3272 <<
" mipmap level " << n;
3274 gobj_cat.info(
false)
3276 << pfm.
get_y_size() <<
" to " << x_size <<
" by "
3280 scaled.resize(x_size, y_size);
3283 convert_from_pfm(cdata->_ram_images[n]._image,
3284 do_get_expected_ram_mipmap_page_size(cdata, n), z,
3285 scaled, cdata->_num_components, cdata->_component_width);
3289 convert_from_pfm(cdata->_ram_images[n]._image,
3290 do_get_expected_ram_mipmap_page_size(cdata, n), z,
3291 pfm, cdata->_num_components, cdata->_component_width);
3305 do_load_sub_image(CData *cdata,
const PNMImage &image,
int x,
int y,
int z,
int n) {
3306 nassertr(n >= 0 && (
size_t)n < cdata->_ram_images.size(),
false);
3308 int tex_x_size = do_get_expected_mipmap_x_size(cdata, n);
3309 int tex_y_size = do_get_expected_mipmap_y_size(cdata, n);
3310 int tex_z_size = do_get_expected_mipmap_z_size(cdata, n);
3312 nassertr(x >= 0 && x < tex_x_size,
false);
3313 nassertr(y >= 0 && y < tex_y_size,
false);
3314 nassertr(z >= 0 && z < tex_z_size,
false);
3316 nassertr(image.
get_x_size() + x < tex_x_size,
false);
3317 nassertr(image.
get_y_size() + y < tex_y_size,
false);
3320 y = cdata->_y_size - (image.
get_y_size() + y);
3322 cdata->inc_image_modified();
3323 do_modify_ram_mipmap_image(cdata, n);
3324 convert_from_pnmimage(cdata->_ram_images[n]._image,
3325 do_get_expected_ram_mipmap_page_size(cdata, n),
3326 tex_x_size, x, y, z, image,
3327 cdata->_num_components, cdata->_component_width);
3339 do_read_txo_file(CData *cdata,
const Filename &fullpath) {
3342 Filename filename = Filename::binary_filename(fullpath);
3347 <<
"Could not find " << fullpath <<
"\n";
3351 if (gobj_cat.is_debug()) {
3353 <<
"Reading texture object " << filename <<
"\n";
3356 istream *in = file->open_read_file(
true);
3357 bool success = do_read_txo(cdata, *in, fullpath);
3360 cdata->_fullpath = fullpath;
3361 cdata->_alpha_fullpath =
Filename();
3362 cdata->_keep_ram_image =
false;
3373 do_read_txo(CData *cdata, istream &in,
const string &filename) {
3374 PT(
Texture) other = make_from_txo(in, filename);
3375 if (other == (
Texture *)NULL) {
3379 CDReader cdata_other(other->_cycler);
3380 Namable::operator = (*other);
3381 do_assign(cdata, other, cdata_other);
3383 cdata->_loaded_from_image =
true;
3384 cdata->_loaded_from_txo =
true;
3385 cdata->_has_read_pages =
false;
3386 cdata->_has_read_mipmaps =
false;
3387 cdata->_num_mipmap_levels_read = 0;
3398 do_read_dds_file(CData *cdata,
const Filename &fullpath,
bool header_only) {
3401 Filename filename = Filename::binary_filename(fullpath);
3406 <<
"Could not find " << fullpath <<
"\n";
3410 if (gobj_cat.is_debug()) {
3412 <<
"Reading DDS file " << filename <<
"\n";
3415 istream *in = file->open_read_file(
true);
3416 bool success = do_read_dds(cdata, *in, fullpath, header_only);
3423 cdata->_fullpath = fullpath;
3424 cdata->_alpha_fullpath =
Filename();
3425 cdata->_keep_ram_image =
false;
3436 do_read_dds(CData *cdata, istream &in,
const string &filename,
bool header_only) {
3441 header.dds_magic = dds.get_uint32();
3442 header.dds_size = dds.get_uint32();
3443 header.dds_flags = dds.get_uint32();
3444 header.height = dds.get_uint32();
3445 header.width = dds.get_uint32();
3446 header.pitch = dds.get_uint32();
3447 header.depth = dds.get_uint32();
3448 header.num_levels = dds.get_uint32();
3452 header.pf.pf_size = dds.get_uint32();
3453 header.pf.pf_flags = dds.get_uint32();
3454 header.pf.four_cc = dds.get_uint32();
3455 header.pf.rgb_bitcount = dds.get_uint32();
3456 header.pf.r_mask = dds.get_uint32();
3457 header.pf.g_mask = dds.get_uint32();
3458 header.pf.b_mask = dds.get_uint32();
3459 header.pf.a_mask = dds.get_uint32();
3462 header.caps.caps1 = dds.get_uint32();
3463 header.caps.caps2 = dds.get_uint32();
3464 header.caps.ddsx = dds.get_uint32();
3470 if (header.dds_magic != DDS_MAGIC || (in.fail() || in.eof())) {
3472 << filename <<
" is not a DDS file.\n";
3476 if ((header.dds_flags & DDSD_MIPMAPCOUNT) == 0) {
3478 header.num_levels = 1;
3480 }
else if (header.num_levels == 0) {
3483 header.num_levels = 1;
3486 TextureType texture_type;
3487 if (header.caps.caps2 & DDSCAPS2_CUBEMAP) {
3488 static const unsigned int all_faces =
3489 (DDSCAPS2_CUBEMAP_POSITIVEX |
3490 DDSCAPS2_CUBEMAP_POSITIVEY |
3491 DDSCAPS2_CUBEMAP_POSITIVEZ |
3492 DDSCAPS2_CUBEMAP_NEGATIVEX |
3493 DDSCAPS2_CUBEMAP_NEGATIVEY |
3494 DDSCAPS2_CUBEMAP_NEGATIVEZ);
3495 if ((header.caps.caps2 & all_faces) != all_faces) {
3497 << filename <<
" is missing some cube map faces; cannot load.\n";
3501 texture_type = TT_cube_map;
3503 }
else if (header.caps.caps2 & DDSCAPS2_VOLUME) {
3504 texture_type = TT_3d_texture;
3507 texture_type = TT_2d_texture;
3512 typedef PTA_uchar (*ReadDDSLevelFunc)(
Texture *tex, Texture::CData *cdata,
3513 const DDSHeader &header,
int n, istream &in);
3514 ReadDDSLevelFunc func = NULL;
3516 Format format = F_rgb;
3518 do_clear_ram_image(cdata);
3519 CompressionMode compression = CM_off;
3521 if (header.pf.pf_flags & DDPF_FOURCC) {
3523 if (texture_type == TT_3d_texture) {
3525 << filename <<
": unsupported compression on 3-d texture.\n";
3529 if (header.pf.four_cc == 0x31545844) {
3530 compression = CM_dxt1;
3531 func = read_dds_level_dxt1;
3532 }
else if (header.pf.four_cc == 0x32545844) {
3533 compression = CM_dxt2;
3534 func = read_dds_level_dxt23;
3535 }
else if (header.pf.four_cc == 0x33545844) {
3536 compression = CM_dxt3;
3537 func = read_dds_level_dxt23;
3538 }
else if (header.pf.four_cc == 0x34545844) {
3539 compression = CM_dxt4;
3540 func = read_dds_level_dxt45;
3541 }
else if (header.pf.four_cc == 0x35545844) {
3542 compression = CM_dxt5;
3543 func = read_dds_level_dxt45;
3546 << filename <<
": unsupported texture compression.\n";
3556 func = read_dds_level_generic_uncompressed;
3558 if (header.pf.pf_flags & DDPF_ALPHAPIXELS) {
3561 if (header.pf.rgb_bitcount == 32 &&
3562 header.pf.r_mask == 0x000000ff &&
3563 header.pf.g_mask == 0x0000ff00 &&
3564 header.pf.b_mask == 0x00ff0000 &&
3565 header.pf.a_mask == 0xff000000U) {
3566 func = read_dds_level_abgr8;
3567 }
else if (header.pf.rgb_bitcount == 32 &&
3568 header.pf.r_mask == 0x00ff0000 &&
3569 header.pf.g_mask == 0x0000ff00 &&
3570 header.pf.b_mask == 0x000000ff &&
3571 header.pf.a_mask == 0xff000000U) {
3572 func = read_dds_level_rgba8;
3574 }
else if (header.pf.r_mask != 0 &&
3575 header.pf.g_mask == 0 &&
3576 header.pf.b_mask == 0) {
3577 func = read_dds_level_luminance_uncompressed;
3578 format = F_luminance_alpha;
3582 if (header.pf.rgb_bitcount == 24 &&
3583 header.pf.r_mask == 0x00ff0000 &&
3584 header.pf.g_mask == 0x0000ff00 &&
3585 header.pf.b_mask == 0x000000ff) {
3586 func = read_dds_level_bgr8;
3587 }
else if (header.pf.rgb_bitcount == 24 &&
3588 header.pf.r_mask == 0x000000ff &&
3589 header.pf.g_mask == 0x0000ff00 &&
3590 header.pf.b_mask == 0x00ff0000) {
3591 func = read_dds_level_rgb8;
3593 }
else if (header.pf.r_mask != 0 &&
3594 header.pf.g_mask == 0 &&
3595 header.pf.b_mask == 0) {
3596 func = read_dds_level_luminance_uncompressed;
3597 format = F_luminance;
3602 do_setup_texture(cdata, texture_type, header.width, header.height, header.depth,
3603 T_unsigned_byte, format);
3605 cdata->_orig_file_x_size = cdata->_x_size;
3606 cdata->_orig_file_y_size = cdata->_y_size;
3607 cdata->_compression = compression;
3608 cdata->_ram_image_compression = compression;
3611 switch (texture_type) {
3616 for (
int n = 0; n < (int)header.num_levels; ++n) {
3617 int z_size = do_get_expected_mipmap_z_size(cdata, n);
3619 size_t page_size = 0;
3621 for (z = 0; z < z_size; ++z) {
3622 PTA_uchar page = func(
this, cdata, header, n, in);
3623 if (page.is_null()) {
3626 nassertr(page_size == 0 || page_size == page.size(),
false);
3627 page_size = page.size();
3628 pages.push_back(page);
3633 PTA_uchar image = PTA_uchar::empty_array(page_size * z_size);
3634 unsigned char *imagep = (
unsigned char *)image.p();
3635 for (z = 0; z < z_size; ++z) {
3636 int fz = z_size - 1 - z;
3637 memcpy(imagep + z * page_size, pages[fz].p(), page_size);
3640 do_set_ram_mipmap_image(cdata, n, image, page_size);
3652 for (z = 0; z < 6; ++z) {
3655 levels.reserve(header.num_levels);
3657 for (n = 0; n < (int)header.num_levels; ++n) {
3658 PTA_uchar image = func(
this, cdata, header, n, in);
3659 if (image.is_null()) {
3662 levels.push_back(image);
3669 static const int level_remap[6] = {
3672 for (n = 0; n < (int)header.num_levels; ++n) {
3673 size_t page_size = pages[0][n].size();
3674 PTA_uchar image = PTA_uchar::empty_array(page_size * 6);
3675 unsigned char *imagep = (
unsigned char *)image.p();
3676 for (z = 0; z < 6; ++z) {
3677 int fz = level_remap[z];
3678 nassertr(pages[fz][n].size() == page_size,
false);
3679 memcpy(imagep + z * page_size, pages[fz][n].p(), page_size);
3682 do_set_ram_mipmap_image(cdata, n, image, page_size);
3690 for (
int n = 0; n < (int)header.num_levels; ++n) {
3691 PTA_uchar image = func(
this, cdata, header, n, in);
3692 if (image.is_null()) {
3695 do_set_ram_mipmap_image(cdata, n, image, 0);
3699 cdata->_has_read_pages =
true;
3700 cdata->_has_read_mipmaps =
true;
3701 cdata->_num_mipmap_levels_read = cdata->_ram_images.size();
3704 if (in.fail() || in.eof()) {
3706 << filename <<
": truncated DDS file.\n";
3710 cdata->_loaded_from_image =
true;
3711 cdata->_loaded_from_txo =
true;
3723 do_write(CData *cdata,
3724 const Filename &fullpath,
int z,
int n,
bool write_pages,
bool write_mipmaps) {
3725 if (is_txo_filename(fullpath)) {
3726 if (!do_has_bam_rawdata(cdata)) {
3727 do_get_bam_rawdata(cdata);
3729 nassertr(do_has_bam_rawdata(cdata),
false);
3730 return do_write_txo_file(cdata, fullpath);
3733 if (!do_has_uncompressed_ram_image(cdata)) {
3734 do_get_uncompressed_ram_image(cdata);
3737 nassertr(do_has_ram_mipmap_image(cdata, n),
false);
3738 nassertr(cdata->_ram_image_compression == CM_off,
false);
3740 if (write_pages && write_mipmaps) {
3743 int num_levels = cdata->_ram_images.size();
3745 for (
int n = 0; n < num_levels; ++n) {
3746 int num_pages = do_get_expected_mipmap_num_pages(cdata, n);
3748 for (z = 0; z < num_pages; ++z) {
3753 <<
"Filename requires two different hash sequences: " << fullpath
3764 }
else if (write_pages) {
3767 if (!fullpath_pattern.
has_hash()) {
3769 <<
"Filename requires a hash mark: " << fullpath
3774 int num_pages = cdata->_z_size * cdata->_num_views;
3775 for (z = 0; z < num_pages; ++z) {
3781 }
else if (write_mipmaps) {
3784 if (!fullpath_pattern.
has_hash()) {
3786 <<
"Filename requires a hash mark: " << fullpath
3791 int num_levels = cdata->_ram_images.size();
3792 for (
int n = 0; n < num_levels; ++n) {
3800 if (!do_write_one(cdata, fullpath, z, n)) {
3815 do_write_one(CData *cdata,
const Filename &fullpath,
int z,
int n) {
3816 if (!do_has_ram_mipmap_image(cdata, n)) {
3820 nassertr(cdata->_ram_image_compression == CM_off,
false);
3823 if (cdata->_component_type == T_float) {
3826 if (!do_store_one(cdata, pfm, z, n)) {
3829 success = pfm.
write(fullpath);
3833 if (!do_store_one(cdata, pnmimage, z, n)) {
3836 success = pnmimage.
write(fullpath);
3841 <<
"Texture::write() - couldn't write: " << fullpath << endl;
3855 do_store_one(CData *cdata,
PNMImage &pnmimage,
int z,
int n) {
3857 do_get_uncompressed_ram_image(cdata);
3859 if (!do_has_ram_mipmap_image(cdata, n)) {
3863 nassertr(z >= 0 && z < do_get_expected_mipmap_num_pages(cdata, n),
false);
3864 nassertr(cdata->_ram_image_compression == CM_off,
false);
3866 if (cdata->_component_type == T_float) {
3869 bool success = convert_to_pfm(pfm,
3870 do_get_expected_mipmap_x_size(cdata, n),
3871 do_get_expected_mipmap_y_size(cdata, n),
3872 cdata->_num_components, cdata->_component_width,
3873 cdata->_ram_images[n]._image,
3874 do_get_ram_mipmap_page_size(cdata, n), z);
3878 return pfm.
store(pnmimage);
3881 return convert_to_pnmimage(pnmimage,
3882 do_get_expected_mipmap_x_size(cdata, n),
3883 do_get_expected_mipmap_y_size(cdata, n),
3884 cdata->_num_components, cdata->_component_width,
3885 cdata->_ram_images[n]._image,
3886 do_get_ram_mipmap_page_size(cdata, n), z);
3896 do_store_one(CData *cdata,
PfmFile &pfm,
int z,
int n) {
3898 do_get_uncompressed_ram_image(cdata);
3900 if (!do_has_ram_mipmap_image(cdata, n)) {
3904 nassertr(z >= 0 && z < do_get_expected_mipmap_num_pages(cdata, n),
false);
3905 nassertr(cdata->_ram_image_compression == CM_off,
false);
3907 if (cdata->_component_type != T_float) {
3910 bool success = convert_to_pnmimage(pnmimage,
3911 do_get_expected_mipmap_x_size(cdata, n),
3912 do_get_expected_mipmap_y_size(cdata, n),
3913 cdata->_num_components, cdata->_component_width,
3914 cdata->_ram_images[n]._image,
3915 do_get_ram_mipmap_page_size(cdata, n), z);
3919 return pfm.
load(pnmimage);
3922 return convert_to_pfm(pfm,
3923 do_get_expected_mipmap_x_size(cdata, n),
3924 do_get_expected_mipmap_y_size(cdata, n),
3925 cdata->_num_components, cdata->_component_width,
3926 cdata->_ram_images[n]._image,
3927 do_get_ram_mipmap_page_size(cdata, n), z);
3937 do_write_txo_file(
const CData *cdata,
const Filename &fullpath)
const {
3939 Filename filename = Filename::binary_filename(fullpath);
3943 <<
"Unable to open " << filename <<
"\n";
3947 bool success = do_write_txo(cdata, *out, fullpath);
3958 do_write_txo(
const CData *cdata, ostream &out,
const string &filename)
const {
3961 if (!dout.
open(out, filename)) {
3963 <<
"Could not write texture object: " << filename <<
"\n";
3969 <<
"Unable to write to " << filename <<
"\n";
3974 if (!writer.init()) {
3978 writer.set_file_texture_mode(BamWriter::BTM_rawdata);
3980 if (!writer.write_object(
this)) {
3984 if (!do_has_bam_rawdata(cdata)) {
3986 << get_name() <<
" does not have ram image\n";
4013 Texture::CData *Texture::
4014 unlocked_ensure_ram_image(
bool allow_compression) {
4020 while (_reloading) {
4025 const CData *cdata = _cycler.
read(current_thread);
4027 if (has_ram_image && !allow_compression && cdata->_ram_image_compression != Texture::CM_off) {
4030 has_ram_image =
false;
4032 if (has_ram_image || !do_can_reload(cdata)) {
4039 nassertr(!_reloading, NULL);
4042 PT(
Texture) tex = do_make_copy(cdata);
4043 _cycler.release_read(cdata);
4048 CDWriter cdata_tex(tex->_cycler, true);
4049 tex->do_reload_ram_image(cdata_tex, allow_compression);
4053 CData *cdataw = _cycler.write_upstream(false, current_thread);
4061 cdataw->_orig_file_x_size = cdata_tex->_orig_file_x_size;
4062 cdataw->_orig_file_y_size = cdata_tex->_orig_file_y_size;
4066 if (cdata_tex->_x_size != cdataw->_x_size ||
4067 cdata_tex->_y_size != cdataw->_y_size ||
4068 cdata_tex->_z_size != cdataw->_z_size ||
4069 cdata_tex->_num_views != cdataw->_num_views ||
4070 cdata_tex->_num_components != cdataw->_num_components ||
4071 cdata_tex->_component_width != cdataw->_component_width ||
4072 cdata_tex->_texture_type != cdataw->_texture_type ||
4073 cdata_tex->_component_type != cdataw->_component_type) {
4075 cdataw->_x_size = cdata_tex->_x_size;
4076 cdataw->_y_size = cdata_tex->_y_size;
4077 cdataw->_z_size = cdata_tex->_z_size;
4078 cdataw->_num_views = cdata_tex->_num_views;
4080 cdataw->_num_components = cdata_tex->_num_components;
4081 cdataw->_component_width = cdata_tex->_component_width;
4082 cdataw->_texture_type = cdata_tex->_texture_type;
4083 cdataw->_format = cdata_tex->_format;
4084 cdataw->_component_type = cdata_tex->_component_type;
4086 cdataw->inc_properties_modified();
4087 cdataw->inc_image_modified();
4090 cdataw->_keep_ram_image = cdata_tex->_keep_ram_image;
4091 cdataw->_ram_image_compression = cdata_tex->_ram_image_compression;
4092 cdataw->_ram_images = cdata_tex->_ram_images;
4094 nassertr(_reloading, NULL);
4119 do_reload_ram_image(CData *cdata,
bool allow_compression) {
4123 if (!do_has_compression(cdata)) {
4124 allow_compression =
false;
4131 record = cache->lookup(cdata->_fullpath,
"txo");
4138 int x_size = cdata->_orig_file_x_size;
4139 int y_size = cdata->_orig_file_y_size;
4140 do_adjust_this_size(cdata, x_size, y_size, cdata->_filename.get_basename(), true);
4142 if (gobj_cat.is_debug()) {
4144 <<
"Cached texture " << *
this <<
" has size "
4145 << tex->get_x_size() <<
" x " << tex->get_y_size()
4146 <<
" instead of " << x_size <<
" x " << y_size
4147 <<
"; ignoring cache.\n";
4152 if (!allow_compression && tex->get_ram_image_compression() != Texture::CM_off) {
4153 if (gobj_cat.is_debug()) {
4155 <<
"Cached texture " << *
this
4156 <<
" is compressed in cache; ignoring cache.\n";
4160 <<
"Texture " << get_name() <<
" reloaded from disk cache\n";
4165 CDReader cdata_tex(tex->_cycler);
4166 cdata->_x_size = cdata_tex->_x_size;
4167 cdata->_y_size = cdata_tex->_y_size;
4168 if (cdata->_num_components != cdata_tex->_num_components) {
4169 cdata->_num_components = cdata_tex->_num_components;
4170 cdata->_format = cdata_tex->_format;
4172 cdata->_component_type = cdata_tex->_component_type;
4173 cdata->_compression = cdata_tex->_compression;
4174 cdata->_ram_image_compression = cdata_tex->_ram_image_compression;
4175 cdata->_ram_images = cdata_tex->_ram_images;
4176 cdata->_loaded_from_image =
true;
4178 bool was_compressed = (cdata->_ram_image_compression != CM_off);
4179 if (do_consider_auto_process_ram_image(cdata,
uses_mipmaps(), allow_compression)) {
4180 bool is_compressed = (cdata->_ram_image_compression != CM_off);
4181 if (!was_compressed && is_compressed &&
4187 cache->
store(record);
4198 <<
"Reloading texture " << get_name() <<
"\n";
4203 if (cdata->_has_read_pages) {
4206 if (cdata->_has_read_mipmaps) {
4207 n = cdata->_num_mipmap_levels_read;
4210 cdata->_loaded_from_image =
false;
4211 Format orig_format = cdata->_format;
4212 int orig_num_components = cdata->_num_components;
4215 options.set_texture_flags(LoaderOptions::TF_preload);
4216 do_read(cdata, cdata->_fullpath, cdata->_alpha_fullpath,
4217 cdata->_primary_file_num_channels, cdata->_alpha_file_channel,
4218 z, n, cdata->_has_read_pages, cdata->_has_read_mipmaps, options, NULL);
4220 if (orig_num_components == cdata->_num_components) {
4223 cdata->_format = orig_format;
4226 if (do_has_ram_image(cdata) && record != (
BamCacheRecord *)NULL) {
4233 cache->
store(record);
4245 do_modify_ram_image(CData *cdata) {
4246 if (cdata->_ram_images.empty() || cdata->_ram_images[0]._image.empty() ||
4247 cdata->_ram_image_compression != CM_off) {
4248 do_make_ram_image(cdata);
4250 do_clear_ram_mipmap_images(cdata);
4252 return cdata->_ram_images[0]._image;
4262 do_make_ram_image(CData *cdata) {
4263 int image_size = do_get_expected_ram_image_size(cdata);
4264 cdata->_ram_images.clear();
4265 cdata->_ram_images.push_back(RamImage());
4266 cdata->_ram_images[0]._page_size = do_get_expected_ram_page_size(cdata);
4267 cdata->_ram_images[0]._image = PTA_uchar::empty_array(image_size, get_class_type());
4268 cdata->_ram_images[0]._pointer_image = NULL;
4269 cdata->_ram_image_compression = CM_off;
4271 if (cdata->_has_clear_color) {
4273 unsigned char pixel[16];
4274 const int pixel_size = do_get_clear_data(cdata, pixel);
4275 nassertr(pixel_size > 0, cdata->_ram_images[0]._image);
4277 unsigned char *image_data = cdata->_ram_images[0]._image;
4278 for (
int i = 0; i < image_size; i += pixel_size) {
4279 memcpy(image_data + i, pixel, pixel_size);
4283 return cdata->_ram_images[0]._image;
4297 do_set_ram_image(CData *cdata,
CPTA_uchar image, Texture::CompressionMode compression,
4299 nassertv(compression != CM_default);
4300 nassertv(compression != CM_off || image.size() == do_get_expected_ram_image_size(cdata));
4301 if (cdata->_ram_images.empty()) {
4302 cdata->_ram_images.push_back(RamImage());
4304 do_clear_ram_mipmap_images(cdata);
4306 if (page_size == 0) {
4307 page_size = image.size();
4309 if (cdata->_ram_images[0]._image != image ||
4310 cdata->_ram_images[0]._page_size != page_size ||
4311 cdata->_ram_image_compression != compression) {
4313 cdata->_ram_images[0]._page_size = page_size;
4314 cdata->_ram_images[0]._pointer_image = NULL;
4315 cdata->_ram_image_compression = compression;
4316 cdata->inc_image_modified();
4327 do_modify_ram_mipmap_image(CData *cdata,
int n) {
4328 nassertr(cdata->_ram_image_compression == CM_off, PTA_uchar());
4330 if (n >= (
int)cdata->_ram_images.size() ||
4331 cdata->_ram_images[n]._image.empty()) {
4332 do_make_ram_mipmap_image(cdata, n);
4334 return cdata->_ram_images[n]._image;
4343 do_make_ram_mipmap_image(CData *cdata,
int n) {
4344 nassertr(cdata->_ram_image_compression == CM_off, PTA_uchar(get_class_type()));
4346 while (n >= (
int)cdata->_ram_images.size()) {
4347 cdata->_ram_images.push_back(RamImage());
4350 size_t image_size = do_get_expected_ram_mipmap_image_size(cdata, n);
4351 cdata->_ram_images[n]._image = PTA_uchar::empty_array(image_size, get_class_type());
4352 cdata->_ram_images[n]._pointer_image = NULL;
4353 cdata->_ram_images[n]._page_size = do_get_expected_ram_mipmap_page_size(cdata, n);
4355 if (cdata->_has_clear_color) {
4357 unsigned char pixel[16];
4358 const size_t pixel_size = (size_t)do_get_clear_data(cdata, pixel);
4359 nassertr(pixel_size > 0, cdata->_ram_images[n]._image);
4361 unsigned char *image_data = cdata->_ram_images[n]._image;
4362 for (
size_t i = 0; i < image_size; i += pixel_size) {
4363 memcpy(image_data + i, pixel, pixel_size);
4367 return cdata->_ram_images[n]._image;
4376 do_set_ram_mipmap_image(CData *cdata,
int n,
CPTA_uchar image,
size_t page_size) {
4377 nassertv(cdata->_ram_image_compression != CM_off || image.size() == do_get_expected_ram_mipmap_image_size(cdata, n));
4379 while (n >= (
int)cdata->_ram_images.size()) {
4380 cdata->_ram_images.push_back(RamImage());
4382 if (page_size == 0) {
4383 page_size = image.size();
4386 if (cdata->_ram_images[n]._image != image ||
4387 cdata->_ram_images[n]._page_size != page_size) {
4389 cdata->_ram_images[n]._pointer_image = NULL;
4390 cdata->_ram_images[n]._page_size = page_size;
4391 cdata->inc_image_modified();
4408 do_get_clear_data(
const CData *cdata,
unsigned char *into)
const {
4409 nassertr(cdata->_has_clear_color, 0);
4410 nassertr(cdata->_num_components <= 4, 0);
4413 switch (cdata->_component_type) {
4414 case T_unsigned_byte:
4418 switch (cdata->_num_components) {
4420 into[1] = (
unsigned char)scaled[1];
4422 into[0] = (
unsigned char)scaled[0];
4425 into[3] = (
unsigned char)scaled[3];
4427 into[0] = (
unsigned char)scaled[2];
4428 into[1] = (
unsigned char)scaled[1];
4429 into[2] = (
unsigned char)scaled[0];
4435 case T_unsigned_short:
4439 switch (cdata->_num_components) {
4441 ((
unsigned short *)into)[1] = (
unsigned short)scaled[1];
4443 ((
unsigned short *)into)[0] = (
unsigned short)scaled[0];
4446 ((
unsigned short *)into)[3] = (
unsigned short)scaled[3];
4448 ((
unsigned short *)into)[0] = (
unsigned short)scaled[2];
4449 ((
unsigned short *)into)[1] = (
unsigned short)scaled[1];
4450 ((
unsigned short *)into)[2] = (
unsigned short)scaled[0];
4457 switch (cdata->_num_components) {
4459 ((
float *)into)[1] = cdata->_clear_color[1];
4461 ((
float *)into)[0] = cdata->_clear_color[0];
4464 ((
float *)into)[3] = cdata->_clear_color[3];
4466 ((
float *)into)[0] = cdata->_clear_color[2];
4467 ((
float *)into)[1] = cdata->_clear_color[1];
4468 ((
float *)into)[2] = cdata->_clear_color[0];
4473 case T_unsigned_int_24_8:
4474 nassertr(cdata->_num_components == 1, 0);
4475 *((
unsigned int *)into) =
4476 ((
unsigned int)(cdata->_clear_color[0] * 16777215) << 8) +
4477 (
unsigned int)max(min(cdata->_clear_color[1], (PN_stdfloat)255), (PN_stdfloat)0);
4484 switch (cdata->_num_components) {
4486 ((
int *)into)[1] = (int)cdata->_clear_color[1];
4488 ((
int *)into)[0] = (
int)cdata->_clear_color[0];
4491 ((
int *)into)[3] = (int)cdata->_clear_color[3];
4493 ((
int *)into)[0] = (
int)cdata->_clear_color[2];
4494 ((
int *)into)[1] = (int)cdata->_clear_color[1];
4495 ((
int *)into)[2] = (
int)cdata->_clear_color[0];
4502 return cdata->_num_components * cdata->_component_width;
4516 consider_auto_process_ram_image(
bool generate_mipmaps,
bool allow_compression) {
4517 CDWriter cdata(_cycler,
false);
4518 return do_consider_auto_process_ram_image(cdata, generate_mipmaps, allow_compression);
4532 do_consider_auto_process_ram_image(CData *cdata,
bool generate_mipmaps,
4533 bool allow_compression) {
4534 bool modified =
false;
4536 if (generate_mipmaps && !driver_generate_mipmaps &&
4537 cdata->_ram_images.size() == 1) {
4538 do_generate_ram_mipmap_images(cdata);
4542 if (allow_compression && !driver_compress_textures) {
4543 CompressionMode compression = cdata->_compression;
4544 if (compression == CM_default && compressed_textures) {
4545 compression = CM_on;
4547 if (compression != CM_off && cdata->_ram_image_compression == CM_off) {
4549 if (do_compress_ram_image(cdata, compression, QL_default, gsg)) {
4550 if (gobj_cat.is_debug()) {
4552 <<
"Compressed " << get_name() <<
" with "
4553 << cdata->_ram_image_compression <<
"\n";
4569 do_compress_ram_image(CData *cdata, Texture::CompressionMode compression,
4570 Texture::QualityLevel quality_level,
4572 nassertr(compression != CM_off,
false);
4574 if (compression == CM_on) {
4576 switch (cdata->_format) {
4577 case Texture::F_rgbm:
4578 case Texture::F_rgb:
4579 case Texture::F_rgb5:
4580 case Texture::F_rgba5:
4581 case Texture::F_rgb8:
4582 case Texture::F_rgb12:
4583 case Texture::F_rgb332:
4584 case Texture::F_rgb16:
4585 case Texture::F_rgb32:
4586 if (gsg == NULL || gsg->get_supports_compressed_texture_format(CM_dxt1)) {
4587 compression = CM_dxt1;
4588 }
else if (gsg == NULL || gsg->get_supports_compressed_texture_format(CM_dxt3)) {
4589 compression = CM_dxt3;
4590 }
else if (gsg == NULL || gsg->get_supports_compressed_texture_format(CM_dxt5)) {
4591 compression = CM_dxt5;
4595 case Texture::F_rgba4:
4596 if (gsg == NULL || gsg->get_supports_compressed_texture_format(CM_dxt3)) {
4597 compression = CM_dxt3;
4598 }
else if (gsg == NULL || gsg->get_supports_compressed_texture_format(CM_dxt5)) {
4599 compression = CM_dxt5;
4603 case Texture::F_rgba:
4604 case Texture::F_rgba8:
4605 case Texture::F_rgba12:
4606 case Texture::F_rgba16:
4607 case Texture::F_rgba32:
4608 if (gsg == NULL || gsg->get_supports_compressed_texture_format(CM_dxt5)) {
4609 compression = CM_dxt5;
4619 if (quality_level == Texture::QL_default) {
4620 quality_level = cdata->_quality_level;
4622 if (quality_level == Texture::QL_default) {
4623 quality_level = texture_quality_level;
4627 if (cdata->_texture_type != TT_3d_texture &&
4628 cdata->_texture_type != TT_2d_texture_array &&
4629 cdata->_component_type == T_unsigned_byte) {
4630 int squish_flags = 0;
4631 switch (compression) {
4633 squish_flags |= squish::kDxt1;
4637 squish_flags |= squish::kDxt3;
4641 squish_flags |= squish::kDxt5;
4648 if (squish_flags != 0) {
4650 switch (quality_level) {
4652 squish_flags |= squish::kColourRangeFit;
4657 squish_flags |= squish::kColourRangeFit;
4662 squish_flags |= squish::kColourIterativeClusterFit;
4669 if (do_squish(cdata, compression, squish_flags)) {
4674 #endif // HAVE_SQUISH
4685 do_uncompress_ram_image(CData *cdata) {
4688 if (cdata->_texture_type != TT_3d_texture &&
4689 cdata->_texture_type != TT_2d_texture_array &&
4690 cdata->_component_type == T_unsigned_byte) {
4691 int squish_flags = 0;
4692 switch (cdata->_ram_image_compression) {
4694 squish_flags |= squish::kDxt1;
4698 squish_flags |= squish::kDxt3;
4702 squish_flags |= squish::kDxt5;
4709 if (squish_flags != 0) {
4711 if (do_unsquish(cdata, squish_flags)) {
4716 #endif // HAVE_SQUISH
4726 do_has_all_ram_mipmap_images(
const CData *cdata)
const {
4727 if (cdata->_ram_images.empty() || cdata->_ram_images[0]._image.empty()) {
4739 int size = max(cdata->_x_size, max(cdata->_y_size, cdata->_z_size));
4745 if (n >= (
int)cdata->_ram_images.size() || cdata->_ram_images[n]._image.empty()) {
4764 do_reconsider_z_size(CData *cdata,
int z,
const LoaderOptions &options) {
4765 if (z >= cdata->_z_size * cdata->_num_views) {
4766 bool num_views_specified =
true;
4767 if (options.get_texture_flags() & LoaderOptions::TF_multiview) {
4775 if (num_views_specified &&
4776 (cdata->_texture_type == Texture::TT_3d_texture ||
4777 cdata->_texture_type == Texture::TT_2d_texture_array)) {
4782 nassertr(cdata->_num_views != 0,
false);
4783 cdata->_z_size = (z / cdata->_num_views) + 1;
4785 }
else if (cdata->_z_size != 0) {
4789 cdata->_num_views = (z / cdata->_z_size) + 1;
4798 do_allocate_pages(cdata);
4814 do_allocate_pages(CData *cdata) {
4815 size_t new_size = do_get_expected_ram_image_size(cdata);
4816 if (!cdata->_ram_images.empty() &&
4817 !cdata->_ram_images[0]._image.empty() &&
4818 new_size > cdata->_ram_images[0]._image.size()) {
4819 cdata->_ram_images[0]._image.insert(cdata->_ram_images[0]._image.end(), new_size - cdata->_ram_images[0]._image.size(), 0);
4820 nassertv(cdata->_ram_images[0]._image.size() == new_size);
4834 do_reconsider_image_properties(CData *cdata,
int x_size,
int y_size,
int num_components,
4835 Texture::ComponentType component_type,
int z,
4837 if (!cdata->_loaded_from_image || num_components != cdata->_num_components || component_type != cdata->_component_type) {
4843 switch (num_components) {
4845 cdata->_format = F_luminance;
4849 cdata->_format = F_luminance_alpha;
4853 cdata->_format = F_rgb;
4857 cdata->_format = F_rgba;
4862 nassertr(
false,
false);
4863 cdata->_format = F_rgb;
4867 if (!cdata->_loaded_from_image) {
4868 if ((options.get_texture_flags() & LoaderOptions::TF_allow_1d) &&
4869 cdata->_texture_type == TT_2d_texture && x_size != 1 && y_size == 1) {
4871 cdata->_texture_type = TT_1d_texture;
4875 if (cdata->_texture_type == TT_1d_texture) {
4876 nassertr(y_size == 1,
false);
4877 }
else if (cdata->_texture_type == TT_cube_map) {
4878 nassertr(x_size == y_size,
false);
4881 if ((cdata->_x_size != x_size)||(cdata->_y_size != y_size)) {
4882 do_set_pad_size(cdata, 0, 0, 0);
4884 cdata->_x_size = x_size;
4885 cdata->_y_size = y_size;
4886 cdata->_num_components = num_components;
4887 do_set_component_type(cdata, component_type);
4890 if (cdata->_x_size != x_size ||
4891 cdata->_y_size != y_size ||
4892 cdata->_num_components != num_components ||
4893 cdata->_component_type != component_type) {
4895 <<
"Texture properties have changed for texture " << get_name()
4896 <<
" page " << z <<
".\n";
4910 do_rescale_texture(CData *cdata) {
4911 int new_x_size = cdata->_x_size;
4912 int new_y_size = cdata->_y_size;
4913 if (cdata->_z_size * cdata->_num_views != 1) {
4914 nassert_raise(
"rescale_texture() doesn't support 3-d or multiview textures.");
4918 if (do_adjust_this_size(cdata, new_x_size, new_y_size, get_name(),
false)) {
4921 if (!do_store_one(cdata, orig_image, 0, 0)) {
4923 <<
"Couldn't get image in rescale_texture()\n";
4928 <<
"Resizing " << get_name() <<
" to " << new_x_size <<
" x "
4929 << new_y_size <<
"\n";
4935 do_clear_ram_image(cdata);
4936 cdata->inc_image_modified();
4937 cdata->_x_size = new_x_size;
4938 cdata->_y_size = new_y_size;
4939 if (!do_load_one(cdata, new_image, get_name(), 0, 0,
LoaderOptions())) {
4949 if (do_get_auto_texture_scale(cdata) == ATS_pad) {
4950 new_x_size = cdata->_x_size;
4951 new_y_size = cdata->_y_size;
4952 if (do_adjust_this_size(cdata, new_x_size, new_y_size, get_name(),
true)) {
4953 pad_x_size = new_x_size - cdata->_x_size;
4954 pad_y_size = new_y_size - cdata->_y_size;
4957 if (!do_store_one(cdata, orig_image, 0, 0)) {
4959 <<
"Couldn't get image in rescale_texture()\n";
4967 do_clear_ram_image(cdata);
4968 cdata->_loaded_from_image =
false;
4969 cdata->inc_image_modified();
4970 if (!do_load_one(cdata, new_image, get_name(), 0, 0,
LoaderOptions())) {
4974 do_set_pad_size(cdata, pad_x_size, pad_y_size, 0);
4988 PT(Texture) Texture::
4989 make_copy_impl()
const {
4990 CDReader cdata(_cycler);
4991 return do_make_copy(cdata);
4999 PT(Texture) Texture::
5000 do_make_copy(const CData *cdata)
const {
5001 PT(Texture) tex = new Texture(get_name());
5002 CDWriter cdata_tex(tex->_cycler, true);
5003 tex->do_assign(cdata_tex, this, cdata);
5014 do_assign(CData *cdata, const Texture *copy, const CData *cdata_copy) {
5015 cdata->do_assign(cdata_copy);
5025 do_clear(CData *cdata) {
5028 CDReader cdata_tex(tex._cycler);
5029 do_assign(cdata, &tex, cdata_tex);
5031 cdata->inc_properties_modified();
5032 cdata->inc_image_modified();
5033 cdata->inc_simple_image_modified();
5042 do_setup_texture(CData *cdata, Texture::TextureType texture_type,
5043 int x_size,
int y_size,
int z_size,
5044 Texture::ComponentType component_type,
5045 Texture::Format format) {
5046 switch (texture_type) {
5048 nassertv(y_size == 1 && z_size == 1);
5052 nassertv(z_size == 1);
5058 case TT_2d_texture_array:
5063 nassertv(x_size == y_size && z_size == 6);
5068 cdata->_default_sampler.set_wrap_u(SamplerState::WM_clamp);
5069 cdata->_default_sampler.set_wrap_v(SamplerState::WM_clamp);
5070 cdata->_default_sampler.set_wrap_w(SamplerState::WM_clamp);
5074 if (texture_type != TT_2d_texture) {
5075 do_clear_simple_ram_image(cdata);
5078 cdata->_texture_type = texture_type;
5079 cdata->_x_size = x_size;
5080 cdata->_y_size = y_size;
5081 cdata->_z_size = z_size;
5082 cdata->_num_views = 1;
5083 do_set_component_type(cdata, component_type);
5084 do_set_format(cdata, format);
5086 do_clear_ram_image(cdata);
5087 do_set_pad_size(cdata, 0, 0, 0);
5088 cdata->_orig_file_x_size = 0;
5089 cdata->_orig_file_y_size = 0;
5090 cdata->_loaded_from_image =
false;
5091 cdata->_loaded_from_txo =
false;
5092 cdata->_has_read_pages =
false;
5093 cdata->_has_read_mipmaps =
false;
5102 do_set_format(CData *cdata, Texture::Format format) {
5103 if (format == cdata->_format) {
5106 cdata->_format = format;
5107 cdata->inc_properties_modified();
5109 switch (cdata->_format) {
5111 case F_depth_stencil:
5112 case F_depth_component:
5113 case F_depth_component16:
5114 case F_depth_component24:
5115 case F_depth_component32:
5126 cdata->_num_components = 1;
5129 case F_luminance_alpha:
5130 case F_luminance_alphamask:
5132 case F_sluminance_alpha:
5135 cdata->_num_components = 2;
5147 cdata->_num_components = 3;
5160 cdata->_num_components = 4;
5171 do_set_component_type(CData *cdata, Texture::ComponentType component_type) {
5172 cdata->_component_type = component_type;
5174 switch (component_type) {
5175 case T_unsigned_byte:
5176 cdata->_component_width = 1;
5179 case T_unsigned_short:
5180 cdata->_component_width = 2;
5184 cdata->_component_width = 4;
5187 case T_unsigned_int_24_8:
5188 cdata->_component_width = 4;
5192 cdata->_component_width = 4;
5203 do_set_x_size(CData *cdata,
int x_size) {
5204 if (cdata->_x_size != x_size) {
5205 cdata->_x_size = x_size;
5206 cdata->inc_image_modified();
5207 do_clear_ram_image(cdata);
5208 do_set_pad_size(cdata, 0, 0, 0);
5218 do_set_y_size(CData *cdata,
int y_size) {
5219 if (cdata->_y_size != y_size) {
5220 nassertv(cdata->_texture_type != Texture::TT_1d_texture || y_size == 1);
5221 cdata->_y_size = y_size;
5222 cdata->inc_image_modified();
5223 do_clear_ram_image(cdata);
5224 do_set_pad_size(cdata, 0, 0, 0);
5236 do_set_z_size(CData *cdata,
int z_size) {
5237 if (cdata->_z_size != z_size) {
5238 nassertv((cdata->_texture_type == Texture::TT_3d_texture) ||
5239 (cdata->_texture_type == Texture::TT_cube_map && z_size == 6) ||
5240 (cdata->_texture_type == Texture::TT_2d_texture_array) || (z_size == 1));
5241 cdata->_z_size = z_size;
5242 cdata->inc_image_modified();
5243 do_clear_ram_image(cdata);
5244 do_set_pad_size(cdata, 0, 0, 0);
5254 do_set_num_views(CData *cdata,
int num_views) {
5255 nassertv(num_views >= 1);
5256 if (cdata->_num_views != num_views) {
5257 cdata->_num_views = num_views;
5258 if (do_has_ram_image(cdata)) {
5259 cdata->inc_image_modified();
5260 do_clear_ram_image(cdata);
5262 do_set_pad_size(cdata, 0, 0, 0);
5272 do_set_wrap_u(CData *cdata, SamplerState::WrapMode wrap) {
5273 if (cdata->_default_sampler.get_wrap_u() != wrap) {
5274 cdata->inc_properties_modified();
5275 cdata->_default_sampler.set_wrap_u(wrap);
5285 do_set_wrap_v(CData *cdata, SamplerState::WrapMode wrap) {
5286 if (cdata->_default_sampler.get_wrap_v() != wrap) {
5287 cdata->inc_properties_modified();
5288 cdata->_default_sampler.set_wrap_v(wrap);
5298 do_set_wrap_w(CData *cdata, SamplerState::WrapMode wrap) {
5299 if (cdata->_default_sampler.get_wrap_w() != wrap) {
5300 cdata->inc_properties_modified();
5301 cdata->_default_sampler.set_wrap_w(wrap);
5311 do_set_minfilter(CData *cdata, SamplerState::FilterType filter) {
5312 if (cdata->_default_sampler.get_minfilter() != filter) {
5313 cdata->inc_properties_modified();
5314 cdata->_default_sampler.set_minfilter(filter);
5324 do_set_magfilter(CData *cdata, SamplerState::FilterType filter) {
5325 if (cdata->_default_sampler.get_magfilter() != filter) {
5326 cdata->inc_properties_modified();
5327 cdata->_default_sampler.set_magfilter(filter);
5337 do_set_anisotropic_degree(CData *cdata,
int anisotropic_degree) {
5338 if (cdata->_default_sampler.get_anisotropic_degree() != anisotropic_degree) {
5339 cdata->inc_properties_modified();
5340 cdata->_default_sampler.set_anisotropic_degree(anisotropic_degree);
5350 do_set_border_color(CData *cdata,
const LColor &
color) {
5351 if (cdata->_default_sampler.get_border_color() != color) {
5352 cdata->inc_properties_modified();
5353 cdata->_default_sampler.set_border_color(color);
5363 do_set_compression(CData *cdata, Texture::CompressionMode compression) {
5364 if (cdata->_compression != compression) {
5365 cdata->inc_properties_modified();
5366 cdata->_compression = compression;
5368 if (do_has_ram_image(cdata)) {
5370 bool has_ram_image_compression = (cdata->_ram_image_compression != CM_off);
5371 if (has_compression != has_ram_image_compression ||
5388 do_set_quality_level(CData *cdata, Texture::QualityLevel quality_level) {
5389 if (cdata->_quality_level != quality_level) {
5390 cdata->inc_properties_modified();
5391 cdata->_quality_level = quality_level;
5401 do_has_compression(
const CData *cdata)
const {
5402 if (cdata->_compression == CM_default) {
5403 return compressed_textures;
5405 return (cdata->_compression != CM_off);
5416 do_has_ram_image(
const CData *cdata)
const {
5417 return !cdata->_ram_images.empty() && !cdata->_ram_images[0]._image.empty();
5428 do_has_uncompressed_ram_image(
const CData *cdata)
const {
5429 return !cdata->_ram_images.empty() && !cdata->_ram_images[0]._image.empty() && cdata->_ram_image_compression == CM_off;
5438 do_get_ram_image(CData *cdata) {
5439 if (!do_has_ram_image(cdata) && do_can_reload(cdata)) {
5440 do_reload_ram_image(cdata,
true);
5442 if (do_has_ram_image(cdata)) {
5447 cdata->inc_image_modified();
5448 cdata->inc_properties_modified();
5452 if (cdata->_ram_images.empty()) {
5456 return cdata->_ram_images[0]._image;
5465 do_get_uncompressed_ram_image(CData *cdata) {
5466 if (!cdata->_ram_images.empty() && cdata->_ram_image_compression != CM_off) {
5469 if (do_uncompress_ram_image(cdata)) {
5470 if (gobj_cat.is_debug()) {
5472 <<
"Uncompressed " << get_name() <<
"\n";
5474 return cdata->_ram_images[0]._image;
5479 if ((!do_has_ram_image(cdata) || cdata->_ram_image_compression != CM_off) && do_can_reload(cdata)) {
5480 do_reload_ram_image(cdata,
false);
5483 if (!cdata->_ram_images.empty() && cdata->_ram_image_compression != CM_off) {
5485 if (do_uncompress_ram_image(cdata)) {
5487 <<
"Uncompressed " << get_name() <<
"\n";
5488 return cdata->_ram_images[0]._image;
5492 if (cdata->_ram_images.empty() || cdata->_ram_image_compression != CM_off) {
5496 return cdata->_ram_images[0]._image;
5530 string format = upcase(requested_format);
5533 CPTA_uchar data = do_get_uncompressed_ram_image(cdata);
5535 gobj_cat.error() <<
"Couldn't find an uncompressed RAM image!\n";
5538 int imgsize = cdata->_x_size * cdata->_y_size;
5539 nassertr(cdata->_num_components > 0 && cdata->_num_components <= 4,
CPTA_uchar(get_class_type()));
5540 nassertr(data.size() == (size_t)(cdata->_component_width * cdata->_num_components * imgsize),
CPTA_uchar(get_class_type()));
5543 if ((cdata->_num_components == 1 && format.size() == 1) ||
5544 (cdata->_num_components == 2 && format.size() == 2 && format.at(1) ==
'A' && format.at(0) !=
'A') ||
5545 (cdata->_num_components == 3 && format ==
"BGR") ||
5546 (cdata->_num_components == 4 && format ==
"BGRA")) {
5552 PTA_uchar newdata = PTA_uchar::empty_array(imgsize * format.size() * cdata->_component_width, get_class_type());
5555 if (format ==
"RGBA" && cdata->_num_components == 4 && cdata->_component_width == 1) {
5557 for (
int p = 0; p < imgsize; p += 4) {
5558 newdata[p ] = data[p + 2];
5559 newdata[p + 1] = data[p + 1];
5560 newdata[p + 2] = data[p ];
5561 newdata[p + 3] = data[p + 3];
5565 if (format ==
"RGB" && cdata->_num_components == 3 && cdata->_component_width == 1) {
5567 for (
int p = 0; p < imgsize; p += 3) {
5568 newdata[p ] = data[p + 2];
5569 newdata[p + 1] = data[p + 1];
5570 newdata[p + 2] = data[p ];
5574 if (format ==
"A" && cdata->_component_width == 1 && cdata->_num_components != 3) {
5576 int component = cdata->_num_components - 1;
5577 for (
int p = 0; p < imgsize; ++p) {
5578 newdata[p] = data[component];
5582 if (cdata->_component_width == 1) {
5583 for (
int p = 0; p < imgsize; ++p) {
5584 for (uchar s = 0; s < format.size(); ++s) {
5585 signed char component = -1;
5586 if (format.at(s) ==
'B' || (cdata->_num_components <= 2 && format.at(s) !=
'A')) {
5588 }
else if (format.at(s) ==
'G') {
5590 }
else if (format.at(s) ==
'R') {
5592 }
else if (format.at(s) ==
'A') {
5593 nassertr(cdata->_num_components != 3,
CPTA_uchar(get_class_type()));
5594 component = cdata->_num_components - 1;
5595 }
else if (format.at(s) ==
'0') {
5596 newdata[p * format.
size() + s] = 0x00;
5597 }
else if (format.at(s) ==
'1') {
5598 newdata[p * format.
size() + s] = 0xff;
5600 gobj_cat.error() <<
"Unexpected component character '"
5601 << format.at(s) <<
"', expected one of RGBA!\n";
5604 if (component >= 0) {
5605 newdata[p * format.
size() + s] = data[p * cdata->_num_components + component];
5611 for (
int p = 0; p < imgsize; ++p) {
5612 for (uchar s = 0; s < format.size(); ++s) {
5613 signed char component = -1;
5614 if (format.at(s) ==
'B' || (cdata->_num_components <= 2 && format.at(s) !=
'A')) {
5616 }
else if (format.at(s) ==
'G') {
5618 }
else if (format.at(s) ==
'R') {
5620 }
else if (format.at(s) ==
'A') {
5621 nassertr(cdata->_num_components != 3,
CPTA_uchar(get_class_type()));
5622 component = cdata->_num_components - 1;
5623 }
else if (format.at(s) ==
'0') {
5624 memset((
void*)(newdata + (p * format.
size() + s) * cdata->_component_width), 0, cdata->_component_width);
5625 }
else if (format.at(s) ==
'1') {
5626 memset((
void*)(newdata + (p * format.
size() + s) * cdata->_component_width), -1, cdata->_component_width);
5628 gobj_cat.error() <<
"Unexpected component character '"
5629 << format.at(s) <<
"', expected one of RGBA!\n";
5632 if (component >= 0) {
5633 memcpy((
void*)(newdata + (p * format.
size() + s) * cdata->_component_width),
5634 (
void*)(data + (p * cdata->_num_components + component) * cdata->_component_width),
5635 cdata->_component_width);
5648 do_set_simple_ram_image(CData *cdata,
CPTA_uchar image,
int x_size,
int y_size) {
5649 nassertv(cdata->_texture_type == TT_2d_texture);
5650 size_t expected_page_size = (size_t)(x_size * y_size * 4);
5651 nassertv(image.size() == expected_page_size);
5653 cdata->_simple_x_size = x_size;
5654 cdata->_simple_y_size = y_size;
5656 cdata->_simple_ram_image._page_size = image.size();
5657 cdata->_simple_image_date_generated = (PN_int32)time(NULL);
5658 cdata->inc_simple_image_modified();
5667 do_get_expected_num_mipmap_levels(
const CData *cdata)
const {
5668 int size = max(cdata->_x_size, max(cdata->_y_size, cdata->_z_size));
5683 do_get_ram_mipmap_page_size(
const CData *cdata,
int n)
const {
5684 if (cdata->_ram_image_compression != CM_off) {
5685 if (n >= 0 && n < (
int)cdata->_ram_images.size()) {
5686 return cdata->_ram_images[n]._page_size;
5690 return do_get_expected_ram_mipmap_page_size(cdata, n);
5700 do_get_expected_mipmap_x_size(
const CData *cdata,
int n)
const {
5701 int size = max(cdata->_x_size, 1);
5702 while (n > 0 && size > 1) {
5715 do_get_expected_mipmap_y_size(
const CData *cdata,
int n)
const {
5716 int size = max(cdata->_y_size, 1);
5717 while (n > 0 && size > 1) {
5730 do_get_expected_mipmap_z_size(
const CData *cdata,
int n)
const {
5734 if (cdata->_texture_type == Texture::TT_3d_texture) {
5735 int size = max(cdata->_z_size, 1);
5736 while (n > 0 && size > 1) {
5743 return cdata->_z_size;
5753 do_clear_simple_ram_image(CData *cdata) {
5754 cdata->_simple_x_size = 0;
5755 cdata->_simple_y_size = 0;
5756 cdata->_simple_ram_image._image.clear();
5757 cdata->_simple_ram_image._page_size = 0;
5758 cdata->_simple_image_date_generated = 0;
5763 cdata->inc_simple_image_modified();
5772 do_clear_ram_mipmap_images(CData *cdata) {
5773 if (!cdata->_ram_images.empty()) {
5774 cdata->_ram_images.erase(cdata->_ram_images.begin() + 1, cdata->_ram_images.end());
5784 do_generate_ram_mipmap_images(CData *cdata) {
5785 nassertv(do_has_ram_image(cdata));
5787 if (do_get_expected_num_mipmap_levels(cdata) == 1) {
5792 RamImage orig_compressed_image;
5793 CompressionMode orig_compression_mode = CM_off;
5795 if (cdata->_ram_image_compression != CM_off) {
5799 orig_compressed_image = cdata->_ram_images[0];
5800 orig_compression_mode = cdata->_ram_image_compression;
5803 do_get_uncompressed_ram_image(cdata);
5805 nassertv(cdata->_ram_image_compression == CM_off);
5808 do_clear_ram_mipmap_images(cdata);
5810 if (gobj_cat.is_debug()) {
5812 <<
"Generating mipmap levels for " << *
this <<
"\n";
5815 if (cdata->_texture_type == Texture::TT_3d_texture && cdata->_z_size != 1) {
5817 int x_size = cdata->_x_size;
5818 int y_size = cdata->_y_size;
5819 int z_size = cdata->_z_size;
5821 while (x_size > 1 || y_size > 1 || z_size > 1) {
5822 cdata->_ram_images.push_back(RamImage());
5823 do_filter_3d_mipmap_level(cdata, cdata->_ram_images[n + 1], cdata->_ram_images[n],
5824 x_size, y_size, z_size);
5825 x_size = max(x_size >> 1, 1);
5826 y_size = max(y_size >> 1, 1);
5827 z_size = max(z_size >> 1, 1);
5833 int x_size = cdata->_x_size;
5834 int y_size = cdata->_y_size;
5836 while (x_size > 1 || y_size > 1) {
5837 cdata->_ram_images.push_back(RamImage());
5838 do_filter_2d_mipmap_pages(cdata, cdata->_ram_images[n + 1], cdata->_ram_images[n],
5840 x_size = max(x_size >> 1, 1);
5841 y_size = max(y_size >> 1, 1);
5846 if (orig_compression_mode != CM_off) {
5852 nassertv(cdata->_ram_images.size() > 1);
5853 int l0_x_size = cdata->_x_size;
5854 int l0_y_size = cdata->_y_size;
5855 int l0_z_size = cdata->_z_size;
5856 cdata->_x_size = do_get_expected_mipmap_x_size(cdata, 1);
5857 cdata->_y_size = do_get_expected_mipmap_y_size(cdata, 1);
5858 cdata->_z_size = do_get_expected_mipmap_z_size(cdata, 1);
5859 RamImage uncompressed_image = cdata->_ram_images[0];
5860 cdata->_ram_images.erase(cdata->_ram_images.begin());
5862 bool success = do_compress_ram_image(cdata, orig_compression_mode, QL_default, NULL);
5865 cdata->_ram_images.insert(cdata->_ram_images.begin(), orig_compressed_image);
5867 cdata->_ram_images.insert(cdata->_ram_images.begin(), uncompressed_image);
5869 cdata->_x_size = l0_x_size;
5870 cdata->_y_size = l0_y_size;
5871 cdata->_z_size = l0_z_size;
5881 do_set_pad_size(CData *cdata,
int x,
int y,
int z) {
5882 if (x > cdata->_x_size) {
5885 if (y > cdata->_y_size) {
5888 if (z > cdata->_z_size) {
5892 cdata->_pad_x_size = x;
5893 cdata->_pad_y_size = y;
5894 cdata->_pad_z_size = z;
5907 do_can_reload(
const CData *cdata)
const {
5908 return (cdata->_loaded_from_image && !cdata->_fullpath.empty());
5917 do_reload(CData *cdata) {
5918 if (do_can_reload(cdata)) {
5919 do_clear_ram_image(cdata);
5920 do_reload_ram_image(cdata,
true);
5921 if (do_has_ram_image(cdata)) {
5923 cdata->inc_image_modified();
5943 do_has_bam_rawdata(
const CData *cdata)
const {
5944 return do_has_ram_image(cdata);
5954 do_get_bam_rawdata(CData *cdata) {
5955 do_get_ram_image(cdata);
5965 convert_from_pnmimage(PTA_uchar &image,
size_t page_size,
5966 int row_stride,
int x,
int y,
int z,
5967 const PNMImage &pnmimage,
int num_components,
5968 int component_width) {
5972 int pixel_size = num_components * component_width;
5975 if (row_stride == 0) {
5976 row_stride = x_size;
5978 row_skip = (row_stride - x_size) * pixel_size;
5979 nassertv(row_skip >= 0);
5982 bool is_grayscale = (num_components == 1 || num_components == 2);
5983 bool has_alpha = (num_components == 2 || num_components == 4);
5984 bool img_has_alpha = pnmimage.
has_alpha();
5986 int idx = page_size * z;
5987 nassertv(idx + page_size <= image.size());
5988 unsigned char *p = &image[idx];
5990 if (x != 0 || y != 0) {
5991 p += (row_stride * y + x) * pixel_size;
5994 if (maxval == 255 && component_width == 1) {
5997 for (
int j = y_size-1; j >= 0; j--) {
5998 for (
int i = 0; i < x_size; i++) {
6004 store_unscaled_byte(p, pnmimage.
get_red_val(i, j));
6007 if (img_has_alpha) {
6010 store_unscaled_byte(p, 255);
6017 }
else if (maxval == 65535 && component_width == 2) {
6020 for (
int j = y_size-1; j >= 0; j--) {
6021 for (
int i = 0; i < x_size; i++) {
6027 store_unscaled_short(p, pnmimage.
get_red_val(i, j));
6030 if (img_has_alpha) {
6033 store_unscaled_short(p, 65535);
6040 }
else if (component_width == 1) {
6044 double scale = 255.0 / (double)maxval;
6046 for (
int j = y_size-1; j >= 0; j--) {
6047 for (
int i = 0; i < x_size; i++) {
6049 store_scaled_byte(p, pnmimage.
get_gray_val(i, j), scale);
6051 store_scaled_byte(p, pnmimage.
get_blue_val(i, j), scale);
6053 store_scaled_byte(p, pnmimage.
get_red_val(i, j), scale);
6056 if (img_has_alpha) {
6059 store_unscaled_byte(p, 255);
6070 double scale = 65535.0 / (double)maxval;
6072 for (
int j = y_size-1; j >= 0; j--) {
6073 for (
int i = 0; i < x_size; i++) {
6075 store_scaled_short(p, pnmimage.
get_gray_val(i, j), scale);
6077 store_scaled_short(p, pnmimage.
get_blue_val(i, j), scale);
6079 store_scaled_short(p, pnmimage.
get_red_val(i, j), scale);
6082 if (img_has_alpha) {
6085 store_unscaled_short(p, 65535);
6101 convert_from_pfm(PTA_uchar &image,
size_t page_size,
int z,
6102 const PfmFile &pfm,
int num_components,
int component_width) {
6103 nassertv(component_width == 4);
6107 int idx = page_size * z;
6108 nassertv(idx + page_size <= image.size());
6109 PN_float32 *p = (PN_float32 *)&image[idx];
6111 switch (num_components) {
6114 for (
int j = y_size-1; j >= 0; j--) {
6115 for (
int i = 0; i < x_size; i++) {
6125 for (
int j = y_size-1; j >= 0; j--) {
6126 for (
int i = 0; i < x_size; i++) {
6138 for (
int j = y_size-1; j >= 0; j--) {
6139 for (
int i = 0; i < x_size; i++) {
6152 for (
int j = y_size-1; j >= 0; j--) {
6153 for (
int i = 0; i < x_size; i++) {
6168 nassertv((
unsigned char *)p == &image[idx] + page_size);
6178 convert_to_pnmimage(
PNMImage &pnmimage,
int x_size,
int y_size,
6179 int num_components,
int component_width,
6181 xelval maxval = 0xff;
6182 if (component_width > 1) {
6185 pnmimage.
clear(x_size, y_size, num_components, maxval);
6189 int idx = page_size * z;
6190 nassertr(idx + page_size <= image.size(),
false);
6191 const unsigned char *p = &image[idx];
6193 if (component_width == 1) {
6194 for (
int j = y_size-1; j >= 0; j--) {
6195 for (
int i = 0; i < x_size; i++) {
6197 pnmimage.
set_gray(i, j, get_unsigned_byte(p));
6199 pnmimage.
set_blue(i, j, get_unsigned_byte(p));
6200 pnmimage.
set_green(i, j, get_unsigned_byte(p));
6201 pnmimage.
set_red(i, j, get_unsigned_byte(p));
6204 pnmimage.
set_alpha(i, j, get_unsigned_byte(p));
6209 }
else if (component_width == 2) {
6210 for (
int j = y_size-1; j >= 0; j--) {
6211 for (
int i = 0; i < x_size; i++) {
6213 pnmimage.
set_gray(i, j, get_unsigned_short(p));
6215 pnmimage.
set_blue(i, j, get_unsigned_short(p));
6216 pnmimage.
set_green(i, j, get_unsigned_short(p));
6217 pnmimage.
set_red(i, j, get_unsigned_short(p));
6220 pnmimage.
set_alpha(i, j, get_unsigned_short(p));
6229 nassertr(p == &image[idx] + page_size,
false);
6240 convert_to_pfm(
PfmFile &pfm,
int x_size,
int y_size,
6241 int num_components,
int component_width,
6243 nassertr(component_width == 4,
false);
6244 pfm.
clear(x_size, y_size, num_components);
6246 int idx = page_size * z;
6247 nassertr(idx + page_size <= image.size(),
false);
6248 const PN_float32 *p = (
const PN_float32 *)&image[idx];
6250 switch (num_components) {
6252 for (
int j = y_size-1; j >= 0; j--) {
6253 for (
int i = 0; i < x_size; i++) {
6261 for (
int j = y_size-1; j >= 0; j--) {
6262 for (
int i = 0; i < x_size; i++) {
6272 for (
int j = y_size-1; j >= 0; j--) {
6273 for (
int i = 0; i < x_size; i++) {
6284 for (
int j = y_size-1; j >= 0; j--) {
6285 for (
int i = 0; i < x_size; i++) {
6296 nassertr(
false,
false);
6299 nassertr((
unsigned char *)p == &image[idx] + page_size,
false);
6309 read_dds_level_bgr8(Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
6311 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
6312 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
6314 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
6315 size_t row_bytes = x_size * 3;
6316 PTA_uchar image = PTA_uchar::empty_array(size);
6317 for (
int y = y_size - 1; y >= 0; --y) {
6318 unsigned char *p = image.p() + y * row_bytes;
6319 nassertr(p + row_bytes <= image.p() + size, PTA_uchar());
6320 in.read((
char *)p, row_bytes);
6332 read_dds_level_rgb8(Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
6334 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
6335 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
6337 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
6338 size_t row_bytes = x_size * 3;
6339 PTA_uchar image = PTA_uchar::empty_array(size);
6340 for (
int y = y_size - 1; y >= 0; --y) {
6341 unsigned char *p = image.p() + y * row_bytes;
6342 nassertr(p + row_bytes <= image.p() + size, PTA_uchar());
6343 in.read((
char *)p, row_bytes);
6346 for (
int x = 0; x < x_size; ++x) {
6347 unsigned char r = p[0];
6352 nassertr(p <= image.p() + size, PTA_uchar());
6364 read_dds_level_abgr8(Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
6366 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
6367 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
6369 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
6370 size_t row_bytes = x_size * 4;
6371 PTA_uchar image = PTA_uchar::empty_array(size);
6372 for (
int y = y_size - 1; y >= 0; --y) {
6373 unsigned char *p = image.p() + y * row_bytes;
6374 in.read((
char *)p, row_bytes);
6376 PN_uint32 *pw = (PN_uint32 *)p;
6377 for (
int x = 0; x < x_size; ++x) {
6379 #ifdef WORDS_BIGENDIAN
6381 w = ((w & 0xff00) << 16) | ((w & 0xff000000U) >> 16) | (w & 0xff00ff);
6384 w = ((w & 0xff) << 16) | ((w & 0xff0000) >> 16) | (w & 0xff00ff00U);
6389 nassertr((
unsigned char *)pw <= image.p() + size, PTA_uchar());
6401 read_dds_level_rgba8(Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
6403 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
6404 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
6406 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
6407 size_t row_bytes = x_size * 4;
6408 PTA_uchar image = PTA_uchar::empty_array(size);
6409 for (
int y = y_size - 1; y >= 0; --y) {
6410 unsigned char *p = image.p() + y * row_bytes;
6411 nassertr(p + row_bytes <= image.p() + size, PTA_uchar());
6412 in.read((
char *)p, row_bytes);
6425 read_dds_level_generic_uncompressed(Texture *tex, CData *cdata,
const DDSHeader &header,
6426 int n, istream &in) {
6427 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
6428 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
6430 int pitch = (x_size * header.pf.rgb_bitcount) / 8;
6438 pitch = ((pitch + 3) / 4) * 4;
6439 if (header.dds_flags & DDSD_PITCH) {
6440 pitch = header.pitch;
6444 int bpp = header.pf.rgb_bitcount / 8;
6445 int skip_bytes = pitch - (bpp * x_size);
6446 nassertr(skip_bytes >= 0, PTA_uchar());
6448 unsigned int r_mask = header.pf.r_mask;
6449 unsigned int g_mask = header.pf.g_mask;
6450 unsigned int b_mask = header.pf.b_mask;
6451 unsigned int a_mask = header.pf.a_mask;
6455 int r_shift = get_lowest_on_bit(r_mask);
6456 int g_shift = get_lowest_on_bit(g_mask);
6457 int b_shift = get_lowest_on_bit(b_mask);
6458 int a_shift = get_lowest_on_bit(a_mask);
6462 unsigned int r_scale = 0;
6464 r_scale = 0xff000000 / (r_mask >> r_shift);
6466 unsigned int g_scale = 0;
6468 g_scale = 0xff000000 / (g_mask >> g_shift);
6470 unsigned int b_scale = 0;
6472 b_scale = 0xff000000 / (b_mask >> b_shift);
6474 unsigned int a_scale = 0;
6476 a_scale = 0xff000000 / (a_mask >> a_shift);
6479 bool add_alpha =
has_alpha(cdata->_format);
6481 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
6482 size_t row_bytes = x_size * cdata->_num_components;
6483 PTA_uchar image = PTA_uchar::empty_array(size);
6484 for (
int y = y_size - 1; y >= 0; --y) {
6485 unsigned char *p = image.p() + y * row_bytes;
6486 for (
int x = 0; x < x_size; ++x) {
6489 unsigned int pixel = 0;
6491 for (
int bi = 0; bi < bpp; ++bi) {
6492 unsigned int ch = (
unsigned char)in.get();
6493 pixel |= (ch << shift);
6499 unsigned int r = (((pixel & r_mask) >> r_shift) * r_scale) >> 24;
6500 unsigned int g = (((pixel & g_mask) >> g_shift) * g_scale) >> 24;
6501 unsigned int b = (((pixel & b_mask) >> b_shift) * b_scale) >> 24;
6504 store_unscaled_byte(p, b);
6505 store_unscaled_byte(p, g);
6506 store_unscaled_byte(p, r);
6508 unsigned int a = (((pixel & a_mask) >> a_shift) * a_scale) >> 24;
6509 store_unscaled_byte(p, a);
6512 nassertr(p <= image.p() + size, PTA_uchar());
6513 for (
int bi = 0; bi < skip_bytes; ++bi) {
6528 read_dds_level_luminance_uncompressed(Texture *tex, CData *cdata,
const DDSHeader &header,
6529 int n, istream &in) {
6530 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
6531 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
6533 int pitch = (x_size * header.pf.rgb_bitcount) / 8;
6541 pitch = ((pitch + 3) / 4) * 4;
6542 if (header.dds_flags & DDSD_PITCH) {
6543 pitch = header.pitch;
6547 int bpp = header.pf.rgb_bitcount / 8;
6548 int skip_bytes = pitch - (bpp * x_size);
6549 nassertr(skip_bytes >= 0, PTA_uchar());
6551 unsigned int r_mask = header.pf.r_mask;
6552 unsigned int a_mask = header.pf.a_mask;
6556 int r_shift = get_lowest_on_bit(r_mask);
6557 int a_shift = get_lowest_on_bit(a_mask);
6561 unsigned int r_scale = 0;
6563 r_scale = 0xff000000 / (r_mask >> r_shift);
6565 unsigned int a_scale = 0;
6567 a_scale = 0xff000000 / (a_mask >> a_shift);
6570 bool add_alpha =
has_alpha(cdata->_format);
6572 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
6573 size_t row_bytes = x_size * cdata->_num_components;
6574 PTA_uchar image = PTA_uchar::empty_array(size);
6575 for (
int y = y_size - 1; y >= 0; --y) {
6576 unsigned char *p = image.p() + y * row_bytes;
6577 for (
int x = 0; x < x_size; ++x) {
6580 unsigned int pixel = 0;
6582 for (
int bi = 0; bi < bpp; ++bi) {
6583 unsigned int ch = (
unsigned char)in.get();
6584 pixel |= (ch << shift);
6588 unsigned int r = (((pixel & r_mask) >> r_shift) * r_scale) >> 24;
6591 store_unscaled_byte(p, r);
6593 unsigned int a = (((pixel & a_mask) >> a_shift) * a_scale) >> 24;
6594 store_unscaled_byte(p, a);
6597 nassertr(p <= image.p() + size, PTA_uchar());
6598 for (
int bi = 0; bi < skip_bytes; ++bi) {
6612 read_dds_level_dxt1(Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
6613 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
6614 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
6616 static const int div = 4;
6617 static const int block_bytes = 8;
6621 int num_cols = max(div, x_size) / div;
6622 int num_rows = max(div, y_size) / div;
6623 int row_length = num_cols * block_bytes;
6624 int linear_size = row_length * num_rows;
6627 if (header.dds_flags & DDSD_LINEARSIZE) {
6628 nassertr(linear_size == (
int)header.pitch, PTA_uchar());
6632 PTA_uchar image = PTA_uchar::empty_array(linear_size);
6638 for (
int ri = num_rows - 1; ri >= 0; --ri) {
6639 unsigned char *p = image.p() + row_length * ri;
6640 in.read((
char *)p, row_length);
6642 for (
int ci = 0; ci < num_cols; ++ci) {
6645 PN_uint32 *cells = (PN_uint32 *)p;
6646 PN_uint32 w = cells[1];
6647 w = ((w & 0xff) << 24) | ((w & 0xff00) << 8) | ((w & 0xff0000) >> 8) | ((w & 0xff000000U) >> 24);
6654 }
else if (y_size >= 2) {
6656 unsigned char *p = image.p();
6657 in.read((
char *)p, row_length);
6659 for (
int ci = 0; ci < num_cols; ++ci) {
6660 PN_uint32 *cells = (PN_uint32 *)p;
6661 PN_uint32 w = cells[1];
6662 w = ((w & 0xff) << 8) | ((w & 0xff00) >> 8);
6668 }
else if (y_size >= 1) {
6670 unsigned char *p = image.p();
6671 in.read((
char *)p, row_length);
6683 read_dds_level_dxt23(Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
6684 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
6685 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
6687 static const int div = 4;
6688 static const int block_bytes = 16;
6694 int num_cols = max(div, x_size) / div;
6695 int num_rows = max(div, y_size) / div;
6696 int row_length = num_cols * block_bytes;
6697 int linear_size = row_length * num_rows;
6700 if (header.dds_flags & DDSD_LINEARSIZE) {
6701 nassertr(linear_size == (
int)header.pitch, PTA_uchar());
6705 PTA_uchar image = PTA_uchar::empty_array(linear_size);
6711 for (
int ri = num_rows - 1; ri >= 0; --ri) {
6712 unsigned char *p = image.p() + row_length * ri;
6713 in.read((
char *)p, row_length);
6715 for (
int ci = 0; ci < num_cols; ++ci) {
6718 PN_uint32 *cells = (PN_uint32 *)p;
6721 PN_uint32 w0 = cells[0];
6722 PN_uint32 w1 = cells[1];
6723 w0 = ((w0 & 0xffff) << 16) | ((w0 & 0xffff0000U) >> 16);
6724 w1 = ((w1 & 0xffff) << 16) | ((w1 & 0xffff0000U) >> 16);
6730 PN_uint32 w = cells[3];
6731 w = ((w & 0xff) << 24) | ((w & 0xff00) << 8) | ((w & 0xff0000) >> 8) | ((w & 0xff000000U) >> 24);
6738 }
else if (y_size >= 2) {
6740 unsigned char *p = image.p();
6741 in.read((
char *)p, row_length);
6743 for (
int ci = 0; ci < num_cols; ++ci) {
6744 PN_uint32 *cells = (PN_uint32 *)p;
6746 PN_uint32 w0 = cells[0];
6747 w0 = ((w0 & 0xffff) << 16) | ((w0 & 0xffff0000U) >> 16);
6750 PN_uint32 w = cells[3];
6751 w = ((w & 0xff) << 8) | ((w & 0xff00) >> 8);
6757 }
else if (y_size >= 1) {
6759 unsigned char *p = image.p();
6760 in.read((
char *)p, row_length);
6772 read_dds_level_dxt45(Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
6773 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
6774 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
6776 static const int div = 4;
6777 static const int block_bytes = 16;
6782 int num_cols = max(div, x_size) / div;
6783 int num_rows = max(div, y_size) / div;
6784 int row_length = num_cols * block_bytes;
6785 int linear_size = row_length * num_rows;
6788 if (header.dds_flags & DDSD_LINEARSIZE) {
6789 nassertr(linear_size == (
int)header.pitch, PTA_uchar());
6793 PTA_uchar image = PTA_uchar::empty_array(linear_size);
6799 for (
int ri = num_rows - 1; ri >= 0; --ri) {
6800 unsigned char *p = image.p() + row_length * ri;
6801 in.read((
char *)p, row_length);
6803 for (
int ci = 0; ci < num_cols; ++ci) {
6806 PN_uint32 *cells = (PN_uint32 *)p;
6811 unsigned char p2 = p[2];
6812 unsigned char p3 = p[3];
6813 unsigned char p4 = p[4];
6814 unsigned char p5 = p[5];
6815 unsigned char p6 = p[6];
6816 unsigned char p7 = p[7];
6818 p[2] = ((p7 & 0xf) << 4) | ((p6 & 0xf0) >> 4);
6819 p[3] = ((p5 & 0xf) << 4) | ((p7 & 0xf0) >> 4);
6820 p[4] = ((p6 & 0xf) << 4) | ((p5 & 0xf0) >> 4);
6821 p[5] = ((p4 & 0xf) << 4) | ((p3 & 0xf0) >> 4);
6822 p[6] = ((p2 & 0xf) << 4) | ((p4 & 0xf0) >> 4);
6823 p[7] = ((p3 & 0xf) << 4) | ((p2 & 0xf0) >> 4);
6827 PN_uint32 w = cells[3];
6828 w = ((w & 0xff) << 24) | ((w & 0xff00) << 8) | ((w & 0xff0000) >> 8) | ((w & 0xff000000U) >> 24);
6835 }
else if (y_size >= 2) {
6837 unsigned char *p = image.p();
6838 in.read((
char *)p, row_length);
6840 for (
int ci = 0; ci < num_cols; ++ci) {
6841 PN_uint32 *cells = (PN_uint32 *)p;
6843 unsigned char p2 = p[2];
6844 unsigned char p3 = p[3];
6845 unsigned char p4 = p[4];
6847 p[2] = ((p4 & 0xf) << 4) | ((p3 & 0xf0) >> 4);
6848 p[3] = ((p2 & 0xf) << 4) | ((p4 & 0xf0) >> 4);
6849 p[4] = ((p3 & 0xf) << 4) | ((p2 & 0xf0) >> 4);
6851 PN_uint32 w0 = cells[0];
6852 w0 = ((w0 & 0xffff) << 16) | ((w0 & 0xffff0000U) >> 16);
6855 PN_uint32 w = cells[3];
6856 w = ((w & 0xff) << 8) | ((w & 0xff00) >> 8);
6862 }
else if (y_size >= 1) {
6864 unsigned char *p = image.p();
6865 in.read((
char *)p, row_length);
6882 PreparedViews::iterator pvi;
6883 pvi = _prepared_views.find(prepared_objects);
6884 if (pvi != _prepared_views.end()) {
6885 Contexts &contexts = (*pvi).second;
6886 Contexts::iterator ci;
6887 ci = contexts.find(view);
6888 if (ci != contexts.end()) {
6892 if (contexts.empty()) {
6893 _prepared_views.erase(pvi);
6905 consider_downgrade(
PNMImage &pnmimage,
int num_channels,
const string &name) {
6914 <<
"Downgrading " << name <<
" from "
6916 << num_channels <<
".\n";
6936 for (
int yi = 0; yi < a.
get_y_size(); ++yi) {
6937 for (
int xi = 0; xi < a.
get_x_size(); ++xi) {
6946 return (average_delta <= simple_image_threshold);
6963 do_filter_2d_mipmap_pages(
const CData *cdata,
6964 Texture::RamImage &to,
const Texture::RamImage &from,
6965 int x_size,
int y_size)
const {
6966 Filter2DComponent *filter_component;
6967 Filter2DComponent *filter_alpha;
6969 if (
is_srgb(cdata->_format)) {
6972 nassertv(cdata->_component_type == T_unsigned_byte);
6974 if (has_sse2_sRGB_encode()) {
6975 filter_component = &filter_2d_unsigned_byte_srgb_sse2;
6977 filter_component = &filter_2d_unsigned_byte_srgb;
6981 filter_alpha = &filter_2d_unsigned_byte;
6984 switch (cdata->_component_type) {
6985 case T_unsigned_byte:
6986 filter_component = &filter_2d_unsigned_byte;
6989 case T_unsigned_short:
6990 filter_component = &filter_2d_unsigned_short;
6994 filter_component = &filter_2d_float;
6999 <<
"Unable to generate mipmaps for 2D texture with component type "
7000 << cdata->_component_type <<
"!";
7003 filter_alpha = filter_component;
7006 size_t pixel_size = cdata->_num_components * cdata->_component_width;
7007 size_t row_size = (size_t)x_size * pixel_size;
7009 int to_x_size = max(x_size >> 1, 1);
7010 int to_y_size = max(y_size >> 1, 1);
7012 size_t to_row_size = (size_t)to_x_size * pixel_size;
7013 to._page_size = (size_t)to_y_size * to_row_size;
7014 to._image = PTA_uchar::empty_array(to._page_size * cdata->_z_size * cdata->_num_views, get_class_type());
7017 int num_color_components = cdata->_num_components;
7019 --num_color_components;
7022 int num_pages = cdata->_z_size * cdata->_num_views;
7023 for (
int z = 0; z < num_pages; ++z) {
7025 unsigned char *p = to._image.p() + z * to._page_size;
7026 nassertv(p <= to._image.p() + to._image.size() + to._page_size);
7027 const unsigned char *q = from._image.p() + z * from._page_size;
7028 nassertv(q <= from._image.p() + from._image.size() + from._page_size);
7031 for (y = 0; y < y_size - 1; y += 2) {
7033 nassertv(p == to._image.p() + z * to._page_size + (y / 2) * to_row_size);
7034 nassertv(q == from._image.p() + z * from._page_size + y * row_size);
7037 for (x = 0; x < x_size - 1; x += 2) {
7039 for (
int c = 0; c < num_color_components; ++c) {
7041 filter_component(p, q, pixel_size, row_size);
7044 filter_alpha(p, q, pixel_size, row_size);
7054 for (
int c = 0; c < num_color_components; ++c) {
7056 filter_component(p, q, 0, row_size);
7059 filter_alpha(p, q, 0, row_size);
7073 for (x = 0; x < x_size - 1; x += 2) {
7075 for (
int c = 0; c < num_color_components; ++c) {
7077 filter_component(p, q, pixel_size, 0);
7080 filter_alpha(p, q, pixel_size, 0);
7090 for (
int c = 0; c < num_color_components; ++c) {
7092 filter_component(p, q, 0, 0);
7095 filter_alpha(p, q, pixel_size, 0);
7100 nassertv(p == to._image.p() + (z + 1) * to._page_size);
7101 nassertv(q == from._image.p() + (z + 1) * from._page_size);
7119 do_filter_3d_mipmap_level(
const CData *cdata,
7120 Texture::RamImage &to,
const Texture::RamImage &from,
7121 int x_size,
int y_size,
int z_size)
const {
7122 Filter3DComponent *filter_component;
7123 Filter3DComponent *filter_alpha;
7125 if (
is_srgb(cdata->_format)) {
7128 nassertv(cdata->_component_type == T_unsigned_byte);
7130 if (has_sse2_sRGB_encode()) {
7131 filter_component = &filter_3d_unsigned_byte_srgb_sse2;
7133 filter_component = &filter_3d_unsigned_byte_srgb;
7137 filter_alpha = &filter_3d_unsigned_byte;
7140 switch (cdata->_component_type) {
7141 case T_unsigned_byte:
7142 filter_component = &filter_3d_unsigned_byte;
7145 case T_unsigned_short:
7146 filter_component = &filter_3d_unsigned_short;
7150 filter_component = &filter_3d_float;
7155 <<
"Unable to generate mipmaps for 3D texture with component type "
7156 << cdata->_component_type <<
"!";
7159 filter_alpha = filter_component;
7162 size_t pixel_size = cdata->_num_components * cdata->_component_width;
7163 size_t row_size = (size_t)x_size * pixel_size;
7164 size_t page_size = (size_t)y_size * row_size;
7165 size_t view_size = (size_t)z_size * page_size;
7167 int to_x_size = max(x_size >> 1, 1);
7168 int to_y_size = max(y_size >> 1, 1);
7169 int to_z_size = max(z_size >> 1, 1);
7171 size_t to_row_size = (size_t)to_x_size * pixel_size;
7172 size_t to_page_size = (size_t)to_y_size * to_row_size;
7173 size_t to_view_size = (size_t)to_z_size * to_page_size;
7174 to._page_size = to_page_size;
7175 to._image = PTA_uchar::empty_array(to_page_size * to_z_size * cdata->_num_views, get_class_type());
7178 int num_color_components = cdata->_num_components;
7180 --num_color_components;
7183 for (
int view = 0; view < cdata->_num_views; ++view) {
7184 unsigned char *start_to = to._image.p() + view * to_view_size;
7185 const unsigned char *start_from = from._image.p() + view * view_size;
7186 nassertv(start_to + to_view_size <= to._image.p() + to._image.size());
7187 nassertv(start_from + view_size <= from._image.p() + from._image.size());
7188 unsigned char *p = start_to;
7189 const unsigned char *q = start_from;
7192 for (z = 0; z < z_size - 1; z += 2) {
7194 nassertv(p == start_to + (z / 2) * to_page_size);
7195 nassertv(q == start_from + z * page_size);
7198 for (y = 0; y < y_size - 1; y += 2) {
7200 nassertv(p == start_to + (z / 2) * to_page_size + (y / 2) * to_row_size);
7201 nassertv(q == start_from + z * page_size + y * row_size);
7204 for (x = 0; x < x_size - 1; x += 2) {
7206 for (
int c = 0; c < num_color_components; ++c) {
7208 filter_component(p, q, pixel_size, row_size, page_size);
7211 filter_alpha(p, q, pixel_size, row_size, page_size);
7221 for (
int c = 0; c < num_color_components; ++c) {
7223 filter_component(p, q, 0, row_size, page_size);
7226 filter_alpha(p, q, 0, row_size, page_size);
7240 for (x = 0; x < x_size - 1; x += 2) {
7242 for (
int c = 0; c < num_color_components; ++c) {
7244 filter_component(p, q, pixel_size, 0, page_size);
7247 filter_alpha(p, q, pixel_size, 0, page_size);
7257 for (
int c = 0; c < num_color_components; ++c) {
7259 filter_component(p, q, 0, 0, page_size);
7262 filter_alpha(p, q, 0, 0, page_size);
7276 for (y = 0; y < y_size - 1; y += 2) {
7278 nassertv(p == start_to + (y / 2) * to_row_size);
7279 nassertv(q == start_from + y * row_size);
7282 for (x = 0; x < x_size - 1; x += 2) {
7284 for (
int c = 0; c < num_color_components; ++c) {
7286 filter_component(p, q, pixel_size, row_size, 0);
7289 filter_alpha(p, q, pixel_size, row_size, 0);
7299 for (
int c = 0; c < num_color_components; ++c) {
7301 filter_component(p, q, 0, row_size, 0);
7304 filter_alpha(p, q, 0, row_size, 0);
7318 for (x = 0; x < x_size - 1; x += 2) {
7320 for (
int c = 0; c < num_color_components; ++c) {
7322 filter_component(p, q, pixel_size, 0, 0);
7325 filter_alpha(p, q, pixel_size, 0, 0);
7335 for (
int c = 0; c < num_color_components; ++c) {
7337 filter_component(p, q, 0, 0, 0);
7340 filter_alpha(p, q, 0, 0, 0);
7346 nassertv(p == start_to + to_z_size * to_page_size);
7347 nassertv(q == start_from + z_size * page_size);
7359 filter_2d_unsigned_byte(
unsigned char *&p,
const unsigned char *&q,
7360 size_t pixel_size,
size_t row_size) {
7361 unsigned int result = ((
unsigned int)q[0] +
7362 (
unsigned int)q[pixel_size] +
7363 (
unsigned int)q[row_size] +
7364 (
unsigned int)q[pixel_size + row_size]) >> 2;
7365 *p = (
unsigned char)result;
7378 filter_2d_unsigned_byte_srgb(
unsigned char *&p,
const unsigned char *&q,
7379 size_t pixel_size,
size_t row_size) {
7380 float result = (decode_sRGB_float(q[0]) +
7381 decode_sRGB_float(q[pixel_size]) +
7382 decode_sRGB_float(q[row_size]) +
7383 decode_sRGB_float(q[pixel_size + row_size]));
7385 *p = encode_sRGB_uchar(result * 0.25f);
7398 filter_2d_unsigned_byte_srgb_sse2(
unsigned char *&p,
const unsigned char *&q,
7399 size_t pixel_size,
size_t row_size) {
7400 float result = (decode_sRGB_float(q[0]) +
7401 decode_sRGB_float(q[pixel_size]) +
7402 decode_sRGB_float(q[row_size]) +
7403 decode_sRGB_float(q[pixel_size + row_size]));
7405 *p = encode_sRGB_uchar_sse2(result * 0.25f);
7418 filter_2d_unsigned_short(
unsigned char *&p,
const unsigned char *&q,
7419 size_t pixel_size,
size_t row_size) {
7420 unsigned int result = ((
unsigned int)*(
unsigned short *)&q[0] +
7421 (
unsigned int)*(
unsigned short *)&q[pixel_size] +
7422 (
unsigned int)*(
unsigned short *)&q[row_size] +
7423 (
unsigned int)*(
unsigned short *)&q[pixel_size + row_size]) >> 2;
7424 store_unscaled_short(p, result);
7436 filter_2d_float(
unsigned char *&p,
const unsigned char *&q,
7437 size_t pixel_size,
size_t row_size) {
7438 *(
float *)p = (*(
float *)&q[0] +
7439 *(
float *)&q[pixel_size] +
7440 *(
float *)&q[row_size] +
7441 *(
float *)&q[pixel_size + row_size]) / 4.0f;
7454 filter_3d_unsigned_byte(
unsigned char *&p,
const unsigned char *&q,
7455 size_t pixel_size,
size_t row_size,
size_t page_size) {
7456 unsigned int result = ((
unsigned int)q[0] +
7457 (
unsigned int)q[pixel_size] +
7458 (
unsigned int)q[row_size] +
7459 (
unsigned int)q[pixel_size + row_size] +
7460 (
unsigned int)q[page_size] +
7461 (
unsigned int)q[pixel_size + page_size] +
7462 (
unsigned int)q[row_size + page_size] +
7463 (
unsigned int)q[pixel_size + row_size + page_size]) >> 3;
7464 *p = (
unsigned char)result;
7477 filter_3d_unsigned_byte_srgb(
unsigned char *&p,
const unsigned char *&q,
7478 size_t pixel_size,
size_t row_size,
size_t page_size) {
7479 float result = (decode_sRGB_float(q[0]) +
7480 decode_sRGB_float(q[pixel_size]) +
7481 decode_sRGB_float(q[row_size]) +
7482 decode_sRGB_float(q[pixel_size + row_size]) +
7483 decode_sRGB_float(q[page_size]) +
7484 decode_sRGB_float(q[pixel_size + page_size]) +
7485 decode_sRGB_float(q[row_size + page_size]) +
7486 decode_sRGB_float(q[pixel_size + row_size + page_size]));
7488 *p = encode_sRGB_uchar(result * 0.125f);
7501 filter_3d_unsigned_byte_srgb_sse2(
unsigned char *&p,
const unsigned char *&q,
7502 size_t pixel_size,
size_t row_size,
size_t page_size) {
7503 float result = (decode_sRGB_float(q[0]) +
7504 decode_sRGB_float(q[pixel_size]) +
7505 decode_sRGB_float(q[row_size]) +
7506 decode_sRGB_float(q[pixel_size + row_size]) +
7507 decode_sRGB_float(q[page_size]) +
7508 decode_sRGB_float(q[pixel_size + page_size]) +
7509 decode_sRGB_float(q[row_size + page_size]) +
7510 decode_sRGB_float(q[pixel_size + row_size + page_size]));
7512 *p = encode_sRGB_uchar_sse2(result * 0.125f);
7525 filter_3d_unsigned_short(
unsigned char *&p,
const unsigned char *&q,
7526 size_t pixel_size,
size_t row_size,
7528 unsigned int result = ((
unsigned int)*(
unsigned short *)&q[0] +
7529 (
unsigned int)*(
unsigned short *)&q[pixel_size] +
7530 (
unsigned int)*(
unsigned short *)&q[row_size] +
7531 (
unsigned int)*(
unsigned short *)&q[pixel_size + row_size] +
7532 (
unsigned int)*(
unsigned short *)&q[page_size] +
7533 (
unsigned int)*(
unsigned short *)&q[pixel_size + page_size] +
7534 (
unsigned int)*(
unsigned short *)&q[row_size + page_size] +
7535 (
unsigned int)*(
unsigned short *)&q[pixel_size + row_size + page_size]) >> 3;
7536 store_unscaled_short(p, result);
7548 filter_3d_float(
unsigned char *&p,
const unsigned char *&q,
7549 size_t pixel_size,
size_t row_size,
size_t page_size) {
7550 *(
float *)p = (*(
float *)&q[0] +
7551 *(
float *)&q[pixel_size] +
7552 *(
float *)&q[row_size] +
7553 *(
float *)&q[pixel_size + row_size] +
7554 *(
float *)&q[page_size] +
7555 *(
float *)&q[pixel_size + page_size] +
7556 *(
float *)&q[row_size + page_size] +
7557 *(
float *)&q[pixel_size + row_size + page_size]) / 8.0f;
7569 do_squish(CData *cdata, Texture::CompressionMode compression,
int squish_flags) {
7571 if (cdata->_ram_images.empty() || cdata->_ram_image_compression != CM_off) {
7575 if (!do_has_all_ram_mipmap_images(cdata)) {
7578 do_generate_ram_mipmap_images(cdata);
7581 RamImages compressed_ram_images;
7582 compressed_ram_images.reserve(cdata->_ram_images.size());
7583 for (
size_t n = 0; n < cdata->_ram_images.size(); ++n) {
7584 RamImage compressed_image;
7585 int x_size = do_get_expected_mipmap_x_size(cdata, n);
7586 int y_size = do_get_expected_mipmap_y_size(cdata, n);
7587 int num_pages = do_get_expected_mipmap_num_pages(cdata, n);
7588 int page_size = squish::GetStorageRequirements(x_size, y_size, squish_flags);
7589 int cell_size = squish::GetStorageRequirements(4, 4, squish_flags);
7591 compressed_image._page_size = page_size;
7592 compressed_image._image = PTA_uchar::empty_array(page_size * num_pages);
7593 for (
int z = 0; z < num_pages; ++z) {
7594 unsigned char *dest_page = compressed_image._image.p() + z * page_size;
7595 unsigned const char *source_page = cdata->_ram_images[n]._image.p() + z * cdata->_ram_images[n]._page_size;
7596 unsigned const char *source_page_end = source_page + cdata->_ram_images[n]._page_size;
7598 unsigned char *d = dest_page;
7599 for (
int y = 0; y < y_size; y += 4) {
7600 for (
int x = 0; x < x_size; x += 4) {
7601 unsigned char tb[16 * 4];
7603 unsigned char *t = tb;
7604 for (
int i = 0; i < 16; ++i) {
7607 unsigned const char *s = source_page + (yi * x_size + xi) * cdata->_num_components;
7608 if (s < source_page_end) {
7609 switch (cdata->_num_components) {
7642 squish::CompressMasked(tb, mask, d, squish_flags);
7648 compressed_ram_images.push_back(compressed_image);
7650 cdata->_ram_images.swap(compressed_ram_images);
7651 cdata->_ram_image_compression = compression;
7654 #else // HAVE_SQUISH
7657 #endif // HAVE_SQUISH
7667 do_unsquish(CData *cdata,
int squish_flags) {
7669 if (cdata->_ram_images.empty()) {
7672 RamImages uncompressed_ram_images;
7673 uncompressed_ram_images.reserve(cdata->_ram_images.size());
7674 for (
size_t n = 0; n < cdata->_ram_images.size(); ++n) {
7675 RamImage uncompressed_image;
7676 int x_size = do_get_expected_mipmap_x_size(cdata, n);
7677 int y_size = do_get_expected_mipmap_y_size(cdata, n);
7678 int num_pages = do_get_expected_mipmap_num_pages(cdata, n);
7679 int page_size = squish::GetStorageRequirements(x_size, y_size, squish_flags);
7680 int cell_size = squish::GetStorageRequirements(4, 4, squish_flags);
7682 uncompressed_image._page_size = do_get_expected_ram_mipmap_page_size(cdata, n);
7683 uncompressed_image._image = PTA_uchar::empty_array(uncompressed_image._page_size * num_pages);
7684 for (
int z = 0; z < num_pages; ++z) {
7685 unsigned char *dest_page = uncompressed_image._image.p() + z * uncompressed_image._page_size;
7686 unsigned char *dest_page_end = dest_page + uncompressed_image._page_size;
7687 unsigned const char *source_page = cdata->_ram_images[n]._image.p() + z * page_size;
7689 unsigned const char *s = source_page;
7690 for (
int y = 0; y < y_size; y += 4) {
7691 for (
int x = 0; x < x_size; x += 4) {
7692 unsigned char tb[16 * 4];
7693 squish::Decompress(tb, s, squish_flags);
7696 unsigned char *t = tb;
7697 for (
int i = 0; i < 16; ++i) {
7700 unsigned char *d = dest_page + (yi * x_size + xi) * cdata->_num_components;
7701 if (d < dest_page_end) {
7702 switch (cdata->_num_components) {
7732 uncompressed_ram_images.push_back(uncompressed_image);
7734 cdata->_ram_images.swap(uncompressed_ram_images);
7735 cdata->_ram_image_compression = CM_off;
7738 #else // HAVE_SQUISH
7741 #endif // HAVE_SQUISH
7764 bool has_rawdata =
false;
7765 do_write_datagram_header(cdata, manager, me, has_rawdata);
7766 do_write_datagram_body(cdata, manager, me);
7771 do_write_datagram_rawdata(cdata, manager, me);
7817 do_write_datagram_header(CData *cdata,
BamWriter *manager,
Datagram &me,
bool &has_rawdata) {
7827 has_rawdata = (file_texture_mode == BamWriter::BTM_rawdata ||
7828 (cdata->_filename.empty() && do_has_bam_rawdata(cdata)));
7829 if (has_rawdata && !do_has_bam_rawdata(cdata)) {
7830 do_get_bam_rawdata(cdata);
7831 if (!do_has_bam_rawdata(cdata)) {
7833 has_rawdata =
false;
7839 Filename filename = cdata->_filename;
7840 Filename alpha_filename = cdata->_alpha_filename;
7844 switch (file_texture_mode) {
7845 case BamWriter::BTM_unchanged:
7846 case BamWriter::BTM_rawdata:
7849 case BamWriter::BTM_fullpath:
7850 filename = cdata->_fullpath;
7851 alpha_filename = cdata->_alpha_fullpath;
7854 case BamWriter::BTM_relative:
7855 filename = cdata->_fullpath;
7856 alpha_filename = cdata->_alpha_fullpath;
7861 if (gobj_cat.is_debug()) {
7863 <<
"Texture file " << cdata->_fullpath
7864 <<
" found as " << filename <<
"\n";
7869 if (gobj_cat.is_debug()) {
7871 <<
"Alpha image " << cdata->_alpha_fullpath
7872 <<
" found as " << alpha_filename <<
"\n";
7876 case BamWriter::BTM_basename:
7878 alpha_filename = cdata->_alpha_fullpath.
get_basename();
7883 <<
"Unsupported bam-texture-mode: " << (int)file_texture_mode <<
"\n";
7886 if (filename.empty() && do_has_bam_rawdata(cdata)) {
7894 me.
add_uint8(cdata->_primary_file_num_channels);
7895 me.
add_uint8(cdata->_alpha_file_channel);
7898 me.
add_bool(cdata->_has_read_mipmaps);
7910 cdata->_default_sampler.write_datagram(me);
7918 me.
add_uint8(cdata->_auto_texture_scale);
7926 if (has_simple_ram_image) {
7929 me.
add_int32(cdata->_simple_image_date_generated);
7930 me.
add_uint32(cdata->_simple_ram_image._image.size());
7931 me.
append_data(cdata->_simple_ram_image._image, cdata->_simple_ram_image._image.size());
7954 me.
add_uint8(cdata->_ram_image_compression);
7955 me.
add_uint8(cdata->_ram_images.size());
7956 for (
size_t n = 0; n < cdata->_ram_images.size(); ++n) {
7957 me.
add_uint32(cdata->_ram_images[n]._page_size);
7958 me.
add_uint32(cdata->_ram_images[n]._image.size());
7959 me.
append_data(cdata->_ram_images[n]._image, cdata->_ram_images[n]._image.size());
7970 PT(Texture) dummy = new Texture;
7971 return dummy->make_this_from_bam(params);
7995 parse_params(params, scan, manager);
8003 int primary_file_num_channels = scan.
get_uint8();
8004 int alpha_file_channel = scan.
get_uint8();
8005 bool has_rawdata = scan.
get_bool();
8006 TextureType texture_type = (TextureType)scan.
get_uint8();
8011 if (texture_type == TT_2d_texture_array) {
8012 texture_type = TT_cube_map;
8015 bool has_read_mipmaps =
false;
8017 has_read_mipmaps = scan.
get_bool();
8028 CDWriter cdata_me(me->_cycler,
true);
8029 cdata_me->_filename = filename;
8030 cdata_me->_alpha_filename = alpha_filename;
8031 cdata_me->_primary_file_num_channels = primary_file_num_channels;
8032 cdata_me->_alpha_file_channel = alpha_file_channel;
8033 cdata_me->_texture_type = texture_type;
8034 cdata_me->_has_read_mipmaps = has_read_mipmaps;
8037 me->do_fillin_body(cdata_me, scan, manager);
8038 me->do_fillin_rawdata(cdata_me, scan, manager);
8050 Texture *dummy =
this;
8051 AutoTextureScale auto_texture_scale = ATS_unspecified;
8053 CDWriter cdata_dummy(dummy->_cycler,
true);
8054 dummy->do_fillin_body(cdata_dummy, scan, manager);
8055 auto_texture_scale = cdata_dummy->_auto_texture_scale;
8058 if (filename.empty()) {
8062 <<
"Cannot create texture '" << name <<
"' with no filename.\n";
8072 if (!alpha_filename.empty()) {
8079 options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_generate_mipmaps);
8083 switch (texture_type) {
8086 if (alpha_filename.empty()) {
8088 has_read_mipmaps, options);
8091 primary_file_num_channels,
8093 has_read_mipmaps, options);
8101 case TT_2d_texture_array:
8111 if (me != (Texture *)NULL) {
8113 CDWriter cdata_me(me->_cycler,
true);
8114 me->do_fillin_from(cdata_me, dummy);
8133 cdata->_default_sampler.read_datagram(scan, manager);
8136 cdata->_compression = (CompressionMode)scan.
get_uint8();
8139 cdata->_quality_level = (QualityLevel)scan.
get_uint8();
8142 cdata->_format = (Format)scan.
get_uint8();
8143 cdata->_num_components = scan.
get_uint8();
8145 if ((
int)cdata->_texture_type == 5) {
8150 <<
"Buffer textures are not supported in this version of Panda3D.\n";
8153 cdata->inc_properties_modified();
8155 cdata->_auto_texture_scale = ATS_unspecified;
8157 cdata->_auto_texture_scale = (AutoTextureScale)scan.
get_uint8();
8160 bool has_simple_ram_image =
false;
8162 cdata->_orig_file_x_size = scan.
get_uint32();
8163 cdata->_orig_file_y_size = scan.
get_uint32();
8165 has_simple_ram_image = scan.
get_bool();
8168 if (has_simple_ram_image) {
8171 cdata->_simple_image_date_generated = scan.
get_int32();
8174 PTA_uchar image = PTA_uchar::empty_array(u_size, get_class_type());
8177 cdata->_simple_ram_image._image = image;
8178 cdata->_simple_ram_image._page_size = u_size;
8179 cdata->inc_simple_image_modified();
8200 do_set_pad_size(cdata, 0, 0, 0);
8203 cdata->_num_views = 1;
8207 cdata->_component_type = (ComponentType)scan.
get_uint8();
8208 cdata->_component_width = scan.
get_uint8();
8209 cdata->_ram_image_compression = CM_off;
8211 cdata->_ram_image_compression = (CompressionMode)scan.
get_uint8();
8214 int num_ram_images = 1;
8219 cdata->_ram_images.clear();
8220 cdata->_ram_images.reserve(num_ram_images);
8221 for (
int n = 0; n < num_ram_images; ++n) {
8222 cdata->_ram_images.push_back(RamImage());
8225 cdata->_ram_images[n]._page_size = scan.
get_uint32();
8230 PTA_uchar image = PTA_uchar::empty_array(u_size, get_class_type());
8233 cdata->_ram_images[n]._image = image;
8235 cdata->_loaded_from_image =
true;
8236 cdata->inc_image_modified();
8248 do_fillin_from(CData *cdata,
const Texture *dummy) {
8256 CDReader cdata_dummy(dummy->_cycler);
8258 do_set_wrap_u(cdata, cdata_dummy->_default_sampler.get_wrap_u());
8259 do_set_wrap_v(cdata, cdata_dummy->_default_sampler.get_wrap_v());
8260 do_set_wrap_w(cdata, cdata_dummy->_default_sampler.get_wrap_w());
8261 do_set_border_color(cdata, cdata_dummy->_default_sampler.get_border_color());
8263 if (cdata_dummy->_default_sampler.get_minfilter() != SamplerState::FT_default) {
8264 do_set_minfilter(cdata, cdata_dummy->_default_sampler.get_minfilter());
8266 if (cdata_dummy->_default_sampler.get_magfilter() != SamplerState::FT_default) {
8267 do_set_magfilter(cdata, cdata_dummy->_default_sampler.get_magfilter());
8269 if (cdata_dummy->_default_sampler.get_anisotropic_degree() != 0) {
8270 do_set_anisotropic_degree(cdata, cdata_dummy->_default_sampler.get_anisotropic_degree());
8272 if (cdata_dummy->_compression != CM_default) {
8273 do_set_compression(cdata, cdata_dummy->_compression);
8275 if (cdata_dummy->_quality_level != QL_default) {
8276 do_set_quality_level(cdata, cdata_dummy->_quality_level);
8279 Format format = cdata_dummy->_format;
8280 int num_components = cdata_dummy->_num_components;
8282 if (num_components == cdata->_num_components) {
8287 do_set_format(cdata, format);
8290 if (!cdata_dummy->_simple_ram_image._image.empty()) {
8293 if (cdata->_simple_ram_image._image.empty() ||
8294 cdata_dummy->_simple_image_date_generated > cdata->_simple_image_date_generated) {
8295 do_set_simple_ram_image(cdata,
8296 cdata_dummy->_simple_ram_image._image,
8297 cdata_dummy->_simple_x_size,
8298 cdata_dummy->_simple_y_size);
8299 cdata->_simple_image_date_generated = cdata_dummy->_simple_image_date_generated;
8311 _primary_file_num_channels = 0;
8312 _alpha_file_channel = 0;
8313 _keep_ram_image =
true;
8314 _compression = CM_default;
8315 _auto_texture_scale = ATS_unspecified;
8316 _ram_image_compression = CM_off;
8317 _render_to_texture =
false;
8318 _match_framebuffer_format =
false;
8319 _post_load_store_cache =
false;
8320 _quality_level = QL_default;
8322 _texture_type = TT_2d_texture;
8337 _orig_file_x_size = 0;
8338 _orig_file_y_size = 0;
8340 _loaded_from_image =
false;
8341 _loaded_from_txo =
false;
8342 _has_read_pages =
false;
8343 _has_read_mipmaps =
false;
8344 _num_mipmap_levels_read = 0;
8348 _simple_ram_image._page_size = 0;
8350 _has_clear_color =
false;
8359 CData(
const Texture::CData ©) {
8360 _num_mipmap_levels_read = 0;
8364 _properties_modified = copy._properties_modified;
8365 _image_modified = copy._image_modified;
8366 _simple_image_modified = copy._simple_image_modified;
8376 return new CData(*
this);
8384 void Texture::CData::
8385 do_assign(
const Texture::CData *copy) {
8386 _filename = copy->_filename;
8387 _alpha_filename = copy->_alpha_filename;
8388 if (!copy->_fullpath.empty()) {
8391 _fullpath = copy->_fullpath;
8392 _alpha_fullpath = copy->_alpha_fullpath;
8394 _primary_file_num_channels = copy->_primary_file_num_channels;
8395 _alpha_file_channel = copy->_alpha_file_channel;
8396 _x_size = copy->_x_size;
8397 _y_size = copy->_y_size;
8398 _z_size = copy->_z_size;
8399 _num_views = copy->_num_views;
8400 _pad_x_size = copy->_pad_x_size;
8401 _pad_y_size = copy->_pad_y_size;
8402 _pad_z_size = copy->_pad_z_size;
8403 _orig_file_x_size = copy->_orig_file_x_size;
8404 _orig_file_y_size = copy->_orig_file_y_size;
8405 _num_components = copy->_num_components;
8406 _component_width = copy->_component_width;
8407 _texture_type = copy->_texture_type;
8408 _format = copy->_format;
8409 _component_type = copy->_component_type;
8410 _loaded_from_image = copy->_loaded_from_image;
8411 _loaded_from_txo = copy->_loaded_from_txo;
8412 _has_read_pages = copy->_has_read_pages;
8413 _has_read_mipmaps = copy->_has_read_mipmaps;
8414 _num_mipmap_levels_read = copy->_num_mipmap_levels_read;
8415 _default_sampler = copy->_default_sampler;
8416 _keep_ram_image = copy->_keep_ram_image;
8417 _compression = copy->_compression;
8418 _match_framebuffer_format = copy->_match_framebuffer_format;
8419 _quality_level = copy->_quality_level;
8420 _auto_texture_scale = copy->_auto_texture_scale;
8421 _ram_image_compression = copy->_ram_image_compression;
8422 _ram_images = copy->_ram_images;
8423 _simple_x_size = copy->_simple_x_size;
8424 _simple_y_size = copy->_simple_y_size;
8425 _simple_ram_image = copy->_simple_ram_image;
8434 void Texture::CData::
8445 int Texture::CData::
8457 void Texture::CData::
8466 operator << (ostream &out, Texture::TextureType tt) {
8475 operator << (ostream &out, Texture::ComponentType ct) {
8484 operator << (ostream &out, Texture::Format f) {
8493 operator << (ostream &out, Texture::CompressionMode cm) {
8502 operator << (ostream &out, Texture::QualityLevel tql) {
8511 operator >> (istream &in, Texture::QualityLevel &tql) {
void set_data(TypedWritable *ptr, ReferenceCount *ref_ptr)
Stores a new data object on the record.
virtual bool has_cull_callback() const
Should be overridden by derived classes to return true if cull_callback() has been defined...
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. ...
static string format_quality_level(QualityLevel tql)
Returns the indicated QualityLevel converted to a string word.
Texture * load_related(const InternalName *suffix) const
Loads a texture whose filename is derived by concatenating a suffix to the filename of this texture...
bool is_texture_queued(const Texture *tex) const
Returns true if the texture has been queued on this GSG, false otherwise.
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...
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 write(const Filename &filename, PNMFileType *type=NULL) const
Writes the image to the indicated 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. ...
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...
bool is_valid() const
Returns true if the image has been read in or correctly initialized with a height and width...
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...
void release_texture(TextureContext *tc)
Indicates that a texture context, created by a previous call to prepare_texture(), is no longer needed.
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...
const Filename & get_filename() const
If a BAM is a file, then the BamReader should contain the name of the file.
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...
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...
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 ...
bool store(PNMImage &pnmimage) const
Copies the data to the indicated PNMImage, converting to RGB values.
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.
int release_all()
Frees the context allocated on all objects for which the texture has been declared.
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.
bool get_resident() const
Returns the resident flag associated with this object.
static Format string_format(const string &str)
Returns the Format corresponding to the indicated string word.
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-...
PN_float32 get_channel(int x, int y, int c) const
Returns the cth channel of the point value at the indicated point.
xelval get_blue_val(int x, int y) const
Returns the blue component color at the indicated pixel.
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.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
bool write_header(const string &header)
Writes a sequence of bytes to the beginning of the datagram file.
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...
float get_gray(int x, int y) const
Returns the gray component color at the indicated pixel.
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 ...
TypedReferenceCount * get_aux_data(const string &key) const
Returns a record previously recorded via set_aux_data().
bool read_txo(istream &in, const string &filename="")
Reads the texture from a Panda texture object.
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
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 ...
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...
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const
Returns true if the texture has already been prepared or enqueued for preparation on the indicated GS...
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
string get_dirname() const
Returns the directory part of the filename.
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.
AutoTextureScale get_auto_texture_scale() const
See set_auto_texture_scale().
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...
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 get_active(PreparedGraphicsObjects *prepared_objects) const
Returns true if this Texture was rendered in the most recent frame within the indicated GSG...
float get_alpha(int x, int y) const
Returns the alpha component color at the indicated pixel.
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
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().
const LoaderOptions & get_loader_options() const
Returns the LoaderOptions passed to the loader when the model was requested, if any.
string get_string()
Extracts a variable-length string.
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...
bool uses_mipmaps() const
Returns true if the minfilter settings on this texture indicate the use of mipmapping, false otherwise.
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.
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.
bool has_data() const
Returns true if this cache record has an in-memory data object associated–that is, the object stored in the cache.
static QualityLevel string_quality_level(const string &str)
Returns the QualityLevel value associated with the given string representation.
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().
bool release(PreparedGraphicsObjects *prepared_objects)
Frees the texture context only on the indicated object, if it exists there.
xelval get_green_val(int x, int y) const
Returns the green component color at the indicated pixel.
bool has_hash() const
Returns true if the filename is indicated to be a filename pattern (that is, set_pattern(true) was ca...
void consider_rescale(PNMImage &pnmimage)
Asks the PNMImage to change its scale when it reads the image, according to the whims of the Config...
Filename get_cwd() const
Returns the current directory name.
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.
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...
bool get_cache_textures() const
Returns whether texture files (e.g.
void add_bool(bool value)
Adds a boolean value to the datagram.
A base class for all things which can have a name.
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_texture_num_views() const
See set_texture_num_views().
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 ...
The name of a file, such as a texture file or an Egg file.
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.
virtual bool unref() const
Explicitly decrements the reference count.
size_t get_data_size_bytes() const
Returns the number of bytes previously reported for the data object.
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.
void set_blue(int x, int y, float b)
Sets the blue component color only at the indicated pixel.
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...
int get_num_unique_values() const
Returns the number of unique values in the variable.
virtual bool is_cacheable() const
Returns true if there is enough information in this Texture object to write it to the bam cache succe...
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...
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...
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.
CPTA_uchar get_ram_mipmap_image(int n) const
Returns the system-RAM image data associated with the nth mipmap level, if present.
bool resolve_filename(Filename &filename, const DSearchPath &searchpath, const string &default_extension=string()) const
Searches the given search path for the filename.
xelval get_channel_val(int x, int y, int channel) const
Returns the nth component color at the indicated pixel.
bool read_dds(istream &in, const string &filename="", bool header_only=false)
Reads the texture from a DDS file object.
const CycleDataType * read(Thread *current_thread) const
See PipelineCyclerBase::read().
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...
bool has_compression() const
Returns true if the texture indicates it wants to be compressed, either with CM_on or higher...
bool get_cache_compressed_textures() const
Returns whether compressed texture files will be stored in the cache, as compressed txo files...
This is an abstract base class that defines the interface for reading image files of various types...
bool has_simple_ram_image() const
Returns true if the Texture has a "simple" image available in main RAM.
PointerToArray< Element > cast_non_const() const
Casts away the constness of the CPTA(Element), and returns an equivalent PTA(Element).
ColorSpace get_color_space() const
Returns the color space in which the image is encoded.
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.
const Filename & get_filename() const
If a BAM is a file, then the BamWriter should contain the name of the file.
xelval get_alpha_val(int x, int y) const
Returns the alpha component color at the indicated pixel.
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...
void add_alpha()
Adds an alpha channel to the image, if it does not already have one.
bool exists(const Filename &filename) const
Convenience function; returns true if the named file exists.
string get_basename_wo_extension() const
Returns the basename part of the filename, without the file extension.
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).
string get_basename() const
Returns the basename part of the filename.
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.
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...
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 was_image_modified() const
Returns true if the texture image has been modified since the last time mark_loaded() was called...
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.
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.
BamTextureMode get_file_texture_mode() const
Returns the BamTextureMode preference indicated by the Bam file currently being written.
bool has_ram_image() const
Returns true if the Texture has its image contents available in main RAM, false if it exists only in ...
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.
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 ...
void ref() const
Explicitly increments the reference count.
bool write_txo(ostream &out, const string &filename="") const
Writes the texture to a Panda texture object.
string get_unique_value(int n) const
Returns the nth unique value of the variable.
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...
bool get_active() const
Returns the active flag associated with this object.
void add_int32(PN_int32 value)
Adds a signed 32-bit integer to the datagram.
xelval get_red_val(int x, int y) const
Returns the red component color at the indicated pixel.
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 ...
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...
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
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.
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.
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_read_size(int x_size, int y_size)
Specifies the size to we'd like to scale the image upon reading it.
int get_ref_count() const
Returns the current reference count.
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.
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.
int get_y_size() const
Returns the height of the texture image in texels.
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.
bool get_resident(PreparedGraphicsObjects *prepared_objects) const
Returns true if this Texture is reported to be resident within graphics memory for the indicated GSG...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling...
int get_x_size() const
Returns the width of the texture image in texels.
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.
LVecBase3f xform_point(const LVecBase3f &v) const
The matrix transforms a 3-component point (including translation component) and returns the result...
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...
int get_word(int n) const
Returns the variable's nth value.
xelval get_gray_val(int x, int y) const
Returns the gray component color at the indicated pixel.
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...
static const LVecBase4f & zero()
Returns a zero-length vector.
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.
static int size()
Returns 3: the number of components of a LVecBase3.
size_t estimate_texture_memory() const
Estimates the amount of texture memory that will be consumed by loading this texture.