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()) {
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);
1147 get_keep_ram_image()
const {
1148 CDReader cdata(_cycler);
1149 return cdata->_keep_ram_image;
1158 is_cacheable()
const {
1159 CDReader cdata(_cycler);
1160 return do_has_bam_rawdata(cdata);
1176 get_num_loadable_ram_mipmap_images()
const {
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);
1345 if (!scaled.has_alpha()) {
1347 scaled.alpha_fill(1.0);
1349 scaled.set_num_channels(4);
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)) {
1365 scaled.take_from(smaller);
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)) {
1380 scaled.take_from(smaller);
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);
2558 switch (compression) {
2584 case F_luminance_alpha:
2585 case F_luminance_alphamask:
2587 case F_sluminance_alpha:
2622 case F_sluminance_alpha:
2641 bool for_padding, AutoTextureScale auto_texture_scale) {
2642 bool exclude =
false;
2644 for (
int i = 0; i < num_excludes && !exclude; ++i) {
2646 if (pat.matches(name)) {
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 " 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();
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 " 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";
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";
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() && do_has_bam_rawdata(cdata)) {
9962 me.
add_uint8(cdata->_primary_file_num_channels);
9963 me.
add_uint8(cdata->_alpha_file_channel);
9967 cdata->_texture_type == TT_cube_map) {
9976 me.
add_bool(cdata->_has_read_mipmaps);
9987 cdata->_default_sampler.write_datagram(me);
10005 if (cdata->_texture_type == TT_buffer_texture) {
10010 me.
add_uint8(cdata->_auto_texture_scale);
10016 me.
add_bool(has_simple_ram_image);
10019 if (has_simple_ram_image) {
10022 me.
add_int32(cdata->_simple_image_date_generated);
10023 me.
add_uint32(cdata->_simple_ram_image._image.size());
10024 me.
append_data(cdata->_simple_ram_image._image, cdata->_simple_ram_image._image.size());
10048 me.
add_uint8(cdata->_ram_image_compression);
10049 me.
add_uint8(cdata->_ram_images.size());
10050 for (
size_t n = 0; n < cdata->_ram_images.size(); ++n) {
10051 me.
add_uint32(cdata->_ram_images[n]._page_size);
10052 me.
add_uint32(cdata->_ram_images[n]._image.size());
10053 me.
append_data(cdata->_ram_images[n]._image, cdata->_ram_images[n]._image.size());
10063 return dummy->make_this_from_bam(params);
10090 int primary_file_num_channels = scan.
get_uint8();
10091 int alpha_file_channel = scan.
get_uint8();
10092 bool has_rawdata = scan.
get_bool();
10093 TextureType texture_type = (TextureType)scan.
get_uint8();
10097 if (texture_type == TT_2d_texture_array) {
10098 texture_type = TT_cube_map;
10101 bool has_read_mipmaps =
false;
10103 has_read_mipmaps = scan.
get_bool();
10113 me->set_name(name);
10114 CDWriter cdata_me(me->_cycler,
true);
10115 cdata_me->_filename = filename;
10116 cdata_me->_alpha_filename = alpha_filename;
10117 cdata_me->_primary_file_num_channels = primary_file_num_channels;
10118 cdata_me->_alpha_file_channel = alpha_file_channel;
10119 cdata_me->_texture_type = texture_type;
10120 cdata_me->_has_read_mipmaps = has_read_mipmaps;
10123 me->do_fillin_body(cdata_me, scan, manager);
10124 me->do_fillin_rawdata(cdata_me, scan, manager);
10136 AutoTextureScale auto_texture_scale = ATS_unspecified;
10138 CDWriter cdata_dummy(dummy->_cycler,
true);
10139 dummy->do_fillin_body(cdata_dummy, scan, manager);
10140 auto_texture_scale = cdata_dummy->_auto_texture_scale;
10143 if (filename.empty()) {
10147 <<
"Cannot create texture '" << name <<
"' with no filename.\n";
10157 if (!alpha_filename.empty()) {
10164 options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_generate_mipmaps);
10168 switch (texture_type) {
10169 case TT_buffer_texture:
10170 case TT_1d_texture:
10171 case TT_2d_texture:
10172 case TT_1d_texture_array:
10173 if (alpha_filename.empty()) {
10175 has_read_mipmaps, options);
10178 primary_file_num_channels,
10179 alpha_file_channel,
10180 has_read_mipmaps, options);
10184 case TT_3d_texture:
10188 case TT_2d_texture_array:
10189 case TT_cube_map_array:
10199 if (me !=
nullptr) {
10200 me->set_name(name);
10201 CDWriter cdata_me(me->_cycler,
true);
10202 me->do_fillin_from(cdata_me, dummy);
10219 cdata->_default_sampler.read_datagram(scan, manager);
10222 cdata->_compression = (CompressionMode)scan.
get_uint8();
10225 cdata->_quality_level = (QualityLevel)scan.
get_uint8();
10228 cdata->_format = (Format)scan.
get_uint8();
10229 cdata->_num_components = scan.
get_uint8();
10231 if (cdata->_texture_type == TT_buffer_texture) {
10232 cdata->_usage_hint = (GeomEnums::UsageHint)scan.
get_uint8();
10235 cdata->inc_properties_modified();
10237 cdata->_auto_texture_scale = ATS_unspecified;
10239 cdata->_auto_texture_scale = (AutoTextureScale)scan.
get_uint8();
10242 bool has_simple_ram_image =
false;
10244 cdata->_orig_file_x_size = scan.
get_uint32();
10245 cdata->_orig_file_y_size = scan.
get_uint32();
10247 has_simple_ram_image = scan.
get_bool();
10250 if (has_simple_ram_image) {
10253 cdata->_simple_image_date_generated = scan.
get_int32();
10260 <<
"simple RAM image extends past end of datagram, is texture corrupt?\n";
10264 PTA_uchar image = PTA_uchar::empty_array(u_size, get_class_type());
10267 cdata->_simple_ram_image._image = image;
10268 cdata->_simple_ram_image._page_size = u_size;
10269 cdata->inc_simple_image_modified();
10288 do_set_pad_size(cdata, 0, 0, 0);
10291 cdata->_num_views = 1;
10295 cdata->_component_type = (ComponentType)scan.
get_uint8();
10296 cdata->_component_width = scan.
get_uint8();
10297 cdata->_ram_image_compression = CM_off;
10299 cdata->_ram_image_compression = (CompressionMode)scan.
get_uint8();
10302 int num_ram_images = 1;
10307 cdata->_ram_images.clear();
10308 cdata->_ram_images.reserve(num_ram_images);
10309 for (
int n = 0; n < num_ram_images; ++n) {
10310 cdata->_ram_images.push_back(RamImage());
10313 cdata->_ram_images[n]._page_size = scan.
get_uint32();
10322 <<
"RAM image " << n <<
" extends past end of datagram, is texture corrupt?\n";
10326 PTA_uchar image = PTA_uchar::empty_array(u_size, get_class_type());
10329 cdata->_ram_images[n]._image = image;
10331 cdata->_loaded_from_image =
true;
10332 cdata->inc_image_modified();
10341 do_fillin_from(CData *cdata,
const Texture *dummy) {
10348 CDReader cdata_dummy(dummy->_cycler);
10350 do_set_wrap_u(cdata, cdata_dummy->_default_sampler.get_wrap_u());
10351 do_set_wrap_v(cdata, cdata_dummy->_default_sampler.get_wrap_v());
10352 do_set_wrap_w(cdata, cdata_dummy->_default_sampler.get_wrap_w());
10353 do_set_border_color(cdata, cdata_dummy->_default_sampler.get_border_color());
10355 if (cdata_dummy->_default_sampler.get_minfilter() != SamplerState::FT_default) {
10356 do_set_minfilter(cdata, cdata_dummy->_default_sampler.get_minfilter());
10358 if (cdata_dummy->_default_sampler.get_magfilter() != SamplerState::FT_default) {
10359 do_set_magfilter(cdata, cdata_dummy->_default_sampler.get_magfilter());
10361 if (cdata_dummy->_default_sampler.get_anisotropic_degree() != 0) {
10362 do_set_anisotropic_degree(cdata, cdata_dummy->_default_sampler.get_anisotropic_degree());
10364 if (cdata_dummy->_compression != CM_default) {
10365 do_set_compression(cdata, cdata_dummy->_compression);
10367 if (cdata_dummy->_quality_level != QL_default) {
10368 do_set_quality_level(cdata, cdata_dummy->_quality_level);
10371 Format format = cdata_dummy->_format;
10372 int num_components = cdata_dummy->_num_components;
10374 if (num_components == cdata->_num_components) {
10378 do_set_format(cdata, format);
10381 if (!cdata_dummy->_simple_ram_image._image.empty()) {
10384 if (cdata->_simple_ram_image._image.empty() ||
10385 cdata_dummy->_simple_image_date_generated > cdata->_simple_image_date_generated) {
10386 do_set_simple_ram_image(cdata,
10387 cdata_dummy->_simple_ram_image._image,
10388 cdata_dummy->_simple_x_size,
10389 cdata_dummy->_simple_y_size);
10390 cdata->_simple_image_date_generated = cdata_dummy->_simple_image_date_generated;
10400 _primary_file_num_channels = 0;
10401 _alpha_file_channel = 0;
10402 _keep_ram_image =
true;
10403 _compression = CM_default;
10404 _auto_texture_scale = ATS_unspecified;
10405 _ram_image_compression = CM_off;
10406 _render_to_texture =
false;
10407 _match_framebuffer_format =
false;
10408 _post_load_store_cache =
false;
10409 _quality_level = QL_default;
10411 _texture_type = TT_2d_texture;
10423 _usage_hint = GeomEnums::UH_unspecified;
10429 _orig_file_x_size = 0;
10430 _orig_file_y_size = 0;
10432 _loaded_from_image =
false;
10433 _loaded_from_txo =
false;
10434 _has_read_pages =
false;
10435 _has_read_mipmaps =
false;
10436 _num_mipmap_levels_read = 0;
10438 _simple_x_size = 0;
10439 _simple_y_size = 0;
10440 _simple_ram_image._page_size = 0;
10442 _has_clear_color =
false;
10449 CData(
const Texture::CData ©) {
10450 _num_mipmap_levels_read = 0;
10454 _properties_modified = copy._properties_modified;
10455 _image_modified = copy._image_modified;
10456 _simple_image_modified = copy._simple_image_modified;
10463 make_copy()
const {
10464 return new CData(*
this);
10470 void Texture::CData::
10471 do_assign(
const Texture::CData *copy) {
10472 _filename = copy->_filename;
10473 _alpha_filename = copy->_alpha_filename;
10474 if (!copy->_fullpath.empty()) {
10477 _fullpath = copy->_fullpath;
10478 _alpha_fullpath = copy->_alpha_fullpath;
10480 _primary_file_num_channels = copy->_primary_file_num_channels;
10481 _alpha_file_channel = copy->_alpha_file_channel;
10482 _x_size = copy->_x_size;
10483 _y_size = copy->_y_size;
10484 _z_size = copy->_z_size;
10485 _num_views = copy->_num_views;
10486 _pad_x_size = copy->_pad_x_size;
10487 _pad_y_size = copy->_pad_y_size;
10488 _pad_z_size = copy->_pad_z_size;
10489 _orig_file_x_size = copy->_orig_file_x_size;
10490 _orig_file_y_size = copy->_orig_file_y_size;
10491 _num_components = copy->_num_components;
10492 _component_width = copy->_component_width;
10493 _texture_type = copy->_texture_type;
10494 _format = copy->_format;
10495 _component_type = copy->_component_type;
10496 _loaded_from_image = copy->_loaded_from_image;
10497 _loaded_from_txo = copy->_loaded_from_txo;
10498 _has_read_pages = copy->_has_read_pages;
10499 _has_read_mipmaps = copy->_has_read_mipmaps;
10500 _num_mipmap_levels_read = copy->_num_mipmap_levels_read;
10501 _default_sampler = copy->_default_sampler;
10502 _keep_ram_image = copy->_keep_ram_image;
10503 _compression = copy->_compression;
10504 _match_framebuffer_format = copy->_match_framebuffer_format;
10505 _quality_level = copy->_quality_level;
10506 _auto_texture_scale = copy->_auto_texture_scale;
10507 _ram_image_compression = copy->_ram_image_compression;
10508 _ram_images = copy->_ram_images;
10509 _simple_x_size = copy->_simple_x_size;
10510 _simple_y_size = copy->_simple_y_size;
10511 _simple_ram_image = copy->_simple_ram_image;
10518 void Texture::CData::
10526 int Texture::CData::
10535 void Texture::CData::
10543 operator << (ostream &out, Texture::TextureType tt) {
10551 operator << (ostream &out, Texture::ComponentType ct) {
10559 operator << (ostream &out, Texture::Format f) {
10567 operator << (ostream &out, Texture::CompressionMode cm) {
10575 operator << (ostream &out, Texture::QualityLevel tql) {
10583 operator >> (istream &in, Texture::QualityLevel &tql) {
Texture(const std::string &name=std::string())
Constructs an empty texture.
Filename get_filename_index(int index) const
If the pattern flag is set for this Filename and the filename string actually includes a sequence of ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_minfilter
Returns the filter mode of the texture for minification.
virtual void ensure_loader_type(const Filename &filename)
May be called prior to calling read_txo() or any bam-related Texture- creating callback,...
static bool is_srgb(Format format)
Returns true if the indicated format is in the sRGB color space, false otherwise.
void add_int16(int16_t value)
Adds a signed 16-bit integer to the datagram.
static std::string format_quality_level(QualityLevel tql)
Returns the indicated QualityLevel converted to a string word.
bool was_image_modified() const
Returns true if the texture image has been modified since the last time mark_loaded() was called.
get_wrap_u
Returns the wrap mode of the texture in the U direction.
get_ref_count
Returns the current reference count.
set_data
Stores a new data object on the record.
void set_green(int x, int y, float g)
Sets the green component color only at the indicated pixel.
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
This is our own Panda specialization on the default STL map.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static std::string format_component_type(ComponentType ct)
Returns the indicated ComponentType converted to a string word.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This class represents a thread-safe handle to a promised future result of an asynchronous operation,...
void copy_sub_image(const PNMImage ©, int xto, int yto, int xfrom=0, int yfrom=0, int x_size=-1, int y_size=-1)
Copies a rectangular area of another image into a rectangular area of this image.
static CompressionMode string_compression_mode(const std::string &str)
Returns the CompressionMode value associated with the given string representation.
get_active
Returns the active flag associated with this object.
xelval get_channel_val(int x, int y, int channel) const
Returns the nth component color at the indicated pixel.
bool get_bool()
Extracts a boolean value.
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
static Format string_format(const std::string &str)
Returns the Format corresponding to the indicated string word.
static Texture * load_cube_map(const Filename &filename_pattern, bool read_mipmaps=false, const LoaderOptions &options=LoaderOptions())
Loads a cube map texture that is specified with a series of 6 pages, numbered 0 through 5.
ColorSpace get_color_space() const
Returns the color space in which the image is encoded.
uint8_t get_uint8()
Extracts an unsigned 8-bit integer.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void release_texture(TextureContext *tc)
Indicates that a texture context, created by a previous call to prepare_texture(),...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_cache_textures
Returns whether texture files (e.g.
xelval get_gray_val(int x, int y) const
Returns the gray component color at the indicated pixel.
void wait()
Waits on the condition.
static std::string format_format(Format f)
Returns the indicated Format converted to a string word.
void append_data(const void *data, size_t size)
Appends some more raw data to the end of the datagram.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
bool get_resident(PreparedGraphicsObjects *prepared_objects) const
Returns true if this Texture is reported to be resident within graphics memory for the indicated GSG.
size_t get_num_unique_values() const
Returns the number of unique values in the variable.
bool resolve()
This may be called at any time during processing of the Bam file to resolve all the known pointers so...
void alpha_fill(float alpha=0.0)
Sets the entire alpha channel to the given level.
void set_ram_mipmap_pointer_from_int(long long pointer, int n, int page_size)
Accepts a raw pointer cast as an int, which is then passed to set_ram_mipmap_pointer(); see the docum...
Specifies parameters that may be passed to the loader.
This class maintains a cache of Bam and/or Txo objects generated from model files and texture images ...
get_file_texture_mode
Returns the BamTextureMode preference indicated by the Bam file currently being written.
A hierarchy of directories and files that appears to be one continuous file system,...
bool dequeue_texture(Texture *tex)
Removes a texture from the queued list of textures to be prepared.
TypedWritable * read_object()
Reads a single object from the Bam file.
int release_all()
Frees the context allocated on all objects for which the texture has been declared.
float get_gray(int x, int y) const
Returns the gray component color at the indicated pixel.
static void register_with_read_factory()
Factory method to generate a Texture object.
A single page of data maintained by a PipelineCycler.
std::string get_basename_wo_extension() const
Returns the basename part of the filename, without the file extension.
bool was_image_modified(PreparedGraphicsObjects *prepared_objects) const
Returns true if the texture needs to be re-loaded onto the indicated GSG, either because its image da...
virtual bool is_floating_point()
Returns true if this PNMFileType represents a floating-point image type, false if it is a normal,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Base class for objects that can be written to and read from Bam files.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool write(const Filename &filename, PNMFileType *type=nullptr) const
Writes the image to the indicated filename.
bool write_header(const std::string &header)
Writes a sequence of bytes to the beginning of the datagram file.
static QualityLevel string_quality_level(const std::string &str)
Returns the QualityLevel value associated with the given string representation.
size_t estimate_texture_memory() const
Estimates the amount of texture memory that will be consumed by loading this texture.
void set_orig_file_size(int x, int y, int z=1)
Specifies the size of the texture as it exists in its original disk file, before any Panda scaling.
static bool is_specific(CompressionMode compression)
Returns true if the indicated compression mode is one of the specific compression types,...
bool get_active(PreparedGraphicsObjects *prepared_objects) const
Returns true if this Texture was rendered in the most recent frame within the indicated GSG.
bool read(const Filename &filename, PNMFileType *type=nullptr, bool report_unknown_type=true)
Reads the indicated image filename.
This is a special class object that holds all the information returned by a particular GSG to indicat...
This collects together the pieces of data that are accumulated for each node while walking the scene ...
A base class for things which need to inherit from both TypedObject and from ReferenceCount.
get_wrap_w
Returns the wrap mode of the texture in the W direction.
virtual void write_datagram(BamWriter *manager, Datagram &me)
Function to write the important information in the particular object to a Datagram.
PTA_uchar modify_simple_ram_image()
Returns a modifiable pointer to the internal "simple" texture image.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_next_higher_bit(uint16_t x)
Returns the smallest power of 2 greater than x.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being written.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
xel * get_array()
Directly access the underlying PNMImage array.
bool resolve_filename(Filename &filename, const DSearchPath &searchpath, const std::string &default_extension=std::string()) const
Searches the given search path for the filename.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
int get_lowest_on_bit(uint16_t x)
Returns the index of the lowest 1 bit in the word.
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
get_aux_data
Returns a record previously recorded via set_aux_data().
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void set_red(int x, int y, float r)
Sets the red component color only at the indicated pixel.
int32_t get_int32()
Extracts a signed 32-bit integer.
void unlock()
Alias for release() to match C++11 semantics.
static void consider_yield()
Possibly suspends the current thread for the rest of the current epoch, if it has run for enough this...
The abstract base class for a file or directory within the VirtualFileSystem.
A table of objects that are saved within the graphics context for reference by handle later.
size_t get_remaining_size() const
Return the bytes left in the datagram.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool has_ram_image() const
Returns true if the Texture has its image contents available in main RAM, false if it exists only in ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_name
Returns the complete name represented by the InternalName and all of its parents.
std::string get_string()
Extracts a variable-length string.
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
BEGIN_PUBLISH EXPCL_PANDA_PNMIMAGE float decode_sRGB_float(unsigned char val)
Decodes the sRGB-encoded unsigned char value to a linearized float in the range 0-1.
void quick_filter_from(const PNMImage ©, int xborder=0, int yborder=0)
Resizes from the given image, with a fixed radius of 0.5.
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
bool open(const FileReference *file)
Opens the indicated filename for writing.
void add_uint32(uint32_t value)
Adds an unsigned 32-bit integer to the datagram.
bool is_valid() const
Returns true if the image has been read in or correctly initialized with a height and width.
This is our own Panda specialization on the default STL vector.
void notify_all()
Informs all of the other threads who are currently blocked on wait() that the relevant condition has ...
CPTA_uchar get_ram_mipmap_image(int n) const
Returns the system-RAM image data associated with the nth mipmap level, if present.
bool release(PreparedGraphicsObjects *prepared_objects)
Frees the texture context only on the indicated object, if it exists there.
PT(Texture) Texture
Constructs a new Texture object from the txo file.
static void close_read_file(std::istream *stream)
Closes a file opened by a previous call to open_read_file().
void consider_rescale(PNMImage &pnmimage)
Asks the PNMImage to change its scale when it reads the image, according to the whims of the Config....
static TextureType string_texture_type(const std::string &str)
Returns the TextureType corresponding to the indicated string word.
void set_size_padded(int x=1, int y=1, int z=1)
Changes the size of the texture, padding if necessary, and setting the pad region as well.
bool store(BamCacheRecord *record)
Flushes a cache entry to disk.
bool read(const Filename &fullpath)
Reads the PFM data from the indicated file, returning true on success, false on failure.
A lightweight class that represents a single element that may be timed and/or counted via stats.
get_wrap_v
Returns the wrap mode of the texture in the V direction.
static AutoTextureScale get_textures_power_2()
This flag returns ATS_none, ATS_up, or ATS_down and controls the scaling of textures in general.
vector_uchar extract_bytes(size_t size)
Extracts the indicated number of bytes in the datagram and returns them as a string.
bool write(const Filename &fullpath)
Writes the PFM data to the indicated file, returning true on success, false on failure.
virtual bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const
If has_cull_callback() returns true, this function will be called during the cull traversal to perfor...
void parse_params(const FactoryParams ¶ms, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
void generate_alpha_scale_map()
Generates a special 256x1 1-d texture that can be used to apply an arbitrary alpha scale to objects b...
get_current_thread
Returns a pointer to the currently-executing Thread object.
void add_bool(bool value)
Adds a boolean value to the datagram.
A base class for all things which can have a name.
get_expected_ram_page_size
Returns the number of bytes that should be used per each Z page of the 3-d texture.
bool uses_mipmaps() const
Returns true if the minfilter settings on this texture indicate the use of mipmapping,...
bool exists(const Filename &filename) const
Convenience function; returns true if the named file exists.
bool init()
Initializes the BamReader prior to reading any objects from its source.
clear_aux_data
Removes a record previously recorded via set_aux_data().
int get_read_y_size() const
Returns the requested y_size of the image if set_read_size() has been called, or the image y_size oth...
get_filename
If a BAM is a file, then the BamWriter should contain the name of the file.
The name of a file, such as a texture file or an Egg file.
PointerToArray< Element > cast_non_const() const
Casts away the constness of the CPTA(Element), and returns an equivalent PTA(Element).
Defines a pfm file, a 2-d table of floating-point numbers, either 3-component or 1-component,...
CPTA_uchar get_ram_image_as(const std::string &requested_format)
Returns the uncompressed system-RAM image data associated with the texture.
An instance of this class is written to the front of a Bam or Txo file to make the file a cached inst...
static bool has_alpha(Format format)
Returns true if the indicated format includes alpha, false otherwise.
get_anisotropic_degree
Returns the degree of anisotropic filtering that should be applied to the texture.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
void copy_header_from(const PNMImageHeader &header)
Copies just the header information into this image.
xelval get_blue_val(int x, int y) const
Returns the blue component color at the indicated pixel.
void set_blue(int x, int y, float b)
Sets the blue component color only at the indicated pixel.
This template class calls PipelineCycler::read() in the constructor and PipelineCycler::release_read(...
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
static GraphicsStateGuardianBase * get_default_gsg()
Returns a pointer to the "default" GSG.
void add_string(const std::string &str)
Adds a variable-length string to the datagram.
int get_word(size_t n) const
Returns the variable's nth value.
get_data
Returns a pointer to the data stored in the record, or NULL if there is no data.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
PN_float32 get_channel(int x, int y, int c) const
Returns the cth channel of the point value at the indicated point.
uint32_t get_uint32()
Extracts an unsigned 32-bit integer.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void register_factory(TypeHandle handle, CreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
get_loader_options
Returns the LoaderOptions passed to the loader when the model was requested, if any.
Texture * load_related(const InternalName *suffix) const
Loads a texture whose filename is derived by concatenating a suffix to the filename of this texture.
This class specializes ConfigVariable as an enumerated type.
set_aux_data
Records an arbitrary object in the Texture, associated with a specified key.
PointerTo< VirtualFile > get_file(const Filename &filename, bool status_only=false) const
Looks up the file by the indicated name in the file system.
get_texture_num_views
See set_texture_num_views().
void register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
static Texture * load_texture(const Filename &filename, int primary_file_num_channels=0, bool read_mipmaps=false, const LoaderOptions &options=LoaderOptions())
Loads the given filename up into a texture, if it has not already been loaded, and returns the new te...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool read_dds(std::istream &in, const std::string &filename="", bool header_only=false)
Reads the texture from a DDS file object.
std::string get_unique_value(size_t n) const
Returns the nth unique value of the variable.
xelval * get_alpha_array()
Directly access the underlying PNMImage array of alpha values.
static ComponentType string_component_type(const std::string &str)
Returns the ComponentType corresponding to the indicated string word.
size_t get_data_size_bytes(PreparedGraphicsObjects *prepared_objects) const
Returns the number of bytes which the texture is reported to consume within graphics memory,...
This is an abstract base class that defines the interface for reading image files of various types.
Encodes a string name in a hash table, mapping it to a pointer.
void ref() const
Explicitly increments the reference count.
bool make_relative_to(Filename directory, bool allow_backups=true)
Adjusts this filename, which must be a fully-specified pathname beginning with a slash,...
std::string get_basename() const
Returns the basename part of the filename.
bool is_texture_queued(const Texture *tex) const
Returns true if the texture has been queued on this GSG, false otherwise.
void set_ram_image_as(CPTA_uchar image, const std::string &provided_format)
Replaces the current system-RAM image with the new data, converting it first if necessary from the in...
An instance of this object is returned by Texture::peek().
void set_channel(int x, int y, int c, PN_float32 value)
Replaces the cth channel of the point value at the indicated point.
Represents a set of settings that indicate how a texture is sampled.
void local_object()
This function should be called, once, immediately after creating a new instance of some ReferenceCoun...
static void close_write_file(std::ostream *stream)
Closes a file opened by a previous call to open_write_file().
TextureContext * prepare_now(int view, PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg)
Creates a context for the texture on the particular GSG, if it does not already exist.
bool load(const PNMImage &pnmimage)
Fills the PfmFile with the data from the indicated PNMImage, converted to floating-point values.
void set_basename_wo_extension(const std::string &s)
Replaces the basename part of the filename, without the file extension.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static bool is_unsigned(ComponentType ctype)
Returns true if the indicated component type is unsigned, false otherwise.
This class can be used to write a binary file that consists of an arbitrary header followed by a numb...
void add_alpha()
Adds an alpha channel to the image, if it does not already have one.
void make_absolute()
Converts the filename to a fully-qualified pathname from the root (if it is a relative pathname),...
void generate_simple_ram_image()
Computes the "simple" ram image by loading the main RAM image, if it is not already available,...
std::ostream * open_write_file(const Filename &filename, bool auto_wrap, bool truncate)
Convenience function; returns a newly allocated ostream if the file exists and can be written,...
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
CycleDataType * elevate_read_upstream(const CycleDataType *pointer, bool force_to_0, Thread *current_thread)
See PipelineCyclerBase::elevate_read_upstream().
void clear()
Frees all memory allocated for the image, and clears all its parameters (size, color,...
static int up_to_power_2(int value)
Returns the smallest power of 2 greater than or equal to value.
void add_int32(int32_t value)
Adds a signed 32-bit integer to the datagram.
void set_alpha(int x, int y, float a)
Sets the alpha component color only at the indicated pixel.
get_magfilter
Returns the filter mode of the texture for magnification.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
PTA_uchar new_simple_ram_image(int x_size, int y_size)
Creates an empty array for the simple ram image of the indicated size, and returns a modifiable point...
A thread; that is, a lightweight process.
void take_from(PNMImage &orig)
Move the contents of the other image into this one, and empty the other image.
string upcase(const string &s)
Returns the input string with all lowercase letters converted to uppercase.
TextureContext * prepare_texture_now(Texture *tex, int view, GraphicsStateGuardianBase *gsg)
Immediately creates a new TextureContext for the indicated texture and returns it.
int find_on_searchpath(const DSearchPath &searchpath)
Performs the reverse of the resolve_filename() operation: assuming that the current filename is fully...
get_border_color
Returns the solid color of the texture's border.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const
Returns true if the texture has already been prepared or enqueued for preparation on the indicated GS...
CycleDataType * write_upstream(bool force_to_0, Thread *current_thread)
See PipelineCyclerBase::write_upstream().
static std::string format_texture_type(TextureType tt)
Returns the indicated TextureType converted to a string word.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static int down_to_power_2(int value)
Returns the largest power of 2 less than or equal to value.
static bool adjust_size(int &x_size, int &y_size, const std::string &name, bool for_padding, AutoTextureScale auto_texture_scale=ATS_unspecified)
Computes the proper size of the texture, based on the original size, the filename,...
void generate_normalization_cube_map(int size)
Generates a special cube map image in the texture that can be used to apply bump mapping effects: for...
set_auto_texture_scale
Set this flag to ATS_none, ATS_up, ATS_down, or ATS_pad to control how a texture is scaled from disk ...
bool read(const Filename &fullpath, const LoaderOptions &options=LoaderOptions())
Reads the named filename into the texture.
void add_uint8(uint8_t value)
Adds an unsigned 8-bit integer to the datagram.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Filename get_cwd() const
Returns the current directory name.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_cache_compressed_textures
Returns whether compressed texture files will be stored in the cache, as compressed txo files.
void clear_ram_mipmap_image(int n)
Discards the current system-RAM image for the nth mipmap level.
void add_dependent_file(const Filename &pathname)
Adds the indicated file to the list of files that will be loaded to generate the data in this record.
bool read_txo(std::istream &in, const std::string &filename="")
Reads the texture from a Panda texture object.
A class to retrieve the individual data elements previously stored in a Datagram.
void texture_uploaded()
This method is called by the GraphicsEngine at the beginning of the frame *after* a texture has been ...
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
static Texture * load_3d_texture(const Filename &filename_pattern, bool read_mipmaps=false, const LoaderOptions &options=LoaderOptions())
Loads a 3-D texture that is specified with a series of n pages, all numbered in sequence,...
static Texture * load_2d_texture_array(const Filename &filename_pattern, bool read_mipmaps=false, const LoaderOptions &options=LoaderOptions())
Loads a 2-D texture array that is specified with a series of n pages, all numbered in sequence,...
has_simple_ram_image
Returns true if the Texture has a "simple" image available in main RAM.
xelval get_alpha_val(int x, int y) const
Returns the alpha component color at the indicated pixel.
get_data_size_bytes
Returns the number of bytes previously reported for the data object.
TypeHandle is the identifier used to differentiate C++ class types.
static Filename pattern_filename(const std::string &filename)
Constructs a filename that represents a sequence of numbered files.
void fill(float red, float green, float blue)
Sets the entire image (except the alpha channel) to the given color.
get_auto_texture_scale
Returns the power-of-2 texture-scaling mode that will be applied to this particular texture when it i...
bool store(PNMImage &pnmimage) const
Copies the data to the indicated PNMImage, converting to RGB values.
bool has_compression() const
Returns true if the texture indicates it wants to be compressed, either with CM_on or higher,...
void set_num_channels(int num_channels)
Changes the number of channels associated with the image.
A class to read sequential binary data directly from an istream.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void set_read_size(int x_size, int y_size)
Specifies the size to we'd like to scale the image upon reading it.
bool has_hash() const
Returns true if the filename is indicated to be a filename pattern (that is, set_pattern(true) was ca...
const CycleDataType * read(Thread *current_thread) const
See PipelineCyclerBase::read().
get_filename
If a BAM is a file, then the BamReader should contain the name of the file.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
static bool has_binary_alpha(Format format)
Returns true if the indicated format includes a binary alpha only, false otherwise.
void lock()
Alias for acquire() to match C++11 semantics.
void release_read(const CycleData *pointer) const
Releases a pointer previously obtained via a call to read().
get_auto_texture_scale
See set_auto_texture_scale().
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static std::string format_compression_mode(CompressionMode cm)
Returns the indicated CompressionMode converted to a string word.
xelval get_green_val(int x, int y) const
Returns the green component color at the indicated pixel.
EXPCL_PANDA_PNMIMAGE unsigned char encode_sRGB_uchar(unsigned char val)
Encodes the linearized unsigned char value to an sRGB-encoded unsigned char value.
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
xelval get_red_val(int x, int y) const
Returns the red component color at the indicated pixel.
static BamCache * get_global_ptr()
Returns a pointer to the global BamCache object, which is used automatically by the ModelPool and Tex...
void clear()
Eliminates all data in the file.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual bool has_cull_callback() const
Should be overridden by derived classes to return true if cull_callback() has been defined.
bool write(const Filename &fullpath)
Writes the texture to the named filename.
This class can be used to test for string matches against standard Unix- shell filename globbing conv...
virtual bool unref() const
Explicitly decrements the reference count.
get_resident
Returns the resident flag associated with this object.
float get_alpha(int x, int y) const
Returns the alpha component color at the indicated pixel.
int get_read_x_size() const
Returns the requested x_size of the image if set_read_size() has been called, or the image x_size oth...
void set_ram_mipmap_pointer(int n, void *image, size_t page_size=0)
Sets an explicit void pointer as the texture's mipmap image for the indicated level.
void * get_ram_mipmap_pointer(int n) const
Similiar to get_ram_mipmap_image(), however, in this case the void pointer for the given ram image is...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool read_ktx(std::istream &in, const std::string &filename="", bool header_only=false)
Reads the texture from a KTX file object.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.