61 (
"texture-quality-level", Texture::QL_normal,
62 PRC_DESC(
"This specifies a global quality level for all textures. You "
63 "may specify either fastest, normal, or best. This actually "
64 "affects the meaning of Texture::set_quality_level(QL_default), "
65 "so it may be overridden on a per-texture basis. This generally "
66 "only has an effect when using the tinydisplay software renderer; "
67 "it has little or no effect on normal, hardware-accelerated "
68 "renderers. See Texture::set_quality_level()."));
70 PStatCollector Texture::_texture_read_pcollector(
"*:Texture:Read");
73 AutoTextureScale Texture::_textures_power_2 = ATS_unspecified;
78 #define DDS_MAGIC 0x20534444
82 #define DDSD_CAPS 0x00000001
83 #define DDSD_HEIGHT 0x00000002
84 #define DDSD_WIDTH 0x00000004
85 #define DDSD_PITCH 0x00000008
86 #define DDSD_PIXELFORMAT 0x00001000
87 #define DDSD_MIPMAPCOUNT 0x00020000
88 #define DDSD_LINEARSIZE 0x00080000
89 #define DDSD_DEPTH 0x00800000
92 #define DDPF_ALPHAPIXELS 0x00000001
93 #define DDPF_FOURCC 0x00000004
94 #define DDPF_INDEXED 0x00000020
95 #define DDPF_RGB 0x00000040
98 #define DDSCAPS_COMPLEX 0x00000008
99 #define DDSCAPS_TEXTURE 0x00001000
100 #define DDSCAPS_MIPMAP 0x00400000
103 #define DDSCAPS2_CUBEMAP 0x00000200
104 #define DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400
105 #define DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800
106 #define DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000
107 #define DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000
108 #define DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000
109 #define DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000
110 #define DDSCAPS2_VOLUME 0x00200000
112 struct DDSPixelFormat {
113 unsigned int pf_size;
114 unsigned int pf_flags;
115 unsigned int four_cc;
116 unsigned int rgb_bitcount;
130 unsigned int dds_magic;
131 unsigned int dds_size;
132 unsigned int dds_flags;
137 unsigned int num_levels;
146 KTX_UNSIGNED_BYTE = 0x1401,
148 KTX_UNSIGNED_SHORT = 0x1403,
150 KTX_UNSIGNED_INT = 0x1405,
152 KTX_HALF_FLOAT = 0x140B,
153 KTX_UNSIGNED_BYTE_3_3_2 = 0x8032,
154 KTX_UNSIGNED_SHORT_4_4_4_4 = 0x8033,
155 KTX_UNSIGNED_SHORT_5_5_5_1 = 0x8034,
156 KTX_UNSIGNED_INT_8_8_8_8 = 0x8035,
157 KTX_UNSIGNED_INT_10_10_10_2 = 0x8036,
158 KTX_UNSIGNED_BYTE_2_3_3_REV = 0x8362,
159 KTX_UNSIGNED_SHORT_5_6_5 = 0x8363,
160 KTX_UNSIGNED_SHORT_5_6_5_REV = 0x8364,
161 KTX_UNSIGNED_SHORT_4_4_4_4_REV = 0x8365,
162 KTX_UNSIGNED_SHORT_1_5_5_5_REV = 0x8366,
163 KTX_UNSIGNED_INT_8_8_8_8_REV = 0x8367,
164 KTX_UNSIGNED_INT_2_10_10_10_REV = 0x8368,
165 KTX_UNSIGNED_INT_24_8 = 0x84FA,
166 KTX_UNSIGNED_INT_10F_11F_11F_REV = 0x8C3B,
167 KTX_UNSIGNED_INT_5_9_9_9_REV = 0x8C3E,
168 KTX_FLOAT_32_UNSIGNED_INT_24_8_REV = 0x8DAD,
173 KTX_ALPHA12 = 0x803D,
174 KTX_ALPHA16 = 0x803E,
175 KTX_ALPHA16_SNORM = 0x9018,
178 KTX_ALPHA8_SNORM = 0x9014,
179 KTX_ALPHA_SNORM = 0x9010,
181 KTX_BGR_INTEGER = 0x8D9A,
183 KTX_BGRA_INTEGER = 0x8D9B,
185 KTX_BLUE_INTEGER = 0x8D96,
186 KTX_COLOR_INDEX = 0x1900,
187 KTX_DEPTH24_STENCIL8 = 0x88F0,
188 KTX_DEPTH32F_STENCIL8 = 0x8CAD,
189 KTX_DEPTH_COMPONENT = 0x1902,
190 KTX_DEPTH_COMPONENT16 = 0x81A5,
191 KTX_DEPTH_COMPONENT24 = 0x81A6,
192 KTX_DEPTH_COMPONENT32 = 0x81A7,
193 KTX_DEPTH_COMPONENT32F = 0x8CAC,
194 KTX_DEPTH_STENCIL = 0x84F9,
196 KTX_GREEN_INTEGER = 0x8D95,
197 KTX_INTENSITY = 0x8049,
198 KTX_INTENSITY12 = 0x804C,
199 KTX_INTENSITY16 = 0x804D,
200 KTX_INTENSITY16_SNORM = 0x901B,
201 KTX_INTENSITY4 = 0x804A,
202 KTX_INTENSITY8 = 0x804B,
203 KTX_INTENSITY8_SNORM = 0x9017,
204 KTX_INTENSITY_SNORM = 0x9013,
205 KTX_LUMINANCE = 0x1909,
206 KTX_LUMINANCE12 = 0x8041,
207 KTX_LUMINANCE12_ALPHA12 = 0x8047,
208 KTX_LUMINANCE12_ALPHA4 = 0x8046,
209 KTX_LUMINANCE16 = 0x8042,
210 KTX_LUMINANCE16_ALPHA16 = 0x8048,
211 KTX_LUMINANCE16_ALPHA16_SNORM = 0x901A,
212 KTX_LUMINANCE16_SNORM = 0x9019,
213 KTX_LUMINANCE4 = 0x803F,
214 KTX_LUMINANCE4_ALPHA4 = 0x8043,
215 KTX_LUMINANCE6_ALPHA2 = 0x8044,
216 KTX_LUMINANCE8 = 0x8040,
217 KTX_LUMINANCE8_ALPHA8 = 0x8045,
218 KTX_LUMINANCE8_ALPHA8_SNORM = 0x9016,
219 KTX_LUMINANCE8_SNORM = 0x9015,
220 KTX_LUMINANCE_ALPHA = 0x190A,
221 KTX_LUMINANCE_ALPHA_SNORM = 0x9012,
222 KTX_LUMINANCE_SNORM = 0x9011,
223 KTX_R11F_G11F_B10F = 0x8C3A,
225 KTX_R16_SNORM = 0x8F98,
232 KTX_R3_G3_B2 = 0x2A10,
234 KTX_R8_SNORM = 0x8F94,
238 KTX_RED_INTEGER = 0x8D94,
239 KTX_RED_SNORM = 0x8F90,
242 KTX_RG16_SNORM = 0x8F99,
250 KTX_RG8_SNORM = 0x8F95,
253 KTX_RG_INTEGER = 0x8228,
254 KTX_RG_SNORM = 0x8F91,
257 KTX_RGB10_A2 = 0x8059,
260 KTX_RGB16_SNORM = 0x8F9A,
263 KTX_RGB16UI = 0x8D77,
267 KTX_RGB32UI = 0x8D71,
270 KTX_RGB5_A1 = 0x8057,
272 KTX_RGB8_SNORM = 0x8F96,
275 KTX_RGB9_E5 = 0x8C3D,
276 KTX_RGB_INTEGER = 0x8D98,
277 KTX_RGB_SNORM = 0x8F92,
281 KTX_RGBA16_SNORM = 0x8F9B,
282 KTX_RGBA16F = 0x881A,
283 KTX_RGBA16I = 0x8D88,
284 KTX_RGBA16UI = 0x8D76,
286 KTX_RGBA32F = 0x8814,
287 KTX_RGBA32I = 0x8D82,
288 KTX_RGBA32UI = 0x8D70,
291 KTX_RGBA8_SNORM = 0x8F97,
293 KTX_RGBA8UI = 0x8D7C,
294 KTX_RGBA_INTEGER = 0x8D99,
295 KTX_RGBA_SNORM = 0x8F93,
296 KTX_SLUMINANCE = 0x8C46,
297 KTX_SLUMINANCE8 = 0x8C47,
298 KTX_SLUMINANCE8_ALPHA8 = 0x8C45,
299 KTX_SLUMINANCE_ALPHA = 0x8C44,
302 KTX_SRGB8_ALPHA8 = 0x8C43,
303 KTX_SRGB_ALPHA = 0x8C42,
304 KTX_STENCIL_INDEX = 0x1901,
305 KTX_STENCIL_INDEX1 = 0x8D46,
306 KTX_STENCIL_INDEX16 = 0x8D49,
307 KTX_STENCIL_INDEX4 = 0x8D47,
308 KTX_STENCIL_INDEX8 = 0x8D48,
311 enum KTXCompressedFormat {
312 KTX_COMPRESSED_LUMINANCE_ALPHA_LATC2 = 0x8C72,
313 KTX_COMPRESSED_LUMINANCE_LATC1 = 0x8C70,
314 KTX_COMPRESSED_R11_EAC = 0x9270,
315 KTX_COMPRESSED_RED = 0x8225,
316 KTX_COMPRESSED_RED_RGTC1 = 0x8DBB,
317 KTX_COMPRESSED_RG = 0x8226,
318 KTX_COMPRESSED_RG11_EAC = 0x9272,
319 KTX_COMPRESSED_RG_RGTC2 = 0x8DBD,
320 KTX_COMPRESSED_RGB = 0x84ED,
321 KTX_COMPRESSED_RGB8_ETC2 = 0x9274,
322 KTX_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9276,
323 KTX_COMPRESSED_RGB_BPTC_SIGNED_FLOAT = 0x8E8E,
324 KTX_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT = 0x8E8F,
325 KTX_COMPRESSED_RGB_FXT1_3DFX = 0x86B0,
326 KTX_COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01,
327 KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00,
328 KTX_COMPRESSED_RGB_S3TC_DXT1 = 0x83F0,
329 KTX_COMPRESSED_RGBA = 0x84EE,
330 KTX_COMPRESSED_RGBA8_ETC2_EAC = 0x9278,
331 KTX_COMPRESSED_RGBA_BPTC_UNORM = 0x8E8C,
332 KTX_COMPRESSED_RGBA_FXT1_3DFX = 0x86B1,
333 KTX_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03,
334 KTX_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG = 0x9137,
335 KTX_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02,
336 KTX_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG = 0x9138,
337 KTX_COMPRESSED_RGBA_S3TC_DXT1 = 0x83F1,
338 KTX_COMPRESSED_RGBA_S3TC_DXT3 = 0x83F2,
339 KTX_COMPRESSED_RGBA_S3TC_DXT5 = 0x83F3,
340 KTX_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2 = 0x8C73,
341 KTX_COMPRESSED_SIGNED_LUMINANCE_LATC1 = 0x8C71,
342 KTX_COMPRESSED_SIGNED_R11_EAC = 0x9271,
343 KTX_COMPRESSED_SIGNED_RED_RGTC1 = 0x8DBC,
344 KTX_COMPRESSED_SIGNED_RG11_EAC = 0x9273,
345 KTX_COMPRESSED_SIGNED_RG_RGTC2 = 0x8DBE,
346 KTX_COMPRESSED_SLUMINANCE = 0x8C4A,
347 KTX_COMPRESSED_SLUMINANCE_ALPHA = 0x8C4B,
348 KTX_COMPRESSED_SRGB = 0x8C48,
349 KTX_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC = 0x9279,
350 KTX_COMPRESSED_SRGB8_ETC2 = 0x9275,
351 KTX_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9277,
352 KTX_COMPRESSED_SRGB_ALPHA = 0x8C49,
353 KTX_COMPRESSED_SRGB_ALPHA_BPTC_UNORM = 0x8E8D,
354 KTX_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1 = 0x8A56,
355 KTX_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2 = 0x93F0,
356 KTX_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1 = 0x8A57,
357 KTX_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2 = 0x93F1,
358 KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT1 = 0x8C4D,
359 KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT3 = 0x8C4E,
360 KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT5 = 0x8C4F,
361 KTX_COMPRESSED_SRGB_PVRTC_2BPPV1 = 0x8A54,
362 KTX_COMPRESSED_SRGB_PVRTC_4BPPV1 = 0x8A55,
363 KTX_COMPRESSED_SRGB_S3TC_DXT1 = 0x8C4C,
364 KTX_ETC1_RGB8 = 0x8D64,
365 KTX_ETC1_SRGB8 = 0x88EE,
382 do_set_format(cdata, F_rgb);
383 do_set_component_type(cdata, T_unsigned_byte);
392 _cycler(copy._cycler),
393 _lock(copy.get_name()),
403 operator = (
const Texture ©) {
404 Namable::operator = (copy);
405 _cycler = copy._cycler;
414 nassertv(!_reloading);
426 do_setup_texture(cdata, TT_cube_map, size, size, 6, T_unsigned_byte, F_rgb);
427 PTA_uchar image = do_make_ram_image(cdata);
428 cdata->_keep_ram_image =
true;
430 cdata->inc_image_modified();
431 cdata->inc_properties_modified();
433 PN_stdfloat half_size = (PN_stdfloat)size * 0.5f;
434 PN_stdfloat center = half_size - 0.5f;
437 (127.5f, 0.0f, 0.0f, 0.0f,
438 0.0f, 127.5f, 0.0f, 0.0f,
439 0.0f, 0.0f, 127.5f, 0.0f,
440 127.5f, 127.5f, 127.5f, 1.0f);
442 unsigned char *p = image;
446 for (yi = 0; yi < size; ++yi) {
447 for (xi = 0; xi < size; ++xi) {
448 LVector3 vec(half_size, center - yi, center - xi);
450 vec = scale.xform_point(vec);
452 *p++ = (
unsigned char)vec[2];
453 *p++ = (
unsigned char)vec[1];
454 *p++ = (
unsigned char)vec[0];
459 for (yi = 0; yi < size; ++yi) {
460 for (xi = 0; xi < size; ++xi) {
461 LVector3 vec(-half_size, center - yi, xi - center);
463 vec = scale.xform_point(vec);
464 *p++ = (
unsigned char)vec[2];
465 *p++ = (
unsigned char)vec[1];
466 *p++ = (
unsigned char)vec[0];
471 for (yi = 0; yi < size; ++yi) {
472 for (xi = 0; xi < size; ++xi) {
473 LVector3 vec(xi - center, half_size, yi - center);
475 vec = scale.xform_point(vec);
476 *p++ = (
unsigned char)vec[2];
477 *p++ = (
unsigned char)vec[1];
478 *p++ = (
unsigned char)vec[0];
483 for (yi = 0; yi < size; ++yi) {
484 for (xi = 0; xi < size; ++xi) {
485 LVector3 vec(xi - center, -half_size, center - yi);
487 vec = scale.xform_point(vec);
488 *p++ = (
unsigned char)vec[2];
489 *p++ = (
unsigned char)vec[1];
490 *p++ = (
unsigned char)vec[0];
495 for (yi = 0; yi < size; ++yi) {
496 for (xi = 0; xi < size; ++xi) {
497 LVector3 vec(xi - center, center - yi, half_size);
499 vec = scale.xform_point(vec);
500 *p++ = (
unsigned char)vec[2];
501 *p++ = (
unsigned char)vec[1];
502 *p++ = (
unsigned char)vec[0];
507 for (yi = 0; yi < size; ++yi) {
508 for (xi = 0; xi < size; ++xi) {
509 LVector3 vec(center - xi, center - yi, -half_size);
511 vec = scale.xform_point(vec);
512 *p++ = (
unsigned char)vec[2];
513 *p++ = (
unsigned char)vec[1];
514 *p++ = (
unsigned char)vec[0];
528 do_setup_texture(cdata, TT_1d_texture, 256, 1, 1, T_unsigned_byte, F_alpha);
529 cdata->_default_sampler.set_wrap_u(SamplerState::WM_clamp);
530 cdata->_default_sampler.set_minfilter(SamplerState::FT_nearest);
531 cdata->_default_sampler.set_magfilter(SamplerState::FT_nearest);
533 cdata->_compression = CM_off;
535 cdata->inc_image_modified();
536 cdata->inc_properties_modified();
538 PTA_uchar image = do_make_ram_image(cdata);
539 cdata->_keep_ram_image =
true;
541 unsigned char *p = image;
542 for (
int xi = 0; xi < 256; ++xi) {
554 cdata->inc_properties_modified();
555 cdata->inc_image_modified();
556 return do_read(cdata, fullpath,
Filename(), 0, 0, 0, 0,
false,
false,
569 int primary_file_num_channels,
int alpha_file_channel,
573 cdata->inc_properties_modified();
574 cdata->inc_image_modified();
575 return do_read(cdata, fullpath, alpha_fullpath, primary_file_num_channels,
576 alpha_file_channel, 0, 0,
false,
false,
589 bool read_pages,
bool read_mipmaps,
592 cdata->inc_properties_modified();
593 cdata->inc_image_modified();
594 return do_read(cdata, fullpath,
Filename(), 0, 0, z, n, read_pages, read_mipmaps,
652 int primary_file_num_channels,
int alpha_file_channel,
653 int z,
int n,
bool read_pages,
bool read_mipmaps,
657 cdata->inc_properties_modified();
658 cdata->inc_image_modified();
659 return do_read(cdata, fullpath, alpha_fullpath, primary_file_num_channels,
660 alpha_file_channel, z, n, read_pages, read_mipmaps,
677 size_t pixels = cdata->_x_size * cdata->_y_size * cdata->_z_size;
680 switch (cdata->_format) {
681 case Texture::F_rgb332:
685 case Texture::F_alpha:
687 case Texture::F_green:
688 case Texture::F_blue:
689 case Texture::F_luminance:
690 case Texture::F_sluminance:
695 case Texture::F_luminance_alpha:
696 case Texture::F_luminance_alphamask:
697 case Texture::F_sluminance_alpha:
698 case Texture::F_rgba4:
699 case Texture::F_rgb5:
700 case Texture::F_rgba5:
705 case Texture::F_rgba:
706 case Texture::F_rgbm:
708 case Texture::F_srgb:
714 case Texture::F_color_index:
715 case Texture::F_rgb8:
716 case Texture::F_rgba8:
717 case Texture::F_srgb_alpha:
718 case Texture::F_rgb8i:
719 case Texture::F_rgba8i:
723 case Texture::F_depth_stencil:
727 case Texture::F_depth_component:
728 case Texture::F_depth_component16:
732 case Texture::F_depth_component24:
733 case Texture::F_depth_component32:
737 case Texture::F_rgba12:
738 case Texture::F_rgb12:
742 case Texture::F_rgba16:
745 case Texture::F_rgba32:
750 case Texture::F_r16i:
751 case Texture::F_rg8i:
754 case Texture::F_rg16:
757 case Texture::F_rgb16:
761 case Texture::F_r32i:
766 case Texture::F_rg32:
770 case Texture::F_rgb32:
774 case Texture::F_r11_g11_b10:
775 case Texture::F_rgb9_e5:
776 case Texture::F_rgb10_a2:
781 gobj_cat.warning() <<
"Unhandled format in estimate_texture_memory(): "
782 << cdata->_format <<
"\n";
786 size_t bytes = pixels * bpp;
788 bytes = (bytes * 4) / 3;
804 _aux_data[key] = aux_data;
813 _aux_data.erase(key);
823 AuxData::const_iterator di;
824 di = _aux_data.find(key);
825 if (di != _aux_data.end()) {
840 read_txo(istream &in,
const string &filename) {
842 cdata->inc_properties_modified();
843 cdata->inc_image_modified();
844 return do_read_txo(cdata, in, filename);
855 make_from_txo(istream &in,
const string &filename) {
858 if (!din.
open(in, filename)) {
860 <<
"Could not read texture object: " << filename <<
"\n";
867 << filename <<
" is not a texture object file.\n";
871 if (head != _bam_header) {
873 << filename <<
" is not a texture object file.\n";
878 if (!reader.
init()) {
884 if (
object !=
nullptr &&
893 if (
object ==
nullptr) {
895 <<
"Texture object " << filename <<
" is empty.\n";
898 }
else if (!object->
is_of_type(Texture::get_class_type())) {
900 <<
"Texture object " << filename <<
" contains a "
901 <<
object->get_type() <<
", not a Texture.\n";
908 <<
"Unable to fully resolve texture object file.\n";
923 write_txo(ostream &out,
const string &filename)
const {
924 CDReader cdata(_cycler);
925 return do_write_txo(cdata, out, filename);
938 read_dds(istream &in,
const string &filename,
bool header_only) {
940 cdata->inc_properties_modified();
941 cdata->inc_image_modified();
942 return do_read_dds(cdata, in, filename, header_only);
955 read_ktx(istream &in,
const string &filename,
bool header_only) {
957 cdata->inc_properties_modified();
958 cdata->inc_image_modified();
959 return do_read_ktx(cdata, in, filename, header_only);
972 RelatedTextures::const_iterator ti;
973 ti = _related_textures.find(suffix);
974 if (ti != _related_textures.end()) {
977 if (cdata->_fullpath.empty()) {
981 main.set_basename_wo_extension(main.get_basename_wo_extension() +
984 if (!cdata->_alpha_fullpath.empty()) {
985 Filename alph = cdata->_alpha_fullpath;
993 cdata->_primary_file_num_channels,
994 cdata->_alpha_file_channel,
false);
1009 ((
Texture *)
this)->_related_textures.insert(RelatedTextures::value_type(suffix, res));
1023 string format =
upcase(supplied_format);
1026 int imgsize = cdata->_x_size * cdata->_y_size;
1027 nassertv(image.size() == (
size_t)(cdata->_component_width * format.size() * imgsize));
1030 if ((cdata->_num_components == 1 && format.size() == 1) ||
1031 (cdata->_num_components == 2 && format.size() == 2 && format.at(1) ==
'A' && format.at(0) !=
'A') ||
1032 (cdata->_num_components == 3 && format ==
"BGR") ||
1033 (cdata->_num_components == 4 && format ==
"BGRA")) {
1035 do_set_ram_image(cdata, image);
1040 PTA_uchar newdata = PTA_uchar::empty_array(imgsize * cdata->_num_components * cdata->_component_width, get_class_type());
1043 if (cdata->_component_width == 1) {
1044 if (format ==
"RGBA" && cdata->_num_components == 4) {
1046 for (
int p = 0; p < imgsize; p += 4) {
1047 newdata[p + 2] = image[p ];
1048 newdata[p + 1] = image[p + 1];
1049 newdata[p ] = image[p + 2];
1050 newdata[p + 3] = image[p + 3];
1052 do_set_ram_image(cdata, newdata);
1055 if (format ==
"RGB" && cdata->_num_components == 3) {
1057 for (
int p = 0; p < imgsize; p += 3) {
1058 newdata[p + 2] = image[p ];
1059 newdata[p + 1] = image[p + 1];
1060 newdata[p ] = image[p + 2];
1062 do_set_ram_image(cdata, newdata);
1065 if (format ==
"A" && cdata->_num_components != 3) {
1067 int component = cdata->_num_components - 1;
1068 for (
int p = 0; p < imgsize; ++p) {
1069 newdata[component] = image[p];
1071 do_set_ram_image(cdata, newdata);
1074 for (
int p = 0; p < imgsize; ++p) {
1075 for (uchar s = 0; s < format.size(); ++s) {
1076 signed char component = -1;
1077 if (format.at(s) ==
'B' || (cdata->_num_components <= 2 && format.at(s) !=
'A')) {
1079 }
else if (format.at(s) ==
'G') {
1081 }
else if (format.at(s) ==
'R') {
1083 }
else if (format.at(s) ==
'A') {
1084 if (cdata->_num_components != 3) {
1085 component = cdata->_num_components - 1;
1089 }
else if (format.at(s) ==
'0') {
1091 }
else if (format.at(s) ==
'1') {
1094 gobj_cat.error() <<
"Unexpected component character '"
1095 << format.at(s) <<
"', expected one of RGBA!\n";
1098 if (component >= 0) {
1099 newdata[p * cdata->_num_components + component] = image[p * format.size() + s];
1103 do_set_ram_image(cdata, newdata);
1106 for (
int p = 0; p < imgsize; ++p) {
1107 for (uchar s = 0; s < format.size(); ++s) {
1108 signed char component = -1;
1109 if (format.at(s) ==
'B' || (cdata->_num_components <= 2 && format.at(s) !=
'A')) {
1111 }
else if (format.at(s) ==
'G') {
1113 }
else if (format.at(s) ==
'R') {
1115 }
else if (format.at(s) ==
'A') {
1116 if (cdata->_num_components != 3) {
1117 component = cdata->_num_components - 1;
1121 }
else if (format.at(s) ==
'0') {
1123 }
else if (format.at(s) ==
'1') {
1126 gobj_cat.error() <<
"Unexpected component character '"
1127 << format.at(s) <<
"', expected one of RGBA!\n";
1130 if (component >= 0) {
1131 memcpy((
void*)(newdata + (p * cdata->_num_components + component) * cdata->_component_width),
1132 (
void*)(image + (p * format.size() + s) * cdata->_component_width),
1133 cdata->_component_width);
1137 do_set_ram_image(cdata, newdata);
1148 CDReader cdata(_cycler);
1149 return cdata->_keep_ram_image;
1159 CDReader cdata(_cycler);
1160 return do_has_bam_rawdata(cdata);
1177 CDReader cdata(_cycler);
1178 if (cdata->_ram_images.empty() || cdata->_ram_images[0]._image.empty()) {
1188 int size = max(cdata->_x_size, max(cdata->_y_size, cdata->_z_size));
1194 if (n >= (
int)cdata->_ram_images.size() || cdata->_ram_images[n]._image.empty()) {
1210 if (n < (
int)cdata->_ram_images.size() && !cdata->_ram_images[n]._image.empty()) {
1211 return cdata->_ram_images[n]._image;
1224 if (n < (
int)cdata->_ram_images.size()) {
1225 return cdata->_ram_images[n]._pointer_image;
1243 nassertv(cdata->_ram_image_compression != CM_off || do_get_expected_ram_mipmap_image_size(cdata, n));
1245 while (n >= (
int)cdata->_ram_images.size()) {
1246 cdata->_ram_images.push_back(RamImage());
1249 cdata->_ram_images[n]._page_size = page_size;
1251 cdata->_ram_images[n]._pointer_image = image;
1252 cdata->inc_image_modified();
1273 if (n >= (
int)cdata->_ram_images.size()) {
1276 cdata->_ram_images[n]._page_size = 0;
1277 cdata->_ram_images[n]._image.clear();
1278 cdata->_ram_images[n]._pointer_image =
nullptr;
1288 cdata->_simple_image_date_generated = (int32_t)time(
nullptr);
1289 return cdata->_simple_ram_image._image;
1299 nassertr(cdata->_texture_type == TT_2d_texture, PTA_uchar());
1300 size_t expected_page_size = (size_t)(x_size * y_size * 4);
1302 cdata->_simple_x_size = x_size;
1303 cdata->_simple_y_size = y_size;
1304 cdata->_simple_ram_image._image = PTA_uchar::empty_array(expected_page_size);
1305 cdata->_simple_ram_image._page_size = expected_page_size;
1306 cdata->_simple_image_date_generated = (int32_t)time(
nullptr);
1307 cdata->inc_simple_image_modified();
1309 return cdata->_simple_ram_image._image;
1321 if (cdata->_texture_type != TT_2d_texture ||
1322 cdata->_ram_image_compression != CM_off) {
1327 if (!do_store_one(cdata, pnmimage, 0, 0)) {
1332 int x_size = simple_image_size.
get_word(0);
1333 int y_size = simple_image_size.
get_word(1);
1354 did_anything =
false;
1358 int new_x_size = (x_size >> 1);
1359 PNMImage smaller(new_x_size, y_size, 4);
1361 PNMImage bigger(x_size, y_size, 4);
1364 if (compare_images(scaled, bigger)) {
1366 x_size = new_x_size;
1367 did_anything =
true;
1373 int new_y_size = (y_size >> 1);
1374 PNMImage smaller(x_size, new_y_size, 4);
1376 PNMImage bigger(x_size, y_size, 4);
1379 if (compare_images(scaled, bigger)) {
1381 y_size = new_y_size;
1382 did_anything =
true;
1385 }
while (did_anything);
1387 size_t expected_page_size = (size_t)(x_size * y_size * 4);
1388 PTA_uchar image = PTA_uchar::empty_array(expected_page_size, get_class_type());
1389 convert_from_pnmimage(image, expected_page_size, x_size, 0, 0, 0, scaled, 4, 1);
1391 do_set_simple_ram_image(cdata, image, x_size, y_size);
1392 cdata->_simple_image_date_generated = (int32_t)time(
nullptr);
1409 CDWriter cdata(_cycler, unlocked_ensure_ram_image(
true));
1412 if (peeker->is_valid()) {
1430 return prepared_objects->enqueue_texture_future(
this);
1440 PreparedViews::const_iterator pvi;
1441 pvi = _prepared_views.find(prepared_objects);
1442 if (pvi != _prepared_views.end()) {
1458 PreparedViews::const_iterator pvi;
1459 pvi = _prepared_views.find(prepared_objects);
1460 if (pvi != _prepared_views.end()) {
1461 const Contexts &contexts = (*pvi).second;
1462 for (
int view = 0; view < cdata->_num_views; ++view) {
1463 Contexts::const_iterator ci;
1464 ci = contexts.find(view);
1465 if (ci == contexts.end()) {
1490 PreparedViews::const_iterator pvi;
1491 size_t total_size = 0;
1492 pvi = _prepared_views.find(prepared_objects);
1493 if (pvi != _prepared_views.end()) {
1494 const Contexts &contexts = (*pvi).second;
1495 for (
int view = 0; view < cdata->_num_views; ++view) {
1496 Contexts::const_iterator ci;
1497 ci = contexts.find(view);
1498 if (ci != contexts.end()) {
1517 PreparedViews::const_iterator pvi;
1518 pvi = _prepared_views.find(prepared_objects);
1519 if (pvi != _prepared_views.end()) {
1520 const Contexts &contexts = (*pvi).second;
1521 for (
int view = 0; view < cdata->_num_views; ++view) {
1522 Contexts::const_iterator ci;
1523 ci = contexts.find(view);
1524 if (ci != contexts.end()) {
1544 PreparedViews::const_iterator pvi;
1545 pvi = _prepared_views.find(prepared_objects);
1546 if (pvi != _prepared_views.end()) {
1547 const Contexts &contexts = (*pvi).second;
1548 for (
int view = 0; view < cdata->_num_views; ++view) {
1549 Contexts::const_iterator ci;
1550 ci = contexts.find(view);
1551 if (ci != contexts.end()) {
1569 PreparedViews::iterator pvi;
1570 pvi = _prepared_views.find(prepared_objects);
1571 if (pvi != _prepared_views.end()) {
1573 temp.swap((*pvi).second);
1574 Contexts::iterator ci;
1575 for (ci = temp.begin(); ci != temp.end(); ++ci) {
1577 if (tc !=
nullptr) {
1581 _prepared_views.erase(pvi);
1601 temp.swap(_prepared_views);
1602 int num_freed = (int)temp.size();
1604 PreparedViews::iterator pvi;
1605 for (pvi = temp.begin(); pvi != temp.end(); ++pvi) {
1608 temp.swap((*pvi).second);
1609 Contexts::iterator ci;
1610 for (ci = temp.begin(); ci != temp.end(); ++ci) {
1612 if (tc !=
nullptr) {
1626 write(ostream &out,
int indent_level)
const {
1628 indent(out, indent_level)
1629 << cdata->_texture_type <<
" " << get_name();
1630 if (!cdata->_filename.empty()) {
1631 out <<
" (from " << cdata->_filename <<
")";
1635 indent(out, indent_level + 2);
1637 switch (cdata->_texture_type) {
1639 out <<
"1-d, " << cdata->_x_size;
1643 out <<
"2-d, " << cdata->_x_size <<
" x " << cdata->_y_size;
1647 out <<
"3-d, " << cdata->_x_size <<
" x " << cdata->_y_size <<
" x " << cdata->_z_size;
1650 case TT_2d_texture_array:
1651 out <<
"2-d array, " << cdata->_x_size <<
" x " << cdata->_y_size <<
" x " << cdata->_z_size;
1655 out <<
"cube map, " << cdata->_x_size <<
" x " << cdata->_y_size;
1658 case TT_cube_map_array:
1659 out <<
"cube map array, " << cdata->_x_size <<
" x " << cdata->_y_size <<
" x " << cdata->_z_size;
1662 case TT_buffer_texture:
1663 out <<
"buffer, " << cdata->_x_size;
1666 case TT_1d_texture_array:
1667 out <<
"1-d array, " << cdata->_x_size <<
" x " << cdata->_y_size;
1671 if (cdata->_num_views > 1) {
1672 out <<
" (x " << cdata->_num_views <<
" views)";
1675 out <<
" pixels, each " << cdata->_num_components;
1677 switch (cdata->_component_type) {
1678 case T_unsigned_byte:
1683 case T_unsigned_short:
1694 case T_unsigned_int_24_8:
1696 case T_unsigned_int:
1705 switch (cdata->_format) {
1707 out <<
"color_index";
1709 case F_depth_stencil:
1710 out <<
"depth_stencil";
1712 case F_depth_component:
1713 out <<
"depth_component";
1715 case F_depth_component16:
1716 out <<
"depth_component16";
1718 case F_depth_component24:
1719 out <<
"depth_component24";
1721 case F_depth_component32:
1722 out <<
"depth_component32";
1781 case F_luminance_alpha:
1782 out <<
"luminance_alpha";
1784 case F_luminance_alphamask:
1785 out <<
"luminance_alphamask";
1806 out <<
"srgb_alpha";
1809 out <<
"sluminance";
1811 case F_sluminance_alpha:
1812 out <<
"sluminance_alpha";
1842 out <<
"r11_g11_b10";
1856 if (cdata->_compression != CM_default) {
1857 out <<
", compression " << cdata->_compression;
1861 indent(out, indent_level + 2);
1863 cdata->_default_sampler.output(out);
1865 if (do_has_ram_image(cdata)) {
1866 indent(out, indent_level + 2)
1867 << do_get_ram_image_size(cdata) <<
" bytes in ram, compression "
1868 << cdata->_ram_image_compression <<
"\n";
1870 if (cdata->_ram_images.size() > 1) {
1872 size_t total_size = 0;
1873 for (
size_t n = 1; n < cdata->_ram_images.size(); ++n) {
1874 if (!cdata->_ram_images[n]._image.empty()) {
1876 total_size += cdata->_ram_images[n]._image.size();
1882 indent(out, indent_level + 2)
1884 <<
" mipmap levels also present in ram (" << total_size
1889 indent(out, indent_level + 2)
1890 <<
"no ram image\n";
1893 if (!cdata->_simple_ram_image._image.empty()) {
1894 indent(out, indent_level + 2)
1895 <<
"simple image: " << cdata->_simple_x_size <<
" x "
1896 << cdata->_simple_y_size <<
", "
1897 << cdata->_simple_ram_image._image.size() <<
" bytes\n";
1909 if (do_get_auto_texture_scale(cdata) != ATS_none) {
1913 if (cdata->_texture_type == TT_3d_texture) {
1918 do_set_z_size(cdata, z);
1921 do_set_x_size(cdata, x);
1922 do_set_y_size(cdata, y);
1923 do_set_z_size(cdata, z);
1925 do_set_pad_size(cdata,
1928 cdata->_z_size - z);
1938 cdata->_orig_file_x_size = x;
1939 cdata->_orig_file_y_size = y;
1941 nassertv(z == cdata->_z_size);
1963 view = max(min(view, cdata->_num_views - 1), 0);
1966 Contexts &contexts = _prepared_views[prepared_objects];
1967 Contexts::const_iterator pvi;
1968 pvi = contexts.find(view);
1969 if (pvi != contexts.end()) {
1970 return (*pvi).second;
1974 contexts[view] = tc;
2032 if (
adjust_size(new_x_size, new_y_size, name,
false, auto_texture_scale)) {
2055 return "1d_texture";
2057 return "2d_texture";
2059 return "3d_texture";
2060 case TT_2d_texture_array:
2061 return "2d_texture_array";
2064 case TT_cube_map_array:
2065 return "cube_map_array";
2066 case TT_buffer_texture:
2067 return "buffer_texture";
2068 case TT_1d_texture_array:
2069 return "1d_texture_array";
2071 return "**invalid**";
2079 if (cmp_nocase(str,
"1d_texture") == 0) {
2080 return TT_1d_texture;
2081 }
else if (cmp_nocase(str,
"2d_texture") == 0) {
2082 return TT_2d_texture;
2083 }
else if (cmp_nocase(str,
"3d_texture") == 0) {
2084 return TT_3d_texture;
2085 }
else if (cmp_nocase(str,
"2d_texture_array") == 0) {
2086 return TT_2d_texture_array;
2087 }
else if (cmp_nocase(str,
"cube_map") == 0) {
2089 }
else if (cmp_nocase(str,
"cube_map_array") == 0) {
2090 return TT_cube_map_array;
2091 }
else if (cmp_nocase(str,
"buffer_texture") == 0) {
2092 return TT_buffer_texture;
2096 <<
"Invalid Texture::TextureType value: " << str <<
"\n";
2097 return TT_2d_texture;
2106 case T_unsigned_byte:
2107 return "unsigned_byte";
2108 case T_unsigned_short:
2109 return "unsigned_short";
2112 case T_unsigned_int_24_8:
2113 return "unsigned_int_24_8";
2117 return "unsigned_byte";
2121 return "half_float";
2122 case T_unsigned_int:
2123 return "unsigned_int";
2126 return "**invalid**";
2134 if (cmp_nocase(str,
"unsigned_byte") == 0) {
2135 return T_unsigned_byte;
2136 }
else if (cmp_nocase(str,
"unsigned_short") == 0) {
2137 return T_unsigned_short;
2138 }
else if (cmp_nocase(str,
"float") == 0) {
2140 }
else if (cmp_nocase(str,
"unsigned_int_24_8") == 0) {
2141 return T_unsigned_int_24_8;
2142 }
else if (cmp_nocase(str,
"int") == 0) {
2144 }
else if (cmp_nocase(str,
"byte") == 0) {
2146 }
else if (cmp_nocase(str,
"short") == 0) {
2148 }
else if (cmp_nocase(str,
"half_float") == 0) {
2149 return T_half_float;
2150 }
else if (cmp_nocase(str,
"unsigned_int") == 0) {
2151 return T_unsigned_int;
2155 <<
"Invalid Texture::ComponentType value: " << str <<
"\n";
2156 return T_unsigned_byte;
2165 case F_depth_stencil:
2166 return "depth_stencil";
2167 case F_depth_component:
2168 return "depth_component";
2169 case F_depth_component16:
2170 return "depth_component16";
2171 case F_depth_component24:
2172 return "depth_component24";
2173 case F_depth_component32:
2174 return "depth_component32";
2176 return "color_index";
2209 case F_luminance_alpha:
2210 return "luminance_alpha";
2211 case F_luminance_alphamask:
2212 return "luminance_alphamask";
2228 return "srgb_alpha";
2230 return "sluminance";
2231 case F_sluminance_alpha:
2232 return "sluminance_alpha";
2258 return "**invalid**";
2266 if (cmp_nocase(str,
"depth_stencil") == 0) {
2267 return F_depth_stencil;
2268 }
else if (cmp_nocase(str,
"depth_component") == 0) {
2269 return F_depth_component;
2270 }
else if (cmp_nocase(str,
"depth_component16") == 0 || cmp_nocase(str,
"d16") == 0) {
2271 return F_depth_component16;
2272 }
else if (cmp_nocase(str,
"depth_component24") == 0 || cmp_nocase(str,
"d24") == 0) {
2273 return F_depth_component24;
2274 }
else if (cmp_nocase(str,
"depth_component32") == 0 || cmp_nocase(str,
"d32") == 0) {
2275 return F_depth_component32;
2276 }
else if (cmp_nocase(str,
"color_index") == 0) {
2277 return F_color_index;
2278 }
else if (cmp_nocase(str,
"red") == 0) {
2280 }
else if (cmp_nocase(str,
"green") == 0) {
2282 }
else if (cmp_nocase(str,
"blue") == 0) {
2284 }
else if (cmp_nocase(str,
"alpha") == 0) {
2286 }
else if (cmp_nocase(str,
"rgb") == 0) {
2288 }
else if (cmp_nocase(str,
"rgb5") == 0) {
2290 }
else if (cmp_nocase(str,
"rgb8") == 0 || cmp_nocase(str,
"r8g8b8") == 0) {
2292 }
else if (cmp_nocase(str,
"rgb12") == 0) {
2294 }
else if (cmp_nocase(str,
"rgb332") == 0 || cmp_nocase(str,
"r3g3b2") == 0) {
2296 }
else if (cmp_nocase(str,
"rgba") == 0) {
2298 }
else if (cmp_nocase(str,
"rgbm") == 0) {
2300 }
else if (cmp_nocase(str,
"rgba4") == 0) {
2302 }
else if (cmp_nocase(str,
"rgba5") == 0) {
2304 }
else if (cmp_nocase(str,
"rgba8") == 0 || cmp_nocase(str,
"r8g8b8a8") == 0) {
2306 }
else if (cmp_nocase(str,
"rgba12") == 0) {
2308 }
else if (cmp_nocase(str,
"luminance") == 0) {
2310 }
else if (cmp_nocase(str,
"luminance_alpha") == 0) {
2311 return F_luminance_alpha;
2312 }
else if (cmp_nocase(str,
"luminance_alphamask") == 0) {
2313 return F_luminance_alphamask;
2314 }
else if (cmp_nocase(str,
"rgba16") == 0 || cmp_nocase(str,
"r16g16b16a16") == 0) {
2316 }
else if (cmp_nocase(str,
"rgba32") == 0 || cmp_nocase(str,
"r32g32b32a32") == 0) {
2318 }
else if (cmp_nocase(str,
"r16") == 0 || cmp_nocase(str,
"red16") == 0) {
2320 }
else if (cmp_nocase(str,
"r16i") == 0) {
2322 }
else if (cmp_nocase(str,
"rg16") == 0 || cmp_nocase(str,
"r16g16") == 0) {
2324 }
else if (cmp_nocase(str,
"rgb16") == 0 || cmp_nocase(str,
"r16g16b16") == 0) {
2326 }
else if (cmp_nocase(str,
"srgb") == 0) {
2328 }
else if (cmp_nocase(str,
"srgb_alpha") == 0) {
2329 return F_srgb_alpha;
2330 }
else if (cmp_nocase(str,
"sluminance") == 0) {
2331 return F_sluminance;
2332 }
else if (cmp_nocase(str,
"sluminance_alpha") == 0) {
2333 return F_sluminance_alpha;
2334 }
else if (cmp_nocase(str,
"r32i") == 0) {
2336 }
else if (cmp_nocase(str,
"r32") == 0 || cmp_nocase(str,
"red32") == 0) {
2338 }
else if (cmp_nocase(str,
"rg32") == 0 || cmp_nocase(str,
"r32g32") == 0) {
2340 }
else if (cmp_nocase(str,
"rgb32") == 0 || cmp_nocase(str,
"r32g32b32") == 0) {
2342 }
else if (cmp_nocase(str,
"r11g11b10") == 0) {
2343 return F_r11_g11_b10;
2344 }
else if (cmp_nocase(str,
"rgb9_e5") == 0) {
2346 }
else if (cmp_nocase_uh(str,
"rgb10_a2") == 0 || cmp_nocase(str,
"r10g10b10a2") == 0) {
2348 }
else if (cmp_nocase_uh(str,
"rg") == 0) {
2353 <<
"Invalid Texture::Format value: " << str <<
"\n";
2395 return "**invalid**";
2404 if (cmp_nocase_uh(str,
"default") == 0) {
2406 }
else if (cmp_nocase_uh(str,
"off") == 0) {
2408 }
else if (cmp_nocase_uh(str,
"on") == 0) {
2410 }
else if (cmp_nocase_uh(str,
"fxt1") == 0) {
2412 }
else if (cmp_nocase_uh(str,
"dxt1") == 0) {
2414 }
else if (cmp_nocase_uh(str,
"dxt2") == 0) {
2416 }
else if (cmp_nocase_uh(str,
"dxt3") == 0) {
2418 }
else if (cmp_nocase_uh(str,
"dxt4") == 0) {
2420 }
else if (cmp_nocase_uh(str,
"dxt5") == 0) {
2422 }
else if (cmp_nocase_uh(str,
"pvr1_2bpp") == 0) {
2423 return CM_pvr1_2bpp;
2424 }
else if (cmp_nocase_uh(str,
"pvr1_4bpp") == 0) {
2425 return CM_pvr1_4bpp;
2426 }
else if (cmp_nocase_uh(str,
"rgtc") == 0) {
2428 }
else if (cmp_nocase_uh(str,
"etc1") == 0) {
2430 }
else if (cmp_nocase_uh(str,
"etc2") == 0) {
2432 }
else if (cmp_nocase_uh(str,
"eac") == 0) {
2437 <<
"Invalid Texture::CompressionMode value: " << str <<
"\n";
2458 return "**invalid**";
2467 if (cmp_nocase(str,
"default") == 0) {
2469 }
else if (cmp_nocase(str,
"fastest") == 0) {
2471 }
else if (cmp_nocase(str,
"normal") == 0) {
2473 }
else if (cmp_nocase(str,
"best") == 0) {
2478 <<
"Invalid Texture::QualityLevel value: " << str <<
"\n";
2495 if (!keep_texture_ram && !cdata->_keep_ram_image) {
2500 CDWriter cdataw(_cycler, cdata,
false);
2501 if (gobj_cat.is_debug()) {
2503 <<
"Dumping RAM for texture " << get_name() <<
"\n";
2505 do_clear_ram_image(cdataw);
2546 return (ctype == T_unsigned_byte ||
2547 ctype == T_unsigned_short ||
2548 ctype == T_unsigned_int_24_8 ||
2549 ctype == T_unsigned_int);
2557 is_specific(Texture::CompressionMode compression) {
2558 switch (compression) {
2584 case F_luminance_alpha:
2585 case F_luminance_alphamask:
2587 case F_sluminance_alpha:
2622 case F_sluminance_alpha:
2640 adjust_size(
int &x_size,
int &y_size,
const string &name,
2641 bool for_padding, AutoTextureScale auto_texture_scale) {
2642 bool exclude =
false;
2644 for (
int i = 0; i < num_excludes && !exclude; ++i) {
2651 int new_x_size = x_size;
2652 int new_y_size = y_size;
2655 new_x_size = (int)cfloor(new_x_size * texture_scale + 0.5);
2656 new_y_size = (int)cfloor(new_y_size * texture_scale + 0.5);
2660 new_x_size = min(max(new_x_size, (
int)texture_scale_limit), x_size);
2661 new_y_size = min(max(new_y_size, (
int)texture_scale_limit), y_size);
2664 AutoTextureScale ats = auto_texture_scale;
2665 if (ats == ATS_unspecified) {
2668 if (!for_padding && ats == ATS_pad) {
2688 case ATS_unspecified:
2692 ats = textures_square.get_value();
2693 if (!for_padding && ats == ATS_pad) {
2698 new_x_size = new_y_size = min(new_x_size, new_y_size);
2703 new_x_size = new_y_size = max(new_x_size, new_y_size);
2707 case ATS_unspecified:
2712 int max_dimension = max_texture_dimension;
2714 if (max_dimension < 0) {
2716 if (gsg !=
nullptr) {
2717 max_dimension = gsg->get_max_texture_dimension();
2721 if (max_dimension > 0) {
2722 new_x_size = min(new_x_size, (
int)max_dimension);
2723 new_y_size = min(new_y_size, (
int)max_dimension);
2727 if (x_size != new_x_size || y_size != new_y_size) {
2728 x_size = new_x_size;
2729 y_size = new_y_size;
2759 reconsider_dirty() {
2768 do_adjust_this_size(
const CData *cdata,
int &x_size,
int &y_size,
const string &name,
2769 bool for_padding)
const {
2770 return adjust_size(x_size, y_size, name, for_padding, cdata->_auto_texture_scale);
2777 do_read(CData *cdata,
const Filename &fullpath,
const Filename &alpha_fullpath,
2778 int primary_file_num_channels,
int alpha_file_channel,
2779 int z,
int n,
bool read_pages,
bool read_mipmaps,
2787 bool header_only = ((options.get_texture_flags() & (LoaderOptions::TF_preload | LoaderOptions::TF_preload_simple)) == 0);
2788 if (record !=
nullptr) {
2789 header_only =
false;
2792 if ((z == 0 || read_pages) && (n == 0 || read_mipmaps)) {
2795 do_clear_ram_image(cdata);
2798 if (is_txo_filename(fullpath)) {
2799 if (record !=
nullptr) {
2802 return do_read_txo_file(cdata, fullpath);
2805 if (is_dds_filename(fullpath)) {
2806 if (record !=
nullptr) {
2809 return do_read_dds_file(cdata, fullpath, header_only);
2812 if (is_ktx_filename(fullpath)) {
2813 if (record !=
nullptr) {
2816 return do_read_ktx_file(cdata, fullpath, header_only);
2828 switch (cdata->_texture_type) {
2831 case TT_buffer_texture:
2845 if (options.get_texture_flags() & LoaderOptions::TF_multiview) {
2850 do_set_num_views(cdata, num_views);
2856 if (read_pages && read_mipmaps) {
2860 do_set_z_size(cdata, z_size);
2868 z_size = do_get_expected_mipmap_z_size(cdata, n);
2878 <<
"Filename requires two different hash sequences: " << fullpath
2886 if ((n_size == 0 && (vfs->
exists(file) || n == 0)) ||
2887 (n_size != 0 && n < n_size)) {
2894 int num_pages = z_size * num_views;
2895 while ((num_pages == 0 && (vfs->
exists(file) || z == 0)) ||
2896 (num_pages != 0 && z < num_pages)) {
2897 if (!do_read_one(cdata, file, alpha_file, z, n, primary_file_num_channels,
2898 alpha_file_channel, options, header_only, record)) {
2908 if (n == 0 && n_size == 0) {
2911 n_size = do_get_expected_num_mipmap_levels(cdata);
2915 cdata->_fullpath = fullpath_pattern;
2916 cdata->_alpha_fullpath = alpha_fullpath_pattern;
2918 }
else if (read_pages) {
2922 if (!fullpath_pattern.
has_hash()) {
2924 <<
"Filename requires a hash mark: " << fullpath
2929 do_set_z_size(cdata, z_size);
2934 int num_pages = z_size * num_views;
2935 while ((num_pages == 0 && (vfs->
exists(file) || z == 0)) ||
2936 (num_pages != 0 && z < num_pages)) {
2937 if (!do_read_one(cdata, file, alpha_file, z, 0, primary_file_num_channels,
2938 alpha_file_channel, options, header_only, record)) {
2946 cdata->_fullpath = fullpath_pattern;
2947 cdata->_alpha_fullpath = alpha_fullpath_pattern;
2949 }
else if (read_mipmaps) {
2953 if (!fullpath_pattern.
has_hash()) {
2955 <<
"Filename requires a hash mark: " << fullpath
2964 while ((n_size == 0 && (vfs->
exists(file) || n == 0)) ||
2965 (n_size != 0 && n < n_size)) {
2966 if (!do_read_one(cdata, file, alpha_file, z, n,
2967 primary_file_num_channels, alpha_file_channel,
2968 options, header_only, record)) {
2973 if (n_size == 0 && n >= do_get_expected_num_mipmap_levels(cdata)) {
2982 cdata->_fullpath = fullpath_pattern;
2983 cdata->_alpha_fullpath = alpha_fullpath_pattern;
2987 if (!do_read_one(cdata, fullpath, alpha_fullpath, z, n,
2988 primary_file_num_channels, alpha_file_channel,
2989 options, header_only, record)) {
2994 cdata->_has_read_pages = read_pages;
2995 cdata->_has_read_mipmaps = read_mipmaps;
2996 cdata->_num_mipmap_levels_read = cdata->_ram_images.size();
3001 do_clear_ram_image(cdata);
3003 if ((options.get_texture_flags() & LoaderOptions::TF_preload) != 0) {
3006 bool generate_mipmaps = ((options.get_texture_flags() & LoaderOptions::TF_generate_mipmaps) != 0);
3007 bool allow_compression = ((options.get_texture_flags() & LoaderOptions::TF_allow_compression) != 0);
3008 do_consider_auto_process_ram_image(cdata, generate_mipmaps ||
uses_mipmaps(), allow_compression);
3020 do_read_one(CData *cdata,
const Filename &fullpath,
const Filename &alpha_fullpath,
3021 int z,
int n,
int primary_file_num_channels,
int alpha_file_channel,
3023 if (record !=
nullptr) {
3024 nassertr(!header_only,
false);
3031 if (image_reader ==
nullptr) {
3033 <<
"Texture::read() - couldn't read: " << fullpath << endl;
3038 AutoTextureScale auto_texture_scale = do_get_auto_texture_scale(cdata);
3042 bool read_floating_point;
3043 int texture_load_type = (options.get_texture_flags() & (LoaderOptions::TF_integer | LoaderOptions::TF_float));
3044 switch (texture_load_type) {
3045 case LoaderOptions::TF_integer:
3046 read_floating_point =
false;
3049 case LoaderOptions::TF_float:
3050 read_floating_point =
true;
3057 if (!alpha_fullpath.empty()) {
3058 read_floating_point =
false;
3062 if (header_only || textures_header_only) {
3065 if (z == 0 && n == 0) {
3066 cdata->_orig_file_x_size = x_size;
3067 cdata->_orig_file_y_size = y_size;
3070 if (textures_header_only) {
3080 if (read_floating_point) {
3086 image.
fill(0.2, 0.3, 1.0);
3091 delete image_reader;
3094 if (z == 0 && n == 0) {
3098 cdata->_orig_file_x_size = x_size;
3099 cdata->_orig_file_y_size = y_size;
3105 image.
set_read_size(do_get_expected_mipmap_x_size(cdata, n),
3106 do_get_expected_mipmap_y_size(cdata, n));
3112 <<
"Implicitly rescaling " << fullpath.
get_basename() <<
" from "
3119 if (read_floating_point) {
3120 success = pfm.
read(image_reader);
3122 success = image.
read(image_reader);
3127 <<
"Texture::read() - couldn't read: " << fullpath << endl;
3134 if (!alpha_fullpath.empty()) {
3136 if (alpha_image_reader ==
nullptr) {
3138 <<
"Texture::read() - couldn't read: " << alpha_fullpath << endl;
3143 if (record !=
nullptr) {
3147 if (header_only || textures_header_only) {
3153 alpha_image.
fill(1.0);
3157 delete alpha_image_reader;
3163 <<
"Implicitly rescaling " << alpha_fullpath.
get_basename()
3164 <<
" from " << alpha_image.
get_x_size() <<
" by "
3170 if (!alpha_image.
read(alpha_image_reader)) {
3172 <<
"Texture::read() - couldn't read (alpha): " << alpha_fullpath << endl;
3179 if (z == 0 && n == 0) {
3183 if (cdata->_filename.empty()) {
3184 cdata->_filename = fullpath;
3185 cdata->_alpha_filename = alpha_fullpath;
3190 cdata->_keep_ram_image =
false;
3193 cdata->_fullpath = fullpath;
3194 cdata->_alpha_fullpath = alpha_fullpath;
3197 if (!alpha_fullpath.empty()) {
3203 <<
"Automatically rescaling " << alpha_fullpath.
get_basename()
3204 <<
" from " << alpha_image.
get_x_size() <<
" by "
3212 scaled.quick_filter_from(alpha_image);
3214 alpha_image = scaled;
3219 consider_downgrade(image, primary_file_num_channels, get_name());
3221 cdata->_alpha_file_channel = 0;
3224 if (!alpha_fullpath.empty()) {
3229 if (alpha_file_channel == 4 ||
3234 << alpha_fullpath.
get_basename() <<
" has no channel " << alpha_file_channel <<
".\n";
3237 for (
int x = 0; x < image.
get_x_size(); x++) {
3238 for (
int y = 0; y < image.
get_y_size(); y++) {
3245 }
else if (alpha_file_channel >= 1 && alpha_file_channel <= 3 &&
3248 for (
int x = 0; x < image.
get_x_size(); x++) {
3249 for (
int y = 0; y < image.
get_y_size(); y++) {
3253 cdata->_alpha_file_channel = alpha_file_channel;
3257 for (
int x = 0; x < image.
get_x_size(); x++) {
3258 for (
int y = 0; y < image.
get_y_size(); y++) {
3262 cdata->_alpha_file_channel = 0;
3266 if (read_floating_point) {
3267 if (!do_load_one(cdata, pfm, fullpath.
get_basename(), z, n, options)) {
3274 if (do_get_auto_texture_scale(cdata) == ATS_pad) {
3277 if (do_adjust_this_size(cdata, new_x_size, new_y_size, fullpath.
get_basename(),
true)) {
3278 pad_x_size = new_x_size - image.
get_x_size();
3279 pad_y_size = new_y_size - image.
get_y_size();
3283 new_image.copy_sub_image(image, 0, new_y_size - image.
get_y_size());
3288 if (!do_load_one(cdata, image, fullpath.
get_basename(), z, n, options)) {
3292 do_set_pad_size(cdata, pad_x_size, pad_y_size, 0);
3301 do_load_one(CData *cdata,
const PNMImage &pnmimage,
const string &name,
int z,
int n,
3303 if (cdata->_ram_images.size() <= 1 && n == 0) {
3307 if (!do_reconsider_z_size(cdata, z, options)) {
3310 nassertr(z >= 0 && z < cdata->_z_size * cdata->_num_views,
false);
3313 ComponentType component_type = T_unsigned_byte;
3316 component_type = T_unsigned_short;
3326 do_modify_ram_image(cdata);
3327 cdata->_loaded_from_image =
true;
3330 do_modify_ram_mipmap_image(cdata, n);
3333 int x_size = do_get_expected_mipmap_x_size(cdata, n);
3334 int y_size = do_get_expected_mipmap_y_size(cdata, n);
3338 <<
"Automatically rescaling " << name;
3340 gobj_cat.info(
false)
3341 <<
" mipmap level " << n;
3343 gobj_cat.info(
false)
3344 <<
" from " << pnmimage.
get_x_size() <<
" by "
3345 << pnmimage.
get_y_size() <<
" to " << x_size <<
" by "
3351 scaled.quick_filter_from(pnmimage);
3354 convert_from_pnmimage(cdata->_ram_images[n]._image,
3355 do_get_expected_ram_mipmap_page_size(cdata, n),
3356 x_size, 0, 0, z, scaled,
3357 cdata->_num_components, cdata->_component_width);
3361 convert_from_pnmimage(cdata->_ram_images[n]._image,
3362 do_get_expected_ram_mipmap_page_size(cdata, n),
3363 x_size, 0, 0, z, pnmimage,
3364 cdata->_num_components, cdata->_component_width);
3375 do_load_one(CData *cdata,
const PfmFile &pfm,
const string &name,
int z,
int n,
3377 if (cdata->_ram_images.size() <= 1 && n == 0) {
3381 if (!do_reconsider_z_size(cdata, z, options)) {
3384 nassertr(z >= 0 && z < cdata->_z_size * cdata->_num_views,
false);
3387 ComponentType component_type = T_float;
3395 do_modify_ram_image(cdata);
3396 cdata->_loaded_from_image =
true;
3399 do_modify_ram_mipmap_image(cdata, n);
3402 int x_size = do_get_expected_mipmap_x_size(cdata, n);
3403 int y_size = do_get_expected_mipmap_y_size(cdata, n);
3407 <<
"Automatically rescaling " << name;
3409 gobj_cat.info(
false)
3410 <<
" mipmap level " << n;
3412 gobj_cat.info(
false)
3414 << pfm.
get_y_size() <<
" to " << x_size <<
" by "
3418 scaled.resize(x_size, y_size);
3421 convert_from_pfm(cdata->_ram_images[n]._image,
3422 do_get_expected_ram_mipmap_page_size(cdata, n), z,
3423 scaled, cdata->_num_components, cdata->_component_width);
3427 convert_from_pfm(cdata->_ram_images[n]._image,
3428 do_get_expected_ram_mipmap_page_size(cdata, n), z,
3429 pfm, cdata->_num_components, cdata->_component_width);
3441 do_load_sub_image(CData *cdata,
const PNMImage &image,
int x,
int y,
int z,
int n) {
3442 nassertr(n >= 0 && (
size_t)n < cdata->_ram_images.size(),
false);
3444 int tex_x_size = do_get_expected_mipmap_x_size(cdata, n);
3445 int tex_y_size = do_get_expected_mipmap_y_size(cdata, n);
3446 int tex_z_size = do_get_expected_mipmap_z_size(cdata, n);
3448 nassertr(x >= 0 && x < tex_x_size,
false);
3449 nassertr(y >= 0 && y < tex_y_size,
false);
3450 nassertr(z >= 0 && z < tex_z_size,
false);
3452 nassertr(image.
get_x_size() + x <= tex_x_size,
false);
3453 nassertr(image.
get_y_size() + y <= tex_y_size,
false);
3456 y = cdata->_y_size - (image.
get_y_size() + y);
3458 cdata->inc_image_modified();
3459 do_modify_ram_mipmap_image(cdata, n);
3460 convert_from_pnmimage(cdata->_ram_images[n]._image,
3461 do_get_expected_ram_mipmap_page_size(cdata, n),
3462 tex_x_size, x, y, z, image,
3463 cdata->_num_components, cdata->_component_width);
3473 do_read_txo_file(CData *cdata,
const Filename &fullpath) {
3476 Filename filename = Filename::binary_filename(fullpath);
3478 if (file ==
nullptr) {
3481 <<
"Could not find " << fullpath <<
"\n";
3485 if (gobj_cat.is_debug()) {
3487 <<
"Reading texture object " << filename <<
"\n";
3490 istream *in = file->open_read_file(
true);
3491 bool success = do_read_txo(cdata, *in, fullpath);
3494 cdata->_fullpath = fullpath;
3495 cdata->_alpha_fullpath =
Filename();
3496 cdata->_keep_ram_image =
false;
3505 do_read_txo(CData *cdata, istream &in,
const string &filename) {
3506 PT(
Texture) other = make_from_txo(in, filename);
3507 if (other ==
nullptr) {
3511 CDReader cdata_other(other->_cycler);
3512 Namable::operator = (*other);
3513 do_assign(cdata, other, cdata_other);
3515 cdata->_loaded_from_image =
true;
3516 cdata->_loaded_from_txo =
true;
3517 cdata->_has_read_pages =
false;
3518 cdata->_has_read_mipmaps =
false;
3519 cdata->_num_mipmap_levels_read = 0;
3528 do_read_dds_file(CData *cdata,
const Filename &fullpath,
bool header_only) {
3531 Filename filename = Filename::binary_filename(fullpath);
3533 if (file ==
nullptr) {
3536 <<
"Could not find " << fullpath <<
"\n";
3540 if (gobj_cat.is_debug()) {
3542 <<
"Reading DDS file " << filename <<
"\n";
3545 istream *in = file->open_read_file(
true);
3546 bool success = do_read_dds(cdata, *in, fullpath, header_only);
3553 cdata->_fullpath = fullpath;
3554 cdata->_alpha_fullpath =
Filename();
3555 cdata->_keep_ram_image =
false;
3564 do_read_dds(CData *cdata, istream &in,
const string &filename,
bool header_only) {
3569 header.dds_magic = dds.get_uint32();
3570 header.dds_size = dds.get_uint32();
3571 header.dds_flags = dds.get_uint32();
3572 header.height = dds.get_uint32();
3573 header.width = dds.get_uint32();
3574 header.pitch = dds.get_uint32();
3575 header.depth = dds.get_uint32();
3576 header.num_levels = dds.get_uint32();
3580 header.pf.pf_size = dds.get_uint32();
3581 header.pf.pf_flags = dds.get_uint32();
3582 header.pf.four_cc = dds.get_uint32();
3583 header.pf.rgb_bitcount = dds.get_uint32();
3584 header.pf.r_mask = dds.get_uint32();
3585 header.pf.g_mask = dds.get_uint32();
3586 header.pf.b_mask = dds.get_uint32();
3587 header.pf.a_mask = dds.get_uint32();
3590 header.caps.caps1 = dds.get_uint32();
3591 header.caps.caps2 = dds.get_uint32();
3592 header.caps.ddsx = dds.get_uint32();
3598 if (header.dds_magic != DDS_MAGIC || (in.fail() || in.eof())) {
3600 << filename <<
" is not a DDS file.\n";
3604 if ((header.dds_flags & DDSD_MIPMAPCOUNT) == 0) {
3606 header.num_levels = 1;
3608 }
else if (header.num_levels == 0) {
3611 header.num_levels = 1;
3614 TextureType texture_type;
3615 if (header.caps.caps2 & DDSCAPS2_CUBEMAP) {
3616 static const unsigned int all_faces =
3617 (DDSCAPS2_CUBEMAP_POSITIVEX |
3618 DDSCAPS2_CUBEMAP_POSITIVEY |
3619 DDSCAPS2_CUBEMAP_POSITIVEZ |
3620 DDSCAPS2_CUBEMAP_NEGATIVEX |
3621 DDSCAPS2_CUBEMAP_NEGATIVEY |
3622 DDSCAPS2_CUBEMAP_NEGATIVEZ);
3623 if ((header.caps.caps2 & all_faces) != all_faces) {
3625 << filename <<
" is missing some cube map faces; cannot load.\n";
3629 texture_type = TT_cube_map;
3631 }
else if (header.caps.caps2 & DDSCAPS2_VOLUME) {
3632 texture_type = TT_3d_texture;
3635 texture_type = TT_2d_texture;
3640 typedef PTA_uchar (*ReadDDSLevelFunc)(
Texture *tex, Texture::CData *cdata,
3641 const DDSHeader &header,
int n, istream &in);
3642 ReadDDSLevelFunc func =
nullptr;
3644 Format format = F_rgb;
3645 ComponentType component_type = T_unsigned_byte;
3647 do_clear_ram_image(cdata);
3648 CompressionMode compression = CM_off;
3650 if ((header.pf.pf_flags & DDPF_FOURCC) != 0 &&
3651 header.pf.four_cc == 0x30315844) {
3653 func = read_dds_level_generic_uncompressed;
3654 unsigned int dxgi_format = dds.get_uint32();
3655 unsigned int dimension = dds.get_uint32();
3656 unsigned int misc_flag = dds.get_uint32();
3657 unsigned int array_size = dds.get_uint32();
3660 switch (dxgi_format) {
3663 component_type = T_float;
3664 func = read_dds_level_abgr32;
3668 component_type = T_half_float;
3669 func = read_dds_level_abgr16;
3673 component_type = T_unsigned_short;
3674 func = read_dds_level_abgr16;
3678 component_type = T_float;
3679 func = read_dds_level_raw;
3684 func = read_dds_level_abgr8;
3687 format = F_srgb_alpha;
3688 func = read_dds_level_abgr8;
3692 func = read_dds_level_abgr8;
3696 component_type = T_byte;
3697 func = read_dds_level_abgr8;
3701 component_type = T_byte;
3702 func = read_dds_level_abgr8;
3706 component_type = T_half_float;
3707 func = read_dds_level_raw;
3711 component_type = T_unsigned_short;
3712 func = read_dds_level_raw;
3716 component_type = T_short;
3717 func = read_dds_level_raw;
3720 format = F_depth_component32;
3721 component_type = T_float;
3722 func = read_dds_level_raw;
3726 component_type = T_float;
3727 func = read_dds_level_raw;
3731 component_type = T_unsigned_int;
3732 func = read_dds_level_raw;
3736 component_type = T_int;
3737 func = read_dds_level_raw;
3748 component_type = T_byte;
3752 component_type = T_byte;
3756 component_type = T_half_float;
3757 func = read_dds_level_raw;
3760 format = F_depth_component16;
3761 component_type = T_unsigned_short;
3762 func = read_dds_level_raw;
3766 component_type = T_unsigned_short;
3767 func = read_dds_level_raw;
3771 component_type = T_unsigned_short;
3772 func = read_dds_level_raw;
3776 component_type = T_short;
3777 func = read_dds_level_raw;
3781 component_type = T_short;
3782 func = read_dds_level_raw;
3793 component_type = T_byte;
3797 component_type = T_byte;
3805 compression = CM_dxt1;
3806 func = read_dds_level_bc1;
3810 compression = CM_dxt1;
3811 func = read_dds_level_bc1;
3816 compression = CM_dxt3;
3817 func = read_dds_level_bc2;
3820 format = F_srgb_alpha;
3821 compression = CM_dxt3;
3822 func = read_dds_level_bc2;
3827 compression = CM_dxt5;
3828 func = read_dds_level_bc3;
3831 format = F_srgb_alpha;
3832 compression = CM_dxt5;
3833 func = read_dds_level_bc3;
3838 compression = CM_rgtc;
3839 func = read_dds_level_bc4;
3844 compression = CM_rgtc;
3845 func = read_dds_level_bc5;
3856 format = F_srgb_alpha;
3866 << filename <<
": unsupported DXGI format " << dxgi_format <<
".\n";
3870 switch (dimension) {
3872 texture_type = TT_1d_texture;
3876 if (misc_flag & 0x4) {
3877 if (array_size > 1) {
3878 texture_type = TT_cube_map_array;
3879 header.depth = array_size * 6;
3881 texture_type = TT_cube_map;
3885 if (array_size > 1) {
3886 texture_type = TT_2d_texture_array;
3887 header.depth = array_size;
3889 texture_type = TT_2d_texture;
3895 texture_type = TT_3d_texture;
3899 << filename <<
": unsupported dimension.\n";
3903 }
else if (header.pf.pf_flags & DDPF_FOURCC) {
3905 if (texture_type == TT_3d_texture) {
3907 << filename <<
": unsupported compression on 3-d texture.\n";
3913 switch (header.pf.four_cc) {
3915 compression = CM_dxt1;
3916 func = read_dds_level_bc1;
3920 compression = CM_dxt2;
3921 func = read_dds_level_bc2;
3924 compression = CM_dxt3;
3925 func = read_dds_level_bc2;
3928 compression = CM_dxt4;
3929 func = read_dds_level_bc3;
3932 compression = CM_dxt5;
3933 func = read_dds_level_bc3;
3937 compression = CM_rgtc;
3938 func = read_dds_level_bc4;
3943 compression = CM_rgtc;
3944 func = read_dds_level_bc5;
3948 func = read_dds_level_abgr16;
3950 component_type = T_unsigned_short;
3953 func = read_dds_level_abgr16;
3955 component_type = T_short;
3958 func = read_dds_level_abgr16;
3960 component_type = T_half_float;
3963 func = read_dds_level_abgr32;
3965 component_type = T_float;
3969 << filename <<
": unsupported texture compression (FourCC: 0x"
3970 << std::hex << header.pf.four_cc << std::dec <<
").\n";
3976 func = read_dds_level_generic_uncompressed;
3978 if (header.pf.pf_flags & DDPF_ALPHAPIXELS) {
3981 if (header.pf.rgb_bitcount == 32 &&
3982 header.pf.r_mask == 0x000000ff &&
3983 header.pf.g_mask == 0x0000ff00 &&
3984 header.pf.b_mask == 0x00ff0000 &&
3985 header.pf.a_mask == 0xff000000U) {
3986 func = read_dds_level_abgr8;
3987 }
else if (header.pf.rgb_bitcount == 32 &&
3988 header.pf.r_mask == 0x00ff0000 &&
3989 header.pf.g_mask == 0x0000ff00 &&
3990 header.pf.b_mask == 0x000000ff &&
3991 header.pf.a_mask == 0xff000000U) {
3992 func = read_dds_level_rgba8;
3994 }
else if (header.pf.r_mask != 0 &&
3995 header.pf.g_mask == 0 &&
3996 header.pf.b_mask == 0) {
3997 func = read_dds_level_luminance_uncompressed;
3998 format = F_luminance_alpha;
4002 if (header.pf.rgb_bitcount == 24 &&
4003 header.pf.r_mask == 0x00ff0000 &&
4004 header.pf.g_mask == 0x0000ff00 &&
4005 header.pf.b_mask == 0x000000ff) {
4006 func = read_dds_level_bgr8;
4007 }
else if (header.pf.rgb_bitcount == 24 &&
4008 header.pf.r_mask == 0x000000ff &&
4009 header.pf.g_mask == 0x0000ff00 &&
4010 header.pf.b_mask == 0x00ff0000) {
4011 func = read_dds_level_rgb8;
4013 }
else if (header.pf.r_mask != 0 &&
4014 header.pf.g_mask == 0 &&
4015 header.pf.b_mask == 0) {
4016 func = read_dds_level_luminance_uncompressed;
4017 format = F_luminance;
4022 do_setup_texture(cdata, texture_type, header.width, header.height, header.depth,
4023 component_type, format);
4025 cdata->_orig_file_x_size = cdata->_x_size;
4026 cdata->_orig_file_y_size = cdata->_y_size;
4027 cdata->_compression = compression;
4028 cdata->_ram_image_compression = compression;
4031 switch (texture_type) {
4036 for (
int n = 0; n < (int)header.num_levels; ++n) {
4037 int z_size = do_get_expected_mipmap_z_size(cdata, n);
4039 size_t page_size = 0;
4041 for (z = 0; z < z_size; ++z) {
4042 PTA_uchar page = func(
this, cdata, header, n, in);
4043 if (page.is_null()) {
4046 nassertr(page_size == 0 || page_size == page.size(),
false);
4047 page_size = page.size();
4048 pages.push_back(page);
4053 PTA_uchar image = PTA_uchar::empty_array(page_size * z_size);
4054 unsigned char *imagep = (
unsigned char *)image.p();
4055 for (z = 0; z < z_size; ++z) {
4056 int fz = z_size - 1 - z;
4057 memcpy(imagep + z * page_size, pages[fz].p(), page_size);
4060 do_set_ram_mipmap_image(cdata, n, image, page_size);
4072 for (z = 0; z < 6; ++z) {
4075 levels.reserve(header.num_levels);
4077 for (n = 0; n < (int)header.num_levels; ++n) {
4078 PTA_uchar image = func(
this, cdata, header, n, in);
4079 if (image.is_null()) {
4082 levels.push_back(image);
4089 static const int level_remap[6] = {
4092 for (n = 0; n < (int)header.num_levels; ++n) {
4093 size_t page_size = pages[0][n].size();
4094 PTA_uchar image = PTA_uchar::empty_array(page_size * 6);
4095 unsigned char *imagep = (
unsigned char *)image.p();
4096 for (z = 0; z < 6; ++z) {
4097 int fz = level_remap[z];
4098 nassertr(pages[fz][n].size() == page_size,
false);
4099 memcpy(imagep + z * page_size, pages[fz][n].p(), page_size);
4102 do_set_ram_mipmap_image(cdata, n, image, page_size);
4107 case TT_2d_texture_array:
4108 case TT_cube_map_array:
4113 pages.reserve(header.depth);
4115 for (z = 0; z < (int)header.depth; ++z) {
4118 levels.reserve(header.num_levels);
4120 for (n = 0; n < (int)header.num_levels; ++n) {
4121 PTA_uchar image = func(
this, cdata, header, n, in);
4122 if (image.is_null()) {
4125 levels.push_back(image);
4130 for (n = 0; n < (int)header.num_levels; ++n) {
4131 size_t page_size = pages[0][n].size();
4132 PTA_uchar image = PTA_uchar::empty_array(page_size * header.depth);
4133 unsigned char *imagep = (
unsigned char *)image.p();
4134 for (z = 0; z < (int)header.depth; ++z) {
4135 nassertr(pages[z][n].size() == page_size,
false);
4136 memcpy(imagep + z * page_size, pages[z][n].p(), page_size);
4139 do_set_ram_mipmap_image(cdata, n, image, page_size);
4147 for (
int n = 0; n < (int)header.num_levels; ++n) {
4148 PTA_uchar image = func(
this, cdata, header, n, in);
4149 if (image.is_null()) {
4152 do_set_ram_mipmap_image(cdata, n, image, 0);
4156 cdata->_has_read_pages =
true;
4157 cdata->_has_read_mipmaps =
true;
4158 cdata->_num_mipmap_levels_read = cdata->_ram_images.size();
4163 << filename <<
": truncated DDS file.\n";
4167 cdata->_loaded_from_image =
true;
4168 cdata->_loaded_from_txo =
true;
4178 do_read_ktx_file(CData *cdata,
const Filename &fullpath,
bool header_only) {
4181 Filename filename = Filename::binary_filename(fullpath);
4183 if (file ==
nullptr) {
4186 <<
"Could not find " << fullpath <<
"\n";
4190 if (gobj_cat.is_debug()) {
4192 <<
"Reading KTX file " << filename <<
"\n";
4195 istream *in = file->open_read_file(
true);
4196 bool success = do_read_ktx(cdata, *in, fullpath, header_only);
4203 cdata->_fullpath = fullpath;
4204 cdata->_alpha_fullpath =
Filename();
4205 cdata->_keep_ram_image =
false;
4214 do_read_ktx(CData *cdata, istream &in,
const string &filename,
bool header_only) {
4217 unsigned char magic[12];
4218 if (ktx.extract_bytes(magic, 12) != 12 ||
4219 memcmp(magic,
"\xABKTX 11\xBB\r\n\x1A\n", 12) != 0) {
4221 << filename <<
" is not a KTX file.\n";
4226 uint32_t gl_type, gl_format, internal_format, gl_base_format,
4227 width, height, depth, num_array_elements, num_faces, num_mipmap_levels,
4231 if (ktx.get_uint32() == 0x04030201) {
4233 gl_type = ktx.get_uint32();
4235 gl_format = ktx.get_uint32();
4236 internal_format = ktx.get_uint32();
4237 gl_base_format = ktx.get_uint32();
4238 width = ktx.get_uint32();
4239 height = ktx.get_uint32();
4240 depth = ktx.get_uint32();
4241 num_array_elements = ktx.get_uint32();
4242 num_faces = ktx.get_uint32();
4243 num_mipmap_levels = ktx.get_uint32();
4244 kvdata_size = ktx.get_uint32();
4247 gl_type = ktx.get_be_uint32();
4248 ktx.get_be_uint32();
4249 gl_format = ktx.get_be_uint32();
4250 internal_format = ktx.get_be_uint32();
4251 gl_base_format = ktx.get_be_uint32();
4252 width = ktx.get_be_uint32();
4253 height = ktx.get_be_uint32();
4254 depth = ktx.get_be_uint32();
4255 num_array_elements = ktx.get_be_uint32();
4256 num_faces = ktx.get_be_uint32();
4257 num_mipmap_levels = ktx.get_be_uint32();
4258 kvdata_size = ktx.get_be_uint32();
4262 ktx.skip_bytes(kvdata_size);
4265 CompressionMode compression;
4267 bool swap_bgr =
false;
4269 if (gl_type == 0 || gl_format == 0) {
4271 if (gl_type > 0 || gl_format > 0) {
4273 <<
"Compressed textures must have both type and format set to 0.\n";
4276 type = T_unsigned_byte;
4277 compression = CM_on;
4279 KTXFormat base_format;
4280 switch ((KTXCompressedFormat)internal_format) {
4281 case KTX_COMPRESSED_RED:
4283 base_format = KTX_RED;
4285 case KTX_COMPRESSED_RG:
4287 base_format = KTX_RG;
4289 case KTX_COMPRESSED_RGB:
4291 base_format = KTX_RGB;
4293 case KTX_COMPRESSED_RGBA:
4295 base_format = KTX_RGBA;
4297 case KTX_COMPRESSED_SRGB:
4299 base_format = KTX_SRGB;
4301 case KTX_COMPRESSED_SRGB_ALPHA:
4302 format = F_srgb_alpha;
4303 base_format = KTX_SRGB_ALPHA;
4305 case KTX_COMPRESSED_RGB_FXT1_3DFX:
4307 base_format = KTX_RGB;
4308 compression = CM_fxt1;
4310 case KTX_COMPRESSED_RGBA_FXT1_3DFX:
4312 base_format = KTX_RGBA;
4313 compression = CM_fxt1;
4315 case KTX_COMPRESSED_RGB_S3TC_DXT1:
4317 base_format = KTX_RGB;
4318 compression = CM_dxt1;
4320 case KTX_COMPRESSED_RGBA_S3TC_DXT1:
4322 base_format = KTX_RGB;
4323 compression = CM_dxt1;
4325 case KTX_COMPRESSED_RGBA_S3TC_DXT3:
4327 base_format = KTX_RGBA;
4328 compression = CM_dxt3;
4330 case KTX_COMPRESSED_RGBA_S3TC_DXT5:
4332 base_format = KTX_RGBA;
4333 compression = CM_dxt5;
4335 case KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT1:
4336 format = F_srgb_alpha;
4337 base_format = KTX_SRGB_ALPHA;
4338 compression = CM_dxt1;
4340 case KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT3:
4341 format = F_srgb_alpha;
4342 base_format = KTX_SRGB_ALPHA;
4343 compression = CM_dxt3;
4345 case KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT5:
4346 format = F_srgb_alpha;
4347 base_format = KTX_SRGB_ALPHA;
4348 compression = CM_dxt5;
4350 case KTX_COMPRESSED_SRGB_S3TC_DXT1:
4352 base_format = KTX_SRGB;
4353 compression = CM_dxt1;
4355 case KTX_COMPRESSED_RED_RGTC1:
4356 case KTX_COMPRESSED_SIGNED_RED_RGTC1:
4358 base_format = KTX_RED;
4359 compression = CM_rgtc;
4361 case KTX_COMPRESSED_RG_RGTC2:
4362 case KTX_COMPRESSED_SIGNED_RG_RGTC2:
4364 base_format = KTX_RG;
4365 compression = CM_rgtc;
4369 base_format = KTX_RGB;
4370 compression = CM_etc1;
4372 case KTX_ETC1_SRGB8:
4374 base_format = KTX_SRGB;
4375 compression = CM_etc1;
4377 case KTX_COMPRESSED_RGB8_ETC2:
4379 base_format = KTX_RGB;
4380 compression = CM_etc2;
4382 case KTX_COMPRESSED_SRGB8_ETC2:
4384 base_format = KTX_SRGB;
4385 compression = CM_etc2;
4387 case KTX_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
4389 base_format = KTX_RGBA;
4390 compression = CM_etc2;
4392 case KTX_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
4394 base_format = KTX_SRGB8_ALPHA8;
4395 compression = CM_etc2;
4397 case KTX_COMPRESSED_RGBA8_ETC2_EAC:
4399 base_format = KTX_RGBA;
4400 compression = CM_etc2;
4402 case KTX_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
4403 format = F_srgb_alpha;
4404 base_format = KTX_SRGB8_ALPHA8;
4405 compression = CM_etc2;
4407 case KTX_COMPRESSED_R11_EAC:
4408 case KTX_COMPRESSED_SIGNED_R11_EAC:
4410 base_format = KTX_RED;
4411 compression = CM_eac;
4413 case KTX_COMPRESSED_RG11_EAC:
4414 case KTX_COMPRESSED_SIGNED_RG11_EAC:
4416 base_format = KTX_RG;
4417 compression = CM_eac;
4419 case KTX_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1:
4420 format = F_srgb_alpha;
4421 base_format = KTX_SRGB_ALPHA;
4422 compression = CM_pvr1_2bpp;
4424 case KTX_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1:
4425 format = F_srgb_alpha;
4426 base_format = KTX_SRGB_ALPHA;
4427 compression = CM_pvr1_4bpp;
4429 case KTX_COMPRESSED_RGBA_BPTC_UNORM:
4430 case KTX_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
4431 case KTX_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
4432 case KTX_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
4435 << filename <<
" has unsupported compressed internal format " << internal_format <<
"\n";
4439 if (base_format != gl_base_format) {
4441 << filename <<
" has internal format that is incompatible with base "
4442 "format (0x" << std::hex << gl_base_format <<
", expected 0x"
4443 << base_format << std::dec <<
")\n";
4449 compression = CM_off;
4450 switch ((KTXType)gl_type) {
4454 case KTX_UNSIGNED_BYTE:
4455 type = T_unsigned_byte;
4460 case KTX_UNSIGNED_SHORT:
4461 type = T_unsigned_short;
4466 case KTX_UNSIGNED_INT:
4467 type = T_unsigned_int;
4472 case KTX_HALF_FLOAT:
4473 type = T_half_float;
4475 case KTX_UNSIGNED_INT_24_8:
4476 type = T_unsigned_int_24_8;
4480 << filename <<
" has unsupported component type " << gl_type <<
"\n";
4484 if (gl_format != gl_base_format) {
4486 << filename <<
" has mismatched formats: " << gl_format <<
" != "
4487 << gl_base_format <<
"\n";
4490 switch (gl_format) {
4491 case KTX_DEPTH_COMPONENT:
4492 switch (internal_format) {
4493 case KTX_DEPTH_COMPONENT:
4494 format = F_depth_component;
4496 case KTX_DEPTH_COMPONENT16:
4497 format = F_depth_component16;
4499 case KTX_DEPTH_COMPONENT24:
4500 format = F_depth_component24;
4502 case KTX_DEPTH_COMPONENT32:
4503 case KTX_DEPTH_COMPONENT32F:
4504 format = F_depth_component32;
4507 format = F_depth_component;
4509 << filename <<
" has unsupported depth component format " << internal_format <<
"\n";
4513 case KTX_DEPTH_STENCIL:
4514 format = F_depth_stencil;
4515 if (internal_format != KTX_DEPTH_STENCIL &&
4516 internal_format != KTX_DEPTH24_STENCIL8) {
4518 << filename <<
" has unsupported depth stencil format " << internal_format <<
"\n";
4523 switch (internal_format) {
4541 << filename <<
" has unsupported red format " << internal_format <<
"\n";
4545 case KTX_RED_INTEGER:
4546 switch (internal_format) {
4561 << filename <<
" has unsupported red integer format " << internal_format <<
"\n";
4568 if (internal_format != KTX_GREEN) {
4570 << filename <<
" has unsupported green format " << internal_format <<
"\n";
4576 if (internal_format != KTX_BLUE) {
4578 << filename <<
" has unsupported blue format " << internal_format <<
"\n";
4583 switch (internal_format) {
4591 case KTX_RG16_SNORM:
4601 << filename <<
" has unsupported RG format " << internal_format <<
"\n";
4605 case KTX_RG_INTEGER:
4606 switch (internal_format) {
4617 << filename <<
" has unsupported RG integer format " << internal_format <<
"\n";
4625 switch (internal_format) {
4642 case KTX_R11F_G11F_B10F:
4643 format = F_r11_g11_b10;
4646 case KTX_RGB8_SNORM:
4650 case KTX_RGB16_SNORM:
4664 << filename <<
" has unsupported RGB format " << internal_format <<
"\n";
4668 case KTX_RGB_INTEGER:
4670 case KTX_BGR_INTEGER:
4671 switch (internal_format) {
4682 << filename <<
" has unsupported RGB integer format " << internal_format <<
"\n";
4690 switch (internal_format) {
4692 case KTX_RGBA_SNORM:
4705 format = F_rgb10_a2;
4708 case KTX_RGBA8_SNORM:
4712 case KTX_RGBA16_SNORM:
4719 case KTX_SRGB_ALPHA:
4720 case KTX_SRGB8_ALPHA8:
4721 format = F_srgb_alpha;
4726 << filename <<
" has unsupported RGBA format " << internal_format <<
"\n";
4731 case KTX_RGBA_INTEGER:
4733 case KTX_BGRA_INTEGER:
4734 switch (internal_format) {
4745 << filename <<
" has unsupported RGBA integer format " << internal_format <<
"\n";
4751 format = F_luminance;
4754 case KTX_LUMINANCE_ALPHA:
4755 format = F_luminance_alpha;
4762 case KTX_STENCIL_INDEX:
4765 << filename <<
" has unsupported format " << gl_format <<
"\n";
4770 TextureType texture_type;
4772 texture_type = TT_3d_texture;
4774 }
else if (num_faces > 1) {
4775 if (num_faces != 6) {
4777 << filename <<
" has " << num_faces <<
" cube map faces, expected 6\n";
4780 if (width != height) {
4782 << filename <<
" is cube map, but does not have square dimensions\n";
4785 if (num_array_elements > 0) {
4786 depth = num_array_elements * 6;
4787 texture_type = TT_cube_map_array;
4790 texture_type = TT_cube_map;
4793 }
else if (height > 0) {
4794 if (num_array_elements > 0) {
4795 depth = num_array_elements;
4796 texture_type = TT_2d_texture_array;
4799 texture_type = TT_2d_texture;
4802 }
else if (width > 0) {
4804 if (num_array_elements > 0) {
4805 height = num_array_elements;
4806 texture_type = TT_1d_texture_array;
4809 texture_type = TT_1d_texture;
4814 << filename <<
" has zero size\n";
4818 do_setup_texture(cdata, texture_type, width, height, depth, type, format);
4820 cdata->_orig_file_x_size = cdata->_x_size;
4821 cdata->_orig_file_y_size = cdata->_y_size;
4822 cdata->_compression = compression;
4823 cdata->_ram_image_compression = compression;
4826 bool generate_mipmaps =
false;
4827 if (num_mipmap_levels == 0) {
4828 generate_mipmaps =
true;
4829 num_mipmap_levels = 1;
4832 for (uint32_t n = 0; n < num_mipmap_levels; ++n) {
4833 uint32_t image_size;
4835 image_size = ktx.get_be_uint32();
4837 image_size = ktx.get_uint32();
4841 if (compression == CM_off) {
4842 uint32_t row_size = do_get_expected_mipmap_x_size(cdata, (
int)n) * cdata->_num_components * cdata->_component_width;
4843 uint32_t num_rows = do_get_expected_mipmap_y_size(cdata, (
int)n) * do_get_expected_mipmap_z_size(cdata, (
int)n);
4844 uint32_t row_padded = (row_size + 3) & ~3;
4846 if (image_size == row_size * num_rows) {
4847 if (row_padded != row_size) {
4851 << filename <<
" does not have proper row padding for mipmap "
4852 "level " << n <<
"\n";
4854 image = PTA_uchar::empty_array(image_size);
4855 ktx.extract_bytes(image.p(), image_size);
4857 }
else if (image_size != row_padded * num_rows) {
4859 << filename <<
" has invalid image size " << image_size
4860 <<
" for mipmap level " << n <<
" (expected "
4861 << row_padded * num_rows <<
")\n";
4866 image = PTA_uchar::empty_array(row_size * num_rows);
4867 uint32_t skip = row_padded - row_size;
4868 unsigned char *p = image.p();
4869 for (uint32_t row = 0; row < num_rows; ++row) {
4870 ktx.extract_bytes(p, row_size);
4871 ktx.skip_bytes(skip);
4878 unsigned char *begin = image.p();
4879 const unsigned char *end = image.p() + image.size();
4880 size_t skip = cdata->_num_components;
4881 nassertr(skip == 3 || skip == 4,
false);
4883 switch (cdata->_component_width) {
4885 for (
unsigned char *p = begin; p < end; p += skip) {
4890 for (
short *p = (
short *)begin; p < (
short *)end; p += skip) {
4895 for (
int *p = (
int *)begin; p < (
int *)end; p += skip) {
4900 nassert_raise(
"unexpected channel count");
4905 do_set_ram_mipmap_image(cdata, (
int)n, std::move(image),
4906 row_size * do_get_expected_mipmap_y_size(cdata, (
int)n));
4910 image = PTA_uchar::empty_array(image_size);
4911 ktx.extract_bytes(image.p(), image_size);
4912 do_set_ram_mipmap_image(cdata, (
int)n, std::move(image), image_size / depth);
4915 ktx.skip_bytes(3 - ((image_size + 3) & 3));
4918 cdata->_has_read_pages =
true;
4919 cdata->_has_read_mipmaps =
true;
4920 cdata->_num_mipmap_levels_read = cdata->_ram_images.size();
4922 if (generate_mipmaps) {
4923 do_generate_ram_mipmap_images(cdata,
false);
4929 << filename <<
": truncated KTX file.\n";
4933 cdata->_loaded_from_image =
true;
4934 cdata->_loaded_from_txo =
true;
4944 do_write(CData *cdata,
4945 const Filename &fullpath,
int z,
int n,
bool write_pages,
bool write_mipmaps) {
4946 if (is_txo_filename(fullpath)) {
4947 if (!do_has_bam_rawdata(cdata)) {
4948 do_get_bam_rawdata(cdata);
4950 nassertr(do_has_bam_rawdata(cdata),
false);
4951 return do_write_txo_file(cdata, fullpath);
4954 if (!do_has_uncompressed_ram_image(cdata)) {
4955 do_get_uncompressed_ram_image(cdata);
4958 nassertr(do_has_ram_mipmap_image(cdata, n),
false);
4959 nassertr(cdata->_ram_image_compression == CM_off,
false);
4961 if (write_pages && write_mipmaps) {
4964 int num_levels = cdata->_ram_images.size();
4966 for (
int n = 0; n < num_levels; ++n) {
4967 int num_pages = do_get_expected_mipmap_num_pages(cdata, n);
4969 for (z = 0; z < num_pages; ++z) {
4974 <<
"Filename requires two different hash sequences: " << fullpath
4985 }
else if (write_pages) {
4988 if (!fullpath_pattern.
has_hash()) {
4990 <<
"Filename requires a hash mark: " << fullpath
4995 int num_pages = cdata->_z_size * cdata->_num_views;
4996 for (z = 0; z < num_pages; ++z) {
5002 }
else if (write_mipmaps) {
5005 if (!fullpath_pattern.
has_hash()) {
5007 <<
"Filename requires a hash mark: " << fullpath
5012 int num_levels = cdata->_ram_images.size();
5013 for (
int n = 0; n < num_levels; ++n) {
5021 if (!do_write_one(cdata, fullpath, z, n)) {
5034 do_write_one(CData *cdata,
const Filename &fullpath,
int z,
int n) {
5035 if (!do_has_ram_mipmap_image(cdata, n)) {
5039 nassertr(cdata->_ram_image_compression == CM_off,
false);
5042 if (cdata->_component_type == T_float) {
5045 if (!do_store_one(cdata, pfm, z, n)) {
5048 success = pfm.
write(fullpath);
5052 if (!do_store_one(cdata, pnmimage, z, n)) {
5055 success = pnmimage.
write(fullpath);
5060 <<
"Texture::write() - couldn't write: " << fullpath << endl;
5071 do_store_one(CData *cdata,
PNMImage &pnmimage,
int z,
int n) {
5073 do_get_uncompressed_ram_image(cdata);
5075 if (!do_has_ram_mipmap_image(cdata, n)) {
5079 nassertr(z >= 0 && z < do_get_expected_mipmap_num_pages(cdata, n),
false);
5080 nassertr(cdata->_ram_image_compression == CM_off,
false);
5082 if (cdata->_component_type == T_float) {
5085 bool success = convert_to_pfm(pfm,
5086 do_get_expected_mipmap_x_size(cdata, n),
5087 do_get_expected_mipmap_y_size(cdata, n),
5088 cdata->_num_components, cdata->_component_width,
5089 cdata->_ram_images[n]._image,
5090 do_get_ram_mipmap_page_size(cdata, n), z);
5094 return pfm.
store(pnmimage);
5097 return convert_to_pnmimage(pnmimage,
5098 do_get_expected_mipmap_x_size(cdata, n),
5099 do_get_expected_mipmap_y_size(cdata, n),
5100 cdata->_num_components, cdata->_component_type,
5102 cdata->_ram_images[n]._image,
5103 do_get_ram_mipmap_page_size(cdata, n), z);
5110 do_store_one(CData *cdata,
PfmFile &pfm,
int z,
int n) {
5112 do_get_uncompressed_ram_image(cdata);
5114 if (!do_has_ram_mipmap_image(cdata, n)) {
5118 nassertr(z >= 0 && z < do_get_expected_mipmap_num_pages(cdata, n),
false);
5119 nassertr(cdata->_ram_image_compression == CM_off,
false);
5121 if (cdata->_component_type != T_float) {
5125 convert_to_pnmimage(pnmimage,
5126 do_get_expected_mipmap_x_size(cdata, n),
5127 do_get_expected_mipmap_y_size(cdata, n),
5128 cdata->_num_components, cdata->_component_type,
5130 cdata->_ram_images[n]._image,
5131 do_get_ram_mipmap_page_size(cdata, n), z);
5135 return pfm.
load(pnmimage);
5138 return convert_to_pfm(pfm,
5139 do_get_expected_mipmap_x_size(cdata, n),
5140 do_get_expected_mipmap_y_size(cdata, n),
5141 cdata->_num_components, cdata->_component_width,
5142 cdata->_ram_images[n]._image,
5143 do_get_ram_mipmap_page_size(cdata, n), z);
5150 do_write_txo_file(
const CData *cdata,
const Filename &fullpath)
const {
5152 Filename filename = Filename::binary_filename(fullpath);
5154 if (out ==
nullptr) {
5156 <<
"Unable to open " << filename <<
"\n";
5160 bool success = do_write_txo(cdata, *out, fullpath);
5169 do_write_txo(
const CData *cdata, ostream &out,
const string &filename)
const {
5172 if (!dout.
open(out, filename)) {
5174 <<
"Could not write texture object: " << filename <<
"\n";
5180 <<
"Unable to write to " << filename <<
"\n";
5185 if (!writer.init()) {
5189 writer.set_file_texture_mode(BamWriter::BTM_rawdata);
5191 if (!writer.write_object(
this)) {
5195 if (!do_has_bam_rawdata(cdata)) {
5197 << get_name() <<
" does not have ram image\n";
5218 Texture::CData *Texture::
5219 unlocked_ensure_ram_image(
bool allow_compression) {
5225 while (_reloading) {
5230 const CData *cdata = _cycler.
read(current_thread);
5232 if (
has_ram_image && !allow_compression && cdata->_ram_image_compression != Texture::CM_off) {
5244 nassertr(!_reloading,
nullptr);
5247 PT(
Texture) tex = do_make_copy(cdata);
5253 CDWriter cdata_tex(tex->_cycler,
true);
5254 tex->do_reload_ram_image(cdata_tex, allow_compression);
5265 cdataw->_orig_file_x_size = cdata_tex->_orig_file_x_size;
5266 cdataw->_orig_file_y_size = cdata_tex->_orig_file_y_size;
5270 if (cdata_tex->_x_size != cdataw->_x_size ||
5271 cdata_tex->_y_size != cdataw->_y_size ||
5272 cdata_tex->_z_size != cdataw->_z_size ||
5273 cdata_tex->_num_views != cdataw->_num_views ||
5274 cdata_tex->_num_components != cdataw->_num_components ||
5275 cdata_tex->_component_width != cdataw->_component_width ||
5276 cdata_tex->_texture_type != cdataw->_texture_type ||
5277 cdata_tex->_component_type != cdataw->_component_type) {
5279 cdataw->_x_size = cdata_tex->_x_size;
5280 cdataw->_y_size = cdata_tex->_y_size;
5281 cdataw->_z_size = cdata_tex->_z_size;
5282 cdataw->_num_views = cdata_tex->_num_views;
5284 cdataw->_num_components = cdata_tex->_num_components;
5285 cdataw->_component_width = cdata_tex->_component_width;
5286 cdataw->_texture_type = cdata_tex->_texture_type;
5287 cdataw->_format = cdata_tex->_format;
5288 cdataw->_component_type = cdata_tex->_component_type;
5290 cdataw->inc_properties_modified();
5291 cdataw->inc_image_modified();
5294 cdataw->_keep_ram_image = cdata_tex->_keep_ram_image;
5295 cdataw->_ram_image_compression = cdata_tex->_ram_image_compression;
5296 cdataw->_ram_images = cdata_tex->_ram_images;
5298 nassertr(_reloading,
nullptr);
5320 do_reload_ram_image(CData *cdata,
bool allow_compression) {
5324 if (!do_has_compression(cdata)) {
5325 allow_compression =
false;
5331 record = cache->lookup(cdata->_fullpath,
"txo");
5332 if (record !=
nullptr &&
5333 record->has_data()) {
5338 int x_size = cdata->_orig_file_x_size;
5339 int y_size = cdata->_orig_file_y_size;
5340 do_adjust_this_size(cdata, x_size, y_size, cdata->_filename.get_basename(),
true);
5341 if (x_size != tex->get_x_size() || y_size != tex->get_y_size()) {
5342 if (gobj_cat.is_debug()) {
5344 <<
"Cached texture " << *
this <<
" has size "
5345 << tex->get_x_size() <<
" x " << tex->get_y_size()
5346 <<
" instead of " << x_size <<
" x " << y_size
5347 <<
"; ignoring cache.\n";
5352 if (!allow_compression && tex->get_ram_image_compression() != Texture::CM_off) {
5353 if (gobj_cat.is_debug()) {
5355 <<
"Cached texture " << *
this
5356 <<
" is compressed in cache; ignoring cache.\n";
5360 <<
"Texture " << get_name() <<
" reloaded from disk cache\n";
5365 CDReader cdata_tex(tex->_cycler);
5366 cdata->_x_size = cdata_tex->_x_size;
5367 cdata->_y_size = cdata_tex->_y_size;
5368 if (cdata->_num_components != cdata_tex->_num_components) {
5369 cdata->_num_components = cdata_tex->_num_components;
5370 cdata->_format = cdata_tex->_format;
5372 cdata->_component_type = cdata_tex->_component_type;
5373 cdata->_compression = cdata_tex->_compression;
5374 cdata->_ram_image_compression = cdata_tex->_ram_image_compression;
5375 cdata->_ram_images = cdata_tex->_ram_images;
5376 cdata->_loaded_from_image =
true;
5378 bool was_compressed = (cdata->_ram_image_compression != CM_off);
5379 if (do_consider_auto_process_ram_image(cdata,
uses_mipmaps(), allow_compression)) {
5380 bool is_compressed = (cdata->_ram_image_compression != CM_off);
5381 if (!was_compressed && is_compressed &&
5387 cache->
store(record);
5398 <<
"Reloading texture " << get_name() <<
"\n";
5403 if (cdata->_has_read_pages) {
5406 if (cdata->_has_read_mipmaps) {
5407 n = cdata->_num_mipmap_levels_read;
5410 cdata->_loaded_from_image =
false;
5411 Format orig_format = cdata->_format;
5412 int orig_num_components = cdata->_num_components;
5415 if (allow_compression) {
5416 options.set_texture_flags(LoaderOptions::TF_preload |
5417 LoaderOptions::TF_allow_compression);
5419 options.set_texture_flags(LoaderOptions::TF_preload);
5421 do_read(cdata, cdata->_fullpath, cdata->_alpha_fullpath,
5422 cdata->_primary_file_num_channels, cdata->_alpha_file_channel,
5423 z, n, cdata->_has_read_pages, cdata->_has_read_mipmaps, options,
nullptr);
5425 if (orig_num_components == cdata->_num_components) {
5428 cdata->_format = orig_format;
5431 if (do_has_ram_image(cdata) && record !=
nullptr) {
5434 if (record !=
nullptr) {
5438 cache->
store(record);
5448 do_modify_ram_image(CData *cdata) {
5449 if (cdata->_ram_images.empty() || cdata->_ram_images[0]._image.empty() ||
5450 cdata->_ram_image_compression != CM_off) {
5451 do_make_ram_image(cdata);
5453 do_clear_ram_mipmap_images(cdata);
5455 return cdata->_ram_images[0]._image;
5463 do_make_ram_image(CData *cdata) {
5464 int image_size = do_get_expected_ram_image_size(cdata);
5465 cdata->_ram_images.clear();
5466 cdata->_ram_images.push_back(RamImage());
5467 cdata->_ram_images[0]._page_size = do_get_expected_ram_page_size(cdata);
5468 cdata->_ram_images[0]._image = PTA_uchar::empty_array(image_size, get_class_type());
5469 cdata->_ram_images[0]._pointer_image =
nullptr;
5470 cdata->_ram_image_compression = CM_off;
5472 if (cdata->_has_clear_color) {
5474 unsigned char pixel[16];
5475 const int pixel_size = do_get_clear_data(cdata,
pixel);
5476 nassertr(pixel_size > 0, cdata->_ram_images[0]._image);
5478 unsigned char *image_data = cdata->_ram_images[0]._image;
5479 for (
int i = 0; i < image_size; i += pixel_size) {
5480 memcpy(image_data + i,
pixel, pixel_size);
5484 return cdata->_ram_images[0]._image;
5495 do_set_ram_image(CData *cdata,
CPTA_uchar image, Texture::CompressionMode compression,
5497 nassertv(compression != CM_default);
5498 nassertv(compression != CM_off || image.size() == do_get_expected_ram_image_size(cdata));
5499 if (cdata->_ram_images.empty()) {
5500 cdata->_ram_images.push_back(RamImage());
5502 do_clear_ram_mipmap_images(cdata);
5504 if (page_size == 0) {
5505 page_size = image.size();
5507 if (cdata->_ram_images[0]._image != image ||
5508 cdata->_ram_images[0]._page_size != page_size ||
5509 cdata->_ram_image_compression != compression) {
5511 cdata->_ram_images[0]._page_size = page_size;
5512 cdata->_ram_images[0]._pointer_image =
nullptr;
5513 cdata->_ram_image_compression = compression;
5514 cdata->inc_image_modified();
5523 do_modify_ram_mipmap_image(CData *cdata,
int n) {
5524 nassertr(cdata->_ram_image_compression == CM_off, PTA_uchar());
5526 if (n >= (
int)cdata->_ram_images.size() ||
5527 cdata->_ram_images[n]._image.empty()) {
5528 do_make_ram_mipmap_image(cdata, n);
5530 return cdata->_ram_images[n]._image;
5537 do_make_ram_mipmap_image(CData *cdata,
int n) {
5538 nassertr(cdata->_ram_image_compression == CM_off, PTA_uchar(get_class_type()));
5540 while (n >= (
int)cdata->_ram_images.size()) {
5541 cdata->_ram_images.push_back(RamImage());
5544 size_t image_size = do_get_expected_ram_mipmap_image_size(cdata, n);
5545 cdata->_ram_images[n]._image = PTA_uchar::empty_array(image_size, get_class_type());
5546 cdata->_ram_images[n]._pointer_image =
nullptr;
5547 cdata->_ram_images[n]._page_size = do_get_expected_ram_mipmap_page_size(cdata, n);
5549 if (cdata->_has_clear_color) {
5551 unsigned char pixel[16];
5552 const size_t pixel_size = (size_t)do_get_clear_data(cdata,
pixel);
5553 nassertr(pixel_size > 0, cdata->_ram_images[n]._image);
5555 unsigned char *image_data = cdata->_ram_images[n]._image;
5556 for (
size_t i = 0; i < image_size; i += pixel_size) {
5557 memcpy(image_data + i,
pixel, pixel_size);
5561 return cdata->_ram_images[n]._image;
5568 do_set_ram_mipmap_image(CData *cdata,
int n,
CPTA_uchar image,
size_t page_size) {
5569 nassertv(cdata->_ram_image_compression != CM_off || image.size() == do_get_expected_ram_mipmap_image_size(cdata, n));
5571 while (n >= (
int)cdata->_ram_images.size()) {
5572 cdata->_ram_images.push_back(RamImage());
5574 if (page_size == 0) {
5575 page_size = image.size();
5578 if (cdata->_ram_images[n]._image != image ||
5579 cdata->_ram_images[n]._page_size != page_size) {
5581 cdata->_ram_images[n]._pointer_image =
nullptr;
5582 cdata->_ram_images[n]._page_size = page_size;
5583 cdata->inc_image_modified();
5595 do_get_clear_data(
const CData *cdata,
unsigned char *into)
const {
5596 nassertr(cdata->_has_clear_color, 0);
5598 int num_components = cdata->_num_components;
5599 nassertr(num_components > 0, 0);
5600 nassertr(num_components <= 4, 0);
5602 LVecBase4 clear_value = cdata->_clear_color;
5605 if (num_components >= 3) {
5606 std::swap(clear_value[0], clear_value[2]);
5609 switch (cdata->_component_type) {
5610 case T_unsigned_byte:
5611 if (
is_srgb(cdata->_format)) {
5615 switch (num_components) {
5616 case 4: into[3] = (
unsigned char)alpha;
5617 case 3: into[2] = (
unsigned char)color.b;
5618 case 2: into[1] = (
unsigned char)color.g;
5619 case 1: into[0] = (
unsigned char)color.r;
5622 LColor scaled = clear_value.fmin(LColor(1)).fmax(LColor::zero());
5624 for (
int i = 0; i < num_components; ++i) {
5625 into[i] = (
unsigned char)scaled[i];
5630 case T_unsigned_short:
5632 LColor scaled = clear_value.fmin(LColor(1)).fmax(LColor::zero());
5634 for (
int i = 0; i < num_components; ++i) {
5635 ((
unsigned short *)into)[i] = (
unsigned short)scaled[i];
5641 for (
int i = 0; i < num_components; ++i) {
5642 ((
float *)into)[i] = clear_value[i];
5646 case T_unsigned_int_24_8:
5647 nassertr(num_components == 1, 0);
5648 *((
unsigned int *)into) =
5649 ((
unsigned int)(clear_value[0] * 16777215) << 8) +
5650 (
unsigned int)max(min(clear_value[1], (PN_stdfloat)255), (PN_stdfloat)0);
5656 for (
int i = 0; i < num_components; ++i) {
5657 ((
int *)into)[i] = (int)clear_value[i];
5663 LColor scaled = clear_value.fmin(LColor(1)).fmax(LColor(-1));
5665 for (
int i = 0; i < num_components; ++i) {
5666 ((
signed char *)into)[i] = (
signed char)scaled[i];
5673 LColor scaled = clear_value.fmin(LColor(1)).fmax(LColor(-1));
5675 for (
int i = 0; i < num_components; ++i) {
5676 ((
short *)into)[i] = (short)scaled[i];
5682 for (
int i = 0; i < num_components; ++i) {
5687 v.uf = clear_value[i];
5688 uint16_t sign = ((v.ui & 0x80000000u) >> 16u);
5689 uint32_t mantissa = (v.ui & 0x007fffffu);
5690 uint16_t exponent = (uint16_t)std::min(std::max((
int)((v.ui & 0x7f800000u) >> 23u) - 112, 0), 31);
5691 mantissa += (mantissa & 0x00001000u) << 1u;
5692 ((uint16_t *)into)[i] = (uint16_t)(sign | ((exponent << 10u) | (mantissa >> 13u)));
5696 case T_unsigned_int:
5699 for (
int i = 0; i < num_components; ++i) {
5700 ((
unsigned int *)into)[i] = (
unsigned int)clear_value[i];
5704 return num_components * cdata->_component_width;
5715 consider_auto_process_ram_image(
bool generate_mipmaps,
bool allow_compression) {
5716 CDWriter cdata(_cycler,
false);
5717 return do_consider_auto_process_ram_image(cdata, generate_mipmaps, allow_compression);
5728 do_consider_auto_process_ram_image(CData *cdata,
bool generate_mipmaps,
5729 bool allow_compression) {
5730 bool modified =
false;
5732 if (generate_mipmaps && !driver_generate_mipmaps &&
5733 cdata->_ram_images.size() == 1) {
5734 do_generate_ram_mipmap_images(cdata,
false);
5738 if (allow_compression && !driver_compress_textures) {
5739 CompressionMode compression = cdata->_compression;
5740 if (compression == CM_default && compressed_textures) {
5741 compression = CM_on;
5743 if (compression != CM_off && cdata->_ram_image_compression == CM_off) {
5745 if (do_compress_ram_image(cdata, compression, QL_default, gsg)) {
5746 if (gobj_cat.is_debug()) {
5748 <<
"Compressed " << get_name() <<
" with "
5749 << cdata->_ram_image_compression <<
"\n";
5763 do_compress_ram_image(CData *cdata, Texture::CompressionMode compression,
5764 Texture::QualityLevel quality_level,
5766 nassertr(compression != CM_off,
false);
5768 if (cdata->_ram_images.empty() || cdata->_ram_image_compression != CM_off) {
5772 if (compression == CM_on) {
5774 switch (cdata->_format) {
5775 case Texture::F_rgbm:
5776 case Texture::F_rgb:
5777 case Texture::F_rgb5:
5778 case Texture::F_rgba5:
5779 case Texture::F_rgb8:
5780 case Texture::F_rgb12:
5781 case Texture::F_rgb332:
5782 case Texture::F_rgb16:
5783 case Texture::F_rgb32:
5784 case Texture::F_rgb10_a2:
5785 if (gsg ==
nullptr || gsg->get_supports_compressed_texture_format(CM_dxt1)) {
5786 compression = CM_dxt1;
5787 }
else if (gsg->get_supports_compressed_texture_format(CM_dxt3)) {
5788 compression = CM_dxt3;
5789 }
else if (gsg->get_supports_compressed_texture_format(CM_dxt5)) {
5790 compression = CM_dxt5;
5791 }
else if (gsg->get_supports_compressed_texture_format(CM_etc2)) {
5792 compression = CM_etc2;
5793 }
else if (gsg->get_supports_compressed_texture_format(CM_etc1)) {
5794 compression = CM_etc1;
5798 case Texture::F_rgba4:
5799 if (gsg ==
nullptr || gsg->get_supports_compressed_texture_format(CM_dxt3)) {
5800 compression = CM_dxt3;
5801 }
else if (gsg->get_supports_compressed_texture_format(CM_dxt5)) {
5802 compression = CM_dxt5;
5803 }
else if (gsg->get_supports_compressed_texture_format(CM_etc2)) {
5804 compression = CM_etc2;
5808 case Texture::F_rgba:
5809 case Texture::F_rgba8:
5810 case Texture::F_rgba12:
5811 case Texture::F_rgba16:
5812 case Texture::F_rgba32:
5813 if (gsg ==
nullptr || gsg->get_supports_compressed_texture_format(CM_dxt5)) {
5814 compression = CM_dxt5;
5815 }
else if (gsg->get_supports_compressed_texture_format(CM_etc2)) {
5816 compression = CM_etc2;
5820 case Texture::F_red:
5822 if (gsg ==
nullptr || gsg->get_supports_compressed_texture_format(CM_rgtc)) {
5823 compression = CM_rgtc;
5824 }
else if (gsg->get_supports_compressed_texture_format(CM_eac)) {
5825 compression = CM_eac;
5835 if (quality_level == Texture::QL_default) {
5836 quality_level = cdata->_quality_level;
5838 if (quality_level == Texture::QL_default) {
5839 quality_level = texture_quality_level;
5842 if (compression == CM_rgtc) {
5844 if (cdata->_component_type != T_unsigned_byte) {
5848 if (!do_has_all_ram_mipmap_images(cdata)) {
5851 do_generate_ram_mipmap_images(cdata,
false);
5854 RamImages compressed_ram_images;
5855 compressed_ram_images.resize(cdata->_ram_images.size());
5857 for (
size_t n = 0; n < cdata->_ram_images.size(); ++n) {
5858 const RamImage *uncompressed_image = &cdata->_ram_images[n];
5860 int x_size = do_get_expected_mipmap_x_size(cdata, n);
5861 int y_size = do_get_expected_mipmap_y_size(cdata, n);
5862 int num_pages = do_get_expected_mipmap_num_pages(cdata, n);
5867 RamImage temp_image;
5868 if ((x_size | y_size) & 0x3) {
5869 int virtual_x_size = x_size;
5870 int virtual_y_size = y_size;
5871 x_size = (x_size + 3) & ~0x3;
5872 y_size = (y_size + 3) & ~0x3;
5874 temp_image._page_size = x_size * y_size * cdata->_num_components;
5875 temp_image._image = PTA_uchar::empty_array(temp_image._page_size * num_pages);
5877 for (
int z = 0; z < num_pages; ++z) {
5878 unsigned char *dest = temp_image._image.p() + z * temp_image._page_size;
5879 unsigned const char *src = uncompressed_image->_image.p() + z * uncompressed_image->_page_size;
5881 for (
int y = 0; y < virtual_y_size; ++y) {
5882 memcpy(dest, src, virtual_x_size);
5883 src += virtual_x_size;
5888 uncompressed_image = &temp_image;
5892 RamImage &compressed_image = compressed_ram_images[n];
5893 compressed_image._page_size = (x_size * y_size * cdata->_num_components) >> 1;
5894 compressed_image._image = PTA_uchar::empty_array(compressed_image._page_size * num_pages);
5896 if (cdata->_num_components == 1) {
5897 do_compress_ram_image_bc4(*uncompressed_image, compressed_image,
5898 x_size, y_size, num_pages);
5899 }
else if (cdata->_num_components == 2) {
5900 do_compress_ram_image_bc5(*uncompressed_image, compressed_image,
5901 x_size, y_size, num_pages);
5908 cdata->_ram_images.swap(compressed_ram_images);
5909 cdata->_ram_image_compression = CM_rgtc;
5914 if (cdata->_texture_type != TT_3d_texture &&
5915 cdata->_texture_type != TT_2d_texture_array &&
5916 cdata->_component_type == T_unsigned_byte) {
5917 int squish_flags = 0;
5918 switch (compression) {
5920 squish_flags |= squish::kDxt1;
5924 squish_flags |= squish::kDxt3;
5928 squish_flags |= squish::kDxt5;
5935 if (squish_flags != 0) {
5937 switch (quality_level) {
5939 squish_flags |= squish::kColourRangeFit;
5944 squish_flags |= squish::kColourRangeFit;
5949 squish_flags |= squish::kColourIterativeClusterFit;
5956 if (do_squish(cdata, compression, squish_flags)) {
5961 #endif // HAVE_SQUISH
5970 do_uncompress_ram_image(CData *cdata) {
5971 nassertr(!cdata->_ram_images.empty(),
false);
5973 if (cdata->_ram_image_compression == CM_rgtc) {
5975 RamImages uncompressed_ram_images;
5976 uncompressed_ram_images.resize(cdata->_ram_images.size());
5978 for (
size_t n = 0; n < cdata->_ram_images.size(); ++n) {
5979 const RamImage &compressed_image = cdata->_ram_images[n];
5981 int x_size = do_get_expected_mipmap_x_size(cdata, n);
5982 int y_size = do_get_expected_mipmap_y_size(cdata, n);
5983 int num_pages = do_get_expected_mipmap_num_pages(cdata, n);
5985 RamImage &uncompressed_image = uncompressed_ram_images[n];
5986 uncompressed_image._page_size = do_get_expected_ram_mipmap_page_size(cdata, n);
5987 uncompressed_image._image = PTA_uchar::empty_array(uncompressed_image._page_size * num_pages);
5989 if (cdata->_num_components == 1) {
5990 do_uncompress_ram_image_bc4(compressed_image, uncompressed_image,
5991 x_size, y_size, num_pages);
5992 }
else if (cdata->_num_components == 2) {
5993 do_uncompress_ram_image_bc5(compressed_image, uncompressed_image,
5994 x_size, y_size, num_pages);
6000 cdata->_ram_images.swap(uncompressed_ram_images);
6001 cdata->_ram_image_compression = CM_off;
6006 if (cdata->_texture_type != TT_3d_texture &&
6007 cdata->_texture_type != TT_2d_texture_array &&
6008 cdata->_component_type == T_unsigned_byte) {
6009 int squish_flags = 0;
6010 switch (cdata->_ram_image_compression) {
6012 squish_flags |= squish::kDxt1;
6016 squish_flags |= squish::kDxt3;
6020 squish_flags |= squish::kDxt5;
6027 if (squish_flags != 0) {
6029 if (do_unsquish(cdata, squish_flags)) {
6034 #endif // HAVE_SQUISH
6042 do_compress_ram_image_bc4(
const RamImage &uncompressed_image,
6043 RamImage &compressed_image,
6044 int x_size,
int y_size,
int num_pages) {
6045 int x_blocks = (x_size >> 2);
6046 int y_blocks = (y_size >> 2);
6052 nassertv((
size_t)x_blocks * (
size_t)y_blocks * 4 * 4 <= uncompressed_image._page_size);
6053 nassertv((
size_t)x_size * (
size_t)y_size == uncompressed_image._page_size);
6055 static const int remap[] = {1, 7, 6, 5, 4, 3, 2, 0};
6057 for (
int z = 0; z < num_pages; ++z) {
6058 unsigned char *dest = compressed_image._image.p() + z * compressed_image._page_size;
6059 unsigned const char *src = uncompressed_image._image.p() + z * uncompressed_image._page_size;
6062 for (
int y = 0; y < y_blocks; ++y) {
6063 for (
int x = 0; x < x_blocks; ++x) {
6066 unsigned char minv, maxv;
6067 unsigned const char *blk = src;
6072 minv = min(blk[1], minv); maxv = max(blk[1], maxv);
6073 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6074 minv = min(blk[3], minv); maxv = max(blk[3], maxv);
6076 minv = min(blk[0], minv); maxv = max(blk[0], maxv);
6077 minv = min(blk[1], minv); maxv = max(blk[1], maxv);
6078 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6079 minv = min(blk[3], minv); maxv = max(blk[3], maxv);
6081 minv = min(blk[0], minv); maxv = max(blk[0], maxv);
6082 minv = min(blk[1], minv); maxv = max(blk[1], maxv);
6083 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6084 minv = min(blk[3], minv); maxv = max(blk[3], maxv);
6086 minv = min(blk[0], minv); maxv = max(blk[0], maxv);
6087 minv = min(blk[1], minv); maxv = max(blk[1], maxv);
6088 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6089 minv = min(blk[3], minv); maxv = max(blk[3], maxv);
6094 fac = 7.5f / (maxv - minv);
6099 a = (remap[(int)(blk[0] * fac + add)])
6100 | (remap[(
int)(blk[1] * fac + add)] << 3)
6101 | (remap[(int)(blk[2] * fac + add)] << 6)
6102 | (remap[(
int)(blk[3] * fac + add)] << 9);
6104 b = (remap[(int)(blk[0] * fac + add)] << 4)
6105 | (remap[(
int)(blk[1] * fac + add)] << 7)
6106 | (remap[(int)(blk[2] * fac + add)] << 10)
6107 | (remap[(
int)(blk[3] * fac + add)] << 13);
6109 c = (remap[(int)(blk[0] * fac + add)])
6110 | (remap[(
int)(blk[1] * fac + add)] << 3)
6111 | (remap[(int)(blk[2] * fac + add)] << 6)
6112 | (remap[(
int)(blk[3] * fac + add)] << 9);
6114 d = (remap[(int)(blk[0] * fac + add)] << 4)
6115 | (remap[(
int)(blk[1] * fac + add)] << 7)
6116 | (remap[(int)(blk[2] * fac + add)] << 10)
6117 | (remap[(
int)(blk[3] * fac + add)] << 13);
6121 *(dest++) = a & 0xff;
6122 *(dest++) = (a >> 8) | (b & 0xf0);
6124 *(dest++) = c & 0xff;
6125 *(dest++) = (c >> 8) | (d & 0xf0);
6141 do_compress_ram_image_bc5(
const RamImage &uncompressed_image,
6142 RamImage &compressed_image,
6143 int x_size,
int y_size,
int num_pages) {
6144 int x_blocks = (x_size >> 2);
6145 int y_blocks = (y_size >> 2);
6146 int stride = x_size * 2;
6151 nassertv((
size_t)x_blocks * (
size_t)y_blocks * 4 * 4 * 2 <= uncompressed_image._page_size);
6152 nassertv((
size_t)stride * (
size_t)y_size == uncompressed_image._page_size);
6154 static const int remap[] = {1, 7, 6, 5, 4, 3, 2, 0};
6156 for (
int z = 0; z < num_pages; ++z) {
6157 unsigned char *dest = compressed_image._image.p() + z * compressed_image._page_size;
6158 unsigned const char *src = uncompressed_image._image.p() + z * uncompressed_image._page_size;
6161 for (
int y = 0; y < y_blocks; ++y) {
6162 for (
int x = 0; x < x_blocks; ++x) {
6165 unsigned char minv, maxv;
6166 unsigned const char *blk = src;
6171 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6172 minv = min(blk[4], minv); maxv = max(blk[4], maxv);
6173 minv = min(blk[6], minv); maxv = max(blk[6], maxv);
6175 minv = min(blk[0], minv); maxv = max(blk[0], maxv);
6176 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6177 minv = min(blk[4], minv); maxv = max(blk[4], maxv);
6178 minv = min(blk[6], minv); maxv = max(blk[6], maxv);
6180 minv = min(blk[0], minv); maxv = max(blk[0], maxv);
6181 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6182 minv = min(blk[4], minv); maxv = max(blk[4], maxv);
6183 minv = min(blk[6], minv); maxv = max(blk[6], maxv);
6185 minv = min(blk[0], minv); maxv = max(blk[0], maxv);
6186 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6187 minv = min(blk[4], minv); maxv = max(blk[4], maxv);
6188 minv = min(blk[6], minv); maxv = max(blk[6], maxv);
6192 fac = 7.5f / (maxv - minv);
6198 a = (remap[(int)(blk[0] * fac + add)])
6199 | (remap[(
int)(blk[2] * fac + add)] << 3)
6200 | (remap[(int)(blk[4] * fac + add)] << 6)
6201 | (remap[(
int)(blk[6] * fac + add)] << 9);
6203 b = (remap[(int)(blk[0] * fac + add)] << 4)
6204 | (remap[(
int)(blk[2] * fac + add)] << 7)
6205 | (remap[(int)(blk[4] * fac + add)] << 10)
6206 | (remap[(
int)(blk[6] * fac + add)] << 13);
6208 c = (remap[(int)(blk[0] * fac + add)])
6209 | (remap[(
int)(blk[2] * fac + add)] << 3)
6210 | (remap[(int)(blk[4] * fac + add)] << 6)
6211 | (remap[(
int)(blk[6] * fac + add)] << 9);
6213 d = (remap[(int)(blk[0] * fac + add)] << 4)
6214 | (remap[(
int)(blk[2] * fac + add)] << 7)
6215 | (remap[(int)(blk[4] * fac + add)] << 10)
6216 | (remap[(
int)(blk[6] * fac + add)] << 13);
6220 *(dest++) = a & 0xff;
6221 *(dest++) = (a >> 8) | (b & 0xf0);
6223 *(dest++) = c & 0xff;
6224 *(dest++) = (c >> 8) | (d & 0xf0);
6231 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6232 minv = min(blk[4], minv); maxv = max(blk[4], maxv);
6233 minv = min(blk[6], minv); maxv = max(blk[6], maxv);
6235 minv = min(blk[0], minv); maxv = max(blk[0], maxv);
6236 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6237 minv = min(blk[4], minv); maxv = max(blk[4], maxv);
6238 minv = min(blk[6], minv); maxv = max(blk[6], maxv);
6240 minv = min(blk[0], minv); maxv = max(blk[0], maxv);
6241 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6242 minv = min(blk[4], minv); maxv = max(blk[4], maxv);
6243 minv = min(blk[6], minv); maxv = max(blk[6], maxv);
6245 minv = min(blk[0], minv); maxv = max(blk[0], maxv);
6246 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6247 minv = min(blk[4], minv); maxv = max(blk[4], maxv);
6248 minv = min(blk[6], minv); maxv = max(blk[6], maxv);
6252 fac = 7.5f / (maxv - minv);
6258 a = (remap[(int)(blk[0] * fac + add)])
6259 | (remap[(
int)(blk[2] * fac + add)] << 3)
6260 | (remap[(int)(blk[4] * fac + add)] << 6)
6261 | (remap[(
int)(blk[6] * fac + add)] << 9);
6263 b = (remap[(int)(blk[0] * fac + add)] << 4)
6264 | (remap[(
int)(blk[2] * fac + add)] << 7)
6265 | (remap[(int)(blk[4] * fac + add)] << 10)
6266 | (remap[(
int)(blk[6] * fac + add)] << 13);
6268 c = (remap[(int)(blk[0] * fac + add)])
6269 | (remap[(
int)(blk[2] * fac + add)] << 3)
6270 | (remap[(int)(blk[4] * fac + add)] << 6)
6271 | (remap[(
int)(blk[6] * fac + add)] << 9);
6273 d = (remap[(int)(blk[0] * fac + add)] << 4)
6274 | (remap[(
int)(blk[2] * fac + add)] << 7)
6275 | (remap[(int)(blk[4] * fac + add)] << 10)
6276 | (remap[(
int)(blk[6] * fac + add)] << 13);
6280 *(dest++) = a & 0xff;
6281 *(dest++) = (a >> 8) | (b & 0xf0);
6283 *(dest++) = c & 0xff;
6284 *(dest++) = (c >> 8) | (d & 0xf0);
6300 do_uncompress_ram_image_bc4(
const RamImage &compressed_image,
6301 RamImage &uncompressed_image,
6302 int x_size,
int y_size,
int num_pages) {
6303 int x_blocks = (x_size >> 2);
6304 int y_blocks = (y_size >> 2);
6306 for (
int z = 0; z < num_pages; ++z) {
6307 unsigned char *dest = uncompressed_image._image.p() + z * uncompressed_image._page_size;
6308 unsigned const char *src = compressed_image._image.p() + z * compressed_image._page_size;
6312 for (
int y = 0; y < y_blocks; ++y) {
6313 for (
int x = 0; x < x_blocks; ++x) {
6314 unsigned char *blk = dest;
6317 if (tbl[0] > tbl[1]) {
6318 tbl[2] = (tbl[0] * 6 + tbl[1] * 1) / 7.0f;
6319 tbl[3] = (tbl[0] * 5 + tbl[1] * 2) / 7.0f;
6320 tbl[4] = (tbl[0] * 4 + tbl[1] * 3) / 7.0f;
6321 tbl[5] = (tbl[0] * 3 + tbl[1] * 4) / 7.0f;
6322 tbl[6] = (tbl[0] * 2 + tbl[1] * 5) / 7.0f;
6323 tbl[7] = (tbl[0] * 1 + tbl[1] * 6) / 7.0f;
6325 tbl[2] = (tbl[0] * 4 + tbl[1] * 1) / 5.0f;
6326 tbl[3] = (tbl[0] * 3 + tbl[1] * 2) / 5.0f;
6327 tbl[4] = (tbl[0] * 2 + tbl[1] * 3) / 5.0f;
6328 tbl[5] = (tbl[0] * 1 + tbl[1] * 4) / 5.0f;
6332 int v = src[2] + (src[3] << 8) + (src[4] << 16);
6333 blk[0] = tbl[v & 0x7];
6334 blk[1] = tbl[(v & 0x000038) >> 3];
6335 blk[2] = tbl[(v & 0x0001c0) >> 6];
6336 blk[3] = tbl[(v & 0x000e00) >> 9];
6338 blk[0] = tbl[(v & 0x007000) >> 12];
6339 blk[1] = tbl[(v & 0x038000) >> 15];
6340 blk[2] = tbl[(v & 0x1c0000) >> 18];
6341 blk[3] = tbl[(v & 0xe00000) >> 21];
6343 v = src[5] + (src[6] << 8) + (src[7] << 16);
6344 blk[0] = tbl[v & 0x7];
6345 blk[1] = tbl[(v & 0x000038) >> 3];
6346 blk[2] = tbl[(v & 0x0001c0) >> 6];
6347 blk[3] = tbl[(v & 0x000e00) >> 9];
6349 blk[0] = tbl[(v & 0x007000) >> 12];
6350 blk[1] = tbl[(v & 0x038000) >> 15];
6351 blk[2] = tbl[(v & 0x1c0000) >> 18];
6352 blk[3] = tbl[(v & 0xe00000) >> 21];
6366 do_uncompress_ram_image_bc5(
const RamImage &compressed_image,
6367 RamImage &uncompressed_image,
6368 int x_size,
int y_size,
int num_pages) {
6369 int x_blocks = (x_size >> 2);
6370 int y_blocks = (y_size >> 2);
6371 int stride = x_size * 2;
6373 for (
int z = 0; z < num_pages; ++z) {
6374 unsigned char *dest = uncompressed_image._image.p() + z * uncompressed_image._page_size;
6375 unsigned const char *src = compressed_image._image.p() + z * compressed_image._page_size;
6380 for (
int y = 0; y < y_blocks; ++y) {
6381 for (
int x = 0; x < x_blocks; ++x) {
6382 unsigned char *blk = dest;
6385 if (red[0] > red[1]) {
6386 red[2] = (red[0] * 6 + red[1] * 1) / 7.0f;
6387 red[3] = (red[0] * 5 + red[1] * 2) / 7.0f;
6388 red[4] = (red[0] * 4 + red[1] * 3) / 7.0f;
6389 red[5] = (red[0] * 3 + red[1] * 4) / 7.0f;
6390 red[6] = (red[0] * 2 + red[1] * 5) / 7.0f;
6391 red[7] = (red[0] * 1 + red[1] * 6) / 7.0f;
6393 red[2] = (red[0] * 4 + red[1] * 1) / 5.0f;
6394 red[3] = (red[0] * 3 + red[1] * 2) / 5.0f;
6395 red[4] = (red[0] * 2 + red[1] * 3) / 5.0f;
6396 red[5] = (red[0] * 1 + red[1] * 4) / 5.0f;
6402 if (grn[0] > grn[1]) {
6403 grn[2] = (grn[0] * 6 + grn[1] * 1) / 7.0f;
6404 grn[3] = (grn[0] * 5 + grn[1] * 2) / 7.0f;
6405 grn[4] = (grn[0] * 4 + grn[1] * 3) / 7.0f;
6406 grn[5] = (grn[0] * 3 + grn[1] * 4) / 7.0f;
6407 grn[6] = (grn[0] * 2 + grn[1] * 5) / 7.0f;
6408 grn[7] = (grn[0] * 1 + grn[1] * 6) / 7.0f;
6410 grn[2] = (grn[0] * 4 + grn[1] * 1) / 5.0f;
6411 grn[3] = (grn[0] * 3 + grn[1] * 2) / 5.0f;
6412 grn[4] = (grn[0] * 2 + grn[1] * 3) / 5.0f;
6413 grn[5] = (grn[0] * 1 + grn[1] * 4) / 5.0f;
6417 int r = src[2] + (src[3] << 8) + (src[4] << 16);
6418 int g = src[10] + (src[11] << 8) + (src[12] << 16);
6419 blk[0] = red[r & 0x7];
6420 blk[1] = grn[g & 0x7];
6421 blk[2] = red[(r & 0x000038) >> 3];
6422 blk[3] = grn[(g & 0x000038) >> 3];
6423 blk[4] = red[(r & 0x0001c0) >> 6];
6424 blk[5] = grn[(g & 0x0001c0) >> 6];
6425 blk[6] = red[(r & 0x000e00) >> 9];
6426 blk[7] = grn[(g & 0x000e00) >> 9];
6428 blk[0] = red[(r & 0x007000) >> 12];
6429 blk[1] = grn[(g & 0x007000) >> 12];
6430 blk[2] = red[(r & 0x038000) >> 15];
6431 blk[3] = grn[(g & 0x038000) >> 15];
6432 blk[4] = red[(r & 0x1c0000) >> 18];
6433 blk[5] = grn[(g & 0x1c0000) >> 18];
6434 blk[6] = red[(r & 0xe00000) >> 21];
6435 blk[7] = grn[(g & 0xe00000) >> 21];
6437 r = src[5] + (src[6] << 8) + (src[7] << 16);
6438 g = src[13] + (src[14] << 8) + (src[15] << 16);
6439 blk[0] = red[r & 0x7];
6440 blk[1] = grn[g & 0x7];
6441 blk[2] = red[(r & 0x000038) >> 3];
6442 blk[3] = grn[(g & 0x000038) >> 3];
6443 blk[4] = red[(r & 0x0001c0) >> 6];
6444 blk[5] = grn[(g & 0x0001c0) >> 6];
6445 blk[6] = red[(r & 0x000e00) >> 9];
6446 blk[7] = grn[(g & 0x000e00) >> 9];
6448 blk[0] = red[(r & 0x007000) >> 12];
6449 blk[1] = grn[(g & 0x007000) >> 12];
6450 blk[2] = red[(r & 0x038000) >> 15];
6451 blk[3] = grn[(g & 0x038000) >> 15];
6452 blk[4] = red[(r & 0x1c0000) >> 18];
6453 blk[5] = grn[(g & 0x1c0000) >> 18];
6454 blk[6] = red[(r & 0xe00000) >> 21];
6455 blk[7] = grn[(g & 0xe00000) >> 21];
6469 do_has_all_ram_mipmap_images(
const CData *cdata)
const {
6470 if (cdata->_ram_images.empty() || cdata->_ram_images[0]._image.empty()) {
6481 int size = max(cdata->_x_size, max(cdata->_y_size, cdata->_z_size));
6487 if (n >= (
int)cdata->_ram_images.size() || cdata->_ram_images[n]._image.empty()) {
6503 do_reconsider_z_size(CData *cdata,
int z,
const LoaderOptions &options) {
6504 if (z >= cdata->_z_size * cdata->_num_views) {
6505 bool num_views_specified =
true;
6506 if (options.get_texture_flags() & LoaderOptions::TF_multiview) {
6513 if (num_views_specified &&
6514 (cdata->_texture_type == Texture::TT_3d_texture ||
6515 cdata->_texture_type == Texture::TT_2d_texture_array)) {
6520 nassertr(cdata->_num_views != 0,
false);
6521 cdata->_z_size = (z / cdata->_num_views) + 1;
6523 }
else if (cdata->_z_size != 0) {
6527 cdata->_num_views = (z / cdata->_z_size) + 1;
6536 do_allocate_pages(cdata);
6549 do_allocate_pages(CData *cdata) {
6550 size_t new_size = do_get_expected_ram_image_size(cdata);
6551 if (!cdata->_ram_images.empty() &&
6552 !cdata->_ram_images[0]._image.empty() &&
6553 new_size > cdata->_ram_images[0]._image.size()) {
6554 cdata->_ram_images[0]._image.insert(cdata->_ram_images[0]._image.end(), new_size - cdata->_ram_images[0]._image.size(), 0);
6555 nassertv(cdata->_ram_images[0]._image.size() == new_size);
6566 do_reconsider_image_properties(CData *cdata,
int x_size,
int y_size,
int num_components,
6567 Texture::ComponentType component_type,
int z,
6569 if (!cdata->_loaded_from_image || num_components != cdata->_num_components || component_type != cdata->_component_type) {
6575 switch (num_components) {
6577 cdata->_format = F_luminance;
6581 cdata->_format = F_luminance_alpha;
6585 cdata->_format = F_rgb;
6589 cdata->_format = F_rgba;
6594 nassert_raise(
"unexpected channel count");
6595 cdata->_format = F_rgb;
6600 if (!cdata->_loaded_from_image) {
6601 if ((options.get_texture_flags() & LoaderOptions::TF_allow_1d) &&
6602 cdata->_texture_type == TT_2d_texture && x_size != 1 && y_size == 1) {
6604 cdata->_texture_type = TT_1d_texture;
6608 switch (cdata->_texture_type) {
6610 case TT_buffer_texture:
6611 nassertr(y_size == 1,
false);
6614 case TT_cube_map_array:
6615 nassertr(x_size == y_size,
false);
6621 if ((cdata->_x_size != x_size)||(cdata->_y_size != y_size)) {
6622 do_set_pad_size(cdata, 0, 0, 0);
6624 cdata->_x_size = x_size;
6625 cdata->_y_size = y_size;
6626 cdata->_num_components = num_components;
6627 do_set_component_type(cdata, component_type);
6630 if (cdata->_x_size != x_size ||
6631 cdata->_y_size != y_size ||
6632 cdata->_num_components != num_components ||
6633 cdata->_component_type != component_type) {
6635 <<
"Texture properties have changed for texture " << get_name()
6636 <<
" page " << z <<
".\n";
6648 do_rescale_texture(CData *cdata) {
6649 int new_x_size = cdata->_x_size;
6650 int new_y_size = cdata->_y_size;
6651 if (cdata->_z_size * cdata->_num_views != 1) {
6652 nassert_raise(
"rescale_texture() doesn't support 3-d or multiview textures.");
6656 if (do_adjust_this_size(cdata, new_x_size, new_y_size, get_name(),
false)) {
6659 if (!do_store_one(cdata, orig_image, 0, 0)) {
6661 <<
"Couldn't get image in rescale_texture()\n";
6666 <<
"Resizing " << get_name() <<
" to " << new_x_size <<
" x "
6667 << new_y_size <<
"\n";
6671 new_image.quick_filter_from(orig_image);
6673 do_clear_ram_image(cdata);
6674 cdata->inc_image_modified();
6675 cdata->_x_size = new_x_size;
6676 cdata->_y_size = new_y_size;
6677 if (!do_load_one(cdata, new_image, get_name(), 0, 0,
LoaderOptions())) {
6687 if (do_get_auto_texture_scale(cdata) == ATS_pad) {
6688 new_x_size = cdata->_x_size;
6689 new_y_size = cdata->_y_size;
6690 if (do_adjust_this_size(cdata, new_x_size, new_y_size, get_name(),
true)) {
6691 pad_x_size = new_x_size - cdata->_x_size;
6692 pad_y_size = new_y_size - cdata->_y_size;
6695 if (!do_store_one(cdata, orig_image, 0, 0)) {
6697 <<
"Couldn't get image in rescale_texture()\n";
6703 new_image.copy_sub_image(orig_image, 0, new_y_size - orig_image.
get_y_size());
6705 do_clear_ram_image(cdata);
6706 cdata->_loaded_from_image =
false;
6707 cdata->inc_image_modified();
6708 if (!do_load_one(cdata, new_image, get_name(), 0, 0,
LoaderOptions())) {
6712 do_set_pad_size(cdata, pad_x_size, pad_y_size, 0);
6725 make_copy_impl()
const {
6726 CDReader cdata(_cycler);
6727 return do_make_copy(cdata);
6734 do_make_copy(
const CData *cdata)
const {
6736 CDWriter cdata_tex(tex->_cycler,
true);
6737 tex->do_assign(cdata_tex,
this, cdata);
6746 do_assign(CData *cdata,
const Texture *copy,
const CData *cdata_copy) {
6747 cdata->do_assign(cdata_copy);
6754 do_clear(CData *cdata) {
6757 CDReader cdata_tex(tex._cycler);
6758 do_assign(cdata, &tex, cdata_tex);
6760 cdata->inc_properties_modified();
6761 cdata->inc_image_modified();
6762 cdata->inc_simple_image_modified();
6769 do_setup_texture(CData *cdata, Texture::TextureType texture_type,
6770 int x_size,
int y_size,
int z_size,
6771 Texture::ComponentType component_type,
6772 Texture::Format format) {
6773 switch (texture_type) {
6775 nassertv(y_size == 1 && z_size == 1);
6779 nassertv(z_size == 1);
6785 case TT_2d_texture_array:
6790 nassertv(x_size == y_size && z_size == 6);
6795 cdata->_default_sampler.set_wrap_u(SamplerState::WM_clamp);
6796 cdata->_default_sampler.set_wrap_v(SamplerState::WM_clamp);
6797 cdata->_default_sampler.set_wrap_w(SamplerState::WM_clamp);
6800 case TT_cube_map_array:
6802 nassertv(x_size == y_size && z_size % 6 == 0);
6804 cdata->_default_sampler.set_wrap_u(SamplerState::WM_clamp);
6805 cdata->_default_sampler.set_wrap_v(SamplerState::WM_clamp);
6806 cdata->_default_sampler.set_wrap_w(SamplerState::WM_clamp);
6809 case TT_buffer_texture:
6810 nassertv(y_size == 1 && z_size == 1);
6813 case TT_1d_texture_array:
6814 nassertv(z_size == 1);
6818 if (texture_type != TT_2d_texture) {
6819 do_clear_simple_ram_image(cdata);
6822 cdata->_texture_type = texture_type;
6823 cdata->_x_size = x_size;
6824 cdata->_y_size = y_size;
6825 cdata->_z_size = z_size;
6826 cdata->_num_views = 1;
6827 do_set_component_type(cdata, component_type);
6828 do_set_format(cdata, format);
6830 do_clear_ram_image(cdata);
6831 do_set_pad_size(cdata, 0, 0, 0);
6832 cdata->_orig_file_x_size = 0;
6833 cdata->_orig_file_y_size = 0;
6834 cdata->_loaded_from_image =
false;
6835 cdata->_loaded_from_txo =
false;
6836 cdata->_has_read_pages =
false;
6837 cdata->_has_read_mipmaps =
false;
6844 do_set_format(CData *cdata, Texture::Format format) {
6845 if (format == cdata->_format) {
6848 cdata->_format = format;
6849 cdata->inc_properties_modified();
6851 switch (cdata->_format) {
6853 case F_depth_stencil:
6854 case F_depth_component:
6855 case F_depth_component16:
6856 case F_depth_component24:
6857 case F_depth_component32:
6869 cdata->_num_components = 1;
6872 case F_luminance_alpha:
6873 case F_luminance_alphamask:
6875 case F_sluminance_alpha:
6879 cdata->_num_components = 2;
6893 cdata->_num_components = 3;
6907 cdata->_num_components = 4;
6916 do_set_component_type(CData *cdata, Texture::ComponentType component_type) {
6917 cdata->_component_type = component_type;
6919 switch (component_type) {
6920 case T_unsigned_byte:
6922 cdata->_component_width = 1;
6925 case T_unsigned_short:
6928 cdata->_component_width = 2;
6932 case T_unsigned_int_24_8:
6934 case T_unsigned_int:
6935 cdata->_component_width = 4;
6944 do_set_x_size(CData *cdata,
int x_size) {
6945 if (cdata->_x_size != x_size) {
6946 cdata->_x_size = x_size;
6947 cdata->inc_image_modified();
6948 do_clear_ram_image(cdata);
6949 do_set_pad_size(cdata, 0, 0, 0);
6957 do_set_y_size(CData *cdata,
int y_size) {
6958 if (cdata->_y_size != y_size) {
6959 nassertv((cdata->_texture_type != Texture::TT_buffer_texture &&
6960 cdata->_texture_type != Texture::TT_1d_texture) || y_size == 1);
6961 cdata->_y_size = y_size;
6962 cdata->inc_image_modified();
6963 do_clear_ram_image(cdata);
6964 do_set_pad_size(cdata, 0, 0, 0);
6973 do_set_z_size(CData *cdata,
int z_size) {
6974 if (cdata->_z_size != z_size) {
6975 nassertv((cdata->_texture_type == Texture::TT_3d_texture) ||
6976 (cdata->_texture_type == Texture::TT_cube_map && z_size == 6) ||
6977 (cdata->_texture_type == Texture::TT_cube_map_array && z_size % 6 == 0) ||
6978 (cdata->_texture_type == Texture::TT_2d_texture_array) || (z_size == 1));
6979 cdata->_z_size = z_size;
6980 cdata->inc_image_modified();
6981 do_clear_ram_image(cdata);
6982 do_set_pad_size(cdata, 0, 0, 0);
6990 do_set_num_views(CData *cdata,
int num_views) {
6991 nassertv(num_views >= 1);
6992 if (cdata->_num_views != num_views) {
6993 cdata->_num_views = num_views;
6994 if (do_has_ram_image(cdata)) {
6995 cdata->inc_image_modified();
6996 do_clear_ram_image(cdata);
6998 do_set_pad_size(cdata, 0, 0, 0);
7006 do_set_wrap_u(CData *cdata, SamplerState::WrapMode wrap) {
7007 if (cdata->_default_sampler.get_wrap_u() != wrap) {
7008 cdata->inc_properties_modified();
7009 cdata->_default_sampler.set_wrap_u(wrap);
7017 do_set_wrap_v(CData *cdata, SamplerState::WrapMode wrap) {
7018 if (cdata->_default_sampler.get_wrap_v() != wrap) {
7019 cdata->inc_properties_modified();
7020 cdata->_default_sampler.set_wrap_v(wrap);
7028 do_set_wrap_w(CData *cdata, SamplerState::WrapMode wrap) {
7029 if (cdata->_default_sampler.get_wrap_w() != wrap) {
7030 cdata->inc_properties_modified();
7031 cdata->_default_sampler.set_wrap_w(wrap);
7039 do_set_minfilter(CData *cdata, SamplerState::FilterType filter) {
7040 if (cdata->_default_sampler.get_minfilter() != filter) {
7041 cdata->inc_properties_modified();
7042 cdata->_default_sampler.set_minfilter(filter);
7050 do_set_magfilter(CData *cdata, SamplerState::FilterType filter) {
7051 if (cdata->_default_sampler.get_magfilter() != filter) {
7052 cdata->inc_properties_modified();
7053 cdata->_default_sampler.set_magfilter(filter);
7061 do_set_anisotropic_degree(CData *cdata,
int anisotropic_degree) {
7062 if (cdata->_default_sampler.get_anisotropic_degree() != anisotropic_degree) {
7063 cdata->inc_properties_modified();
7064 cdata->_default_sampler.set_anisotropic_degree(anisotropic_degree);
7072 do_set_border_color(CData *cdata,
const LColor &color) {
7073 if (cdata->_default_sampler.get_border_color() != color) {
7074 cdata->inc_properties_modified();
7075 cdata->_default_sampler.set_border_color(color);
7083 do_set_compression(CData *cdata, Texture::CompressionMode compression) {
7084 if (cdata->_compression != compression) {
7085 cdata->inc_properties_modified();
7086 cdata->_compression = compression;
7088 if (do_has_ram_image(cdata)) {
7090 bool has_ram_image_compression = (cdata->_ram_image_compression != CM_off);
7105 do_set_quality_level(CData *cdata, Texture::QualityLevel quality_level) {
7106 if (cdata->_quality_level != quality_level) {
7107 cdata->inc_properties_modified();
7108 cdata->_quality_level = quality_level;
7116 do_has_compression(
const CData *cdata)
const {
7117 if (cdata->_compression == CM_default) {
7118 return compressed_textures;
7120 return (cdata->_compression != CM_off);
7129 do_has_ram_image(
const CData *cdata)
const {
7130 return !cdata->_ram_images.empty() && !cdata->_ram_images[0]._image.empty();
7138 do_has_uncompressed_ram_image(
const CData *cdata)
const {
7139 return !cdata->_ram_images.empty() && !cdata->_ram_images[0]._image.empty() && cdata->_ram_image_compression == CM_off;
7146 do_get_ram_image(CData *cdata) {
7147 if (!do_has_ram_image(cdata) && do_can_reload(cdata)) {
7148 do_reload_ram_image(cdata,
true);
7150 if (do_has_ram_image(cdata)) {
7154 cdata->inc_image_modified();
7155 cdata->inc_properties_modified();
7159 if (cdata->_ram_images.empty()) {
7163 return cdata->_ram_images[0]._image;
7170 do_get_uncompressed_ram_image(CData *cdata) {
7171 if (!cdata->_ram_images.empty() && cdata->_ram_image_compression != CM_off) {
7174 if (do_uncompress_ram_image(cdata)) {
7175 if (gobj_cat.is_debug()) {
7177 <<
"Uncompressed " << get_name() <<
"\n";
7179 return cdata->_ram_images[0]._image;
7184 if ((!do_has_ram_image(cdata) || cdata->_ram_image_compression != CM_off) && do_can_reload(cdata)) {
7185 do_reload_ram_image(cdata,
false);
7188 if (!cdata->_ram_images.empty() && cdata->_ram_image_compression != CM_off) {
7190 if (do_uncompress_ram_image(cdata)) {
7192 <<
"Uncompressed " << get_name() <<
"\n";
7193 return cdata->_ram_images[0]._image;
7197 if (cdata->_ram_images.empty() || cdata->_ram_image_compression != CM_off) {
7201 return cdata->_ram_images[0]._image;
7230 string format =
upcase(requested_format);
7233 CPTA_uchar data = do_get_uncompressed_ram_image(cdata);
7234 if (data ==
nullptr) {
7235 gobj_cat.error() <<
"Couldn't find an uncompressed RAM image!\n";
7238 int imgsize = cdata->_x_size * cdata->_y_size;
7239 nassertr(cdata->_num_components > 0 && cdata->_num_components <= 4,
CPTA_uchar(get_class_type()));
7240 nassertr(data.size() == (
size_t)(cdata->_component_width * cdata->_num_components * imgsize),
CPTA_uchar(get_class_type()));
7243 if ((cdata->_num_components == 1 && format.size() == 1) ||
7244 (cdata->_num_components == 2 && format.size() == 2 && format.at(1) ==
'A' && format.at(0) !=
'A') ||
7245 (cdata->_num_components == 3 && format ==
"BGR") ||
7246 (cdata->_num_components == 4 && format ==
"BGRA")) {
7254 alpha = cdata->_num_components - 1;
7258 for (
size_t i = 0; i < format.size(); ++i) {
7259 if (format[i] !=
'B' && format[i] !=
'G' && format[i] !=
'R' &&
7260 format[i] !=
'A' && format[i] !=
'0' && format[i] !=
'1') {
7261 gobj_cat.error() <<
"Unexpected component character '"
7262 << format[i] <<
"', expected one of RGBA01!\n";
7268 PTA_uchar newdata = PTA_uchar::empty_array(imgsize * format.size() * cdata->_component_width, get_class_type());
7271 if (cdata->_component_width == 1) {
7272 if (format ==
"RGBA" && cdata->_num_components == 4) {
7273 const uint32_t *src = (
const uint32_t *)data.p();
7274 uint32_t *dst = (uint32_t *)newdata.p();
7276 for (
int p = 0; p < imgsize; ++p) {
7277 uint32_t v = *src++;
7278 *dst++ = ((v & 0xff00ff00u)) |
7279 ((v & 0x00ff0000u) >> 16) |
7280 ((v & 0x000000ffu) << 16);
7284 if (format ==
"RGB" && cdata->_num_components == 4) {
7285 const uint32_t *src = (
const uint32_t *)data.p();
7286 uint32_t *dst = (uint32_t *)newdata.p();
7290 int blocks = imgsize >> 2;
7291 for (
int i = 0; i < blocks; ++i) {
7292 uint32_t v0 = *src++;
7293 uint32_t v1 = *src++;
7294 uint32_t v2 = *src++;
7295 uint32_t v3 = *src++;
7296 *dst++ = ((v0 & 0x00ff0000u) >> 16) |
7297 ((v0 & 0x0000ff00u)) |
7298 ((v0 & 0x000000ffu) << 16) |
7299 ((v1 & 0x00ff0000u) << 8);
7300 *dst++ = ((v1 & 0x0000ff00u) >> 8) |
7301 ((v1 & 0x000000ffu) << 8) |
7302 ((v2 & 0x00ff0000u)) |
7303 ((v2 & 0x0000ff00u) << 16);
7304 *dst++ = ((v2 & 0x000000ffu)) |
7305 ((v3 & 0x00ff0000u) >> 8) |
7306 ((v3 & 0x0000ff00u) << 8) |
7307 ((v3 & 0x000000ffu) << 24);
7312 uint8_t *tail = (uint8_t *)dst;
7313 for (
int i = (imgsize & ~0x3); i < imgsize; ++i) {
7314 uint32_t v = *src++;
7315 *tail++ = (v & 0x00ff0000u) >> 16;
7316 *tail++ = (v & 0x0000ff00u) >> 8;
7317 *tail++ = (v & 0x000000ffu);
7321 if (format ==
"BGR" && cdata->_num_components == 4) {
7322 const uint32_t *src = (
const uint32_t *)data.p();
7323 uint32_t *dst = (uint32_t *)newdata.p();
7327 int blocks = imgsize >> 2;
7328 for (
int i = 0; i < blocks; ++i) {
7329 uint32_t v0 = *src++;
7330 uint32_t v1 = *src++;
7331 uint32_t v2 = *src++;
7332 uint32_t v3 = *src++;
7333 *dst++ = (v0 & 0x00ffffffu) | ((v1 & 0x000000ffu) << 24);
7334 *dst++ = ((v1 & 0x00ffff00u) >> 8) | ((v2 & 0x0000ffffu) << 16);
7335 *dst++ = ((v2 & 0x00ff0000u) >> 16) | ((v3 & 0x00ffffffu) << 8);
7340 uint8_t *tail = (uint8_t *)dst;
7341 for (
int i = (imgsize & ~0x3); i < imgsize; ++i) {
7342 uint32_t v = *src++;
7343 *tail++ = (v & 0x000000ffu);
7344 *tail++ = (v & 0x0000ff00u) >> 8;
7345 *tail++ = (v & 0x00ff0000u) >> 16;
7349 const uint8_t *src = (
const uint8_t *)data.p();
7350 uint8_t *dst = (uint8_t *)newdata.p();
7352 if (format ==
"RGB" && cdata->_num_components == 3) {
7353 for (
int i = 0; i < imgsize; ++i) {
7361 if (format ==
"A" && cdata->_num_components != 3) {
7363 for (
int p = 0; p < imgsize; ++p) {
7364 dst[p] = src[alpha];
7365 src += cdata->_num_components;
7370 for (
int p = 0; p < imgsize; ++p) {
7371 for (
size_t i = 0; i < format.size(); ++i) {
7372 if (format[i] ==
'B' || (cdata->_num_components <= 2 && format[i] !=
'A')) {
7374 }
else if (format[i] ==
'G') {
7376 }
else if (format[i] ==
'R') {
7378 }
else if (format[i] ==
'A') {
7380 *dst++ = src[alpha];
7384 }
else if (format[i] ==
'1') {
7390 src += cdata->_num_components;
7396 for (
int p = 0; p < imgsize; ++p) {
7397 for (
size_t i = 0; i < format.size(); ++i) {
7399 if (format[i] ==
'B' || (cdata->_num_components <= 2 && format[i] !=
'A')) {
7401 }
else if (format[i] ==
'G') {
7403 }
else if (format[i] ==
'R') {
7405 }
else if (format[i] ==
'A') {
7409 memset((
void*)(newdata + (p * format.size() + i) * cdata->_component_width), -1, cdata->_component_width);
7412 }
else if (format[i] ==
'1') {
7413 memset((
void*)(newdata + (p * format.size() + i) * cdata->_component_width), -1, cdata->_component_width);
7416 memset((
void*)(newdata + (p * format.size() + i) * cdata->_component_width), 0, cdata->_component_width);
7419 memcpy((
void*)(newdata + (p * format.size() + i) * cdata->_component_width),
7420 (
void*)(data + (p * cdata->_num_components + component) * cdata->_component_width),
7421 cdata->_component_width);
7431 do_set_simple_ram_image(CData *cdata,
CPTA_uchar image,
int x_size,
int y_size) {
7432 nassertv(cdata->_texture_type == TT_2d_texture);
7433 size_t expected_page_size = (size_t)(x_size * y_size * 4);
7434 nassertv(image.size() == expected_page_size);
7436 cdata->_simple_x_size = x_size;
7437 cdata->_simple_y_size = y_size;
7439 cdata->_simple_ram_image._page_size = image.size();
7440 cdata->_simple_image_date_generated = (int32_t)time(
nullptr);
7441 cdata->inc_simple_image_modified();
7448 do_get_expected_num_mipmap_levels(
const CData *cdata)
const {
7449 if (cdata->_texture_type == Texture::TT_buffer_texture) {
7452 int size = max(cdata->_x_size, cdata->_y_size);
7453 if (cdata->_texture_type == Texture::TT_3d_texture) {
7454 size = max(size, cdata->_z_size);
7468 do_get_ram_mipmap_page_size(
const CData *cdata,
int n)
const {
7469 if (cdata->_ram_image_compression != CM_off) {
7470 if (n >= 0 && n < (
int)cdata->_ram_images.size()) {
7471 return cdata->_ram_images[n]._page_size;
7475 return do_get_expected_ram_mipmap_page_size(cdata, n);
7483 do_get_expected_mipmap_x_size(
const CData *cdata,
int n)
const {
7484 int size = max(cdata->_x_size, 1);
7485 while (n > 0 && size > 1) {
7496 do_get_expected_mipmap_y_size(
const CData *cdata,
int n)
const {
7497 int size = max(cdata->_y_size, 1);
7498 while (n > 0 && size > 1) {
7509 do_get_expected_mipmap_z_size(
const CData *cdata,
int n)
const {
7513 if (cdata->_texture_type == Texture::TT_3d_texture) {
7514 int size = max(cdata->_z_size, 1);
7515 while (n > 0 && size > 1) {
7522 return cdata->_z_size;
7530 do_clear_simple_ram_image(CData *cdata) {
7531 cdata->_simple_x_size = 0;
7532 cdata->_simple_y_size = 0;
7533 cdata->_simple_ram_image._image.clear();
7534 cdata->_simple_ram_image._page_size = 0;
7535 cdata->_simple_image_date_generated = 0;
7540 cdata->inc_simple_image_modified();
7547 do_clear_ram_mipmap_images(CData *cdata) {
7548 if (!cdata->_ram_images.empty()) {
7549 cdata->_ram_images.erase(cdata->_ram_images.begin() + 1, cdata->_ram_images.end());
7559 do_generate_ram_mipmap_images(CData *cdata,
bool allow_recompress) {
7560 nassertv(do_has_ram_image(cdata));
7562 if (do_get_expected_num_mipmap_levels(cdata) == 1) {
7567 RamImage orig_compressed_image;
7568 CompressionMode orig_compression_mode = CM_off;
7570 if (cdata->_ram_image_compression != CM_off) {
7574 orig_compressed_image = cdata->_ram_images[0];
7575 orig_compression_mode = cdata->_ram_image_compression;
7578 do_get_uncompressed_ram_image(cdata);
7580 if (cdata->_ram_image_compression != CM_off) {
7582 <<
"Cannot generate mipmap levels for image with compression "
7583 << cdata->_ram_image_compression <<
"\n";
7588 do_clear_ram_mipmap_images(cdata);
7590 if (gobj_cat.is_debug()) {
7592 <<
"Generating mipmap levels for " << *
this <<
"\n";
7595 if (cdata->_texture_type == Texture::TT_3d_texture && cdata->_z_size != 1) {
7597 int x_size = cdata->_x_size;
7598 int y_size = cdata->_y_size;
7599 int z_size = cdata->_z_size;
7601 while (x_size > 1 || y_size > 1 || z_size > 1) {
7602 cdata->_ram_images.push_back(RamImage());
7603 do_filter_3d_mipmap_level(cdata, cdata->_ram_images[n + 1], cdata->_ram_images[n],
7604 x_size, y_size, z_size);
7605 x_size = max(x_size >> 1, 1);
7606 y_size = max(y_size >> 1, 1);
7607 z_size = max(z_size >> 1, 1);
7613 int x_size = cdata->_x_size;
7614 int y_size = cdata->_y_size;
7616 while (x_size > 1 || y_size > 1) {
7617 cdata->_ram_images.push_back(RamImage());
7618 do_filter_2d_mipmap_pages(cdata, cdata->_ram_images[n + 1], cdata->_ram_images[n],
7620 x_size = max(x_size >> 1, 1);
7621 y_size = max(y_size >> 1, 1);
7626 if (orig_compression_mode != CM_off && allow_recompress) {
7632 nassertv(cdata->_ram_images.size() > 1);
7633 int l0_x_size = cdata->_x_size;
7634 int l0_y_size = cdata->_y_size;
7635 int l0_z_size = cdata->_z_size;
7636 cdata->_x_size = do_get_expected_mipmap_x_size(cdata, 1);
7637 cdata->_y_size = do_get_expected_mipmap_y_size(cdata, 1);
7638 cdata->_z_size = do_get_expected_mipmap_z_size(cdata, 1);
7639 RamImage uncompressed_image = cdata->_ram_images[0];
7640 cdata->_ram_images.erase(cdata->_ram_images.begin());
7642 bool success = do_compress_ram_image(cdata, orig_compression_mode, QL_default,
nullptr);
7645 if (gobj_cat.is_debug()) {
7647 <<
"Compressed " << get_name() <<
" generated mipmaps with "
7648 << cdata->_ram_image_compression <<
"\n";
7650 cdata->_ram_images.insert(cdata->_ram_images.begin(), orig_compressed_image);
7652 cdata->_ram_images.insert(cdata->_ram_images.begin(), uncompressed_image);
7654 cdata->_x_size = l0_x_size;
7655 cdata->_y_size = l0_y_size;
7656 cdata->_z_size = l0_z_size;
7664 do_set_pad_size(CData *cdata,
int x,
int y,
int z) {
7665 if (x > cdata->_x_size) {
7668 if (y > cdata->_y_size) {
7671 if (z > cdata->_z_size) {
7675 cdata->_pad_x_size = x;
7676 cdata->_pad_y_size = y;
7677 cdata->_pad_z_size = z;
7686 do_can_reload(
const CData *cdata)
const {
7687 return (cdata->_loaded_from_image && !cdata->_fullpath.empty());
7694 do_reload(CData *cdata) {
7695 if (do_can_reload(cdata)) {
7696 do_clear_ram_image(cdata);
7697 do_reload_ram_image(cdata,
true);
7698 if (do_has_ram_image(cdata)) {
7700 cdata->inc_image_modified();
7716 do_has_bam_rawdata(
const CData *cdata)
const {
7717 return do_has_ram_image(cdata);
7725 do_get_bam_rawdata(CData *cdata) {
7726 do_get_ram_image(cdata);
7734 convert_from_pnmimage(PTA_uchar &image,
size_t page_size,
7735 int row_stride,
int x,
int y,
int z,
7736 const PNMImage &pnmimage,
int num_components,
7737 int component_width) {
7741 int pixel_size = num_components * component_width;
7744 if (row_stride == 0) {
7745 row_stride = x_size;
7747 row_skip = (row_stride - x_size) * pixel_size;
7748 nassertv(row_skip >= 0);
7751 bool is_grayscale = (num_components == 1 || num_components == 2);
7752 bool has_alpha = (num_components == 2 || num_components == 4);
7753 bool img_has_alpha = pnmimage.
has_alpha();
7755 int idx = page_size * z;
7756 nassertv(idx + page_size <= image.size());
7757 unsigned char *p = &image[idx];
7759 if (x != 0 || y != 0) {
7760 p += (row_stride * y + x) * pixel_size;
7763 if (maxval == 255 && component_width == 1) {
7768 switch (num_components) {
7770 for (
int j = y_size-1; j >= 0; j--) {
7771 const xel *row = array + j * x_size;
7772 for (
int i = 0; i < x_size; i++) {
7773 *p++ = (uchar)PPM_GETB(row[i]);
7780 if (img_has_alpha) {
7782 for (
int j = y_size-1; j >= 0; j--) {
7783 const xel *row = array + j * x_size;
7784 const xelval *alpha_row = alpha + j * x_size;
7785 for (
int i = 0; i < x_size; i++) {
7786 *p++ = (uchar)PPM_GETB(row[i]);
7787 *p++ = (uchar)alpha_row[i];
7792 for (
int j = y_size-1; j >= 0; j--) {
7793 const xel *row = array + j * x_size;
7794 for (
int i = 0; i < x_size; i++) {
7795 *p++ = (uchar)PPM_GETB(row[i]);
7804 for (
int j = y_size-1; j >= 0; j--) {
7805 const xel *row = array + j * x_size;
7806 for (
int i = 0; i < x_size; i++) {
7807 *p++ = (uchar)PPM_GETB(row[i]);
7808 *p++ = (uchar)PPM_GETG(row[i]);
7809 *p++ = (uchar)PPM_GETR(row[i]);
7816 if (img_has_alpha) {
7818 for (
int j = y_size-1; j >= 0; j--) {
7819 const xel *row = array + j * x_size;
7820 const xelval *alpha_row = alpha + j * x_size;
7821 for (
int i = 0; i < x_size; i++) {
7822 *p++ = (uchar)PPM_GETB(row[i]);
7823 *p++ = (uchar)PPM_GETG(row[i]);
7824 *p++ = (uchar)PPM_GETR(row[i]);
7825 *p++ = (uchar)alpha_row[i];
7830 for (
int j = y_size-1; j >= 0; j--) {
7831 const xel *row = array + j * x_size;
7832 for (
int i = 0; i < x_size; i++) {
7833 *p++ = (uchar)PPM_GETB(row[i]);
7834 *p++ = (uchar)PPM_GETG(row[i]);
7835 *p++ = (uchar)PPM_GETR(row[i]);
7844 nassertv(num_components >= 1 && num_components <= 4);
7848 }
else if (maxval == 65535 && component_width == 2) {
7851 for (
int j = y_size-1; j >= 0; j--) {
7852 for (
int i = 0; i < x_size; i++) {
7858 store_unscaled_short(p, pnmimage.
get_red_val(i, j));
7861 if (img_has_alpha) {
7864 store_unscaled_short(p, 65535);
7871 }
else if (component_width == 1) {
7875 double scale = 255.0 / (double)maxval;
7877 for (
int j = y_size-1; j >= 0; j--) {
7878 for (
int i = 0; i < x_size; i++) {
7880 store_scaled_byte(p, pnmimage.
get_gray_val(i, j), scale);
7882 store_scaled_byte(p, pnmimage.
get_blue_val(i, j), scale);
7884 store_scaled_byte(p, pnmimage.
get_red_val(i, j), scale);
7887 if (img_has_alpha) {
7890 store_unscaled_byte(p, 255);
7900 double scale = 65535.0 / (double)maxval;
7902 for (
int j = y_size-1; j >= 0; j--) {
7903 for (
int i = 0; i < x_size; i++) {
7905 store_scaled_short(p, pnmimage.
get_gray_val(i, j), scale);
7907 store_scaled_short(p, pnmimage.
get_blue_val(i, j), scale);
7909 store_scaled_short(p, pnmimage.
get_red_val(i, j), scale);
7912 if (img_has_alpha) {
7915 store_unscaled_short(p, 65535);
7929 convert_from_pfm(PTA_uchar &image,
size_t page_size,
int z,
7930 const PfmFile &pfm,
int num_components,
int component_width) {
7931 nassertv(component_width == 4);
7935 int idx = page_size * z;
7936 nassertv(idx + page_size <= image.size());
7937 PN_float32 *p = (PN_float32 *)&image[idx];
7939 switch (num_components) {
7942 for (
int j = y_size-1; j >= 0; j--) {
7943 for (
int i = 0; i < x_size; i++) {
7953 for (
int j = y_size-1; j >= 0; j--) {
7954 for (
int i = 0; i < x_size; i++) {
7966 for (
int j = y_size-1; j >= 0; j--) {
7967 for (
int i = 0; i < x_size; i++) {
7980 for (
int j = y_size-1; j >= 0; j--) {
7981 for (
int i = 0; i < x_size; i++) {
7993 nassert_raise(
"unexpected channel count");
7997 nassertv((
unsigned char *)p == &image[idx] + page_size);
8005 convert_to_pnmimage(
PNMImage &pnmimage,
int x_size,
int y_size,
8006 int num_components, ComponentType component_type,
8007 bool is_srgb,
CPTA_uchar image,
size_t page_size,
int z) {
8008 xelval maxval = 0xff;
8009 if (component_type != T_unsigned_byte && component_type != T_byte) {
8012 ColorSpace color_space =
is_srgb ? CS_sRGB : CS_linear;
8013 pnmimage.
clear(x_size, y_size, num_components, maxval,
nullptr, color_space);
8017 int idx = page_size * z;
8018 nassertr(idx + page_size <= image.size(),
false);
8023 switch (component_type) {
8024 case T_unsigned_byte:
8026 const unsigned char *p = &image[idx];
8028 for (
int j = y_size-1; j >= 0; j--) {
8029 xel *row = array + j * x_size;
8030 xelval *alpha_row = alpha + j * x_size;
8031 for (
int i = 0; i < x_size; i++) {
8032 PPM_PUTB(row[i], *p++);
8033 alpha_row[i] = *p++;
8037 for (
int j = y_size-1; j >= 0; j--) {
8038 xel *row = array + j * x_size;
8039 for (
int i = 0; i < x_size; i++) {
8040 PPM_PUTB(row[i], *p++);
8044 nassertr(p == &image[idx] + page_size,
false);
8046 const unsigned char *p = &image[idx];
8048 for (
int j = y_size-1; j >= 0; j--) {
8049 xel *row = array + j * x_size;
8050 xelval *alpha_row = alpha + j * x_size;
8051 for (
int i = 0; i < x_size; i++) {
8052 PPM_PUTB(row[i], *p++);
8053 PPM_PUTG(row[i], *p++);
8054 PPM_PUTR(row[i], *p++);
8055 alpha_row[i] = *p++;
8059 for (
int j = y_size-1; j >= 0; j--) {
8060 xel *row = array + j * x_size;
8061 for (
int i = 0; i < x_size; i++) {
8062 PPM_PUTB(row[i], *p++);
8063 PPM_PUTG(row[i], *p++);
8064 PPM_PUTR(row[i], *p++);
8068 nassertr(p == &image[idx] + page_size,
false);
8072 case T_unsigned_short:
8074 const uint16_t *p = (
const uint16_t *)&image[idx];
8076 for (
int j = y_size-1; j >= 0; j--) {
8077 xel *row = array + j * x_size;
8078 xelval *alpha_row = alpha + j * x_size;
8079 for (
int i = 0; i < x_size; i++) {
8080 PPM_PUTB(row[i], *p++);
8081 if (!is_grayscale) {
8082 PPM_PUTG(row[i], *p++);
8083 PPM_PUTR(row[i], *p++);
8086 alpha_row[i] = *p++;
8090 nassertr((
const unsigned char *)p == &image[idx] + page_size,
false);
8094 case T_unsigned_int:
8096 const uint32_t *p = (
const uint32_t *)&image[idx];
8098 for (
int j = y_size-1; j >= 0; j--) {
8099 xel *row = array + j * x_size;
8100 xelval *alpha_row = alpha + j * x_size;
8101 for (
int i = 0; i < x_size; i++) {
8102 PPM_PUTB(row[i], (*p++) >> 16u);
8103 if (!is_grayscale) {
8104 PPM_PUTG(row[i], (*p++) >> 16u);
8105 PPM_PUTR(row[i], (*p++) >> 16u);
8108 alpha_row[i] = (*p++) >> 16u;
8112 nassertr((
const unsigned char *)p == &image[idx] + page_size,
false);
8118 const unsigned char *p = &image[idx];
8120 for (
int j = y_size-1; j >= 0; j--) {
8121 for (
int i = 0; i < x_size; i++) {
8122 pnmimage.
set_blue(i, j, get_half_float(p));
8123 if (!is_grayscale) {
8124 pnmimage.
set_green(i, j, get_half_float(p));
8125 pnmimage.
set_red(i, j, get_half_float(p));
8128 pnmimage.
set_alpha(i, j, get_half_float(p));
8132 nassertr(p == &image[idx] + page_size,
false);
8148 convert_to_pfm(
PfmFile &pfm,
int x_size,
int y_size,
8149 int num_components,
int component_width,
8151 nassertr(component_width == 4,
false);
8152 pfm.
clear(x_size, y_size, num_components);
8154 int idx = page_size * z;
8155 nassertr(idx + page_size <= image.size(),
false);
8156 const PN_float32 *p = (
const PN_float32 *)&image[idx];
8158 switch (num_components) {
8160 for (
int j = y_size-1; j >= 0; j--) {
8161 for (
int i = 0; i < x_size; i++) {
8169 for (
int j = y_size-1; j >= 0; j--) {
8170 for (
int i = 0; i < x_size; i++) {
8180 for (
int j = y_size-1; j >= 0; j--) {
8181 for (
int i = 0; i < x_size; i++) {
8192 for (
int j = y_size-1; j >= 0; j--) {
8193 for (
int i = 0; i < x_size; i++) {
8204 nassert_raise(
"unexpected channel count");
8208 nassertr((
unsigned char *)p == &image[idx] + page_size,
false);
8216 read_dds_level_bgr8(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
8218 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8219 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8221 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
8222 size_t row_bytes = x_size * 3;
8223 PTA_uchar image = PTA_uchar::empty_array(size);
8224 for (
int y = y_size - 1; y >= 0; --y) {
8225 unsigned char *p = image.p() + y * row_bytes;
8226 nassertr(p + row_bytes <= image.p() + size, PTA_uchar());
8227 in.read((
char *)p, row_bytes);
8237 read_dds_level_rgb8(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
8239 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8240 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8242 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
8243 size_t row_bytes = x_size * 3;
8244 PTA_uchar image = PTA_uchar::empty_array(size);
8245 for (
int y = y_size - 1; y >= 0; --y) {
8246 unsigned char *p = image.p() + y * row_bytes;
8247 nassertr(p + row_bytes <= image.p() + size, PTA_uchar());
8248 in.read((
char *)p, row_bytes);
8251 for (
int x = 0; x < x_size; ++x) {
8252 unsigned char r = p[0];
8257 nassertr(p <= image.p() + size, PTA_uchar());
8267 read_dds_level_abgr8(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
8269 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8270 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8272 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
8273 size_t row_bytes = x_size * 4;
8274 PTA_uchar image = PTA_uchar::empty_array(size);
8275 for (
int y = y_size - 1; y >= 0; --y) {
8276 unsigned char *p = image.p() + y * row_bytes;
8277 in.read((
char *)p, row_bytes);
8279 uint32_t *pw = (uint32_t *)p;
8280 for (
int x = 0; x < x_size; ++x) {
8282 #ifdef WORDS_BIGENDIAN
8284 w = ((w & 0xff00) << 16) | ((w & 0xff000000U) >> 16) | (w & 0xff00ff);
8287 w = ((w & 0xff) << 16) | ((w & 0xff0000) >> 16) | (w & 0xff00ff00U);
8292 nassertr((
unsigned char *)pw <= image.p() + size, PTA_uchar());
8302 read_dds_level_rgba8(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
8304 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8305 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8307 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
8308 size_t row_bytes = x_size * 4;
8309 PTA_uchar image = PTA_uchar::empty_array(size);
8310 for (
int y = y_size - 1; y >= 0; --y) {
8311 unsigned char *p = image.p() + y * row_bytes;
8312 nassertr(p + row_bytes <= image.p() + size, PTA_uchar());
8313 in.read((
char *)p, row_bytes);
8323 read_dds_level_abgr16(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
8325 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8326 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8328 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
8329 size_t row_bytes = x_size * 8;
8330 PTA_uchar image = PTA_uchar::empty_array(size);
8331 for (
int y = y_size - 1; y >= 0; --y) {
8332 unsigned char *p = image.p() + y * row_bytes;
8333 in.read((
char *)p, row_bytes);
8335 uint16_t *pw = (uint16_t *)p;
8336 for (
int x = 0; x < x_size; ++x) {
8340 nassertr((
unsigned char *)pw <= image.p() + size, PTA_uchar());
8350 read_dds_level_abgr32(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
8352 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8353 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8355 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
8356 size_t row_bytes = x_size * 16;
8357 nassertr(row_bytes * y_size == size, PTA_uchar());
8358 PTA_uchar image = PTA_uchar::empty_array(size);
8359 for (
int y = y_size - 1; y >= 0; --y) {
8360 unsigned char *p = image.p() + y * row_bytes;
8361 in.read((
char *)p, row_bytes);
8363 uint32_t *pw = (uint32_t *)p;
8364 for (
int x = 0; x < x_size; ++x) {
8368 nassertr((
unsigned char *)pw <= image.p() + size, PTA_uchar());
8378 read_dds_level_raw(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
8379 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8380 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8382 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
8383 size_t row_bytes = x_size * cdata->_num_components * cdata->_component_width;
8384 nassertr(row_bytes * y_size == size, PTA_uchar());
8385 PTA_uchar image = PTA_uchar::empty_array(size);
8386 for (
int y = y_size - 1; y >= 0; --y) {
8387 unsigned char *p = image.p() + y * row_bytes;
8388 in.read((
char *)p, row_bytes);
8399 read_dds_level_generic_uncompressed(
Texture *tex, CData *cdata,
const DDSHeader &header,
8400 int n, istream &in) {
8401 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8402 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8404 int pitch = (x_size * header.pf.rgb_bitcount) / 8;
8411 pitch = ((pitch + 3) / 4) * 4;
8412 if (header.dds_flags & DDSD_PITCH) {
8413 pitch = header.pitch;
8417 int bpp = header.pf.rgb_bitcount / 8;
8418 int skip_bytes = pitch - (bpp * x_size);
8419 nassertr(skip_bytes >= 0, PTA_uchar());
8421 unsigned int r_mask = header.pf.r_mask;
8422 unsigned int g_mask = header.pf.g_mask;
8423 unsigned int b_mask = header.pf.b_mask;
8424 unsigned int a_mask = header.pf.a_mask;
8435 unsigned int r_scale = 0;
8437 r_scale = 0xff000000 / (r_mask >> r_shift);
8439 unsigned int g_scale = 0;
8441 g_scale = 0xff000000 / (g_mask >> g_shift);
8443 unsigned int b_scale = 0;
8445 b_scale = 0xff000000 / (b_mask >> b_shift);
8447 unsigned int a_scale = 0;
8449 a_scale = 0xff000000 / (a_mask >> a_shift);
8452 bool add_alpha =
has_alpha(cdata->_format);
8454 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
8455 size_t row_bytes = x_size * cdata->_num_components;
8456 PTA_uchar image = PTA_uchar::empty_array(size);
8457 for (
int y = y_size - 1; y >= 0; --y) {
8458 unsigned char *p = image.p() + y * row_bytes;
8459 for (
int x = 0; x < x_size; ++x) {
8462 unsigned int pixel = 0;
8464 for (
int bi = 0; bi < bpp; ++bi) {
8465 unsigned int ch = (
unsigned char)in.get();
8466 pixel |= (ch << shift);
8471 unsigned int r = (((
pixel & r_mask) >> r_shift) * r_scale) >> 24;
8472 unsigned int g = (((
pixel & g_mask) >> g_shift) * g_scale) >> 24;
8473 unsigned int b = (((
pixel & b_mask) >> b_shift) * b_scale) >> 24;
8476 store_unscaled_byte(p, b);
8477 store_unscaled_byte(p, g);
8478 store_unscaled_byte(p, r);
8480 unsigned int a = (((
pixel & a_mask) >> a_shift) * a_scale) >> 24;
8481 store_unscaled_byte(p, a);
8484 nassertr(p <= image.p() + size, PTA_uchar());
8485 for (
int bi = 0; bi < skip_bytes; ++bi) {
8498 read_dds_level_luminance_uncompressed(
Texture *tex, CData *cdata,
const DDSHeader &header,
8499 int n, istream &in) {
8500 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8501 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8503 int pitch = (x_size * header.pf.rgb_bitcount) / 8;
8510 pitch = ((pitch + 3) / 4) * 4;
8511 if (header.dds_flags & DDSD_PITCH) {
8512 pitch = header.pitch;
8516 int bpp = header.pf.rgb_bitcount / 8;
8517 int skip_bytes = pitch - (bpp * x_size);
8518 nassertr(skip_bytes >= 0, PTA_uchar());
8520 unsigned int r_mask = header.pf.r_mask;
8521 unsigned int a_mask = header.pf.a_mask;
8530 unsigned int r_scale = 0;
8532 r_scale = 0xff000000 / (r_mask >> r_shift);
8534 unsigned int a_scale = 0;
8536 a_scale = 0xff000000 / (a_mask >> a_shift);
8539 bool add_alpha =
has_alpha(cdata->_format);
8541 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
8542 size_t row_bytes = x_size * cdata->_num_components;
8543 PTA_uchar image = PTA_uchar::empty_array(size);
8544 for (
int y = y_size - 1; y >= 0; --y) {
8545 unsigned char *p = image.p() + y * row_bytes;
8546 for (
int x = 0; x < x_size; ++x) {
8549 unsigned int pixel = 0;
8551 for (
int bi = 0; bi < bpp; ++bi) {
8552 unsigned int ch = (
unsigned char)in.get();
8553 pixel |= (ch << shift);
8557 unsigned int r = (((
pixel & r_mask) >> r_shift) * r_scale) >> 24;
8560 store_unscaled_byte(p, r);
8562 unsigned int a = (((
pixel & a_mask) >> a_shift) * a_scale) >> 24;
8563 store_unscaled_byte(p, a);
8566 nassertr(p <= image.p() + size, PTA_uchar());
8567 for (
int bi = 0; bi < skip_bytes; ++bi) {
8579 read_dds_level_bc1(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
8580 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8581 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8583 static const int div = 4;
8584 static const int block_bytes = 8;
8588 int num_cols = max(div, x_size) / div;
8589 int num_rows = max(div, y_size) / div;
8590 int row_length = num_cols * block_bytes;
8591 int linear_size = row_length * num_rows;
8594 if (header.dds_flags & DDSD_LINEARSIZE) {
8595 nassertr(linear_size == (
int)header.pitch, PTA_uchar());
8599 PTA_uchar image = PTA_uchar::empty_array(linear_size);
8605 for (
int ri = num_rows - 1; ri >= 0; --ri) {
8606 unsigned char *p = image.p() + row_length * ri;
8607 in.read((
char *)p, row_length);
8609 for (
int ci = 0; ci < num_cols; ++ci) {
8612 uint32_t *cells = (uint32_t *)p;
8613 uint32_t w = cells[1];
8614 w = ((w & 0xff) << 24) | ((w & 0xff00) << 8) | ((w & 0xff0000) >> 8) | ((w & 0xff000000U) >> 24);
8621 }
else if (y_size >= 2) {
8623 unsigned char *p = image.p();
8624 in.read((
char *)p, row_length);
8626 for (
int ci = 0; ci < num_cols; ++ci) {
8627 uint32_t *cells = (uint32_t *)p;
8628 uint32_t w = cells[1];
8629 w = ((w & 0xff) << 8) | ((w & 0xff00) >> 8);
8635 }
else if (y_size >= 1) {
8637 unsigned char *p = image.p();
8638 in.read((
char *)p, row_length);
8648 read_dds_level_bc2(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
8649 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8650 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8652 static const int div = 4;
8653 static const int block_bytes = 16;
8658 int num_cols = max(div, x_size) / div;
8659 int num_rows = max(div, y_size) / div;
8660 int row_length = num_cols * block_bytes;
8661 int linear_size = row_length * num_rows;
8664 if (header.dds_flags & DDSD_LINEARSIZE) {
8665 nassertr(linear_size == (
int)header.pitch, PTA_uchar());
8669 PTA_uchar image = PTA_uchar::empty_array(linear_size);
8675 for (
int ri = num_rows - 1; ri >= 0; --ri) {
8676 unsigned char *p = image.p() + row_length * ri;
8677 in.read((
char *)p, row_length);
8679 for (
int ci = 0; ci < num_cols; ++ci) {
8682 uint32_t *cells = (uint32_t *)p;
8685 uint32_t w0 = cells[0];
8686 uint32_t w1 = cells[1];
8687 w0 = ((w0 & 0xffff) << 16) | ((w0 & 0xffff0000U) >> 16);
8688 w1 = ((w1 & 0xffff) << 16) | ((w1 & 0xffff0000U) >> 16);
8694 uint32_t w = cells[3];
8695 w = ((w & 0xff) << 24) | ((w & 0xff00) << 8) | ((w & 0xff0000) >> 8) | ((w & 0xff000000U) >> 24);
8702 }
else if (y_size >= 2) {
8704 unsigned char *p = image.p();
8705 in.read((
char *)p, row_length);
8707 for (
int ci = 0; ci < num_cols; ++ci) {
8708 uint32_t *cells = (uint32_t *)p;
8710 uint32_t w0 = cells[0];
8711 w0 = ((w0 & 0xffff) << 16) | ((w0 & 0xffff0000U) >> 16);
8714 uint32_t w = cells[3];
8715 w = ((w & 0xff) << 8) | ((w & 0xff00) >> 8);
8721 }
else if (y_size >= 1) {
8723 unsigned char *p = image.p();
8724 in.read((
char *)p, row_length);
8734 read_dds_level_bc3(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
8735 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8736 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8738 static const int div = 4;
8739 static const int block_bytes = 16;
8744 int num_cols = max(div, x_size) / div;
8745 int num_rows = max(div, y_size) / div;
8746 int row_length = num_cols * block_bytes;
8747 int linear_size = row_length * num_rows;
8750 if (header.dds_flags & DDSD_LINEARSIZE) {
8751 nassertr(linear_size == (
int)header.pitch, PTA_uchar());
8755 PTA_uchar image = PTA_uchar::empty_array(linear_size);
8761 for (
int ri = num_rows - 1; ri >= 0; --ri) {
8762 unsigned char *p = image.p() + row_length * ri;
8763 in.read((
char *)p, row_length);
8765 for (
int ci = 0; ci < num_cols; ++ci) {
8768 uint32_t *cells = (uint32_t *)p;
8772 unsigned char p2 = p[2];
8773 unsigned char p3 = p[3];
8774 unsigned char p4 = p[4];
8775 unsigned char p5 = p[5];
8776 unsigned char p6 = p[6];
8777 unsigned char p7 = p[7];
8779 p[2] = ((p7 & 0xf) << 4) | ((p6 & 0xf0) >> 4);
8780 p[3] = ((p5 & 0xf) << 4) | ((p7 & 0xf0) >> 4);
8781 p[4] = ((p6 & 0xf) << 4) | ((p5 & 0xf0) >> 4);
8782 p[5] = ((p4 & 0xf) << 4) | ((p3 & 0xf0) >> 4);
8783 p[6] = ((p2 & 0xf) << 4) | ((p4 & 0xf0) >> 4);
8784 p[7] = ((p3 & 0xf) << 4) | ((p2 & 0xf0) >> 4);
8788 uint32_t w = cells[3];
8789 w = ((w & 0xff) << 24) | ((w & 0xff00) << 8) | ((w & 0xff0000) >> 8) | ((w & 0xff000000U) >> 24);
8796 }
else if (y_size >= 2) {
8798 unsigned char *p = image.p();
8799 in.read((
char *)p, row_length);
8801 for (
int ci = 0; ci < num_cols; ++ci) {
8802 uint32_t *cells = (uint32_t *)p;
8804 unsigned char p2 = p[2];
8805 unsigned char p3 = p[3];
8806 unsigned char p4 = p[4];
8808 p[2] = ((p4 & 0xf) << 4) | ((p3 & 0xf0) >> 4);
8809 p[3] = ((p2 & 0xf) << 4) | ((p4 & 0xf0) >> 4);
8810 p[4] = ((p3 & 0xf) << 4) | ((p2 & 0xf0) >> 4);
8812 uint32_t w0 = cells[0];
8813 w0 = ((w0 & 0xffff) << 16) | ((w0 & 0xffff0000U) >> 16);
8816 uint32_t w = cells[3];
8817 w = ((w & 0xff) << 8) | ((w & 0xff00) >> 8);
8823 }
else if (y_size >= 1) {
8825 unsigned char *p = image.p();
8826 in.read((
char *)p, row_length);
8836 read_dds_level_bc4(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
8837 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8838 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8840 static const int div = 4;
8841 static const int block_bytes = 8;
8845 int num_cols = max(div, x_size) / div;
8846 int num_rows = max(div, y_size) / div;
8847 int row_length = num_cols * block_bytes;
8848 int linear_size = row_length * num_rows;
8851 if (header.dds_flags & DDSD_LINEARSIZE) {
8852 nassertr(linear_size == (
int)header.pitch, PTA_uchar());
8856 PTA_uchar image = PTA_uchar::empty_array(linear_size);
8862 for (
int ri = num_rows - 1; ri >= 0; --ri) {
8863 unsigned char *p = image.p() + row_length * ri;
8864 in.read((
char *)p, row_length);
8866 for (
int ci = 0; ci < num_cols; ++ci) {
8871 unsigned char p2 = p[2];
8872 unsigned char p3 = p[3];
8873 unsigned char p4 = p[4];
8874 unsigned char p5 = p[5];
8875 unsigned char p6 = p[6];
8876 unsigned char p7 = p[7];
8878 p[2] = ((p7 & 0xf) << 4) | ((p6 & 0xf0) >> 4);
8879 p[3] = ((p5 & 0xf) << 4) | ((p7 & 0xf0) >> 4);
8880 p[4] = ((p6 & 0xf) << 4) | ((p5 & 0xf0) >> 4);
8881 p[5] = ((p4 & 0xf) << 4) | ((p3 & 0xf0) >> 4);
8882 p[6] = ((p2 & 0xf) << 4) | ((p4 & 0xf0) >> 4);
8883 p[7] = ((p3 & 0xf) << 4) | ((p2 & 0xf0) >> 4);
8889 }
else if (y_size >= 2) {
8891 unsigned char *p = image.p();
8892 in.read((
char *)p, row_length);
8894 for (
int ci = 0; ci < num_cols; ++ci) {
8895 unsigned char p2 = p[2];
8896 unsigned char p3 = p[3];
8897 unsigned char p4 = p[4];
8899 p[2] = ((p4 & 0xf) << 4) | ((p3 & 0xf0) >> 4);
8900 p[3] = ((p2 & 0xf) << 4) | ((p4 & 0xf0) >> 4);
8901 p[4] = ((p3 & 0xf) << 4) | ((p2 & 0xf0) >> 4);
8906 }
else if (y_size >= 1) {
8908 unsigned char *p = image.p();
8909 in.read((
char *)p, row_length);
8919 read_dds_level_bc5(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
8920 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8921 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8925 int num_cols = max(4, x_size) / 2;
8926 int num_rows = max(4, y_size) / 4;
8927 int row_length = num_cols * 8;
8928 int linear_size = row_length * num_rows;
8931 if (header.dds_flags & DDSD_LINEARSIZE) {
8932 nassertr(linear_size == (
int)header.pitch, PTA_uchar());
8936 PTA_uchar image = PTA_uchar::empty_array(linear_size);
8942 for (
int ri = num_rows - 1; ri >= 0; --ri) {
8943 unsigned char *p = image.p() + row_length * ri;
8944 in.read((
char *)p, row_length);
8946 for (
int ci = 0; ci < num_cols; ++ci) {
8951 unsigned char p2 = p[2];
8952 unsigned char p3 = p[3];
8953 unsigned char p4 = p[4];
8954 unsigned char p5 = p[5];
8955 unsigned char p6 = p[6];
8956 unsigned char p7 = p[7];
8958 p[2] = ((p7 & 0xf) << 4) | ((p6 & 0xf0) >> 4);
8959 p[3] = ((p5 & 0xf) << 4) | ((p7 & 0xf0) >> 4);
8960 p[4] = ((p6 & 0xf) << 4) | ((p5 & 0xf0) >> 4);
8961 p[5] = ((p4 & 0xf) << 4) | ((p3 & 0xf0) >> 4);
8962 p[6] = ((p2 & 0xf) << 4) | ((p4 & 0xf0) >> 4);
8963 p[7] = ((p3 & 0xf) << 4) | ((p2 & 0xf0) >> 4);
8969 }
else if (y_size >= 2) {
8971 unsigned char *p = image.p();
8972 in.read((
char *)p, row_length);
8974 for (
int ci = 0; ci < num_cols; ++ci) {
8975 unsigned char p2 = p[2];
8976 unsigned char p3 = p[3];
8977 unsigned char p4 = p[4];
8979 p[2] = ((p4 & 0xf) << 4) | ((p3 & 0xf0) >> 4);
8980 p[3] = ((p2 & 0xf) << 4) | ((p4 & 0xf0) >> 4);
8981 p[4] = ((p3 & 0xf) << 4) | ((p2 & 0xf0) >> 4);
8986 }
else if (y_size >= 1) {
8988 unsigned char *p = image.p();
8989 in.read((
char *)p, row_length);
9003 PreparedViews::iterator pvi;
9004 pvi = _prepared_views.find(prepared_objects);
9005 if (pvi != _prepared_views.end()) {
9006 Contexts &contexts = (*pvi).second;
9007 Contexts::iterator ci;
9008 ci = contexts.find(view);
9009 if (ci != contexts.end()) {
9013 if (contexts.empty()) {
9014 _prepared_views.erase(pvi);
9024 consider_downgrade(
PNMImage &pnmimage,
int num_channels,
const string &name) {
9033 <<
"Downgrading " << name <<
" from "
9035 << num_channels <<
".\n";
9060 for (
int yi = 0; yi < a.
get_y_size(); ++yi) {
9061 const xel *a_row = a_array + yi * x_size;
9062 const xel *b_row = b_array + yi * x_size;
9063 const xelval *a_alpha_row = a_alpha + yi * x_size;
9064 const xelval *b_alpha_row = b_alpha + yi * x_size;
9065 for (
int xi = 0; xi < x_size; ++xi) {
9066 delta += abs(PPM_GETR(a_row[xi]) - PPM_GETR(b_row[xi]));
9067 delta += abs(PPM_GETG(a_row[xi]) - PPM_GETG(b_row[xi]));
9068 delta += abs(PPM_GETB(a_row[xi]) - PPM_GETB(b_row[xi]));
9069 delta += abs(a_alpha_row[xi] - b_alpha_row[xi]);
9074 return (average_delta <= simple_image_threshold);
9087 do_filter_2d_mipmap_pages(
const CData *cdata,
9088 Texture::RamImage &to,
const Texture::RamImage &from,
9089 int x_size,
int y_size)
const {
9090 Filter2DComponent *filter_component;
9091 Filter2DComponent *filter_alpha;
9093 if (
is_srgb(cdata->_format)) {
9096 nassertv(cdata->_component_type == T_unsigned_byte);
9098 if (has_sse2_sRGB_encode()) {
9099 filter_component = &filter_2d_unsigned_byte_srgb_sse2;
9101 filter_component = &filter_2d_unsigned_byte_srgb;
9105 filter_alpha = &filter_2d_unsigned_byte;
9108 switch (cdata->_component_type) {
9109 case T_unsigned_byte:
9110 filter_component = &filter_2d_unsigned_byte;
9113 case T_unsigned_short:
9114 filter_component = &filter_2d_unsigned_short;
9118 filter_component = &filter_2d_float;
9123 <<
"Unable to generate mipmaps for 2D texture with component type "
9124 << cdata->_component_type <<
"!";
9127 filter_alpha = filter_component;
9130 size_t pixel_size = cdata->_num_components * cdata->_component_width;
9131 size_t row_size = (size_t)x_size * pixel_size;
9133 int to_x_size = max(x_size >> 1, 1);
9134 int to_y_size = max(y_size >> 1, 1);
9136 size_t to_row_size = (size_t)to_x_size * pixel_size;
9137 to._page_size = (size_t)to_y_size * to_row_size;
9138 to._image = PTA_uchar::empty_array(to._page_size * cdata->_z_size * cdata->_num_views, get_class_type());
9141 int num_color_components = cdata->_num_components;
9143 --num_color_components;
9146 int num_pages = cdata->_z_size * cdata->_num_views;
9147 for (
int z = 0; z < num_pages; ++z) {
9149 unsigned char *p = to._image.p() + z * to._page_size;
9150 nassertv(p <= to._image.p() + to._image.size() + to._page_size);
9151 const unsigned char *q = from._image.p() + z * from._page_size;
9152 nassertv(q <= from._image.p() + from._image.size() + from._page_size);
9155 for (y = 0; y < y_size - 1; y += 2) {
9157 nassertv(p == to._image.p() + z * to._page_size + (y / 2) * to_row_size);
9158 nassertv(q == from._image.p() + z * from._page_size + y * row_size);
9161 for (x = 0; x < x_size - 1; x += 2) {
9163 for (
int c = 0; c < num_color_components; ++c) {
9165 filter_component(p, q, pixel_size, row_size);
9168 filter_alpha(p, q, pixel_size, row_size);
9178 for (
int c = 0; c < num_color_components; ++c) {
9180 filter_component(p, q, 0, row_size);
9183 filter_alpha(p, q, 0, row_size);
9197 for (x = 0; x < x_size - 1; x += 2) {
9199 for (
int c = 0; c < num_color_components; ++c) {
9201 filter_component(p, q, pixel_size, 0);
9204 filter_alpha(p, q, pixel_size, 0);
9214 for (
int c = 0; c < num_color_components; ++c) {
9216 filter_component(p, q, 0, 0);
9219 filter_alpha(p, q, pixel_size, 0);
9224 nassertv(p == to._image.p() + (z + 1) * to._page_size);
9225 nassertv(q == from._image.p() + (z + 1) * from._page_size);
9239 do_filter_3d_mipmap_level(
const CData *cdata,
9240 Texture::RamImage &to,
const Texture::RamImage &from,
9241 int x_size,
int y_size,
int z_size)
const {
9242 Filter3DComponent *filter_component;
9243 Filter3DComponent *filter_alpha;
9245 if (
is_srgb(cdata->_format)) {
9248 nassertv(cdata->_component_type == T_unsigned_byte);
9250 if (has_sse2_sRGB_encode()) {
9251 filter_component = &filter_3d_unsigned_byte_srgb_sse2;
9253 filter_component = &filter_3d_unsigned_byte_srgb;
9257 filter_alpha = &filter_3d_unsigned_byte;
9260 switch (cdata->_component_type) {
9261 case T_unsigned_byte:
9262 filter_component = &filter_3d_unsigned_byte;
9265 case T_unsigned_short:
9266 filter_component = &filter_3d_unsigned_short;
9270 filter_component = &filter_3d_float;
9275 <<
"Unable to generate mipmaps for 3D texture with component type "
9276 << cdata->_component_type <<
"!";
9279 filter_alpha = filter_component;
9282 size_t pixel_size = cdata->_num_components * cdata->_component_width;
9283 size_t row_size = (size_t)x_size * pixel_size;
9284 size_t page_size = (size_t)y_size * row_size;
9285 size_t view_size = (size_t)z_size * page_size;
9287 int to_x_size = max(x_size >> 1, 1);
9288 int to_y_size = max(y_size >> 1, 1);
9289 int to_z_size = max(z_size >> 1, 1);
9291 size_t to_row_size = (size_t)to_x_size * pixel_size;
9292 size_t to_page_size = (size_t)to_y_size * to_row_size;
9293 size_t to_view_size = (size_t)to_z_size * to_page_size;
9294 to._page_size = to_page_size;
9295 to._image = PTA_uchar::empty_array(to_page_size * to_z_size * cdata->_num_views, get_class_type());
9298 int num_color_components = cdata->_num_components;
9300 --num_color_components;
9303 for (
int view = 0; view < cdata->_num_views; ++view) {
9304 unsigned char *start_to = to._image.p() + view * to_view_size;
9305 const unsigned char *start_from = from._image.p() + view * view_size;
9306 nassertv(start_to + to_view_size <= to._image.p() + to._image.size());
9307 nassertv(start_from + view_size <= from._image.p() + from._image.size());
9308 unsigned char *p = start_to;
9309 const unsigned char *q = start_from;
9312 for (z = 0; z < z_size - 1; z += 2) {
9314 nassertv(p == start_to + (z / 2) * to_page_size);
9315 nassertv(q == start_from + z * page_size);
9318 for (y = 0; y < y_size - 1; y += 2) {
9320 nassertv(p == start_to + (z / 2) * to_page_size + (y / 2) * to_row_size);
9321 nassertv(q == start_from + z * page_size + y * row_size);
9324 for (x = 0; x < x_size - 1; x += 2) {
9326 for (
int c = 0; c < num_color_components; ++c) {
9328 filter_component(p, q, pixel_size, row_size, page_size);
9331 filter_alpha(p, q, pixel_size, row_size, page_size);
9341 for (
int c = 0; c < num_color_components; ++c) {
9343 filter_component(p, q, 0, row_size, page_size);
9346 filter_alpha(p, q, 0, row_size, page_size);
9360 for (x = 0; x < x_size - 1; x += 2) {
9362 for (
int c = 0; c < num_color_components; ++c) {
9364 filter_component(p, q, pixel_size, 0, page_size);
9367 filter_alpha(p, q, pixel_size, 0, page_size);
9377 for (
int c = 0; c < num_color_components; ++c) {
9379 filter_component(p, q, 0, 0, page_size);
9382 filter_alpha(p, q, 0, 0, page_size);
9396 for (y = 0; y < y_size - 1; y += 2) {
9398 nassertv(p == start_to + (y / 2) * to_row_size);
9399 nassertv(q == start_from + y * row_size);
9402 for (x = 0; x < x_size - 1; x += 2) {
9404 for (
int c = 0; c < num_color_components; ++c) {
9406 filter_component(p, q, pixel_size, row_size, 0);
9409 filter_alpha(p, q, pixel_size, row_size, 0);
9419 for (
int c = 0; c < num_color_components; ++c) {
9421 filter_component(p, q, 0, row_size, 0);
9424 filter_alpha(p, q, 0, row_size, 0);
9438 for (x = 0; x < x_size - 1; x += 2) {
9440 for (
int c = 0; c < num_color_components; ++c) {
9442 filter_component(p, q, pixel_size, 0, 0);
9445 filter_alpha(p, q, pixel_size, 0, 0);
9455 for (
int c = 0; c < num_color_components; ++c) {
9457 filter_component(p, q, 0, 0, 0);
9460 filter_alpha(p, q, 0, 0, 0);
9466 nassertv(p == start_to + to_z_size * to_page_size);
9467 nassertv(q == start_from + z_size * page_size);
9476 filter_2d_unsigned_byte(
unsigned char *&p,
const unsigned char *&q,
9477 size_t pixel_size,
size_t row_size) {
9478 unsigned int result = ((
unsigned int)q[0] +
9479 (
unsigned int)q[pixel_size] +
9480 (
unsigned int)q[row_size] +
9481 (
unsigned int)q[pixel_size + row_size]) >> 2;
9482 *p = (
unsigned char)result;
9492 filter_2d_unsigned_byte_srgb(
unsigned char *&p,
const unsigned char *&q,
9493 size_t pixel_size,
size_t row_size) {
9509 filter_2d_unsigned_byte_srgb_sse2(
unsigned char *&p,
const unsigned char *&q,
9510 size_t pixel_size,
size_t row_size) {
9516 *p = encode_sRGB_uchar_sse2(result * 0.25f);
9526 filter_2d_unsigned_short(
unsigned char *&p,
const unsigned char *&q,
9527 size_t pixel_size,
size_t row_size) {
9528 unsigned int result = ((
unsigned int)*(
unsigned short *)&q[0] +
9529 (
unsigned int)*(
unsigned short *)&q[pixel_size] +
9530 (
unsigned int)*(
unsigned short *)&q[row_size] +
9531 (
unsigned int)*(
unsigned short *)&q[pixel_size + row_size]) >> 2;
9532 store_unscaled_short(p, result);
9541 filter_2d_float(
unsigned char *&p,
const unsigned char *&q,
9542 size_t pixel_size,
size_t row_size) {
9543 *(
float *)p = (*(
float *)&q[0] +
9544 *(
float *)&q[pixel_size] +
9545 *(
float *)&q[row_size] +
9546 *(
float *)&q[pixel_size + row_size]) / 4.0f;
9557 filter_3d_unsigned_byte(
unsigned char *&p,
const unsigned char *&q,
9558 size_t pixel_size,
size_t row_size,
size_t page_size) {
9559 unsigned int result = ((
unsigned int)q[0] +
9560 (
unsigned int)q[pixel_size] +
9561 (
unsigned int)q[row_size] +
9562 (
unsigned int)q[pixel_size + row_size] +
9563 (
unsigned int)q[page_size] +
9564 (
unsigned int)q[pixel_size + page_size] +
9565 (
unsigned int)q[row_size + page_size] +
9566 (
unsigned int)q[pixel_size + row_size + page_size]) >> 3;
9567 *p = (
unsigned char)result;
9578 filter_3d_unsigned_byte_srgb(
unsigned char *&p,
const unsigned char *&q,
9579 size_t pixel_size,
size_t row_size,
size_t page_size) {
9600 filter_3d_unsigned_byte_srgb_sse2(
unsigned char *&p,
const unsigned char *&q,
9601 size_t pixel_size,
size_t row_size,
size_t page_size) {
9611 *p = encode_sRGB_uchar_sse2(result * 0.125f);
9622 filter_3d_unsigned_short(
unsigned char *&p,
const unsigned char *&q,
9623 size_t pixel_size,
size_t row_size,
9625 unsigned int result = ((
unsigned int)*(
unsigned short *)&q[0] +
9626 (
unsigned int)*(
unsigned short *)&q[pixel_size] +
9627 (
unsigned int)*(
unsigned short *)&q[row_size] +
9628 (
unsigned int)*(
unsigned short *)&q[pixel_size + row_size] +
9629 (
unsigned int)*(
unsigned short *)&q[page_size] +
9630 (
unsigned int)*(
unsigned short *)&q[pixel_size + page_size] +
9631 (
unsigned int)*(
unsigned short *)&q[row_size + page_size] +
9632 (
unsigned int)*(
unsigned short *)&q[pixel_size + row_size + page_size]) >> 3;
9633 store_unscaled_short(p, result);
9643 filter_3d_float(
unsigned char *&p,
const unsigned char *&q,
9644 size_t pixel_size,
size_t row_size,
size_t page_size) {
9645 *(
float *)p = (*(
float *)&q[0] +
9646 *(
float *)&q[pixel_size] +
9647 *(
float *)&q[row_size] +
9648 *(
float *)&q[pixel_size + row_size] +
9649 *(
float *)&q[page_size] +
9650 *(
float *)&q[pixel_size + page_size] +
9651 *(
float *)&q[row_size + page_size] +
9652 *(
float *)&q[pixel_size + row_size + page_size]) / 8.0f;
9661 do_squish(CData *cdata, Texture::CompressionMode compression,
int squish_flags) {
9663 if (!do_has_all_ram_mipmap_images(cdata)) {
9666 do_generate_ram_mipmap_images(cdata,
false);
9669 RamImages compressed_ram_images;
9670 compressed_ram_images.reserve(cdata->_ram_images.size());
9671 for (
size_t n = 0; n < cdata->_ram_images.size(); ++n) {
9672 RamImage compressed_image;
9673 int x_size = do_get_expected_mipmap_x_size(cdata, n);
9674 int y_size = do_get_expected_mipmap_y_size(cdata, n);
9675 int num_pages = do_get_expected_mipmap_num_pages(cdata, n);
9676 int page_size = squish::GetStorageRequirements(x_size, y_size, squish_flags);
9677 int cell_size = squish::GetStorageRequirements(4, 4, squish_flags);
9679 compressed_image._page_size = page_size;
9680 compressed_image._image = PTA_uchar::empty_array(page_size * num_pages);
9681 for (
int z = 0; z < num_pages; ++z) {
9682 unsigned char *dest_page = compressed_image._image.p() + z * page_size;
9683 unsigned const char *source_page = cdata->_ram_images[n]._image.p() + z * cdata->_ram_images[n]._page_size;
9684 unsigned const char *source_page_end = source_page + cdata->_ram_images[n]._page_size;
9686 unsigned char *d = dest_page;
9687 for (
int y = 0; y < y_size; y += 4) {
9688 for (
int x = 0; x < x_size; x += 4) {
9689 unsigned char tb[16 * 4];
9691 unsigned char *t = tb;
9692 for (
int i = 0; i < 16; ++i) {
9695 unsigned const char *s = source_page + (yi * x_size + xi) * cdata->_num_components;
9696 if (s < source_page_end) {
9697 switch (cdata->_num_components) {
9730 squish::CompressMasked(tb, mask, d, squish_flags);
9736 compressed_ram_images.push_back(compressed_image);
9738 cdata->_ram_images.swap(compressed_ram_images);
9739 cdata->_ram_image_compression = compression;
9742 #else // HAVE_SQUISH
9745 #endif // HAVE_SQUISH
9752 do_unsquish(CData *cdata,
int squish_flags) {
9754 RamImages uncompressed_ram_images;
9755 uncompressed_ram_images.reserve(cdata->_ram_images.size());
9756 for (
size_t n = 0; n < cdata->_ram_images.size(); ++n) {
9757 RamImage uncompressed_image;
9758 int x_size = do_get_expected_mipmap_x_size(cdata, n);
9759 int y_size = do_get_expected_mipmap_y_size(cdata, n);
9760 int num_pages = do_get_expected_mipmap_num_pages(cdata, n);
9761 int page_size = squish::GetStorageRequirements(x_size, y_size, squish_flags);
9762 int cell_size = squish::GetStorageRequirements(4, 4, squish_flags);
9764 uncompressed_image._page_size = do_get_expected_ram_mipmap_page_size(cdata, n);
9765 uncompressed_image._image = PTA_uchar::empty_array(uncompressed_image._page_size * num_pages);
9766 for (
int z = 0; z < num_pages; ++z) {
9767 unsigned char *dest_page = uncompressed_image._image.p() + z * uncompressed_image._page_size;
9768 unsigned char *dest_page_end = dest_page + uncompressed_image._page_size;
9769 unsigned const char *source_page = cdata->_ram_images[n]._image.p() + z * page_size;
9771 unsigned const char *s = source_page;
9772 for (
int y = 0; y < y_size; y += 4) {
9773 for (
int x = 0; x < x_size; x += 4) {
9774 unsigned char tb[16 * 4];
9775 squish::Decompress(tb, s, squish_flags);
9778 unsigned char *t = tb;
9779 for (
int i = 0; i < 16; ++i) {
9782 unsigned char *d = dest_page + (yi * x_size + xi) * cdata->_num_components;
9783 if (d < dest_page_end) {
9784 switch (cdata->_num_components) {
9814 uncompressed_ram_images.push_back(uncompressed_image);
9816 cdata->_ram_images.swap(uncompressed_ram_images);
9817 cdata->_ram_image_compression = CM_off;
9820 #else // HAVE_SQUISH
9823 #endif // HAVE_SQUISH
9842 bool has_rawdata =
false;
9843 do_write_datagram_header(cdata, manager, me, has_rawdata);
9844 do_write_datagram_body(cdata, manager, me);
9848 do_write_datagram_rawdata(cdata, manager, me);
9886 do_write_datagram_header(CData *cdata,
BamWriter *manager,
Datagram &me,
bool &has_rawdata) {
9895 has_rawdata = (file_texture_mode == BamWriter::BTM_rawdata ||
9896 (cdata->_filename.empty() && do_has_bam_rawdata(cdata)));
9897 if (has_rawdata && !do_has_bam_rawdata(cdata)) {
9898 do_get_bam_rawdata(cdata);
9899 if (!do_has_bam_rawdata(cdata)) {
9901 has_rawdata =
false;
9907 Filename filename = cdata->_filename;
9908 Filename alpha_filename = cdata->_alpha_filename;
9912 switch (file_texture_mode) {
9913 case BamWriter::BTM_unchanged:
9914 case BamWriter::BTM_rawdata:
9917 case BamWriter::BTM_fullpath:
9918 filename = cdata->_fullpath;
9919 alpha_filename = cdata->_alpha_fullpath;
9922 case BamWriter::BTM_relative:
9923 filename = cdata->_fullpath;
9924 alpha_filename = cdata->_alpha_fullpath;
9929 if (gobj_cat.is_debug()) {
9931 <<
"Texture file " << cdata->_fullpath
9932 <<
" found as " << filename <<
"\n";
9937 if (gobj_cat.is_debug()) {
9939 <<
"Alpha image " << cdata->_alpha_fullpath
9940 <<
" found as " << alpha_filename <<
"\n";
9944 case BamWriter::BTM_basename:
9946 alpha_filename = cdata->_alpha_fullpath.
get_basename();
9951 <<
"Unsupported bam-texture-mode: " << (int)file_texture_mode <<
"\n";
9954 if (filename.empty()) {
9955 if (do_has_bam_rawdata(cdata) || cdata->_has_clear_color) {
9964 me.
add_uint8(cdata->_primary_file_num_channels);
9965 me.
add_uint8(cdata->_alpha_file_channel);
9969 cdata->_texture_type == TT_cube_map) {
9978 me.
add_bool(cdata->_has_read_mipmaps);
9989 cdata->_default_sampler.write_datagram(me);
10007 if (cdata->_texture_type == TT_buffer_texture) {
10012 me.
add_uint8(cdata->_auto_texture_scale);
10024 me.
add_int32(cdata->_simple_image_date_generated);
10025 me.
add_uint32(cdata->_simple_ram_image._image.size());
10026 me.
append_data(cdata->_simple_ram_image._image, cdata->_simple_ram_image._image.size());
10030 me.
add_bool(cdata->_has_clear_color);
10031 if (cdata->_has_clear_color) {
10032 cdata->_clear_color.write_datagram(me);
10057 me.
add_uint8(cdata->_ram_image_compression);
10059 if (cdata->_ram_images.empty() && cdata->_has_clear_color &&
10063 int image_size = do_get_expected_ram_image_size(cdata);
10065 me.
add_uint32(do_get_expected_ram_page_size(cdata));
10069 unsigned char pixel[16];
10070 const int pixel_size = do_get_clear_data(cdata,
pixel);
10071 nassertv(pixel_size > 0);
10073 for (
int i = 0; i < image_size; i += pixel_size) {
10077 me.
add_uint8(cdata->_ram_images.size());
10078 for (
size_t n = 0; n < cdata->_ram_images.size(); ++n) {
10079 me.
add_uint32(cdata->_ram_images[n]._page_size);
10080 me.
add_uint32(cdata->_ram_images[n]._image.size());
10081 me.
append_data(cdata->_ram_images[n]._image, cdata->_ram_images[n]._image.size());
10092 return dummy->make_this_from_bam(params);
10119 int primary_file_num_channels = scan.
get_uint8();
10120 int alpha_file_channel = scan.
get_uint8();
10121 bool has_rawdata = scan.
get_bool();
10122 TextureType texture_type = (TextureType)scan.
get_uint8();
10126 if (texture_type == TT_2d_texture_array) {
10127 texture_type = TT_cube_map;
10130 bool has_read_mipmaps =
false;
10132 has_read_mipmaps = scan.
get_bool();
10142 me->set_name(name);
10143 CDWriter cdata_me(me->_cycler,
true);
10144 cdata_me->_filename = filename;
10145 cdata_me->_alpha_filename = alpha_filename;
10146 cdata_me->_primary_file_num_channels = primary_file_num_channels;
10147 cdata_me->_alpha_file_channel = alpha_file_channel;
10148 cdata_me->_texture_type = texture_type;
10149 cdata_me->_has_read_mipmaps = has_read_mipmaps;
10152 me->do_fillin_body(cdata_me, scan, manager);
10153 me->do_fillin_rawdata(cdata_me, scan, manager);
10165 AutoTextureScale auto_texture_scale = ATS_unspecified;
10167 CDWriter cdata_dummy(dummy->_cycler,
true);
10168 dummy->do_fillin_body(cdata_dummy, scan, manager);
10169 auto_texture_scale = cdata_dummy->_auto_texture_scale;
10172 if (filename.empty()) {
10176 <<
"Cannot create texture '" << name <<
"' with no filename.\n";
10186 if (!alpha_filename.empty()) {
10193 options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_generate_mipmaps);
10197 switch (texture_type) {
10198 case TT_buffer_texture:
10199 case TT_1d_texture:
10200 case TT_2d_texture:
10201 case TT_1d_texture_array:
10202 if (alpha_filename.empty()) {
10204 has_read_mipmaps, options);
10207 primary_file_num_channels,
10208 alpha_file_channel,
10209 has_read_mipmaps, options);
10213 case TT_3d_texture:
10217 case TT_2d_texture_array:
10218 case TT_cube_map_array:
10228 if (me !=
nullptr) {
10229 me->set_name(name);
10230 CDWriter cdata_me(me->_cycler,
true);
10231 me->do_fillin_from(cdata_me, dummy);
10248 cdata->_default_sampler.read_datagram(scan, manager);
10251 cdata->_compression = (CompressionMode)scan.
get_uint8();
10254 cdata->_quality_level = (QualityLevel)scan.
get_uint8();
10257 cdata->_format = (Format)scan.
get_uint8();
10258 cdata->_num_components = scan.
get_uint8();
10260 if (cdata->_texture_type == TT_buffer_texture) {
10261 cdata->_usage_hint = (GeomEnums::UsageHint)scan.
get_uint8();
10264 cdata->inc_properties_modified();
10266 cdata->_auto_texture_scale = ATS_unspecified;
10268 cdata->_auto_texture_scale = (AutoTextureScale)scan.
get_uint8();
10273 cdata->_orig_file_x_size = scan.
get_uint32();
10274 cdata->_orig_file_y_size = scan.
get_uint32();
10282 cdata->_simple_image_date_generated = scan.
get_int32();
10289 <<
"simple RAM image extends past end of datagram, is texture corrupt?\n";
10293 PTA_uchar image = PTA_uchar::empty_array(u_size, get_class_type());
10296 cdata->_simple_ram_image._image = image;
10297 cdata->_simple_ram_image._page_size = u_size;
10298 cdata->inc_simple_image_modified();
10302 cdata->_has_clear_color = scan.
get_bool();
10303 if (cdata->_has_clear_color) {
10304 cdata->_clear_color.read_datagram(scan);
10324 do_set_pad_size(cdata, 0, 0, 0);
10327 cdata->_num_views = 1;
10331 cdata->_component_type = (ComponentType)scan.
get_uint8();
10332 cdata->_component_width = scan.
get_uint8();
10333 cdata->_ram_image_compression = CM_off;
10335 cdata->_ram_image_compression = (CompressionMode)scan.
get_uint8();
10338 int num_ram_images = 1;
10343 cdata->_ram_images.clear();
10344 cdata->_ram_images.reserve(num_ram_images);
10345 for (
int n = 0; n < num_ram_images; ++n) {
10346 cdata->_ram_images.push_back(RamImage());
10349 cdata->_ram_images[n]._page_size = scan.
get_uint32();
10358 <<
"RAM image " << n <<
" extends past end of datagram, is texture corrupt?\n";
10362 PTA_uchar image = PTA_uchar::empty_array(u_size, get_class_type());
10365 cdata->_ram_images[n]._image = image;
10367 cdata->_loaded_from_image =
true;
10368 cdata->inc_image_modified();
10377 do_fillin_from(CData *cdata,
const Texture *dummy) {
10384 CDReader cdata_dummy(dummy->_cycler);
10386 do_set_wrap_u(cdata, cdata_dummy->_default_sampler.get_wrap_u());
10387 do_set_wrap_v(cdata, cdata_dummy->_default_sampler.get_wrap_v());
10388 do_set_wrap_w(cdata, cdata_dummy->_default_sampler.get_wrap_w());
10389 do_set_border_color(cdata, cdata_dummy->_default_sampler.get_border_color());
10391 if (cdata_dummy->_default_sampler.get_minfilter() != SamplerState::FT_default) {
10392 do_set_minfilter(cdata, cdata_dummy->_default_sampler.get_minfilter());
10394 if (cdata_dummy->_default_sampler.get_magfilter() != SamplerState::FT_default) {
10395 do_set_magfilter(cdata, cdata_dummy->_default_sampler.get_magfilter());
10397 if (cdata_dummy->_default_sampler.get_anisotropic_degree() != 0) {
10398 do_set_anisotropic_degree(cdata, cdata_dummy->_default_sampler.get_anisotropic_degree());
10400 if (cdata_dummy->_compression != CM_default) {
10401 do_set_compression(cdata, cdata_dummy->_compression);
10403 if (cdata_dummy->_quality_level != QL_default) {
10404 do_set_quality_level(cdata, cdata_dummy->_quality_level);
10407 Format format = cdata_dummy->_format;
10408 int num_components = cdata_dummy->_num_components;
10410 if (num_components == cdata->_num_components) {
10414 do_set_format(cdata, format);
10417 if (!cdata_dummy->_simple_ram_image._image.empty()) {
10420 if (cdata->_simple_ram_image._image.empty() ||
10421 cdata_dummy->_simple_image_date_generated > cdata->_simple_image_date_generated) {
10422 do_set_simple_ram_image(cdata,
10423 cdata_dummy->_simple_ram_image._image,
10424 cdata_dummy->_simple_x_size,
10425 cdata_dummy->_simple_y_size);
10426 cdata->_simple_image_date_generated = cdata_dummy->_simple_image_date_generated;
10436 _primary_file_num_channels = 0;
10437 _alpha_file_channel = 0;
10438 _keep_ram_image =
true;
10439 _compression = CM_default;
10440 _auto_texture_scale = ATS_unspecified;
10441 _ram_image_compression = CM_off;
10442 _render_to_texture =
false;
10443 _match_framebuffer_format =
false;
10444 _post_load_store_cache =
false;
10445 _quality_level = QL_default;
10447 _texture_type = TT_2d_texture;
10459 _usage_hint = GeomEnums::UH_unspecified;
10465 _orig_file_x_size = 0;
10466 _orig_file_y_size = 0;
10468 _loaded_from_image =
false;
10469 _loaded_from_txo =
false;
10470 _has_read_pages =
false;
10471 _has_read_mipmaps =
false;
10472 _num_mipmap_levels_read = 0;
10474 _simple_x_size = 0;
10475 _simple_y_size = 0;
10476 _simple_ram_image._page_size = 0;
10478 _has_clear_color =
false;
10485 CData(
const Texture::CData ©) {
10486 _num_mipmap_levels_read = 0;
10490 _properties_modified = copy._properties_modified;
10491 _image_modified = copy._image_modified;
10492 _simple_image_modified = copy._simple_image_modified;
10499 make_copy()
const {
10500 return new CData(*
this);
10506 void Texture::CData::
10507 do_assign(
const Texture::CData *copy) {
10508 _filename = copy->_filename;
10509 _alpha_filename = copy->_alpha_filename;
10510 if (!copy->_fullpath.empty()) {
10513 _fullpath = copy->_fullpath;
10514 _alpha_fullpath = copy->_alpha_fullpath;
10516 _primary_file_num_channels = copy->_primary_file_num_channels;
10517 _alpha_file_channel = copy->_alpha_file_channel;
10518 _x_size = copy->_x_size;
10519 _y_size = copy->_y_size;
10520 _z_size = copy->_z_size;
10521 _num_views = copy->_num_views;
10522 _pad_x_size = copy->_pad_x_size;
10523 _pad_y_size = copy->_pad_y_size;
10524 _pad_z_size = copy->_pad_z_size;
10525 _orig_file_x_size = copy->_orig_file_x_size;
10526 _orig_file_y_size = copy->_orig_file_y_size;
10527 _num_components = copy->_num_components;
10528 _component_width = copy->_component_width;
10529 _texture_type = copy->_texture_type;
10530 _format = copy->_format;
10531 _component_type = copy->_component_type;
10532 _loaded_from_image = copy->_loaded_from_image;
10533 _loaded_from_txo = copy->_loaded_from_txo;
10534 _has_read_pages = copy->_has_read_pages;
10535 _has_read_mipmaps = copy->_has_read_mipmaps;
10536 _num_mipmap_levels_read = copy->_num_mipmap_levels_read;
10537 _default_sampler = copy->_default_sampler;
10538 _keep_ram_image = copy->_keep_ram_image;
10539 _compression = copy->_compression;
10540 _match_framebuffer_format = copy->_match_framebuffer_format;
10541 _quality_level = copy->_quality_level;
10542 _auto_texture_scale = copy->_auto_texture_scale;
10543 _ram_image_compression = copy->_ram_image_compression;
10544 _ram_images = copy->_ram_images;
10545 _simple_x_size = copy->_simple_x_size;
10546 _simple_y_size = copy->_simple_y_size;
10547 _simple_ram_image = copy->_simple_ram_image;
10554 void Texture::CData::
10562 int Texture::CData::
10571 void Texture::CData::
10579 operator << (ostream &out, Texture::TextureType tt) {
10587 operator << (ostream &out, Texture::ComponentType ct) {
10595 operator << (ostream &out, Texture::Format f) {
10603 operator << (ostream &out, Texture::CompressionMode cm) {
10611 operator << (ostream &out, Texture::QualityLevel tql) {
10619 operator >> (istream &in, Texture::QualityLevel &tql) {