62(
"texture-quality-level", Texture::QL_normal,
63 PRC_DESC(
"This specifies a global quality level for all textures. You "
64 "may specify either fastest, normal, or best. This actually "
65 "affects the meaning of Texture::set_quality_level(QL_default), "
66 "so it may be overridden on a per-texture basis. This generally "
67 "only has an effect when using the tinydisplay software renderer; "
68 "it has little or no effect on normal, hardware-accelerated "
69 "renderers. See Texture::set_quality_level()."));
74AutoTextureScale Texture::_textures_power_2 = ATS_unspecified;
79#define DDS_MAGIC 0x20534444
83#define DDSD_CAPS 0x00000001
84#define DDSD_HEIGHT 0x00000002
85#define DDSD_WIDTH 0x00000004
86#define DDSD_PITCH 0x00000008
87#define DDSD_PIXELFORMAT 0x00001000
88#define DDSD_MIPMAPCOUNT 0x00020000
89#define DDSD_LINEARSIZE 0x00080000
90#define DDSD_DEPTH 0x00800000
93#define DDPF_ALPHAPIXELS 0x00000001
94#define DDPF_FOURCC 0x00000004
95#define DDPF_INDEXED 0x00000020
96#define DDPF_RGB 0x00000040
99#define DDSCAPS_COMPLEX 0x00000008
100#define DDSCAPS_TEXTURE 0x00001000
101#define DDSCAPS_MIPMAP 0x00400000
104#define DDSCAPS2_CUBEMAP 0x00000200
105#define DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400
106#define DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800
107#define DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000
108#define DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000
109#define DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000
110#define DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000
111#define DDSCAPS2_VOLUME 0x00200000
113struct DDSPixelFormat {
114 unsigned int pf_size;
115 unsigned int pf_flags;
116 unsigned int four_cc;
117 unsigned int rgb_bitcount;
131 unsigned int dds_magic;
132 unsigned int dds_size;
133 unsigned int dds_flags;
138 unsigned int num_levels;
147 KTX_UNSIGNED_BYTE = 0x1401,
149 KTX_UNSIGNED_SHORT = 0x1403,
151 KTX_UNSIGNED_INT = 0x1405,
153 KTX_HALF_FLOAT = 0x140B,
154 KTX_UNSIGNED_BYTE_3_3_2 = 0x8032,
155 KTX_UNSIGNED_SHORT_4_4_4_4 = 0x8033,
156 KTX_UNSIGNED_SHORT_5_5_5_1 = 0x8034,
157 KTX_UNSIGNED_INT_8_8_8_8 = 0x8035,
158 KTX_UNSIGNED_INT_10_10_10_2 = 0x8036,
159 KTX_UNSIGNED_BYTE_2_3_3_REV = 0x8362,
160 KTX_UNSIGNED_SHORT_5_6_5 = 0x8363,
161 KTX_UNSIGNED_SHORT_5_6_5_REV = 0x8364,
162 KTX_UNSIGNED_SHORT_4_4_4_4_REV = 0x8365,
163 KTX_UNSIGNED_SHORT_1_5_5_5_REV = 0x8366,
164 KTX_UNSIGNED_INT_8_8_8_8_REV = 0x8367,
165 KTX_UNSIGNED_INT_2_10_10_10_REV = 0x8368,
166 KTX_UNSIGNED_INT_24_8 = 0x84FA,
167 KTX_UNSIGNED_INT_10F_11F_11F_REV = 0x8C3B,
168 KTX_UNSIGNED_INT_5_9_9_9_REV = 0x8C3E,
169 KTX_FLOAT_32_UNSIGNED_INT_24_8_REV = 0x8DAD,
174 KTX_ALPHA12 = 0x803D,
175 KTX_ALPHA16 = 0x803E,
176 KTX_ALPHA16_SNORM = 0x9018,
179 KTX_ALPHA8_SNORM = 0x9014,
180 KTX_ALPHA_SNORM = 0x9010,
182 KTX_BGR_INTEGER = 0x8D9A,
184 KTX_BGRA_INTEGER = 0x8D9B,
186 KTX_BLUE_INTEGER = 0x8D96,
187 KTX_COLOR_INDEX = 0x1900,
188 KTX_DEPTH24_STENCIL8 = 0x88F0,
189 KTX_DEPTH32F_STENCIL8 = 0x8CAD,
190 KTX_DEPTH_COMPONENT = 0x1902,
191 KTX_DEPTH_COMPONENT16 = 0x81A5,
192 KTX_DEPTH_COMPONENT24 = 0x81A6,
193 KTX_DEPTH_COMPONENT32 = 0x81A7,
194 KTX_DEPTH_COMPONENT32F = 0x8CAC,
195 KTX_DEPTH_STENCIL = 0x84F9,
197 KTX_GREEN_INTEGER = 0x8D95,
198 KTX_INTENSITY = 0x8049,
199 KTX_INTENSITY12 = 0x804C,
200 KTX_INTENSITY16 = 0x804D,
201 KTX_INTENSITY16_SNORM = 0x901B,
202 KTX_INTENSITY4 = 0x804A,
203 KTX_INTENSITY8 = 0x804B,
204 KTX_INTENSITY8_SNORM = 0x9017,
205 KTX_INTENSITY_SNORM = 0x9013,
206 KTX_LUMINANCE = 0x1909,
207 KTX_LUMINANCE12 = 0x8041,
208 KTX_LUMINANCE12_ALPHA12 = 0x8047,
209 KTX_LUMINANCE12_ALPHA4 = 0x8046,
210 KTX_LUMINANCE16 = 0x8042,
211 KTX_LUMINANCE16_ALPHA16 = 0x8048,
212 KTX_LUMINANCE16_ALPHA16_SNORM = 0x901A,
213 KTX_LUMINANCE16_SNORM = 0x9019,
214 KTX_LUMINANCE4 = 0x803F,
215 KTX_LUMINANCE4_ALPHA4 = 0x8043,
216 KTX_LUMINANCE6_ALPHA2 = 0x8044,
217 KTX_LUMINANCE8 = 0x8040,
218 KTX_LUMINANCE8_ALPHA8 = 0x8045,
219 KTX_LUMINANCE8_ALPHA8_SNORM = 0x9016,
220 KTX_LUMINANCE8_SNORM = 0x9015,
221 KTX_LUMINANCE_ALPHA = 0x190A,
222 KTX_LUMINANCE_ALPHA_SNORM = 0x9012,
223 KTX_LUMINANCE_SNORM = 0x9011,
224 KTX_R11F_G11F_B10F = 0x8C3A,
226 KTX_R16_SNORM = 0x8F98,
233 KTX_R3_G3_B2 = 0x2A10,
235 KTX_R8_SNORM = 0x8F94,
239 KTX_RED_INTEGER = 0x8D94,
240 KTX_RED_SNORM = 0x8F90,
243 KTX_RG16_SNORM = 0x8F99,
251 KTX_RG8_SNORM = 0x8F95,
254 KTX_RG_INTEGER = 0x8228,
255 KTX_RG_SNORM = 0x8F91,
258 KTX_RGB10_A2 = 0x8059,
261 KTX_RGB16_SNORM = 0x8F9A,
264 KTX_RGB16UI = 0x8D77,
268 KTX_RGB32UI = 0x8D71,
271 KTX_RGB5_A1 = 0x8057,
273 KTX_RGB8_SNORM = 0x8F96,
276 KTX_RGB9_E5 = 0x8C3D,
277 KTX_RGB_INTEGER = 0x8D98,
278 KTX_RGB_SNORM = 0x8F92,
282 KTX_RGBA16_SNORM = 0x8F9B,
283 KTX_RGBA16F = 0x881A,
284 KTX_RGBA16I = 0x8D88,
285 KTX_RGBA16UI = 0x8D76,
287 KTX_RGBA32F = 0x8814,
288 KTX_RGBA32I = 0x8D82,
289 KTX_RGBA32UI = 0x8D70,
292 KTX_RGBA8_SNORM = 0x8F97,
294 KTX_RGBA8UI = 0x8D7C,
295 KTX_RGBA_INTEGER = 0x8D99,
296 KTX_RGBA_SNORM = 0x8F93,
297 KTX_SLUMINANCE = 0x8C46,
298 KTX_SLUMINANCE8 = 0x8C47,
299 KTX_SLUMINANCE8_ALPHA8 = 0x8C45,
300 KTX_SLUMINANCE_ALPHA = 0x8C44,
303 KTX_SRGB8_ALPHA8 = 0x8C43,
304 KTX_SRGB_ALPHA = 0x8C42,
305 KTX_STENCIL_INDEX = 0x1901,
306 KTX_STENCIL_INDEX1 = 0x8D46,
307 KTX_STENCIL_INDEX16 = 0x8D49,
308 KTX_STENCIL_INDEX4 = 0x8D47,
309 KTX_STENCIL_INDEX8 = 0x8D48,
312enum KTXCompressedFormat {
313 KTX_COMPRESSED_LUMINANCE_ALPHA_LATC2 = 0x8C72,
314 KTX_COMPRESSED_LUMINANCE_LATC1 = 0x8C70,
315 KTX_COMPRESSED_R11_EAC = 0x9270,
316 KTX_COMPRESSED_RED = 0x8225,
317 KTX_COMPRESSED_RED_RGTC1 = 0x8DBB,
318 KTX_COMPRESSED_RG = 0x8226,
319 KTX_COMPRESSED_RG11_EAC = 0x9272,
320 KTX_COMPRESSED_RG_RGTC2 = 0x8DBD,
321 KTX_COMPRESSED_RGB = 0x84ED,
322 KTX_COMPRESSED_RGB8_ETC2 = 0x9274,
323 KTX_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9276,
324 KTX_COMPRESSED_RGB_BPTC_SIGNED_FLOAT = 0x8E8E,
325 KTX_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT = 0x8E8F,
326 KTX_COMPRESSED_RGB_FXT1_3DFX = 0x86B0,
327 KTX_COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01,
328 KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00,
329 KTX_COMPRESSED_RGB_S3TC_DXT1 = 0x83F0,
330 KTX_COMPRESSED_RGBA = 0x84EE,
331 KTX_COMPRESSED_RGBA8_ETC2_EAC = 0x9278,
332 KTX_COMPRESSED_RGBA_BPTC_UNORM = 0x8E8C,
333 KTX_COMPRESSED_RGBA_FXT1_3DFX = 0x86B1,
334 KTX_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03,
335 KTX_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG = 0x9137,
336 KTX_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02,
337 KTX_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG = 0x9138,
338 KTX_COMPRESSED_RGBA_S3TC_DXT1 = 0x83F1,
339 KTX_COMPRESSED_RGBA_S3TC_DXT3 = 0x83F2,
340 KTX_COMPRESSED_RGBA_S3TC_DXT5 = 0x83F3,
341 KTX_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2 = 0x8C73,
342 KTX_COMPRESSED_SIGNED_LUMINANCE_LATC1 = 0x8C71,
343 KTX_COMPRESSED_SIGNED_R11_EAC = 0x9271,
344 KTX_COMPRESSED_SIGNED_RED_RGTC1 = 0x8DBC,
345 KTX_COMPRESSED_SIGNED_RG11_EAC = 0x9273,
346 KTX_COMPRESSED_SIGNED_RG_RGTC2 = 0x8DBE,
347 KTX_COMPRESSED_SLUMINANCE = 0x8C4A,
348 KTX_COMPRESSED_SLUMINANCE_ALPHA = 0x8C4B,
349 KTX_COMPRESSED_SRGB = 0x8C48,
350 KTX_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC = 0x9279,
351 KTX_COMPRESSED_SRGB8_ETC2 = 0x9275,
352 KTX_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9277,
353 KTX_COMPRESSED_SRGB_ALPHA = 0x8C49,
354 KTX_COMPRESSED_SRGB_ALPHA_BPTC_UNORM = 0x8E8D,
355 KTX_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1 = 0x8A56,
356 KTX_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2 = 0x93F0,
357 KTX_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1 = 0x8A57,
358 KTX_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2 = 0x93F1,
359 KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT1 = 0x8C4D,
360 KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT3 = 0x8C4E,
361 KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT5 = 0x8C4F,
362 KTX_COMPRESSED_SRGB_PVRTC_2BPPV1 = 0x8A54,
363 KTX_COMPRESSED_SRGB_PVRTC_4BPPV1 = 0x8A55,
364 KTX_COMPRESSED_SRGB_S3TC_DXT1 = 0x8C4C,
365 KTX_ETC1_RGB8 = 0x8D64,
366 KTX_ETC1_SRGB8 = 0x88EE,
383 cdata->inc_properties_modified();
392 _cycler(copy._cycler),
393 _lock(copy.get_name()),
403operator = (
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_rgba32:
743 case Texture::F_rgba32i:
748 case Texture::F_r16i:
749 case Texture::F_rg8i:
752 case Texture::F_rg16:
753 case Texture::F_rg16i:
756 case Texture::F_rgb16:
757 case Texture::F_rgb16i:
758 case Texture::F_rgba16:
759 case Texture::F_rgba16i:
763 case Texture::F_r32i:
768 case Texture::F_rg32:
769 case Texture::F_rg32i:
773 case Texture::F_rgb32:
774 case Texture::F_rgb32i:
778 case Texture::F_r11_g11_b10:
779 case Texture::F_rgb9_e5:
780 case Texture::F_rgb10_a2:
787 gobj_cat.warning() <<
"Unhandled format in estimate_texture_memory(): "
788 << cdata->_format <<
"\n";
791 size_t bytes = pixels * bpp;
793 bytes = (bytes * 4) / 3;
809 _aux_data[key] = aux_data;
818 _aux_data.erase(key);
828 AuxData::const_iterator di;
829 di = _aux_data.find(key);
830 if (di != _aux_data.end()) {
845read_txo(istream &in,
const string &filename) {
847 cdata->inc_properties_modified();
848 cdata->inc_image_modified();
849 return do_read_txo(cdata, in, filename);
860make_from_txo(istream &in,
const string &filename) {
863 if (!din.
open(in, filename)) {
865 <<
"Could not read texture object: " << filename <<
"\n";
872 << filename <<
" is not a texture object file.\n";
876 if (head != _bam_header) {
878 << filename <<
" is not a texture object file.\n";
883 if (!reader.
init()) {
889 if (
object !=
nullptr &&
898 if (
object ==
nullptr) {
900 <<
"Texture object " << filename <<
" is empty.\n";
903 }
else if (!object->
is_of_type(Texture::get_class_type())) {
905 <<
"Texture object " << filename <<
" contains a "
906 <<
object->get_type() <<
", not a Texture.\n";
913 <<
"Unable to fully resolve texture object file.\n";
928write_txo(ostream &out,
const string &filename)
const {
930 return do_write_txo(cdata, out, filename);
943read_dds(istream &in,
const string &filename,
bool header_only) {
945 cdata->inc_properties_modified();
946 cdata->inc_image_modified();
947 return do_read_dds(cdata, in, filename, header_only);
960read_ktx(istream &in,
const string &filename,
bool header_only) {
962 cdata->inc_properties_modified();
963 cdata->inc_image_modified();
964 return do_read_ktx(cdata, in, filename, header_only);
977 RelatedTextures::const_iterator ti;
978 ti = _related_textures.find(suffix);
979 if (ti != _related_textures.end()) {
982 if (cdata->_fullpath.empty()) {
986 main.set_basename_wo_extension(main.get_basename_wo_extension() +
989 if (!cdata->_alpha_fullpath.empty()) {
990 Filename alph = cdata->_alpha_fullpath;
998 cdata->_primary_file_num_channels,
999 cdata->_alpha_file_channel,
false);
1014 ((
Texture *)
this)->_related_textures.insert(RelatedTextures::value_type(suffix, res));
1028 string format =
upcase(supplied_format);
1031 size_t imgsize = (size_t)cdata->_x_size * (
size_t)cdata->_y_size *
1032 (size_t)cdata->_z_size * (
size_t)cdata->_num_views;
1033 nassertv(image.size() == (
size_t)(cdata->_component_width * format.size() * imgsize));
1036 if ((cdata->_num_components == 1 && format.size() == 1) ||
1037 (cdata->_num_components == 2 && format.size() == 2 && format.at(1) ==
'A' && format.at(0) !=
'A') ||
1038 (cdata->_num_components == 3 && format ==
"BGR") ||
1039 (cdata->_num_components == 4 && format ==
"BGRA")) {
1041 do_set_ram_image(cdata, image);
1046 PTA_uchar newdata = PTA_uchar::empty_array(imgsize * cdata->_num_components * cdata->_component_width, get_class_type());
1049 if (cdata->_component_width == 1) {
1050 if (format ==
"RGBA" && cdata->_num_components == 4) {
1052 for (
int p = 0; p < imgsize; p += 4) {
1053 newdata[p + 2] = image[p ];
1054 newdata[p + 1] = image[p + 1];
1055 newdata[p ] = image[p + 2];
1056 newdata[p + 3] = image[p + 3];
1058 do_set_ram_image(cdata, newdata);
1061 if (format ==
"RGB" && cdata->_num_components == 3) {
1063 for (
int p = 0; p < imgsize; p += 3) {
1064 newdata[p + 2] = image[p ];
1065 newdata[p + 1] = image[p + 1];
1066 newdata[p ] = image[p + 2];
1068 do_set_ram_image(cdata, newdata);
1071 if (format ==
"A" && cdata->_num_components != 3) {
1073 int component = cdata->_num_components - 1;
1074 for (
size_t p = 0; p < imgsize; ++p) {
1075 newdata[component] = image[p];
1077 do_set_ram_image(cdata, newdata);
1080 for (
size_t p = 0; p < imgsize; ++p) {
1081 for (uchar s = 0; s < format.size(); ++s) {
1082 signed char component = -1;
1083 if (format.at(s) ==
'B' || (cdata->_num_components <= 2 && format.at(s) !=
'A')) {
1085 }
else if (format.at(s) ==
'G') {
1087 }
else if (format.at(s) ==
'R') {
1089 }
else if (format.at(s) ==
'A') {
1090 if (cdata->_num_components != 3) {
1091 component = cdata->_num_components - 1;
1095 }
else if (format.at(s) ==
'0') {
1097 }
else if (format.at(s) ==
'1') {
1100 gobj_cat.error() <<
"Unexpected component character '"
1101 << format.at(s) <<
"', expected one of RGBA!\n";
1104 if (component >= 0) {
1105 newdata[p * cdata->_num_components + component] = image[p * format.size() + s];
1109 do_set_ram_image(cdata, newdata);
1112 for (
size_t p = 0; p < imgsize; ++p) {
1113 for (uchar s = 0; s < format.size(); ++s) {
1114 signed char component = -1;
1115 if (format.at(s) ==
'B' || (cdata->_num_components <= 2 && format.at(s) !=
'A')) {
1117 }
else if (format.at(s) ==
'G') {
1119 }
else if (format.at(s) ==
'R') {
1121 }
else if (format.at(s) ==
'A') {
1122 if (cdata->_num_components != 3) {
1123 component = cdata->_num_components - 1;
1127 }
else if (format.at(s) ==
'0') {
1129 }
else if (format.at(s) ==
'1') {
1132 gobj_cat.error() <<
"Unexpected component character '"
1133 << format.at(s) <<
"', expected one of RGBA!\n";
1136 if (component >= 0) {
1137 memcpy((
void*)(newdata + (p * cdata->_num_components + component) * cdata->_component_width),
1138 (
void*)(image + (p * format.size() + s) * cdata->_component_width),
1139 cdata->_component_width);
1143 do_set_ram_image(cdata, newdata);
1154 CDReader cdata(_cycler);
1155 return cdata->_keep_ram_image;
1165 CDReader cdata(_cycler);
1166 return do_has_bam_rawdata(cdata);
1183 CDReader cdata(_cycler);
1184 if (cdata->_ram_images.empty() || cdata->_ram_images[0]._image.empty()) {
1194 int size = max(cdata->_x_size, max(cdata->_y_size, cdata->_z_size));
1200 if (n >= (
int)cdata->_ram_images.size() || cdata->_ram_images[n]._image.empty()) {
1216 if (n < (
int)cdata->_ram_images.size() && !cdata->_ram_images[n]._image.empty()) {
1217 return cdata->_ram_images[n]._image;
1230 if (n < (
int)cdata->_ram_images.size()) {
1231 return cdata->_ram_images[n]._pointer_image;
1249 nassertv(cdata->_ram_image_compression != CM_off || do_get_expected_ram_mipmap_image_size(cdata, n));
1251 while (n >= (
int)cdata->_ram_images.size()) {
1252 cdata->_ram_images.push_back(RamImage());
1255 cdata->_ram_images[n]._page_size = page_size;
1257 cdata->_ram_images[n]._pointer_image = image;
1258 cdata->inc_image_modified();
1279 if (n >= (
int)cdata->_ram_images.size()) {
1282 cdata->_ram_images[n]._page_size = 0;
1283 cdata->_ram_images[n]._image.clear();
1284 cdata->_ram_images[n]._pointer_image =
nullptr;
1294 cdata->_simple_image_date_generated = (int32_t)time(
nullptr);
1295 return cdata->_simple_ram_image._image;
1305 nassertr(cdata->_texture_type == TT_2d_texture, PTA_uchar());
1306 size_t expected_page_size = (size_t)(x_size * y_size * 4);
1308 cdata->_simple_x_size = x_size;
1309 cdata->_simple_y_size = y_size;
1310 cdata->_simple_ram_image._image = PTA_uchar::empty_array(expected_page_size);
1311 cdata->_simple_ram_image._page_size = expected_page_size;
1312 cdata->_simple_image_date_generated = (int32_t)time(
nullptr);
1313 cdata->inc_simple_image_modified();
1315 return cdata->_simple_ram_image._image;
1327 if (cdata->_texture_type != TT_2d_texture ||
1328 cdata->_ram_image_compression != CM_off) {
1333 if (!do_store_one(cdata, pnmimage, 0, 0)) {
1338 int x_size = simple_image_size.
get_word(0);
1339 int y_size = simple_image_size.
get_word(1);
1360 did_anything =
false;
1364 int new_x_size = (x_size >> 1);
1365 PNMImage smaller(new_x_size, y_size, 4);
1367 PNMImage bigger(x_size, y_size, 4);
1370 if (compare_images(scaled, bigger)) {
1372 x_size = new_x_size;
1373 did_anything =
true;
1379 int new_y_size = (y_size >> 1);
1380 PNMImage smaller(x_size, new_y_size, 4);
1382 PNMImage bigger(x_size, y_size, 4);
1385 if (compare_images(scaled, bigger)) {
1387 y_size = new_y_size;
1388 did_anything =
true;
1391 }
while (did_anything);
1393 size_t expected_page_size = (size_t)(x_size * y_size * 4);
1394 PTA_uchar image = PTA_uchar::empty_array(expected_page_size, get_class_type());
1395 convert_from_pnmimage(image, expected_page_size, x_size, 0, 0, 0, scaled, 4, 1);
1397 do_set_simple_ram_image(cdata, image, x_size, y_size);
1398 cdata->_simple_image_date_generated = (int32_t)time(
nullptr);
1415 CDWriter cdata(_cycler, unlocked_ensure_ram_image(
true));
1418 if (peeker->is_valid()) {
1436 return prepared_objects->enqueue_texture_future(
this);
1446 PreparedViews::const_iterator pvi;
1447 pvi = _prepared_views.find(prepared_objects);
1448 if (pvi != _prepared_views.end()) {
1464 PreparedViews::const_iterator pvi;
1465 pvi = _prepared_views.find(prepared_objects);
1466 if (pvi != _prepared_views.end()) {
1467 const Contexts &contexts = (*pvi).second;
1468 for (
int view = 0; view < cdata->_num_views; ++view) {
1469 Contexts::const_iterator ci;
1470 ci = contexts.find(view);
1471 if (ci == contexts.end()) {
1496 PreparedViews::const_iterator pvi;
1497 size_t total_size = 0;
1498 pvi = _prepared_views.find(prepared_objects);
1499 if (pvi != _prepared_views.end()) {
1500 const Contexts &contexts = (*pvi).second;
1501 for (
int view = 0; view < cdata->_num_views; ++view) {
1502 Contexts::const_iterator ci;
1503 ci = contexts.find(view);
1504 if (ci != contexts.end()) {
1523 PreparedViews::const_iterator pvi;
1524 pvi = _prepared_views.find(prepared_objects);
1525 if (pvi != _prepared_views.end()) {
1526 const Contexts &contexts = (*pvi).second;
1527 for (
int view = 0; view < cdata->_num_views; ++view) {
1528 Contexts::const_iterator ci;
1529 ci = contexts.find(view);
1530 if (ci != contexts.end()) {
1550 PreparedViews::const_iterator pvi;
1551 pvi = _prepared_views.find(prepared_objects);
1552 if (pvi != _prepared_views.end()) {
1553 const Contexts &contexts = (*pvi).second;
1554 for (
int view = 0; view < cdata->_num_views; ++view) {
1555 Contexts::const_iterator ci;
1556 ci = contexts.find(view);
1557 if (ci != contexts.end()) {
1575 PreparedViews::iterator pvi;
1576 pvi = _prepared_views.find(prepared_objects);
1577 if (pvi != _prepared_views.end()) {
1579 temp.swap((*pvi).second);
1580 Contexts::iterator ci;
1581 for (ci = temp.begin(); ci != temp.end(); ++ci) {
1583 if (tc !=
nullptr) {
1587 _prepared_views.erase(pvi);
1607 temp.swap(_prepared_views);
1608 int num_freed = (int)temp.size();
1610 PreparedViews::iterator pvi;
1611 for (pvi = temp.begin(); pvi != temp.end(); ++pvi) {
1614 temp.swap((*pvi).second);
1615 Contexts::iterator ci;
1616 for (ci = temp.begin(); ci != temp.end(); ++ci) {
1618 if (tc !=
nullptr) {
1632write(ostream &out,
int indent_level)
const {
1634 indent(out, indent_level)
1635 << cdata->_texture_type <<
" " << get_name();
1636 if (!cdata->_filename.empty()) {
1637 out <<
" (from " << cdata->_filename <<
")";
1641 indent(out, indent_level + 2);
1643 switch (cdata->_texture_type) {
1645 out <<
"1-d, " << cdata->_x_size;
1649 out <<
"2-d, " << cdata->_x_size <<
" x " << cdata->_y_size;
1653 out <<
"3-d, " << cdata->_x_size <<
" x " << cdata->_y_size <<
" x " << cdata->_z_size;
1656 case TT_2d_texture_array:
1657 out <<
"2-d array, " << cdata->_x_size <<
" x " << cdata->_y_size <<
" x " << cdata->_z_size;
1661 out <<
"cube map, " << cdata->_x_size <<
" x " << cdata->_y_size;
1664 case TT_cube_map_array:
1665 out <<
"cube map array, " << cdata->_x_size <<
" x " << cdata->_y_size <<
" x " << cdata->_z_size;
1668 case TT_buffer_texture:
1669 out <<
"buffer, " << cdata->_x_size;
1672 case TT_1d_texture_array:
1673 out <<
"1-d array, " << cdata->_x_size <<
" x " << cdata->_y_size;
1677 if (cdata->_num_views > 1) {
1678 out <<
" (x " << cdata->_num_views <<
" views)";
1681 out <<
" pixels, each " << cdata->_num_components;
1683 switch (cdata->_component_type) {
1684 case T_unsigned_byte:
1689 case T_unsigned_short:
1700 case T_unsigned_int_24_8:
1702 case T_unsigned_int:
1711 switch (cdata->_format) {
1713 out <<
"color_index";
1715 case F_depth_stencil:
1716 out <<
"depth_stencil";
1718 case F_depth_component:
1719 out <<
"depth_component";
1721 case F_depth_component16:
1722 out <<
"depth_component16";
1724 case F_depth_component24:
1725 out <<
"depth_component24";
1727 case F_depth_component32:
1728 out <<
"depth_component32";
1787 case F_luminance_alpha:
1788 out <<
"luminance_alpha";
1790 case F_luminance_alphamask:
1791 out <<
"luminance_alphamask";
1808 out <<
"srgb_alpha";
1811 out <<
"sluminance";
1813 case F_sluminance_alpha:
1814 out <<
"sluminance_alpha";
1844 out <<
"r11_g11_b10";
1881 if (cdata->_compression != CM_default) {
1882 out <<
", compression " << cdata->_compression;
1886 indent(out, indent_level + 2);
1888 cdata->_default_sampler.output(out);
1890 if (do_has_ram_image(cdata)) {
1891 indent(out, indent_level + 2)
1892 << do_get_ram_image_size(cdata) <<
" bytes in ram, compression "
1893 << cdata->_ram_image_compression <<
"\n";
1895 if (cdata->_ram_images.size() > 1) {
1897 size_t total_size = 0;
1898 for (
size_t n = 1; n < cdata->_ram_images.size(); ++n) {
1899 if (!cdata->_ram_images[n]._image.empty()) {
1901 total_size += cdata->_ram_images[n]._image.size();
1907 indent(out, indent_level + 2)
1909 <<
" mipmap levels also present in ram (" << total_size
1914 indent(out, indent_level + 2)
1915 <<
"no ram image\n";
1918 if (!cdata->_simple_ram_image._image.empty()) {
1919 indent(out, indent_level + 2)
1920 <<
"simple image: " << cdata->_simple_x_size <<
" x "
1921 << cdata->_simple_y_size <<
", "
1922 << cdata->_simple_ram_image._image.size() <<
" bytes\n";
1934 if (do_get_auto_texture_scale(cdata) != ATS_none) {
1938 if (cdata->_texture_type == TT_3d_texture) {
1943 do_set_z_size(cdata, z);
1946 do_set_x_size(cdata, x);
1947 do_set_y_size(cdata, y);
1948 do_set_z_size(cdata, z);
1950 do_set_pad_size(cdata,
1953 cdata->_z_size - z);
1963 cdata->_orig_file_x_size = x;
1964 cdata->_orig_file_y_size = y;
1966 nassertv(z == cdata->_z_size);
1988 view = max(min(view, cdata->_num_views - 1), 0);
1991 Contexts &contexts = _prepared_views[prepared_objects];
1992 Contexts::const_iterator pvi;
1993 pvi = contexts.find(view);
1994 if (pvi != contexts.end()) {
1995 return (*pvi).second;
1999 contexts[view] = tc;
2057 if (
adjust_size(new_x_size, new_y_size, name,
false, auto_texture_scale)) {
2080 return "1d_texture";
2082 return "2d_texture";
2084 return "3d_texture";
2085 case TT_2d_texture_array:
2086 return "2d_texture_array";
2089 case TT_cube_map_array:
2090 return "cube_map_array";
2091 case TT_buffer_texture:
2092 return "buffer_texture";
2093 case TT_1d_texture_array:
2094 return "1d_texture_array";
2096 return "**invalid**";
2104 if (cmp_nocase(str,
"1d_texture") == 0) {
2105 return TT_1d_texture;
2106 }
else if (cmp_nocase(str,
"2d_texture") == 0) {
2107 return TT_2d_texture;
2108 }
else if (cmp_nocase(str,
"3d_texture") == 0) {
2109 return TT_3d_texture;
2110 }
else if (cmp_nocase(str,
"2d_texture_array") == 0) {
2111 return TT_2d_texture_array;
2112 }
else if (cmp_nocase(str,
"cube_map") == 0) {
2114 }
else if (cmp_nocase(str,
"cube_map_array") == 0) {
2115 return TT_cube_map_array;
2116 }
else if (cmp_nocase(str,
"buffer_texture") == 0) {
2117 return TT_buffer_texture;
2121 <<
"Invalid Texture::TextureType value: " << str <<
"\n";
2122 return TT_2d_texture;
2131 case T_unsigned_byte:
2132 return "unsigned_byte";
2133 case T_unsigned_short:
2134 return "unsigned_short";
2137 case T_unsigned_int_24_8:
2138 return "unsigned_int_24_8";
2142 return "unsigned_byte";
2146 return "half_float";
2147 case T_unsigned_int:
2148 return "unsigned_int";
2151 return "**invalid**";
2159 if (cmp_nocase(str,
"unsigned_byte") == 0) {
2160 return T_unsigned_byte;
2161 }
else if (cmp_nocase(str,
"unsigned_short") == 0) {
2162 return T_unsigned_short;
2163 }
else if (cmp_nocase(str,
"float") == 0) {
2165 }
else if (cmp_nocase(str,
"unsigned_int_24_8") == 0) {
2166 return T_unsigned_int_24_8;
2167 }
else if (cmp_nocase(str,
"int") == 0) {
2169 }
else if (cmp_nocase(str,
"byte") == 0) {
2171 }
else if (cmp_nocase(str,
"short") == 0) {
2173 }
else if (cmp_nocase(str,
"half_float") == 0) {
2174 return T_half_float;
2175 }
else if (cmp_nocase(str,
"unsigned_int") == 0) {
2176 return T_unsigned_int;
2180 <<
"Invalid Texture::ComponentType value: " << str <<
"\n";
2181 return T_unsigned_byte;
2190 case F_depth_stencil:
2191 return "depth_stencil";
2192 case F_depth_component:
2193 return "depth_component";
2194 case F_depth_component16:
2195 return "depth_component16";
2196 case F_depth_component24:
2197 return "depth_component24";
2198 case F_depth_component32:
2199 return "depth_component32";
2201 return "color_index";
2234 case F_luminance_alpha:
2235 return "luminance_alpha";
2236 case F_luminance_alphamask:
2237 return "luminance_alphamask";
2251 return "srgb_alpha";
2253 return "sluminance";
2254 case F_sluminance_alpha:
2255 return "sluminance_alpha";
2295 return "**invalid**";
2303 if (cmp_nocase(str,
"depth_stencil") == 0) {
2304 return F_depth_stencil;
2305 }
else if (cmp_nocase(str,
"depth_component") == 0) {
2306 return F_depth_component;
2307 }
else if (cmp_nocase(str,
"depth_component16") == 0 || cmp_nocase(str,
"d16") == 0) {
2308 return F_depth_component16;
2309 }
else if (cmp_nocase(str,
"depth_component24") == 0 || cmp_nocase(str,
"d24") == 0) {
2310 return F_depth_component24;
2311 }
else if (cmp_nocase(str,
"depth_component32") == 0 || cmp_nocase(str,
"d32") == 0) {
2312 return F_depth_component32;
2313 }
else if (cmp_nocase(str,
"color_index") == 0) {
2314 return F_color_index;
2315 }
else if (cmp_nocase(str,
"red") == 0) {
2317 }
else if (cmp_nocase(str,
"green") == 0) {
2319 }
else if (cmp_nocase(str,
"blue") == 0) {
2321 }
else if (cmp_nocase(str,
"alpha") == 0) {
2323 }
else if (cmp_nocase(str,
"rgb") == 0) {
2325 }
else if (cmp_nocase(str,
"rgb5") == 0) {
2327 }
else if (cmp_nocase(str,
"rgb8") == 0 || cmp_nocase(str,
"r8g8b8") == 0) {
2329 }
else if (cmp_nocase(str,
"rgb12") == 0) {
2331 }
else if (cmp_nocase(str,
"rgb332") == 0 || cmp_nocase(str,
"r3g3b2") == 0) {
2333 }
else if (cmp_nocase(str,
"rgba") == 0) {
2335 }
else if (cmp_nocase(str,
"rgbm") == 0) {
2337 }
else if (cmp_nocase(str,
"rgba4") == 0) {
2339 }
else if (cmp_nocase(str,
"rgba5") == 0) {
2341 }
else if (cmp_nocase(str,
"rgba8") == 0 || cmp_nocase(str,
"r8g8b8a8") == 0) {
2343 }
else if (cmp_nocase(str,
"rgba12") == 0) {
2345 }
else if (cmp_nocase(str,
"luminance") == 0) {
2347 }
else if (cmp_nocase(str,
"luminance_alpha") == 0) {
2348 return F_luminance_alpha;
2349 }
else if (cmp_nocase(str,
"luminance_alphamask") == 0) {
2350 return F_luminance_alphamask;
2351 }
else if (cmp_nocase(str,
"rgba16") == 0 || cmp_nocase(str,
"r16g16b16a16") == 0) {
2353 }
else if (cmp_nocase(str,
"rgba32") == 0 || cmp_nocase(str,
"r32g32b32a32") == 0) {
2355 }
else if (cmp_nocase(str,
"r16") == 0 || cmp_nocase(str,
"red16") == 0) {
2357 }
else if (cmp_nocase(str,
"r16i") == 0) {
2359 }
else if (cmp_nocase(str,
"rg16") == 0 || cmp_nocase(str,
"r16g16") == 0) {
2361 }
else if (cmp_nocase(str,
"rgb16") == 0 || cmp_nocase(str,
"r16g16b16") == 0) {
2363 }
else if (cmp_nocase(str,
"srgb") == 0) {
2365 }
else if (cmp_nocase(str,
"srgb_alpha") == 0) {
2366 return F_srgb_alpha;
2367 }
else if (cmp_nocase(str,
"sluminance") == 0) {
2368 return F_sluminance;
2369 }
else if (cmp_nocase(str,
"sluminance_alpha") == 0) {
2370 return F_sluminance_alpha;
2371 }
else if (cmp_nocase(str,
"r32i") == 0) {
2373 }
else if (cmp_nocase(str,
"r32") == 0 || cmp_nocase(str,
"red32") == 0) {
2375 }
else if (cmp_nocase(str,
"rg32") == 0 || cmp_nocase(str,
"r32g32") == 0) {
2377 }
else if (cmp_nocase(str,
"rgb32") == 0 || cmp_nocase(str,
"r32g32b32") == 0) {
2379 }
else if (cmp_nocase_uh(str,
"r8i") == 0) {
2381 }
else if (cmp_nocase_uh(str,
"rg8i") == 0 || cmp_nocase_uh(str,
"r8g8i") == 0) {
2383 }
else if (cmp_nocase_uh(str,
"rgb8i") == 0 || cmp_nocase_uh(str,
"r8g8b8i") == 0) {
2385 }
else if (cmp_nocase_uh(str,
"rgba8i") == 0 || cmp_nocase_uh(str,
"r8g8b8a8i") == 0) {
2387 }
else if (cmp_nocase(str,
"r11g11b10") == 0) {
2388 return F_r11_g11_b10;
2389 }
else if (cmp_nocase(str,
"rgb9_e5") == 0) {
2391 }
else if (cmp_nocase_uh(str,
"rgb10_a2") == 0 || cmp_nocase(str,
"r10g10b10a2") == 0) {
2393 }
else if (cmp_nocase_uh(str,
"rg") == 0) {
2395 }
else if (cmp_nocase_uh(str,
"r16i") == 0) {
2397 }
else if (cmp_nocase_uh(str,
"rg16i") == 0 || cmp_nocase_uh(str,
"r16g16i") == 0) {
2399 }
else if (cmp_nocase_uh(str,
"rgb16i") == 0 || cmp_nocase_uh(str,
"r16g16b16i") == 0) {
2401 }
else if (cmp_nocase_uh(str,
"rgba16i") == 0 || cmp_nocase_uh(str,
"r16g16b16a16i") == 0) {
2403 }
else if (cmp_nocase_uh(str,
"rg32i") == 0 || cmp_nocase_uh(str,
"r32g32i") == 0) {
2405 }
else if (cmp_nocase_uh(str,
"rgb32i") == 0 || cmp_nocase_uh(str,
"r32g32b32i") == 0) {
2407 }
else if (cmp_nocase_uh(str,
"rgba32i") == 0 || cmp_nocase_uh(str,
"r32g32b32a32i") == 0) {
2412 <<
"Invalid Texture::Format value: " << str <<
"\n";
2454 return "**invalid**";
2463 if (cmp_nocase_uh(str,
"default") == 0) {
2465 }
else if (cmp_nocase_uh(str,
"off") == 0) {
2467 }
else if (cmp_nocase_uh(str,
"on") == 0) {
2469 }
else if (cmp_nocase_uh(str,
"fxt1") == 0) {
2471 }
else if (cmp_nocase_uh(str,
"dxt1") == 0) {
2473 }
else if (cmp_nocase_uh(str,
"dxt2") == 0) {
2475 }
else if (cmp_nocase_uh(str,
"dxt3") == 0) {
2477 }
else if (cmp_nocase_uh(str,
"dxt4") == 0) {
2479 }
else if (cmp_nocase_uh(str,
"dxt5") == 0) {
2481 }
else if (cmp_nocase_uh(str,
"pvr1_2bpp") == 0) {
2482 return CM_pvr1_2bpp;
2483 }
else if (cmp_nocase_uh(str,
"pvr1_4bpp") == 0) {
2484 return CM_pvr1_4bpp;
2485 }
else if (cmp_nocase_uh(str,
"rgtc") == 0) {
2487 }
else if (cmp_nocase_uh(str,
"etc1") == 0) {
2489 }
else if (cmp_nocase_uh(str,
"etc2") == 0) {
2491 }
else if (cmp_nocase_uh(str,
"eac") == 0) {
2496 <<
"Invalid Texture::CompressionMode value: " << str <<
"\n";
2517 return "**invalid**";
2526 if (cmp_nocase(str,
"default") == 0) {
2528 }
else if (cmp_nocase(str,
"fastest") == 0) {
2530 }
else if (cmp_nocase(str,
"normal") == 0) {
2532 }
else if (cmp_nocase(str,
"best") == 0) {
2537 <<
"Invalid Texture::QualityLevel value: " << str <<
"\n";
2554 if (!keep_texture_ram && !cdata->_keep_ram_image) {
2559 CDWriter cdataw(_cycler, cdata,
false);
2560 if (gobj_cat.is_debug()) {
2562 <<
"Dumping RAM for texture " << get_name() <<
"\n";
2564 do_clear_ram_image(cdataw);
2605 return (ctype == T_unsigned_byte ||
2606 ctype == T_unsigned_short ||
2607 ctype == T_unsigned_int_24_8 ||
2608 ctype == T_unsigned_int);
2616is_specific(Texture::CompressionMode compression) {
2617 switch (compression) {
2643 case F_luminance_alpha:
2644 case F_luminance_alphamask:
2646 case F_sluminance_alpha:
2683 case F_sluminance_alpha:
2726adjust_size(
int &x_size,
int &y_size,
const string &name,
2727 bool for_padding, AutoTextureScale auto_texture_scale) {
2728 bool exclude =
false;
2730 for (
int i = 0; i < num_excludes && !exclude; ++i) {
2737 int new_x_size = x_size;
2738 int new_y_size = y_size;
2741 new_x_size = (int)cfloor(new_x_size * texture_scale + 0.5);
2742 new_y_size = (int)cfloor(new_y_size * texture_scale + 0.5);
2746 new_x_size = min(max(new_x_size, (
int)texture_scale_limit), x_size);
2747 new_y_size = min(max(new_y_size, (
int)texture_scale_limit), y_size);
2750 AutoTextureScale ats = auto_texture_scale;
2751 if (ats == ATS_unspecified) {
2754 if (!for_padding && ats == ATS_pad) {
2774 case ATS_unspecified:
2778 ats = textures_square.get_value();
2779 if (!for_padding && ats == ATS_pad) {
2784 new_x_size = new_y_size = min(new_x_size, new_y_size);
2789 new_x_size = new_y_size = max(new_x_size, new_y_size);
2793 case ATS_unspecified:
2798 int max_dimension = max_texture_dimension;
2800 if (max_dimension < 0) {
2802 if (gsg !=
nullptr) {
2803 max_dimension = gsg->get_max_texture_dimension();
2807 if (max_dimension > 0) {
2808 new_x_size = min(new_x_size, (
int)max_dimension);
2809 new_y_size = min(new_y_size, (
int)max_dimension);
2813 if (x_size != new_x_size || y_size != new_y_size) {
2814 x_size = new_x_size;
2815 y_size = new_y_size;
2854do_adjust_this_size(
const CData *cdata,
int &x_size,
int &y_size,
const string &name,
2855 bool for_padding)
const {
2856 return adjust_size(x_size, y_size, name, for_padding, cdata->_auto_texture_scale);
2863do_read(CData *cdata,
const Filename &fullpath,
const Filename &alpha_fullpath,
2864 int primary_file_num_channels,
int alpha_file_channel,
2865 int z,
int n,
bool read_pages,
bool read_mipmaps,
2873 bool header_only = ((options.get_texture_flags() & (LoaderOptions::TF_preload | LoaderOptions::TF_preload_simple)) == 0);
2874 if (record !=
nullptr) {
2875 header_only =
false;
2878 if ((z == 0 || read_pages) && (n == 0 || read_mipmaps)) {
2881 do_clear_ram_image(cdata);
2884 if (is_txo_filename(fullpath)) {
2885 if (record !=
nullptr) {
2888 return do_read_txo_file(cdata, fullpath);
2891 if (is_dds_filename(fullpath)) {
2892 if (record !=
nullptr) {
2895 return do_read_dds_file(cdata, fullpath, header_only);
2898 if (is_ktx_filename(fullpath)) {
2899 if (record !=
nullptr) {
2902 return do_read_ktx_file(cdata, fullpath, header_only);
2914 switch (cdata->_texture_type) {
2917 case TT_buffer_texture:
2931 if (options.get_texture_flags() & LoaderOptions::TF_multiview) {
2936 do_set_num_views(cdata, num_views);
2942 if (read_pages && read_mipmaps) {
2946 do_set_z_size(cdata, z_size);
2954 z_size = do_get_expected_mipmap_z_size(cdata, n);
2964 <<
"Filename requires two different hash sequences: " << fullpath
2972 if ((n_size == 0 && (vfs->
exists(file) || n == 0)) ||
2973 (n_size != 0 && n < n_size)) {
2980 int num_pages = z_size * num_views;
2981 while ((num_pages == 0 && (vfs->
exists(file) || z == 0)) ||
2982 (num_pages != 0 && z < num_pages)) {
2983 if (!do_read_one(cdata, file, alpha_file, z, n, primary_file_num_channels,
2984 alpha_file_channel, options, header_only, record)) {
2994 if (n == 0 && n_size == 0) {
2997 n_size = do_get_expected_num_mipmap_levels(cdata);
3001 cdata->_fullpath = fullpath_pattern;
3002 cdata->_alpha_fullpath = alpha_fullpath_pattern;
3004 }
else if (read_pages) {
3008 if (!fullpath_pattern.
has_hash()) {
3010 <<
"Filename requires a hash mark: " << fullpath
3015 do_set_z_size(cdata, z_size);
3020 int num_pages = z_size * num_views;
3021 while ((num_pages == 0 && (vfs->
exists(file) || z == 0)) ||
3022 (num_pages != 0 && z < num_pages)) {
3023 if (!do_read_one(cdata, file, alpha_file, z, 0, primary_file_num_channels,
3024 alpha_file_channel, options, header_only, record)) {
3032 cdata->_fullpath = fullpath_pattern;
3033 cdata->_alpha_fullpath = alpha_fullpath_pattern;
3035 }
else if (read_mipmaps) {
3039 if (!fullpath_pattern.
has_hash()) {
3041 <<
"Filename requires a hash mark: " << fullpath
3050 while ((n_size == 0 && (vfs->
exists(file) || n == 0)) ||
3051 (n_size != 0 && n < n_size)) {
3052 if (!do_read_one(cdata, file, alpha_file, z, n,
3053 primary_file_num_channels, alpha_file_channel,
3054 options, header_only, record)) {
3059 if (n_size == 0 && n >= do_get_expected_num_mipmap_levels(cdata)) {
3068 cdata->_fullpath = fullpath_pattern;
3069 cdata->_alpha_fullpath = alpha_fullpath_pattern;
3073 if (!do_read_one(cdata, fullpath, alpha_fullpath, z, n,
3074 primary_file_num_channels, alpha_file_channel,
3075 options, header_only, record)) {
3080 cdata->_has_read_pages = read_pages;
3081 cdata->_has_read_mipmaps = read_mipmaps;
3082 cdata->_num_mipmap_levels_read = cdata->_ram_images.size();
3087 do_clear_ram_image(cdata);
3089 if ((options.get_texture_flags() & LoaderOptions::TF_preload) != 0) {
3092 bool generate_mipmaps = ((options.get_texture_flags() & LoaderOptions::TF_generate_mipmaps) != 0);
3093 bool allow_compression = ((options.get_texture_flags() & LoaderOptions::TF_allow_compression) != 0);
3094 do_consider_auto_process_ram_image(cdata, generate_mipmaps ||
uses_mipmaps(), allow_compression);
3106do_read_one(CData *cdata,
const Filename &fullpath,
const Filename &alpha_fullpath,
3107 int z,
int n,
int primary_file_num_channels,
int alpha_file_channel,
3109 if (record !=
nullptr) {
3110 nassertr(!header_only,
false);
3117 if (image_reader ==
nullptr) {
3119 <<
"Texture::read() - couldn't read: " << fullpath << endl;
3124 AutoTextureScale auto_texture_scale = do_get_auto_texture_scale(cdata);
3128 bool read_floating_point;
3129 int texture_load_type = (options.get_texture_flags() & (LoaderOptions::TF_integer | LoaderOptions::TF_float));
3130 switch (texture_load_type) {
3131 case LoaderOptions::TF_integer:
3132 read_floating_point =
false;
3135 case LoaderOptions::TF_float:
3136 read_floating_point =
true;
3143 if (!alpha_fullpath.empty()) {
3144 read_floating_point =
false;
3148 if (header_only || textures_header_only) {
3151 if (z == 0 && n == 0) {
3152 cdata->_orig_file_x_size = x_size;
3153 cdata->_orig_file_y_size = y_size;
3156 if (textures_header_only) {
3166 if (read_floating_point) {
3172 image.
fill(0.2, 0.3, 1.0);
3177 delete image_reader;
3180 if (z == 0 && n == 0) {
3184 cdata->_orig_file_x_size = x_size;
3185 cdata->_orig_file_y_size = y_size;
3191 image.
set_read_size(do_get_expected_mipmap_x_size(cdata, n),
3192 do_get_expected_mipmap_y_size(cdata, n));
3198 <<
"Implicitly rescaling " << fullpath.
get_basename() <<
" from "
3205 if (read_floating_point) {
3206 success = pfm.
read(image_reader);
3208 success = image.
read(image_reader);
3213 <<
"Texture::read() - couldn't read: " << fullpath << endl;
3220 if (!alpha_fullpath.empty()) {
3222 if (alpha_image_reader ==
nullptr) {
3224 <<
"Texture::read() - couldn't read: " << alpha_fullpath << endl;
3229 if (record !=
nullptr) {
3233 if (header_only || textures_header_only) {
3239 alpha_image.
fill(1.0);
3243 delete alpha_image_reader;
3249 <<
"Implicitly rescaling " << alpha_fullpath.
get_basename()
3250 <<
" from " << alpha_image.
get_x_size() <<
" by "
3256 if (!alpha_image.
read(alpha_image_reader)) {
3258 <<
"Texture::read() - couldn't read (alpha): " << alpha_fullpath << endl;
3265 if (z == 0 && n == 0) {
3269 if (cdata->_filename.empty()) {
3270 cdata->_filename = fullpath;
3271 cdata->_alpha_filename = alpha_fullpath;
3276 cdata->_keep_ram_image =
false;
3279 cdata->_fullpath = fullpath;
3280 cdata->_alpha_fullpath = alpha_fullpath;
3283 if (!alpha_fullpath.empty()) {
3289 <<
"Automatically rescaling " << alpha_fullpath.
get_basename()
3290 <<
" from " << alpha_image.
get_x_size() <<
" by "
3298 scaled.quick_filter_from(alpha_image);
3300 alpha_image = scaled;
3305 consider_downgrade(image, primary_file_num_channels, get_name());
3307 cdata->_alpha_file_channel = 0;
3310 if (!alpha_fullpath.empty()) {
3315 if (alpha_file_channel == 4 ||
3320 << alpha_fullpath.
get_basename() <<
" has no channel " << alpha_file_channel <<
".\n";
3323 for (
int x = 0; x < image.
get_x_size(); x++) {
3324 for (
int y = 0; y < image.
get_y_size(); y++) {
3331 }
else if (alpha_file_channel >= 1 && alpha_file_channel <= 3 &&
3334 for (
int x = 0; x < image.
get_x_size(); x++) {
3335 for (
int y = 0; y < image.
get_y_size(); y++) {
3339 cdata->_alpha_file_channel = alpha_file_channel;
3343 for (
int x = 0; x < image.
get_x_size(); x++) {
3344 for (
int y = 0; y < image.
get_y_size(); y++) {
3348 cdata->_alpha_file_channel = 0;
3352 if (read_floating_point) {
3353 if (!do_load_one(cdata, pfm, fullpath.
get_basename(), z, n, options)) {
3360 if (do_get_auto_texture_scale(cdata) == ATS_pad) {
3363 if (do_adjust_this_size(cdata, new_x_size, new_y_size, fullpath.
get_basename(),
true)) {
3364 pad_x_size = new_x_size - image.
get_x_size();
3365 pad_y_size = new_y_size - image.
get_y_size();
3369 new_image.copy_sub_image(image, 0, new_y_size - image.
get_y_size());
3374 if (!do_load_one(cdata, image, fullpath.
get_basename(), z, n, options)) {
3378 do_set_pad_size(cdata, pad_x_size, pad_y_size, 0);
3387do_load_one(CData *cdata,
const PNMImage &pnmimage,
const string &name,
int z,
int n,
3389 if (cdata->_ram_images.size() <= 1 && n == 0) {
3393 if (!do_reconsider_z_size(cdata, z, options)) {
3396 nassertr(z >= 0 && z < cdata->_z_size * cdata->_num_views,
false);
3399 ComponentType component_type = T_unsigned_byte;
3402 component_type = T_unsigned_short;
3412 do_modify_ram_image(cdata);
3413 cdata->_loaded_from_image =
true;
3416 do_modify_ram_mipmap_image(cdata, n);
3419 int x_size = do_get_expected_mipmap_x_size(cdata, n);
3420 int y_size = do_get_expected_mipmap_y_size(cdata, n);
3424 <<
"Automatically rescaling " << name;
3426 gobj_cat.info(
false)
3427 <<
" mipmap level " << n;
3429 gobj_cat.info(
false)
3430 <<
" from " << pnmimage.
get_x_size() <<
" by "
3431 << pnmimage.
get_y_size() <<
" to " << x_size <<
" by "
3437 scaled.quick_filter_from(pnmimage);
3440 convert_from_pnmimage(cdata->_ram_images[n]._image,
3441 do_get_expected_ram_mipmap_page_size(cdata, n),
3442 x_size, 0, 0, z, scaled,
3443 cdata->_num_components, cdata->_component_width);
3447 convert_from_pnmimage(cdata->_ram_images[n]._image,
3448 do_get_expected_ram_mipmap_page_size(cdata, n),
3449 x_size, 0, 0, z, pnmimage,
3450 cdata->_num_components, cdata->_component_width);
3461do_load_one(CData *cdata,
const PfmFile &pfm,
const string &name,
int z,
int n,
3463 if (cdata->_ram_images.size() <= 1 && n == 0) {
3467 if (!do_reconsider_z_size(cdata, z, options)) {
3470 nassertr(z >= 0 && z < cdata->_z_size * cdata->_num_views,
false);
3473 ComponentType component_type = T_float;
3481 do_modify_ram_image(cdata);
3482 cdata->_loaded_from_image =
true;
3485 do_modify_ram_mipmap_image(cdata, n);
3488 int x_size = do_get_expected_mipmap_x_size(cdata, n);
3489 int y_size = do_get_expected_mipmap_y_size(cdata, n);
3493 <<
"Automatically rescaling " << name;
3495 gobj_cat.info(
false)
3496 <<
" mipmap level " << n;
3498 gobj_cat.info(
false)
3500 << pfm.
get_y_size() <<
" to " << x_size <<
" by "
3504 scaled.resize(x_size, y_size);
3507 convert_from_pfm(cdata->_ram_images[n]._image,
3508 do_get_expected_ram_mipmap_page_size(cdata, n), z,
3509 scaled, cdata->_num_components, cdata->_component_width);
3513 convert_from_pfm(cdata->_ram_images[n]._image,
3514 do_get_expected_ram_mipmap_page_size(cdata, n), z,
3515 pfm, cdata->_num_components, cdata->_component_width);
3527do_load_sub_image(CData *cdata,
const PNMImage &image,
int x,
int y,
int z,
int n) {
3528 nassertr(n >= 0 && (
size_t)n < cdata->_ram_images.size(),
false);
3530 int tex_x_size = do_get_expected_mipmap_x_size(cdata, n);
3531 int tex_y_size = do_get_expected_mipmap_y_size(cdata, n);
3532 int tex_z_size = do_get_expected_mipmap_z_size(cdata, n);
3534 nassertr(x >= 0 && x < tex_x_size,
false);
3535 nassertr(y >= 0 && y < tex_y_size,
false);
3536 nassertr(z >= 0 && z < tex_z_size,
false);
3538 nassertr(image.
get_x_size() + x <= tex_x_size,
false);
3539 nassertr(image.
get_y_size() + y <= tex_y_size,
false);
3542 y = cdata->_y_size - (image.
get_y_size() + y);
3544 cdata->inc_image_modified();
3545 do_modify_ram_mipmap_image(cdata, n);
3546 convert_from_pnmimage(cdata->_ram_images[n]._image,
3547 do_get_expected_ram_mipmap_page_size(cdata, n),
3548 tex_x_size, x, y, z, image,
3549 cdata->_num_components, cdata->_component_width);
3559do_read_txo_file(CData *cdata,
const Filename &fullpath) {
3562 Filename filename = Filename::binary_filename(fullpath);
3564 if (file ==
nullptr) {
3567 <<
"Could not find " << fullpath <<
"\n";
3571 if (gobj_cat.is_debug()) {
3573 <<
"Reading texture object " << filename <<
"\n";
3576 istream *in = file->open_read_file(
true);
3577 if (in ==
nullptr) {
3579 <<
"Failed to open " << filename <<
" for reading.\n";
3583 bool success = do_read_txo(cdata, *in, fullpath);
3586 cdata->_fullpath = fullpath;
3587 cdata->_alpha_fullpath =
Filename();
3588 cdata->_keep_ram_image =
false;
3597do_read_txo(CData *cdata, istream &in,
const string &filename) {
3598 PT(
Texture) other = make_from_txo(in, filename);
3599 if (other ==
nullptr) {
3603 CDReader cdata_other(other->_cycler);
3604 Namable::operator = (*other);
3605 do_assign(cdata, other, cdata_other);
3607 cdata->_loaded_from_image =
true;
3608 cdata->_loaded_from_txo =
true;
3609 cdata->_has_read_pages =
false;
3610 cdata->_has_read_mipmaps =
false;
3611 cdata->_num_mipmap_levels_read = 0;
3620do_read_dds_file(CData *cdata,
const Filename &fullpath,
bool header_only) {
3623 Filename filename = Filename::binary_filename(fullpath);
3625 if (file ==
nullptr) {
3628 <<
"Could not find " << fullpath <<
"\n";
3632 if (gobj_cat.is_debug()) {
3634 <<
"Reading DDS file " << filename <<
"\n";
3637 istream *in = file->open_read_file(
true);
3638 if (in ==
nullptr) {
3640 <<
"Failed to open " << filename <<
" for reading.\n";
3644 bool success = do_read_dds(cdata, *in, fullpath, header_only);
3651 cdata->_fullpath = fullpath;
3652 cdata->_alpha_fullpath =
Filename();
3653 cdata->_keep_ram_image =
false;
3662do_read_dds(CData *cdata, istream &in,
const string &filename,
bool header_only) {
3667 header.dds_magic = dds.get_uint32();
3668 header.dds_size = dds.get_uint32();
3669 header.dds_flags = dds.get_uint32();
3670 header.height = dds.get_uint32();
3671 header.width = dds.get_uint32();
3672 header.pitch = dds.get_uint32();
3673 header.depth = dds.get_uint32();
3674 header.num_levels = dds.get_uint32();
3678 header.pf.pf_size = dds.get_uint32();
3679 header.pf.pf_flags = dds.get_uint32();
3680 header.pf.four_cc = dds.get_uint32();
3681 header.pf.rgb_bitcount = dds.get_uint32();
3682 header.pf.r_mask = dds.get_uint32();
3683 header.pf.g_mask = dds.get_uint32();
3684 header.pf.b_mask = dds.get_uint32();
3685 header.pf.a_mask = dds.get_uint32();
3688 header.caps.caps1 = dds.get_uint32();
3689 header.caps.caps2 = dds.get_uint32();
3690 header.caps.ddsx = dds.get_uint32();
3696 if (header.dds_magic != DDS_MAGIC || (in.fail() || in.eof())) {
3698 << filename <<
" is not a DDS file.\n";
3702 if ((header.dds_flags & DDSD_MIPMAPCOUNT) == 0) {
3704 header.num_levels = 1;
3706 }
else if (header.num_levels == 0) {
3709 header.num_levels = 1;
3712 TextureType texture_type;
3713 if (header.caps.caps2 & DDSCAPS2_CUBEMAP) {
3714 static const unsigned int all_faces =
3715 (DDSCAPS2_CUBEMAP_POSITIVEX |
3716 DDSCAPS2_CUBEMAP_POSITIVEY |
3717 DDSCAPS2_CUBEMAP_POSITIVEZ |
3718 DDSCAPS2_CUBEMAP_NEGATIVEX |
3719 DDSCAPS2_CUBEMAP_NEGATIVEY |
3720 DDSCAPS2_CUBEMAP_NEGATIVEZ);
3721 if ((header.caps.caps2 & all_faces) != all_faces) {
3723 << filename <<
" is missing some cube map faces; cannot load.\n";
3727 texture_type = TT_cube_map;
3729 }
else if (header.caps.caps2 & DDSCAPS2_VOLUME) {
3730 texture_type = TT_3d_texture;
3733 texture_type = TT_2d_texture;
3738 typedef PTA_uchar (*ReadDDSLevelFunc)(
Texture *tex, Texture::CData *cdata,
3739 const DDSHeader &header,
int n, istream &in);
3740 ReadDDSLevelFunc func =
nullptr;
3742 Format format = F_rgb;
3743 ComponentType component_type = T_unsigned_byte;
3745 do_clear_ram_image(cdata);
3746 CompressionMode compression = CM_off;
3748 if ((header.pf.pf_flags & DDPF_FOURCC) != 0 &&
3749 header.pf.four_cc == 0x30315844) {
3751 func = read_dds_level_generic_uncompressed;
3752 unsigned int dxgi_format = dds.get_uint32();
3753 unsigned int dimension = dds.get_uint32();
3754 unsigned int misc_flag = dds.get_uint32();
3755 unsigned int array_size = dds.get_uint32();
3758 switch (dxgi_format) {
3761 component_type = T_float;
3762 func = read_dds_level_abgr32;
3766 component_type = T_half_float;
3767 func = read_dds_level_abgr16;
3771 component_type = T_unsigned_short;
3772 func = read_dds_level_abgr16;
3776 component_type = T_unsigned_short;
3777 func = read_dds_level_abgr16;
3781 component_type = T_short;
3782 func = read_dds_level_abgr16;
3786 component_type = T_float;
3787 func = read_dds_level_raw;
3791 component_type = T_unsigned_int;
3792 func = read_dds_level_raw;
3796 component_type = T_int;
3797 func = read_dds_level_raw;
3802 func = read_dds_level_abgr8;
3805 format = F_srgb_alpha;
3806 func = read_dds_level_abgr8;
3810 func = read_dds_level_abgr8;
3814 component_type = T_byte;
3815 func = read_dds_level_abgr8;
3819 component_type = T_byte;
3820 func = read_dds_level_abgr8;
3824 component_type = T_half_float;
3825 func = read_dds_level_raw;
3829 component_type = T_unsigned_short;
3830 func = read_dds_level_raw;
3834 component_type = T_unsigned_short;
3835 func = read_dds_level_raw;
3839 component_type = T_short;
3840 func = read_dds_level_raw;
3844 component_type = T_short;
3845 func = read_dds_level_raw;
3848 format = F_depth_component32;
3849 component_type = T_float;
3850 func = read_dds_level_raw;
3854 component_type = T_float;
3855 func = read_dds_level_raw;
3859 component_type = T_unsigned_int;
3860 func = read_dds_level_raw;
3864 component_type = T_int;
3865 func = read_dds_level_raw;
3876 component_type = T_byte;
3880 component_type = T_byte;
3884 component_type = T_half_float;
3885 func = read_dds_level_raw;
3888 format = F_depth_component16;
3889 component_type = T_unsigned_short;
3890 func = read_dds_level_raw;
3894 component_type = T_unsigned_short;
3895 func = read_dds_level_raw;
3899 component_type = T_unsigned_short;
3900 func = read_dds_level_raw;
3904 component_type = T_short;
3905 func = read_dds_level_raw;
3909 component_type = T_short;
3910 func = read_dds_level_raw;
3921 component_type = T_byte;
3925 component_type = T_byte;
3933 compression = CM_dxt1;
3934 func = read_dds_level_bc1;
3938 compression = CM_dxt1;
3939 func = read_dds_level_bc1;
3944 compression = CM_dxt3;
3945 func = read_dds_level_bc2;
3948 format = F_srgb_alpha;
3949 compression = CM_dxt3;
3950 func = read_dds_level_bc2;
3955 compression = CM_dxt5;
3956 func = read_dds_level_bc3;
3959 format = F_srgb_alpha;
3960 compression = CM_dxt5;
3961 func = read_dds_level_bc3;
3966 compression = CM_rgtc;
3967 func = read_dds_level_bc4;
3972 compression = CM_rgtc;
3973 func = read_dds_level_bc5;
3984 format = F_srgb_alpha;
3994 << filename <<
": unsupported DXGI format " << dxgi_format <<
".\n";
3998 switch (dimension) {
4000 texture_type = TT_1d_texture;
4004 if (misc_flag & 0x4) {
4005 if (array_size > 1) {
4006 texture_type = TT_cube_map_array;
4007 header.depth = array_size * 6;
4009 texture_type = TT_cube_map;
4013 if (array_size > 1) {
4014 texture_type = TT_2d_texture_array;
4015 header.depth = array_size;
4017 texture_type = TT_2d_texture;
4023 texture_type = TT_3d_texture;
4027 << filename <<
": unsupported dimension.\n";
4031 }
else if (header.pf.pf_flags & DDPF_FOURCC) {
4033 if (texture_type == TT_3d_texture) {
4035 << filename <<
": unsupported compression on 3-d texture.\n";
4041 switch (header.pf.four_cc) {
4043 compression = CM_dxt1;
4044 func = read_dds_level_bc1;
4048 compression = CM_dxt2;
4049 func = read_dds_level_bc2;
4052 compression = CM_dxt3;
4053 func = read_dds_level_bc2;
4056 compression = CM_dxt4;
4057 func = read_dds_level_bc3;
4060 compression = CM_dxt5;
4061 func = read_dds_level_bc3;
4065 compression = CM_rgtc;
4066 func = read_dds_level_bc4;
4071 compression = CM_rgtc;
4072 func = read_dds_level_bc5;
4076 func = read_dds_level_abgr16;
4078 component_type = T_unsigned_short;
4081 func = read_dds_level_abgr16;
4083 component_type = T_short;
4086 func = read_dds_level_abgr16;
4088 component_type = T_half_float;
4091 func = read_dds_level_abgr32;
4093 component_type = T_float;
4097 << filename <<
": unsupported texture compression (FourCC: 0x"
4098 << std::hex << header.pf.four_cc << std::dec <<
").\n";
4104 func = read_dds_level_generic_uncompressed;
4106 if (header.pf.pf_flags & DDPF_ALPHAPIXELS) {
4109 if (header.pf.rgb_bitcount == 32 &&
4110 header.pf.r_mask == 0x000000ff &&
4111 header.pf.g_mask == 0x0000ff00 &&
4112 header.pf.b_mask == 0x00ff0000 &&
4113 header.pf.a_mask == 0xff000000U) {
4114 func = read_dds_level_abgr8;
4115 }
else if (header.pf.rgb_bitcount == 32 &&
4116 header.pf.r_mask == 0x00ff0000 &&
4117 header.pf.g_mask == 0x0000ff00 &&
4118 header.pf.b_mask == 0x000000ff &&
4119 header.pf.a_mask == 0xff000000U) {
4120 func = read_dds_level_rgba8;
4122 }
else if (header.pf.r_mask != 0 &&
4123 header.pf.g_mask == 0 &&
4124 header.pf.b_mask == 0) {
4125 func = read_dds_level_luminance_uncompressed;
4126 format = F_luminance_alpha;
4130 if (header.pf.rgb_bitcount == 24 &&
4131 header.pf.r_mask == 0x00ff0000 &&
4132 header.pf.g_mask == 0x0000ff00 &&
4133 header.pf.b_mask == 0x000000ff) {
4134 func = read_dds_level_bgr8;
4135 }
else if (header.pf.rgb_bitcount == 24 &&
4136 header.pf.r_mask == 0x000000ff &&
4137 header.pf.g_mask == 0x0000ff00 &&
4138 header.pf.b_mask == 0x00ff0000) {
4139 func = read_dds_level_rgb8;
4141 }
else if (header.pf.r_mask != 0 &&
4142 header.pf.g_mask == 0 &&
4143 header.pf.b_mask == 0) {
4144 func = read_dds_level_luminance_uncompressed;
4145 format = F_luminance;
4150 do_setup_texture(cdata, texture_type, header.width, header.height, header.depth,
4151 component_type, format);
4153 cdata->_orig_file_x_size = cdata->_x_size;
4154 cdata->_orig_file_y_size = cdata->_y_size;
4155 cdata->_compression = compression;
4156 cdata->_ram_image_compression = compression;
4159 switch (texture_type) {
4164 for (
int n = 0; n < (int)header.num_levels; ++n) {
4165 int z_size = do_get_expected_mipmap_z_size(cdata, n);
4167 size_t page_size = 0;
4169 for (z = 0; z < z_size; ++z) {
4170 PTA_uchar page = func(
this, cdata, header, n, in);
4171 if (page.is_null()) {
4174 nassertr(page_size == 0 || page_size == page.size(),
false);
4175 page_size = page.size();
4176 pages.push_back(page);
4181 PTA_uchar image = PTA_uchar::empty_array(page_size * z_size);
4182 unsigned char *imagep = (
unsigned char *)image.p();
4183 for (z = 0; z < z_size; ++z) {
4184 int fz = z_size - 1 - z;
4185 memcpy(imagep + z * page_size, pages[fz].p(), page_size);
4188 do_set_ram_mipmap_image(cdata, n, image, page_size);
4200 for (z = 0; z < 6; ++z) {
4203 levels.reserve(header.num_levels);
4205 for (n = 0; n < (int)header.num_levels; ++n) {
4206 PTA_uchar image = func(
this, cdata, header, n, in);
4207 if (image.is_null()) {
4210 levels.push_back(image);
4217 static const int level_remap[6] = {
4220 for (n = 0; n < (int)header.num_levels; ++n) {
4221 size_t page_size = pages[0][n].size();
4222 PTA_uchar image = PTA_uchar::empty_array(page_size * 6);
4223 unsigned char *imagep = (
unsigned char *)image.p();
4224 for (z = 0; z < 6; ++z) {
4225 int fz = level_remap[z];
4226 nassertr(pages[fz][n].size() == page_size,
false);
4227 memcpy(imagep + z * page_size, pages[fz][n].p(), page_size);
4230 do_set_ram_mipmap_image(cdata, n, image, page_size);
4235 case TT_2d_texture_array:
4236 case TT_cube_map_array:
4241 pages.reserve(header.depth);
4243 for (z = 0; z < (int)header.depth; ++z) {
4246 levels.reserve(header.num_levels);
4248 for (n = 0; n < (int)header.num_levels; ++n) {
4249 PTA_uchar image = func(
this, cdata, header, n, in);
4250 if (image.is_null()) {
4253 levels.push_back(image);
4258 for (n = 0; n < (int)header.num_levels; ++n) {
4259 size_t page_size = pages[0][n].size();
4260 PTA_uchar image = PTA_uchar::empty_array(page_size * header.depth);
4261 unsigned char *imagep = (
unsigned char *)image.p();
4262 for (z = 0; z < (int)header.depth; ++z) {
4263 nassertr(pages[z][n].size() == page_size,
false);
4264 memcpy(imagep + z * page_size, pages[z][n].p(), page_size);
4267 do_set_ram_mipmap_image(cdata, n, image, page_size);
4275 for (
int n = 0; n < (int)header.num_levels; ++n) {
4276 PTA_uchar image = func(
this, cdata, header, n, in);
4277 if (image.is_null()) {
4280 do_set_ram_mipmap_image(cdata, n, image, 0);
4284 cdata->_has_read_pages =
true;
4285 cdata->_has_read_mipmaps =
true;
4286 cdata->_num_mipmap_levels_read = cdata->_ram_images.size();
4291 << filename <<
": truncated DDS file.\n";
4295 cdata->_loaded_from_image =
true;
4296 cdata->_loaded_from_txo =
true;
4306do_read_ktx_file(CData *cdata,
const Filename &fullpath,
bool header_only) {
4309 Filename filename = Filename::binary_filename(fullpath);
4311 if (file ==
nullptr) {
4314 <<
"Could not find " << fullpath <<
"\n";
4318 if (gobj_cat.is_debug()) {
4320 <<
"Reading KTX file " << filename <<
"\n";
4323 istream *in = file->open_read_file(
true);
4324 if (in ==
nullptr) {
4326 <<
"Failed to open " << filename <<
" for reading.\n";
4330 bool success = do_read_ktx(cdata, *in, fullpath, header_only);
4337 cdata->_fullpath = fullpath;
4338 cdata->_alpha_fullpath =
Filename();
4339 cdata->_keep_ram_image =
false;
4348do_read_ktx(CData *cdata, istream &in,
const string &filename,
bool header_only) {
4351 unsigned char magic[12];
4352 if (ktx.extract_bytes(magic, 12) != 12 ||
4353 memcmp(magic,
"\xABKTX 11\xBB\r\n\x1A\n", 12) != 0) {
4355 << filename <<
" is not a KTX file.\n";
4360 uint32_t gl_type, gl_format, internal_format, gl_base_format,
4361 width, height, depth, num_array_elements, num_faces, num_mipmap_levels,
4365 if (ktx.get_uint32() == 0x04030201) {
4367 gl_type = ktx.get_uint32();
4369 gl_format = ktx.get_uint32();
4370 internal_format = ktx.get_uint32();
4371 gl_base_format = ktx.get_uint32();
4372 width = ktx.get_uint32();
4373 height = ktx.get_uint32();
4374 depth = ktx.get_uint32();
4375 num_array_elements = ktx.get_uint32();
4376 num_faces = ktx.get_uint32();
4377 num_mipmap_levels = ktx.get_uint32();
4378 kvdata_size = ktx.get_uint32();
4381 gl_type = ktx.get_be_uint32();
4382 ktx.get_be_uint32();
4383 gl_format = ktx.get_be_uint32();
4384 internal_format = ktx.get_be_uint32();
4385 gl_base_format = ktx.get_be_uint32();
4386 width = ktx.get_be_uint32();
4387 height = ktx.get_be_uint32();
4388 depth = ktx.get_be_uint32();
4389 num_array_elements = ktx.get_be_uint32();
4390 num_faces = ktx.get_be_uint32();
4391 num_mipmap_levels = ktx.get_be_uint32();
4392 kvdata_size = ktx.get_be_uint32();
4396 ktx.skip_bytes(kvdata_size);
4399 CompressionMode compression;
4401 bool swap_bgr =
false;
4403 if (gl_type == 0 || gl_format == 0) {
4405 if (gl_type > 0 || gl_format > 0) {
4407 <<
"Compressed textures must have both type and format set to 0.\n";
4410 type = T_unsigned_byte;
4411 compression = CM_on;
4413 KTXFormat base_format;
4414 switch ((KTXCompressedFormat)internal_format) {
4415 case KTX_COMPRESSED_RED:
4417 base_format = KTX_RED;
4419 case KTX_COMPRESSED_RG:
4421 base_format = KTX_RG;
4423 case KTX_COMPRESSED_RGB:
4425 base_format = KTX_RGB;
4427 case KTX_COMPRESSED_RGBA:
4429 base_format = KTX_RGBA;
4431 case KTX_COMPRESSED_SRGB:
4433 base_format = KTX_SRGB;
4435 case KTX_COMPRESSED_SRGB_ALPHA:
4436 format = F_srgb_alpha;
4437 base_format = KTX_SRGB_ALPHA;
4439 case KTX_COMPRESSED_RGB_FXT1_3DFX:
4441 base_format = KTX_RGB;
4442 compression = CM_fxt1;
4444 case KTX_COMPRESSED_RGBA_FXT1_3DFX:
4446 base_format = KTX_RGBA;
4447 compression = CM_fxt1;
4449 case KTX_COMPRESSED_RGB_S3TC_DXT1:
4451 base_format = KTX_RGB;
4452 compression = CM_dxt1;
4454 case KTX_COMPRESSED_RGBA_S3TC_DXT1:
4456 base_format = KTX_RGB;
4457 compression = CM_dxt1;
4459 case KTX_COMPRESSED_RGBA_S3TC_DXT3:
4461 base_format = KTX_RGBA;
4462 compression = CM_dxt3;
4464 case KTX_COMPRESSED_RGBA_S3TC_DXT5:
4466 base_format = KTX_RGBA;
4467 compression = CM_dxt5;
4469 case KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT1:
4470 format = F_srgb_alpha;
4471 base_format = KTX_SRGB_ALPHA;
4472 compression = CM_dxt1;
4474 case KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT3:
4475 format = F_srgb_alpha;
4476 base_format = KTX_SRGB_ALPHA;
4477 compression = CM_dxt3;
4479 case KTX_COMPRESSED_SRGB_ALPHA_S3TC_DXT5:
4480 format = F_srgb_alpha;
4481 base_format = KTX_SRGB_ALPHA;
4482 compression = CM_dxt5;
4484 case KTX_COMPRESSED_SRGB_S3TC_DXT1:
4486 base_format = KTX_SRGB;
4487 compression = CM_dxt1;
4489 case KTX_COMPRESSED_RED_RGTC1:
4490 case KTX_COMPRESSED_SIGNED_RED_RGTC1:
4492 base_format = KTX_RED;
4493 compression = CM_rgtc;
4495 case KTX_COMPRESSED_RG_RGTC2:
4496 case KTX_COMPRESSED_SIGNED_RG_RGTC2:
4498 base_format = KTX_RG;
4499 compression = CM_rgtc;
4503 base_format = KTX_RGB;
4504 compression = CM_etc1;
4506 case KTX_ETC1_SRGB8:
4508 base_format = KTX_SRGB;
4509 compression = CM_etc1;
4511 case KTX_COMPRESSED_RGB8_ETC2:
4513 base_format = KTX_RGB;
4514 compression = CM_etc2;
4516 case KTX_COMPRESSED_SRGB8_ETC2:
4518 base_format = KTX_SRGB;
4519 compression = CM_etc2;
4521 case KTX_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
4523 base_format = KTX_RGBA;
4524 compression = CM_etc2;
4526 case KTX_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
4528 base_format = KTX_SRGB8_ALPHA8;
4529 compression = CM_etc2;
4531 case KTX_COMPRESSED_RGBA8_ETC2_EAC:
4533 base_format = KTX_RGBA;
4534 compression = CM_etc2;
4536 case KTX_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
4537 format = F_srgb_alpha;
4538 base_format = KTX_SRGB8_ALPHA8;
4539 compression = CM_etc2;
4541 case KTX_COMPRESSED_R11_EAC:
4542 case KTX_COMPRESSED_SIGNED_R11_EAC:
4544 base_format = KTX_RED;
4545 compression = CM_eac;
4547 case KTX_COMPRESSED_RG11_EAC:
4548 case KTX_COMPRESSED_SIGNED_RG11_EAC:
4550 base_format = KTX_RG;
4551 compression = CM_eac;
4553 case KTX_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1:
4554 format = F_srgb_alpha;
4555 base_format = KTX_SRGB_ALPHA;
4556 compression = CM_pvr1_2bpp;
4558 case KTX_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1:
4559 format = F_srgb_alpha;
4560 base_format = KTX_SRGB_ALPHA;
4561 compression = CM_pvr1_4bpp;
4563 case KTX_COMPRESSED_RGBA_BPTC_UNORM:
4564 case KTX_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
4565 case KTX_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
4566 case KTX_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
4569 << filename <<
" has unsupported compressed internal format " << internal_format <<
"\n";
4573 if (base_format != gl_base_format) {
4575 << filename <<
" has internal format that is incompatible with base "
4576 "format (0x" << std::hex << gl_base_format <<
", expected 0x"
4577 << base_format << std::dec <<
")\n";
4583 compression = CM_off;
4584 switch ((KTXType)gl_type) {
4588 case KTX_UNSIGNED_BYTE:
4589 type = T_unsigned_byte;
4594 case KTX_UNSIGNED_SHORT:
4595 type = T_unsigned_short;
4600 case KTX_UNSIGNED_INT:
4601 type = T_unsigned_int;
4606 case KTX_HALF_FLOAT:
4607 type = T_half_float;
4609 case KTX_UNSIGNED_INT_24_8:
4610 type = T_unsigned_int_24_8;
4614 << filename <<
" has unsupported component type " << gl_type <<
"\n";
4618 if (gl_format != gl_base_format) {
4620 << filename <<
" has mismatched formats: " << gl_format <<
" != "
4621 << gl_base_format <<
"\n";
4624 switch (gl_format) {
4625 case KTX_DEPTH_COMPONENT:
4626 switch (internal_format) {
4627 case KTX_DEPTH_COMPONENT:
4628 format = F_depth_component;
4630 case KTX_DEPTH_COMPONENT16:
4631 format = F_depth_component16;
4633 case KTX_DEPTH_COMPONENT24:
4634 format = F_depth_component24;
4636 case KTX_DEPTH_COMPONENT32:
4637 case KTX_DEPTH_COMPONENT32F:
4638 format = F_depth_component32;
4641 format = F_depth_component;
4643 << filename <<
" has unsupported depth component format " << internal_format <<
"\n";
4647 case KTX_DEPTH_STENCIL:
4648 format = F_depth_stencil;
4649 if (internal_format != KTX_DEPTH_STENCIL &&
4650 internal_format != KTX_DEPTH24_STENCIL8) {
4652 << filename <<
" has unsupported depth stencil format " << internal_format <<
"\n";
4657 switch (internal_format) {
4675 << filename <<
" has unsupported red format " << internal_format <<
"\n";
4679 case KTX_RED_INTEGER:
4680 switch (internal_format) {
4695 << filename <<
" has unsupported red integer format " << internal_format <<
"\n";
4702 if (internal_format != KTX_GREEN) {
4704 << filename <<
" has unsupported green format " << internal_format <<
"\n";
4710 if (internal_format != KTX_BLUE) {
4712 << filename <<
" has unsupported blue format " << internal_format <<
"\n";
4717 switch (internal_format) {
4725 case KTX_RG16_SNORM:
4735 << filename <<
" has unsupported RG format " << internal_format <<
"\n";
4739 case KTX_RG_INTEGER:
4740 switch (internal_format) {
4755 << filename <<
" has unsupported RG integer format " << internal_format <<
"\n";
4763 switch (internal_format) {
4780 case KTX_R11F_G11F_B10F:
4781 format = F_r11_g11_b10;
4784 case KTX_RGB8_SNORM:
4788 case KTX_RGB16_SNORM:
4802 << filename <<
" has unsupported RGB format " << internal_format <<
"\n";
4806 case KTX_RGB_INTEGER:
4808 case KTX_BGR_INTEGER:
4809 switch (internal_format) {
4824 << filename <<
" has unsupported RGB integer format " << internal_format <<
"\n";
4832 switch (internal_format) {
4834 case KTX_RGBA_SNORM:
4847 format = F_rgb10_a2;
4850 case KTX_RGBA8_SNORM:
4854 case KTX_RGBA16_SNORM:
4861 case KTX_SRGB_ALPHA:
4862 case KTX_SRGB8_ALPHA8:
4863 format = F_srgb_alpha;
4868 << filename <<
" has unsupported RGBA format " << internal_format <<
"\n";
4873 case KTX_RGBA_INTEGER:
4875 case KTX_BGRA_INTEGER:
4876 switch (internal_format) {
4891 << filename <<
" has unsupported RGBA integer format " << internal_format <<
"\n";
4897 format = F_luminance;
4900 case KTX_LUMINANCE_ALPHA:
4901 format = F_luminance_alpha;
4908 case KTX_STENCIL_INDEX:
4911 << filename <<
" has unsupported format " << gl_format <<
"\n";
4916 TextureType texture_type;
4918 texture_type = TT_3d_texture;
4920 }
else if (num_faces > 1) {
4921 if (num_faces != 6) {
4923 << filename <<
" has " << num_faces <<
" cube map faces, expected 6\n";
4926 if (width != height) {
4928 << filename <<
" is cube map, but does not have square dimensions\n";
4931 if (num_array_elements > 0) {
4932 depth = num_array_elements * 6;
4933 texture_type = TT_cube_map_array;
4936 texture_type = TT_cube_map;
4939 }
else if (height > 0) {
4940 if (num_array_elements > 0) {
4941 depth = num_array_elements;
4942 texture_type = TT_2d_texture_array;
4945 texture_type = TT_2d_texture;
4948 }
else if (width > 0) {
4950 if (num_array_elements > 0) {
4951 height = num_array_elements;
4952 texture_type = TT_1d_texture_array;
4955 texture_type = TT_1d_texture;
4960 << filename <<
" has zero size\n";
4964 do_setup_texture(cdata, texture_type, width, height, depth, type, format);
4966 cdata->_orig_file_x_size = cdata->_x_size;
4967 cdata->_orig_file_y_size = cdata->_y_size;
4968 cdata->_compression = compression;
4969 cdata->_ram_image_compression = compression;
4972 bool generate_mipmaps =
false;
4973 if (num_mipmap_levels == 0) {
4974 generate_mipmaps =
true;
4975 num_mipmap_levels = 1;
4978 for (uint32_t n = 0; n < num_mipmap_levels; ++n) {
4979 uint32_t image_size;
4981 image_size = ktx.get_be_uint32();
4983 image_size = ktx.get_uint32();
4987 if (compression == CM_off) {
4988 uint32_t row_size = do_get_expected_mipmap_x_size(cdata, (
int)n) * cdata->_num_components * cdata->_component_width;
4989 uint32_t num_rows = do_get_expected_mipmap_y_size(cdata, (
int)n) * do_get_expected_mipmap_z_size(cdata, (
int)n);
4990 uint32_t row_padded = (row_size + 3) & ~3;
4992 if (image_size == row_size * num_rows) {
4993 if (row_padded != row_size) {
4997 << filename <<
" does not have proper row padding for mipmap "
4998 "level " << n <<
"\n";
5000 image = PTA_uchar::empty_array(image_size);
5001 ktx.extract_bytes(image.p(), image_size);
5003 }
else if (image_size != row_padded * num_rows) {
5005 << filename <<
" has invalid image size " << image_size
5006 <<
" for mipmap level " << n <<
" (expected "
5007 << row_padded * num_rows <<
")\n";
5012 image = PTA_uchar::empty_array(row_size * num_rows);
5013 uint32_t skip = row_padded - row_size;
5014 unsigned char *p = image.p();
5015 for (uint32_t row = 0; row < num_rows; ++row) {
5016 ktx.extract_bytes(p, row_size);
5017 ktx.skip_bytes(skip);
5024 unsigned char *begin = image.p();
5025 const unsigned char *end = image.p() + image.size();
5026 size_t skip = cdata->_num_components;
5027 nassertr(skip == 3 || skip == 4,
false);
5029 switch (cdata->_component_width) {
5031 for (
unsigned char *p = begin; p < end; p += skip) {
5036 for (
short *p = (
short *)begin; p < (
short *)end; p += skip) {
5041 for (
int *p = (
int *)begin; p < (
int *)end; p += skip) {
5046 nassert_raise(
"unexpected channel count");
5051 do_set_ram_mipmap_image(cdata, (
int)n, std::move(image),
5052 row_size * do_get_expected_mipmap_y_size(cdata, (
int)n));
5056 image = PTA_uchar::empty_array(image_size);
5057 ktx.extract_bytes(image.p(), image_size);
5058 do_set_ram_mipmap_image(cdata, (
int)n, std::move(image), image_size / depth);
5061 ktx.skip_bytes(3 - ((image_size + 3) & 3));
5064 cdata->_has_read_pages =
true;
5065 cdata->_has_read_mipmaps =
true;
5066 cdata->_num_mipmap_levels_read = cdata->_ram_images.size();
5068 if (generate_mipmaps) {
5069 do_generate_ram_mipmap_images(cdata,
false);
5075 << filename <<
": truncated KTX file.\n";
5079 cdata->_loaded_from_image =
true;
5080 cdata->_loaded_from_txo =
true;
5090do_write(CData *cdata,
5091 const Filename &fullpath,
int z,
int n,
bool write_pages,
bool write_mipmaps) {
5092 if (is_txo_filename(fullpath)) {
5093 if (!do_has_bam_rawdata(cdata)) {
5094 do_get_bam_rawdata(cdata);
5096 nassertr(do_has_bam_rawdata(cdata),
false);
5097 return do_write_txo_file(cdata, fullpath);
5100 if (!do_has_uncompressed_ram_image(cdata)) {
5101 do_get_uncompressed_ram_image(cdata);
5104 nassertr(do_has_ram_mipmap_image(cdata, n),
false);
5105 nassertr(cdata->_ram_image_compression == CM_off,
false);
5107 if (write_pages && write_mipmaps) {
5110 int num_levels = cdata->_ram_images.size();
5112 for (
int n = 0; n < num_levels; ++n) {
5113 int num_pages = do_get_expected_mipmap_num_pages(cdata, n);
5115 for (z = 0; z < num_pages; ++z) {
5120 <<
"Filename requires two different hash sequences: " << fullpath
5131 }
else if (write_pages) {
5134 if (!fullpath_pattern.
has_hash()) {
5136 <<
"Filename requires a hash mark: " << fullpath
5141 int num_pages = cdata->_z_size * cdata->_num_views;
5142 for (z = 0; z < num_pages; ++z) {
5148 }
else if (write_mipmaps) {
5151 if (!fullpath_pattern.
has_hash()) {
5153 <<
"Filename requires a hash mark: " << fullpath
5158 int num_levels = cdata->_ram_images.size();
5159 for (
int n = 0; n < num_levels; ++n) {
5167 if (!do_write_one(cdata, fullpath, z, n)) {
5180do_write_one(CData *cdata,
const Filename &fullpath,
int z,
int n) {
5181 if (!do_has_ram_mipmap_image(cdata, n)) {
5185 nassertr(cdata->_ram_image_compression == CM_off,
false);
5188 if (cdata->_component_type == T_float) {
5191 if (!do_store_one(cdata, pfm, z, n)) {
5194 success = pfm.
write(fullpath);
5199 if (type ==
nullptr) {
5201 <<
"Texture::write() - couldn't determine type from extension: " << fullpath << endl;
5206 if (!do_store_one(cdata, pnmimage, z, n)) {
5209 success = pnmimage.
write(fullpath, type);
5214 <<
"Texture::write() - couldn't write: " << fullpath << endl;
5225do_store_one(CData *cdata,
PNMImage &pnmimage,
int z,
int n) {
5227 do_get_uncompressed_ram_image(cdata);
5229 if (!do_has_ram_mipmap_image(cdata, n)) {
5233 nassertr(z >= 0 && z < do_get_expected_mipmap_num_pages(cdata, n),
false);
5234 nassertr(cdata->_ram_image_compression == CM_off,
false);
5236 if (cdata->_component_type == T_float) {
5239 bool success = convert_to_pfm(pfm,
5240 do_get_expected_mipmap_x_size(cdata, n),
5241 do_get_expected_mipmap_y_size(cdata, n),
5242 cdata->_num_components, cdata->_component_width,
5243 cdata->_ram_images[n]._image,
5244 do_get_ram_mipmap_page_size(cdata, n), z);
5248 return pfm.
store(pnmimage);
5251 return convert_to_pnmimage(pnmimage,
5252 do_get_expected_mipmap_x_size(cdata, n),
5253 do_get_expected_mipmap_y_size(cdata, n),
5254 cdata->_num_components, cdata->_component_type,
5256 cdata->_ram_images[n]._image,
5257 do_get_ram_mipmap_page_size(cdata, n), z);
5264do_store_one(CData *cdata,
PfmFile &pfm,
int z,
int n) {
5266 do_get_uncompressed_ram_image(cdata);
5268 if (!do_has_ram_mipmap_image(cdata, n)) {
5272 nassertr(z >= 0 && z < do_get_expected_mipmap_num_pages(cdata, n),
false);
5273 nassertr(cdata->_ram_image_compression == CM_off,
false);
5275 if (cdata->_component_type != T_float) {
5279 convert_to_pnmimage(pnmimage,
5280 do_get_expected_mipmap_x_size(cdata, n),
5281 do_get_expected_mipmap_y_size(cdata, n),
5282 cdata->_num_components, cdata->_component_type,
5284 cdata->_ram_images[n]._image,
5285 do_get_ram_mipmap_page_size(cdata, n), z);
5289 return pfm.
load(pnmimage);
5292 return convert_to_pfm(pfm,
5293 do_get_expected_mipmap_x_size(cdata, n),
5294 do_get_expected_mipmap_y_size(cdata, n),
5295 cdata->_num_components, cdata->_component_width,
5296 cdata->_ram_images[n]._image,
5297 do_get_ram_mipmap_page_size(cdata, n), z);
5304do_write_txo_file(
const CData *cdata,
const Filename &fullpath)
const {
5306 Filename filename = Filename::binary_filename(fullpath);
5308 if (out ==
nullptr) {
5310 <<
"Unable to open " << filename <<
"\n";
5314 bool success = do_write_txo(cdata, *out, fullpath);
5323do_write_txo(
const CData *cdata, ostream &out,
const string &filename)
const {
5326 if (!dout.
open(out, filename)) {
5328 <<
"Could not write texture object: " << filename <<
"\n";
5334 <<
"Unable to write to " << filename <<
"\n";
5339 if (!writer.init()) {
5343 writer.set_file_texture_mode(BamWriter::BTM_rawdata);
5345 if (!writer.write_object(
this)) {
5349 if (!do_has_bam_rawdata(cdata)) {
5351 << get_name() <<
" does not have ram image\n";
5372Texture::CData *Texture::
5373unlocked_ensure_ram_image(
bool allow_compression) {
5379 while (_reloading) {
5384 const CData *cdata = _cycler.
read(current_thread);
5386 if (
has_ram_image && !allow_compression && cdata->_ram_image_compression != Texture::CM_off) {
5398 nassertr(!_reloading,
nullptr);
5401 PT(
Texture) tex = do_make_copy(cdata);
5407 CDWriter cdata_tex(tex->_cycler,
true);
5408 tex->do_reload_ram_image(cdata_tex, allow_compression);
5419 cdataw->_orig_file_x_size = cdata_tex->_orig_file_x_size;
5420 cdataw->_orig_file_y_size = cdata_tex->_orig_file_y_size;
5424 if (cdata_tex->_x_size != cdataw->_x_size ||
5425 cdata_tex->_y_size != cdataw->_y_size ||
5426 cdata_tex->_z_size != cdataw->_z_size ||
5427 cdata_tex->_num_views != cdataw->_num_views ||
5428 cdata_tex->_num_components != cdataw->_num_components ||
5429 cdata_tex->_component_width != cdataw->_component_width ||
5430 cdata_tex->_texture_type != cdataw->_texture_type ||
5431 cdata_tex->_component_type != cdataw->_component_type) {
5433 cdataw->_x_size = cdata_tex->_x_size;
5434 cdataw->_y_size = cdata_tex->_y_size;
5435 cdataw->_z_size = cdata_tex->_z_size;
5436 cdataw->_num_views = cdata_tex->_num_views;
5438 cdataw->_num_components = cdata_tex->_num_components;
5439 cdataw->_component_width = cdata_tex->_component_width;
5440 cdataw->_texture_type = cdata_tex->_texture_type;
5441 cdataw->_format = cdata_tex->_format;
5442 cdataw->_component_type = cdata_tex->_component_type;
5444 cdataw->inc_properties_modified();
5445 cdataw->inc_image_modified();
5448 cdataw->_keep_ram_image = cdata_tex->_keep_ram_image;
5449 cdataw->_ram_image_compression = cdata_tex->_ram_image_compression;
5450 cdataw->_ram_images = cdata_tex->_ram_images;
5452 nassertr(_reloading,
nullptr);
5474do_reload_ram_image(CData *cdata,
bool allow_compression) {
5478 if (!do_has_compression(cdata)) {
5479 allow_compression =
false;
5485 record = cache->lookup(cdata->_fullpath,
"txo");
5486 if (record !=
nullptr &&
5487 record->has_data()) {
5492 int x_size = cdata->_orig_file_x_size;
5493 int y_size = cdata->_orig_file_y_size;
5494 do_adjust_this_size(cdata, x_size, y_size, cdata->_filename.get_basename(),
true);
5495 if (x_size != tex->get_x_size() || y_size != tex->get_y_size()) {
5496 if (gobj_cat.is_debug()) {
5498 <<
"Cached texture " << *
this <<
" has size "
5499 << tex->get_x_size() <<
" x " << tex->get_y_size()
5500 <<
" instead of " << x_size <<
" x " << y_size
5501 <<
"; ignoring cache.\n";
5506 if (!allow_compression && tex->get_ram_image_compression() != Texture::CM_off) {
5507 if (gobj_cat.is_debug()) {
5509 <<
"Cached texture " << *
this
5510 <<
" is compressed in cache; ignoring cache.\n";
5514 <<
"Texture " << get_name() <<
" reloaded from disk cache\n";
5519 CDReader cdata_tex(tex->_cycler);
5520 cdata->_x_size = cdata_tex->_x_size;
5521 cdata->_y_size = cdata_tex->_y_size;
5522 if (cdata->_num_components != cdata_tex->_num_components) {
5523 cdata->_num_components = cdata_tex->_num_components;
5524 cdata->_format = cdata_tex->_format;
5526 cdata->_component_type = cdata_tex->_component_type;
5527 cdata->_compression = cdata_tex->_compression;
5528 cdata->_ram_image_compression = cdata_tex->_ram_image_compression;
5529 cdata->_ram_images = cdata_tex->_ram_images;
5530 cdata->_loaded_from_image =
true;
5532 bool was_compressed = (cdata->_ram_image_compression != CM_off);
5533 if (do_consider_auto_process_ram_image(cdata,
uses_mipmaps(), allow_compression)) {
5534 bool is_compressed = (cdata->_ram_image_compression != CM_off);
5535 if (!was_compressed && is_compressed &&
5541 cache->
store(record);
5552 <<
"Reloading texture " << get_name() <<
"\n";
5557 if (cdata->_has_read_pages) {
5560 if (cdata->_has_read_mipmaps) {
5561 n = cdata->_num_mipmap_levels_read;
5564 cdata->_loaded_from_image =
false;
5565 Format orig_format = cdata->_format;
5566 int orig_num_components = cdata->_num_components;
5569 if (allow_compression) {
5570 options.set_texture_flags(LoaderOptions::TF_preload |
5571 LoaderOptions::TF_allow_compression);
5573 options.set_texture_flags(LoaderOptions::TF_preload);
5575 do_read(cdata, cdata->_fullpath, cdata->_alpha_fullpath,
5576 cdata->_primary_file_num_channels, cdata->_alpha_file_channel,
5577 z, n, cdata->_has_read_pages, cdata->_has_read_mipmaps, options,
nullptr);
5579 if (orig_num_components == cdata->_num_components) {
5582 cdata->_format = orig_format;
5585 if (do_has_ram_image(cdata) && record !=
nullptr) {
5588 if (record !=
nullptr) {
5592 cache->
store(record);
5602do_modify_ram_image(CData *cdata) {
5603 if (cdata->_ram_images.empty() || cdata->_ram_images[0]._image.empty() ||
5604 cdata->_ram_image_compression != CM_off) {
5605 do_make_ram_image(cdata);
5607 do_clear_ram_mipmap_images(cdata);
5609 return cdata->_ram_images[0]._image;
5617do_make_ram_image(CData *cdata) {
5618 int image_size = do_get_expected_ram_image_size(cdata);
5619 cdata->_ram_images.clear();
5620 cdata->_ram_images.push_back(RamImage());
5621 cdata->_ram_images[0]._page_size = do_get_expected_ram_page_size(cdata);
5622 cdata->_ram_images[0]._image = PTA_uchar::empty_array(image_size, get_class_type());
5623 cdata->_ram_images[0]._pointer_image =
nullptr;
5624 cdata->_ram_image_compression = CM_off;
5626 if (cdata->_has_clear_color) {
5628 unsigned char pixel[16];
5629 const int pixel_size = do_get_clear_data(cdata,
pixel);
5630 nassertr(pixel_size > 0, cdata->_ram_images[0]._image);
5632 unsigned char *image_data = cdata->_ram_images[0]._image;
5633 for (
int i = 0; i < image_size; i += pixel_size) {
5634 memcpy(image_data + i,
pixel, pixel_size);
5638 return cdata->_ram_images[0]._image;
5649do_set_ram_image(CData *cdata,
CPTA_uchar image, Texture::CompressionMode compression,
5651 nassertv(compression != CM_default);
5652 nassertv(compression != CM_off || image.size() == do_get_expected_ram_image_size(cdata));
5653 if (cdata->_ram_images.empty()) {
5654 cdata->_ram_images.push_back(RamImage());
5656 do_clear_ram_mipmap_images(cdata);
5658 if (page_size == 0) {
5659 page_size = image.size();
5661 if (cdata->_ram_images[0]._image != image ||
5662 cdata->_ram_images[0]._page_size != page_size ||
5663 cdata->_ram_image_compression != compression) {
5665 cdata->_ram_images[0]._page_size = page_size;
5666 cdata->_ram_images[0]._pointer_image =
nullptr;
5667 cdata->_ram_image_compression = compression;
5668 cdata->inc_image_modified();
5677do_modify_ram_mipmap_image(CData *cdata,
int n) {
5678 nassertr(cdata->_ram_image_compression == CM_off, PTA_uchar());
5680 if (n >= (
int)cdata->_ram_images.size() ||
5681 cdata->_ram_images[n]._image.empty()) {
5682 do_make_ram_mipmap_image(cdata, n);
5684 return cdata->_ram_images[n]._image;
5691do_make_ram_mipmap_image(CData *cdata,
int n) {
5692 nassertr(cdata->_ram_image_compression == CM_off, PTA_uchar(get_class_type()));
5694 while (n >= (
int)cdata->_ram_images.size()) {
5695 cdata->_ram_images.push_back(RamImage());
5698 size_t image_size = do_get_expected_ram_mipmap_image_size(cdata, n);
5699 cdata->_ram_images[n]._image = PTA_uchar::empty_array(image_size, get_class_type());
5700 cdata->_ram_images[n]._pointer_image =
nullptr;
5701 cdata->_ram_images[n]._page_size = do_get_expected_ram_mipmap_page_size(cdata, n);
5703 if (cdata->_has_clear_color) {
5705 unsigned char pixel[16];
5706 const size_t pixel_size = (size_t)do_get_clear_data(cdata,
pixel);
5707 nassertr(pixel_size > 0, cdata->_ram_images[n]._image);
5709 unsigned char *image_data = cdata->_ram_images[n]._image;
5710 for (
size_t i = 0; i < image_size; i += pixel_size) {
5711 memcpy(image_data + i,
pixel, pixel_size);
5715 return cdata->_ram_images[n]._image;
5722do_set_ram_mipmap_image(CData *cdata,
int n,
CPTA_uchar image,
size_t page_size) {
5723 nassertv(cdata->_ram_image_compression != CM_off || image.size() == do_get_expected_ram_mipmap_image_size(cdata, n));
5725 while (n >= (
int)cdata->_ram_images.size()) {
5726 cdata->_ram_images.push_back(RamImage());
5728 if (page_size == 0) {
5729 page_size = image.size();
5732 if (cdata->_ram_images[n]._image != image ||
5733 cdata->_ram_images[n]._page_size != page_size) {
5735 cdata->_ram_images[n]._pointer_image =
nullptr;
5736 cdata->_ram_images[n]._page_size = page_size;
5737 cdata->inc_image_modified();
5749do_get_clear_data(
const CData *cdata,
unsigned char *into)
const {
5750 nassertr(cdata->_has_clear_color, 0);
5752 int num_components = cdata->_num_components;
5753 nassertr(num_components > 0, 0);
5754 nassertr(num_components <= 4, 0);
5756 LVecBase4 clear_value = cdata->_clear_color;
5759 if (num_components >= 3) {
5760 std::swap(clear_value[0], clear_value[2]);
5763 switch (cdata->_component_type) {
5764 case T_unsigned_byte:
5765 if (
is_srgb(cdata->_format)) {
5769 switch (num_components) {
5770 case 4: into[3] = (
unsigned char)alpha;
5771 case 3: into[2] = (
unsigned char)color.b;
5772 case 2: into[1] = (
unsigned char)color.g;
5773 case 1: into[0] = (
unsigned char)color.r;
5776 LColor scaled = clear_value.fmin(LColor(1)).fmax(LColor::zero());
5778 for (
int i = 0; i < num_components; ++i) {
5779 into[i] = (
unsigned char)scaled[i];
5784 case T_unsigned_short:
5786 LColor scaled = clear_value.fmin(LColor(1)).fmax(LColor::zero());
5788 for (
int i = 0; i < num_components; ++i) {
5789 ((
unsigned short *)into)[i] = (
unsigned short)scaled[i];
5795 for (
int i = 0; i < num_components; ++i) {
5796 ((
float *)into)[i] = clear_value[i];
5800 case T_unsigned_int_24_8:
5801 nassertr(num_components == 1, 0);
5802 *((
unsigned int *)into) =
5803 ((
unsigned int)(clear_value[0] * 16777215) << 8) +
5804 (
unsigned int)max(min(clear_value[1], (PN_stdfloat)255), (PN_stdfloat)0);
5810 for (
int i = 0; i < num_components; ++i) {
5811 ((
int *)into)[i] = (int)clear_value[i];
5817 LColor scaled = clear_value.fmin(LColor(1)).fmax(LColor(-1));
5819 for (
int i = 0; i < num_components; ++i) {
5820 ((
signed char *)into)[i] = (
signed char)scaled[i];
5827 LColor scaled = clear_value.fmin(LColor(1)).fmax(LColor(-1));
5829 for (
int i = 0; i < num_components; ++i) {
5830 ((
short *)into)[i] = (short)scaled[i];
5836 for (
int i = 0; i < num_components; ++i) {
5841 v.uf = clear_value[i];
5842 uint16_t sign = ((v.ui & 0x80000000u) >> 16u);
5843 uint32_t mantissa = (v.ui & 0x007fffffu);
5844 uint16_t exponent = (uint16_t)std::min(std::max((
int)((v.ui & 0x7f800000u) >> 23u) - 112, 0), 31);
5845 mantissa += (mantissa & 0x00001000u) << 1u;
5846 ((uint16_t *)into)[i] = (uint16_t)(sign | ((exponent << 10u) | (mantissa >> 13u)));
5850 case T_unsigned_int:
5853 for (
int i = 0; i < num_components; ++i) {
5854 ((
unsigned int *)into)[i] = (
unsigned int)clear_value[i];
5858 return num_components * cdata->_component_width;
5869consider_auto_process_ram_image(
bool generate_mipmaps,
bool allow_compression) {
5870 CDWriter cdata(_cycler,
false);
5871 return do_consider_auto_process_ram_image(cdata, generate_mipmaps, allow_compression);
5882do_consider_auto_process_ram_image(CData *cdata,
bool generate_mipmaps,
5883 bool allow_compression) {
5884 bool modified =
false;
5886 if (generate_mipmaps && !driver_generate_mipmaps &&
5887 cdata->_ram_images.size() == 1) {
5888 do_generate_ram_mipmap_images(cdata,
false);
5892 if (allow_compression && !driver_compress_textures) {
5893 CompressionMode compression = cdata->_compression;
5894 if (compression == CM_default && compressed_textures) {
5895 if (cdata->_texture_type == Texture::TT_buffer_texture) {
5896 compression = CM_off;
5899 compression = CM_on;
5902 if (compression != CM_off && cdata->_ram_image_compression == CM_off) {
5904 if (do_compress_ram_image(cdata, compression, QL_default, gsg)) {
5905 if (gobj_cat.is_debug()) {
5907 <<
"Compressed " << get_name() <<
" with "
5908 << cdata->_ram_image_compression <<
"\n";
5922do_compress_ram_image(CData *cdata, Texture::CompressionMode compression,
5923 Texture::QualityLevel quality_level,
5925 nassertr(compression != CM_off,
false);
5927 if (cdata->_ram_images.empty() || cdata->_ram_image_compression != CM_off) {
5931 if (compression == CM_on) {
5933 switch (cdata->_format) {
5934 case Texture::F_rgbm:
5935 case Texture::F_rgb:
5936 case Texture::F_rgb5:
5937 case Texture::F_rgba5:
5938 case Texture::F_rgb8:
5939 case Texture::F_rgb12:
5940 case Texture::F_rgb332:
5941 case Texture::F_rgb16:
5942 case Texture::F_rgb32:
5943 case Texture::F_rgb10_a2:
5944 if (gsg ==
nullptr || gsg->get_supports_compressed_texture_format(CM_dxt1)) {
5945 compression = CM_dxt1;
5946 }
else if (gsg->get_supports_compressed_texture_format(CM_dxt3)) {
5947 compression = CM_dxt3;
5948 }
else if (gsg->get_supports_compressed_texture_format(CM_dxt5)) {
5949 compression = CM_dxt5;
5950 }
else if (gsg->get_supports_compressed_texture_format(CM_etc2)) {
5951 compression = CM_etc2;
5952 }
else if (gsg->get_supports_compressed_texture_format(CM_etc1)) {
5953 compression = CM_etc1;
5957 case Texture::F_rgba4:
5958 if (gsg ==
nullptr || gsg->get_supports_compressed_texture_format(CM_dxt3)) {
5959 compression = CM_dxt3;
5960 }
else if (gsg->get_supports_compressed_texture_format(CM_dxt5)) {
5961 compression = CM_dxt5;
5962 }
else if (gsg->get_supports_compressed_texture_format(CM_etc2)) {
5963 compression = CM_etc2;
5967 case Texture::F_rgba:
5968 case Texture::F_rgba8:
5969 case Texture::F_rgba12:
5970 case Texture::F_rgba16:
5971 case Texture::F_rgba32:
5972 if (gsg ==
nullptr || gsg->get_supports_compressed_texture_format(CM_dxt5)) {
5973 compression = CM_dxt5;
5974 }
else if (gsg->get_supports_compressed_texture_format(CM_etc2)) {
5975 compression = CM_etc2;
5979 case Texture::F_red:
5981 if (gsg ==
nullptr || gsg->get_supports_compressed_texture_format(CM_rgtc)) {
5982 compression = CM_rgtc;
5983 }
else if (gsg->get_supports_compressed_texture_format(CM_eac)) {
5984 compression = CM_eac;
5994 if (quality_level == Texture::QL_default) {
5995 quality_level = cdata->_quality_level;
5997 if (quality_level == Texture::QL_default) {
5998 quality_level = texture_quality_level;
6001 if (compression == CM_rgtc) {
6003 if (cdata->_component_type != T_unsigned_byte) {
6007 if (!do_has_all_ram_mipmap_images(cdata)) {
6010 do_generate_ram_mipmap_images(cdata,
false);
6013 RamImages compressed_ram_images;
6014 compressed_ram_images.resize(cdata->_ram_images.size());
6016 for (
size_t n = 0; n < cdata->_ram_images.size(); ++n) {
6017 const RamImage *uncompressed_image = &cdata->_ram_images[n];
6019 int x_size = do_get_expected_mipmap_x_size(cdata, n);
6020 int y_size = do_get_expected_mipmap_y_size(cdata, n);
6021 int num_pages = do_get_expected_mipmap_num_pages(cdata, n);
6026 RamImage temp_image;
6027 if ((x_size | y_size) & 0x3) {
6028 int virtual_x_size = x_size;
6029 int virtual_y_size = y_size;
6030 x_size = (x_size + 3) & ~0x3;
6031 y_size = (y_size + 3) & ~0x3;
6033 temp_image._page_size = x_size * y_size * cdata->_num_components;
6034 temp_image._image = PTA_uchar::empty_array(temp_image._page_size * num_pages);
6036 for (
int z = 0; z < num_pages; ++z) {
6037 unsigned char *dest = temp_image._image.p() + z * temp_image._page_size;
6038 unsigned const char *src = uncompressed_image->_image.p() + z * uncompressed_image->_page_size;
6040 for (
int y = 0; y < virtual_y_size; ++y) {
6041 memcpy(dest, src, virtual_x_size);
6042 src += virtual_x_size;
6047 uncompressed_image = &temp_image;
6051 RamImage &compressed_image = compressed_ram_images[n];
6052 compressed_image._page_size = (x_size * y_size * cdata->_num_components) >> 1;
6053 compressed_image._image = PTA_uchar::empty_array(compressed_image._page_size * num_pages);
6055 if (cdata->_num_components == 1) {
6056 do_compress_ram_image_bc4(*uncompressed_image, compressed_image,
6057 x_size, y_size, num_pages);
6058 }
else if (cdata->_num_components == 2) {
6059 do_compress_ram_image_bc5(*uncompressed_image, compressed_image,
6060 x_size, y_size, num_pages);
6067 cdata->_ram_images.swap(compressed_ram_images);
6068 cdata->_ram_image_compression = CM_rgtc;
6073 if (cdata->_texture_type != TT_3d_texture &&
6074 cdata->_texture_type != TT_2d_texture_array &&
6075 cdata->_component_type == T_unsigned_byte) {
6076 int squish_flags = 0;
6077 switch (compression) {
6079 squish_flags |= squish::kDxt1;
6083 squish_flags |= squish::kDxt3;
6087 squish_flags |= squish::kDxt5;
6094 if (squish_flags != 0) {
6096 switch (quality_level) {
6098 squish_flags |= squish::kColourRangeFit;
6103 squish_flags |= squish::kColourRangeFit;
6108 squish_flags |= squish::kColourIterativeClusterFit;
6115 if (do_squish(cdata, compression, squish_flags)) {
6129do_uncompress_ram_image(CData *cdata) {
6130 nassertr(!cdata->_ram_images.empty(),
false);
6132 if (cdata->_ram_image_compression == CM_rgtc) {
6134 RamImages uncompressed_ram_images;
6135 uncompressed_ram_images.resize(cdata->_ram_images.size());
6137 for (
size_t n = 0; n < cdata->_ram_images.size(); ++n) {
6138 const RamImage &compressed_image = cdata->_ram_images[n];
6140 int x_size = do_get_expected_mipmap_x_size(cdata, n);
6141 int y_size = do_get_expected_mipmap_y_size(cdata, n);
6142 int num_pages = do_get_expected_mipmap_num_pages(cdata, n);
6144 RamImage &uncompressed_image = uncompressed_ram_images[n];
6145 uncompressed_image._page_size = do_get_expected_ram_mipmap_page_size(cdata, n);
6146 uncompressed_image._image = PTA_uchar::empty_array(uncompressed_image._page_size * num_pages);
6148 if (cdata->_num_components == 1) {
6149 do_uncompress_ram_image_bc4(compressed_image, uncompressed_image,
6150 x_size, y_size, num_pages);
6151 }
else if (cdata->_num_components == 2) {
6152 do_uncompress_ram_image_bc5(compressed_image, uncompressed_image,
6153 x_size, y_size, num_pages);
6159 cdata->_ram_images.swap(uncompressed_ram_images);
6160 cdata->_ram_image_compression = CM_off;
6165 if (cdata->_texture_type != TT_3d_texture &&
6166 cdata->_texture_type != TT_2d_texture_array &&
6167 cdata->_component_type == T_unsigned_byte) {
6168 int squish_flags = 0;
6169 switch (cdata->_ram_image_compression) {
6171 squish_flags |= squish::kDxt1;
6175 squish_flags |= squish::kDxt3;
6179 squish_flags |= squish::kDxt5;
6186 if (squish_flags != 0) {
6188 if (do_unsquish(cdata, squish_flags)) {
6201do_compress_ram_image_bc4(
const RamImage &uncompressed_image,
6202 RamImage &compressed_image,
6203 int x_size,
int y_size,
int num_pages) {
6204 int x_blocks = (x_size >> 2);
6205 int y_blocks = (y_size >> 2);
6211 nassertv((
size_t)x_blocks * (
size_t)y_blocks * 4 * 4 <= uncompressed_image._page_size);
6212 nassertv((
size_t)x_size * (
size_t)y_size == uncompressed_image._page_size);
6214 static const int remap[] = {1, 7, 6, 5, 4, 3, 2, 0};
6216 for (
int z = 0; z < num_pages; ++z) {
6217 unsigned char *dest = compressed_image._image.p() + z * compressed_image._page_size;
6218 unsigned const char *src = uncompressed_image._image.p() + z * uncompressed_image._page_size;
6221 for (
int y = 0; y < y_blocks; ++y) {
6222 for (
int x = 0; x < x_blocks; ++x) {
6225 unsigned char minv, maxv;
6226 unsigned const char *blk = src;
6231 minv = min(blk[1], minv); maxv = max(blk[1], maxv);
6232 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6233 minv = min(blk[3], minv); maxv = max(blk[3], maxv);
6235 minv = min(blk[0], minv); maxv = max(blk[0], maxv);
6236 minv = min(blk[1], minv); maxv = max(blk[1], maxv);
6237 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6238 minv = min(blk[3], minv); maxv = max(blk[3], maxv);
6240 minv = min(blk[0], minv); maxv = max(blk[0], maxv);
6241 minv = min(blk[1], minv); maxv = max(blk[1], maxv);
6242 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6243 minv = min(blk[3], minv); maxv = max(blk[3], maxv);
6245 minv = min(blk[0], minv); maxv = max(blk[0], maxv);
6246 minv = min(blk[1], minv); maxv = max(blk[1], maxv);
6247 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6248 minv = min(blk[3], minv); maxv = max(blk[3], maxv);
6253 fac = 7.5f / (maxv - minv);
6258 a = (remap[(int)(blk[0] * fac + add)])
6259 | (remap[(
int)(blk[1] * fac + add)] << 3)
6260 | (remap[(int)(blk[2] * fac + add)] << 6)
6261 | (remap[(
int)(blk[3] * fac + add)] << 9);
6263 b = (remap[(int)(blk[0] * fac + add)] << 4)
6264 | (remap[(
int)(blk[1] * fac + add)] << 7)
6265 | (remap[(int)(blk[2] * fac + add)] << 10)
6266 | (remap[(
int)(blk[3] * fac + add)] << 13);
6268 c = (remap[(int)(blk[0] * fac + add)])
6269 | (remap[(
int)(blk[1] * fac + add)] << 3)
6270 | (remap[(int)(blk[2] * fac + add)] << 6)
6271 | (remap[(
int)(blk[3] * fac + add)] << 9);
6273 d = (remap[(int)(blk[0] * fac + add)] << 4)
6274 | (remap[(
int)(blk[1] * fac + add)] << 7)
6275 | (remap[(int)(blk[2] * fac + add)] << 10)
6276 | (remap[(
int)(blk[3] * fac + add)] << 13);
6280 *(dest++) = a & 0xff;
6281 *(dest++) = (a >> 8) | (b & 0xf0);
6283 *(dest++) = c & 0xff;
6284 *(dest++) = (c >> 8) | (d & 0xf0);
6300do_compress_ram_image_bc5(
const RamImage &uncompressed_image,
6301 RamImage &compressed_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);
6305 int stride = x_size * 2;
6310 nassertv((
size_t)x_blocks * (
size_t)y_blocks * 4 * 4 * 2 <= uncompressed_image._page_size);
6311 nassertv((
size_t)stride * (
size_t)y_size == uncompressed_image._page_size);
6313 static const int remap[] = {1, 7, 6, 5, 4, 3, 2, 0};
6315 for (
int z = 0; z < num_pages; ++z) {
6316 unsigned char *dest = compressed_image._image.p() + z * compressed_image._page_size;
6317 unsigned const char *src = uncompressed_image._image.p() + z * uncompressed_image._page_size;
6320 for (
int y = 0; y < y_blocks; ++y) {
6321 for (
int x = 0; x < x_blocks; ++x) {
6324 unsigned char minv, maxv;
6325 unsigned const char *blk = src;
6330 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6331 minv = min(blk[4], minv); maxv = max(blk[4], maxv);
6332 minv = min(blk[6], minv); maxv = max(blk[6], maxv);
6334 minv = min(blk[0], minv); maxv = max(blk[0], maxv);
6335 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6336 minv = min(blk[4], minv); maxv = max(blk[4], maxv);
6337 minv = min(blk[6], minv); maxv = max(blk[6], maxv);
6339 minv = min(blk[0], minv); maxv = max(blk[0], maxv);
6340 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6341 minv = min(blk[4], minv); maxv = max(blk[4], maxv);
6342 minv = min(blk[6], minv); maxv = max(blk[6], maxv);
6344 minv = min(blk[0], minv); maxv = max(blk[0], maxv);
6345 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6346 minv = min(blk[4], minv); maxv = max(blk[4], maxv);
6347 minv = min(blk[6], minv); maxv = max(blk[6], maxv);
6351 fac = 7.5f / (maxv - minv);
6357 a = (remap[(int)(blk[0] * fac + add)])
6358 | (remap[(
int)(blk[2] * fac + add)] << 3)
6359 | (remap[(int)(blk[4] * fac + add)] << 6)
6360 | (remap[(
int)(blk[6] * fac + add)] << 9);
6362 b = (remap[(int)(blk[0] * fac + add)] << 4)
6363 | (remap[(
int)(blk[2] * fac + add)] << 7)
6364 | (remap[(int)(blk[4] * fac + add)] << 10)
6365 | (remap[(
int)(blk[6] * fac + add)] << 13);
6367 c = (remap[(int)(blk[0] * fac + add)])
6368 | (remap[(
int)(blk[2] * fac + add)] << 3)
6369 | (remap[(int)(blk[4] * fac + add)] << 6)
6370 | (remap[(
int)(blk[6] * fac + add)] << 9);
6372 d = (remap[(int)(blk[0] * fac + add)] << 4)
6373 | (remap[(
int)(blk[2] * fac + add)] << 7)
6374 | (remap[(int)(blk[4] * fac + add)] << 10)
6375 | (remap[(
int)(blk[6] * fac + add)] << 13);
6379 *(dest++) = a & 0xff;
6380 *(dest++) = (a >> 8) | (b & 0xf0);
6382 *(dest++) = c & 0xff;
6383 *(dest++) = (c >> 8) | (d & 0xf0);
6390 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6391 minv = min(blk[4], minv); maxv = max(blk[4], maxv);
6392 minv = min(blk[6], minv); maxv = max(blk[6], maxv);
6394 minv = min(blk[0], minv); maxv = max(blk[0], maxv);
6395 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6396 minv = min(blk[4], minv); maxv = max(blk[4], maxv);
6397 minv = min(blk[6], minv); maxv = max(blk[6], maxv);
6399 minv = min(blk[0], minv); maxv = max(blk[0], maxv);
6400 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6401 minv = min(blk[4], minv); maxv = max(blk[4], maxv);
6402 minv = min(blk[6], minv); maxv = max(blk[6], maxv);
6404 minv = min(blk[0], minv); maxv = max(blk[0], maxv);
6405 minv = min(blk[2], minv); maxv = max(blk[2], maxv);
6406 minv = min(blk[4], minv); maxv = max(blk[4], maxv);
6407 minv = min(blk[6], minv); maxv = max(blk[6], maxv);
6411 fac = 7.5f / (maxv - minv);
6417 a = (remap[(int)(blk[0] * fac + add)])
6418 | (remap[(
int)(blk[2] * fac + add)] << 3)
6419 | (remap[(int)(blk[4] * fac + add)] << 6)
6420 | (remap[(
int)(blk[6] * fac + add)] << 9);
6422 b = (remap[(int)(blk[0] * fac + add)] << 4)
6423 | (remap[(
int)(blk[2] * fac + add)] << 7)
6424 | (remap[(int)(blk[4] * fac + add)] << 10)
6425 | (remap[(
int)(blk[6] * fac + add)] << 13);
6427 c = (remap[(int)(blk[0] * fac + add)])
6428 | (remap[(
int)(blk[2] * fac + add)] << 3)
6429 | (remap[(int)(blk[4] * fac + add)] << 6)
6430 | (remap[(
int)(blk[6] * fac + add)] << 9);
6432 d = (remap[(int)(blk[0] * fac + add)] << 4)
6433 | (remap[(
int)(blk[2] * fac + add)] << 7)
6434 | (remap[(int)(blk[4] * fac + add)] << 10)
6435 | (remap[(
int)(blk[6] * fac + add)] << 13);
6439 *(dest++) = a & 0xff;
6440 *(dest++) = (a >> 8) | (b & 0xf0);
6442 *(dest++) = c & 0xff;
6443 *(dest++) = (c >> 8) | (d & 0xf0);
6459do_uncompress_ram_image_bc4(
const RamImage &compressed_image,
6460 RamImage &uncompressed_image,
6461 int x_size,
int y_size,
int num_pages) {
6462 int x_blocks = (x_size >> 2);
6463 int y_blocks = (y_size >> 2);
6465 for (
int z = 0; z < num_pages; ++z) {
6466 unsigned char *dest = uncompressed_image._image.p() + z * uncompressed_image._page_size;
6467 unsigned const char *src = compressed_image._image.p() + z * compressed_image._page_size;
6471 for (
int y = 0; y < y_blocks; ++y) {
6472 for (
int x = 0; x < x_blocks; ++x) {
6473 unsigned char *blk = dest;
6476 if (tbl[0] > tbl[1]) {
6477 tbl[2] = (tbl[0] * 6 + tbl[1] * 1) / 7.0f;
6478 tbl[3] = (tbl[0] * 5 + tbl[1] * 2) / 7.0f;
6479 tbl[4] = (tbl[0] * 4 + tbl[1] * 3) / 7.0f;
6480 tbl[5] = (tbl[0] * 3 + tbl[1] * 4) / 7.0f;
6481 tbl[6] = (tbl[0] * 2 + tbl[1] * 5) / 7.0f;
6482 tbl[7] = (tbl[0] * 1 + tbl[1] * 6) / 7.0f;
6484 tbl[2] = (tbl[0] * 4 + tbl[1] * 1) / 5.0f;
6485 tbl[3] = (tbl[0] * 3 + tbl[1] * 2) / 5.0f;
6486 tbl[4] = (tbl[0] * 2 + tbl[1] * 3) / 5.0f;
6487 tbl[5] = (tbl[0] * 1 + tbl[1] * 4) / 5.0f;
6491 int v = src[2] + (src[3] << 8) + (src[4] << 16);
6492 blk[0] = tbl[v & 0x7];
6493 blk[1] = tbl[(v & 0x000038) >> 3];
6494 blk[2] = tbl[(v & 0x0001c0) >> 6];
6495 blk[3] = tbl[(v & 0x000e00) >> 9];
6497 blk[0] = tbl[(v & 0x007000) >> 12];
6498 blk[1] = tbl[(v & 0x038000) >> 15];
6499 blk[2] = tbl[(v & 0x1c0000) >> 18];
6500 blk[3] = tbl[(v & 0xe00000) >> 21];
6502 v = src[5] + (src[6] << 8) + (src[7] << 16);
6503 blk[0] = tbl[v & 0x7];
6504 blk[1] = tbl[(v & 0x000038) >> 3];
6505 blk[2] = tbl[(v & 0x0001c0) >> 6];
6506 blk[3] = tbl[(v & 0x000e00) >> 9];
6508 blk[0] = tbl[(v & 0x007000) >> 12];
6509 blk[1] = tbl[(v & 0x038000) >> 15];
6510 blk[2] = tbl[(v & 0x1c0000) >> 18];
6511 blk[3] = tbl[(v & 0xe00000) >> 21];
6525do_uncompress_ram_image_bc5(
const RamImage &compressed_image,
6526 RamImage &uncompressed_image,
6527 int x_size,
int y_size,
int num_pages) {
6528 int x_blocks = (x_size >> 2);
6529 int y_blocks = (y_size >> 2);
6530 int stride = x_size * 2;
6532 for (
int z = 0; z < num_pages; ++z) {
6533 unsigned char *dest = uncompressed_image._image.p() + z * uncompressed_image._page_size;
6534 unsigned const char *src = compressed_image._image.p() + z * compressed_image._page_size;
6539 for (
int y = 0; y < y_blocks; ++y) {
6540 for (
int x = 0; x < x_blocks; ++x) {
6541 unsigned char *blk = dest;
6544 if (red[0] > red[1]) {
6545 red[2] = (red[0] * 6 + red[1] * 1) / 7.0f;
6546 red[3] = (red[0] * 5 + red[1] * 2) / 7.0f;
6547 red[4] = (red[0] * 4 + red[1] * 3) / 7.0f;
6548 red[5] = (red[0] * 3 + red[1] * 4) / 7.0f;
6549 red[6] = (red[0] * 2 + red[1] * 5) / 7.0f;
6550 red[7] = (red[0] * 1 + red[1] * 6) / 7.0f;
6552 red[2] = (red[0] * 4 + red[1] * 1) / 5.0f;
6553 red[3] = (red[0] * 3 + red[1] * 2) / 5.0f;
6554 red[4] = (red[0] * 2 + red[1] * 3) / 5.0f;
6555 red[5] = (red[0] * 1 + red[1] * 4) / 5.0f;
6561 if (grn[0] > grn[1]) {
6562 grn[2] = (grn[0] * 6 + grn[1] * 1) / 7.0f;
6563 grn[3] = (grn[0] * 5 + grn[1] * 2) / 7.0f;
6564 grn[4] = (grn[0] * 4 + grn[1] * 3) / 7.0f;
6565 grn[5] = (grn[0] * 3 + grn[1] * 4) / 7.0f;
6566 grn[6] = (grn[0] * 2 + grn[1] * 5) / 7.0f;
6567 grn[7] = (grn[0] * 1 + grn[1] * 6) / 7.0f;
6569 grn[2] = (grn[0] * 4 + grn[1] * 1) / 5.0f;
6570 grn[3] = (grn[0] * 3 + grn[1] * 2) / 5.0f;
6571 grn[4] = (grn[0] * 2 + grn[1] * 3) / 5.0f;
6572 grn[5] = (grn[0] * 1 + grn[1] * 4) / 5.0f;
6576 int r = src[2] + (src[3] << 8) + (src[4] << 16);
6577 int g = src[10] + (src[11] << 8) + (src[12] << 16);
6578 blk[0] = red[r & 0x7];
6579 blk[1] = grn[g & 0x7];
6580 blk[2] = red[(r & 0x000038) >> 3];
6581 blk[3] = grn[(g & 0x000038) >> 3];
6582 blk[4] = red[(r & 0x0001c0) >> 6];
6583 blk[5] = grn[(g & 0x0001c0) >> 6];
6584 blk[6] = red[(r & 0x000e00) >> 9];
6585 blk[7] = grn[(g & 0x000e00) >> 9];
6587 blk[0] = red[(r & 0x007000) >> 12];
6588 blk[1] = grn[(g & 0x007000) >> 12];
6589 blk[2] = red[(r & 0x038000) >> 15];
6590 blk[3] = grn[(g & 0x038000) >> 15];
6591 blk[4] = red[(r & 0x1c0000) >> 18];
6592 blk[5] = grn[(g & 0x1c0000) >> 18];
6593 blk[6] = red[(r & 0xe00000) >> 21];
6594 blk[7] = grn[(g & 0xe00000) >> 21];
6596 r = src[5] + (src[6] << 8) + (src[7] << 16);
6597 g = src[13] + (src[14] << 8) + (src[15] << 16);
6598 blk[0] = red[r & 0x7];
6599 blk[1] = grn[g & 0x7];
6600 blk[2] = red[(r & 0x000038) >> 3];
6601 blk[3] = grn[(g & 0x000038) >> 3];
6602 blk[4] = red[(r & 0x0001c0) >> 6];
6603 blk[5] = grn[(g & 0x0001c0) >> 6];
6604 blk[6] = red[(r & 0x000e00) >> 9];
6605 blk[7] = grn[(g & 0x000e00) >> 9];
6607 blk[0] = red[(r & 0x007000) >> 12];
6608 blk[1] = grn[(g & 0x007000) >> 12];
6609 blk[2] = red[(r & 0x038000) >> 15];
6610 blk[3] = grn[(g & 0x038000) >> 15];
6611 blk[4] = red[(r & 0x1c0000) >> 18];
6612 blk[5] = grn[(g & 0x1c0000) >> 18];
6613 blk[6] = red[(r & 0xe00000) >> 21];
6614 blk[7] = grn[(g & 0xe00000) >> 21];
6628do_has_all_ram_mipmap_images(
const CData *cdata)
const {
6629 if (cdata->_ram_images.empty() || cdata->_ram_images[0]._image.empty()) {
6640 int size = max(cdata->_x_size, max(cdata->_y_size, cdata->_z_size));
6646 if (n >= (
int)cdata->_ram_images.size() || cdata->_ram_images[n]._image.empty()) {
6662do_reconsider_z_size(CData *cdata,
int z,
const LoaderOptions &options) {
6663 if (z >= cdata->_z_size * cdata->_num_views) {
6664 bool num_views_specified =
true;
6665 if (options.get_texture_flags() & LoaderOptions::TF_multiview) {
6672 if (num_views_specified &&
6673 (cdata->_texture_type == Texture::TT_3d_texture ||
6674 cdata->_texture_type == Texture::TT_2d_texture_array)) {
6679 nassertr(cdata->_num_views != 0,
false);
6680 cdata->_z_size = (z / cdata->_num_views) + 1;
6682 }
else if (cdata->_z_size != 0) {
6686 cdata->_num_views = (z / cdata->_z_size) + 1;
6695 do_allocate_pages(cdata);
6708do_allocate_pages(CData *cdata) {
6709 size_t new_size = do_get_expected_ram_image_size(cdata);
6710 if (!cdata->_ram_images.empty() &&
6711 !cdata->_ram_images[0]._image.empty() &&
6712 new_size > cdata->_ram_images[0]._image.size()) {
6713 cdata->_ram_images[0]._image.insert(cdata->_ram_images[0]._image.end(), new_size - cdata->_ram_images[0]._image.size(), 0);
6714 nassertv(cdata->_ram_images[0]._image.size() == new_size);
6725do_reconsider_image_properties(CData *cdata,
int x_size,
int y_size,
int num_components,
6726 Texture::ComponentType component_type,
int z,
6728 if (!cdata->_loaded_from_image || num_components != cdata->_num_components || component_type != cdata->_component_type) {
6734 switch (num_components) {
6736 cdata->_format = F_luminance;
6740 cdata->_format = F_luminance_alpha;
6744 cdata->_format = F_rgb;
6748 cdata->_format = F_rgba;
6753 nassert_raise(
"unexpected channel count");
6754 cdata->_format = F_rgb;
6759 if (!cdata->_loaded_from_image) {
6760 if ((options.get_texture_flags() & LoaderOptions::TF_allow_1d) &&
6761 cdata->_texture_type == TT_2d_texture && x_size != 1 && y_size == 1) {
6763 cdata->_texture_type = TT_1d_texture;
6767 switch (cdata->_texture_type) {
6769 case TT_buffer_texture:
6770 nassertr(y_size == 1,
false);
6773 case TT_cube_map_array:
6774 nassertr(x_size == y_size,
false);
6780 if ((cdata->_x_size != x_size)||(cdata->_y_size != y_size)) {
6781 do_set_pad_size(cdata, 0, 0, 0);
6783 cdata->_x_size = x_size;
6784 cdata->_y_size = y_size;
6785 cdata->_num_components = num_components;
6786 do_set_component_type(cdata, component_type);
6789 if (cdata->_x_size != x_size ||
6790 cdata->_y_size != y_size ||
6791 cdata->_num_components != num_components ||
6792 cdata->_component_type != component_type) {
6794 <<
"Texture properties have changed for texture " << get_name()
6795 <<
" page " << z <<
".\n";
6807do_rescale_texture(CData *cdata) {
6808 int new_x_size = cdata->_x_size;
6809 int new_y_size = cdata->_y_size;
6810 if (cdata->_z_size * cdata->_num_views != 1) {
6811 nassert_raise(
"rescale_texture() doesn't support 3-d or multiview textures.");
6815 if (do_adjust_this_size(cdata, new_x_size, new_y_size, get_name(),
false)) {
6818 if (!do_store_one(cdata, orig_image, 0, 0)) {
6820 <<
"Couldn't get image in rescale_texture()\n";
6825 <<
"Resizing " << get_name() <<
" to " << new_x_size <<
" x "
6826 << new_y_size <<
"\n";
6830 new_image.quick_filter_from(orig_image);
6832 do_clear_ram_image(cdata);
6833 cdata->inc_image_modified();
6834 cdata->_x_size = new_x_size;
6835 cdata->_y_size = new_y_size;
6836 if (!do_load_one(cdata, new_image, get_name(), 0, 0,
LoaderOptions())) {
6846 if (do_get_auto_texture_scale(cdata) == ATS_pad) {
6847 new_x_size = cdata->_x_size;
6848 new_y_size = cdata->_y_size;
6849 if (do_adjust_this_size(cdata, new_x_size, new_y_size, get_name(),
true)) {
6850 pad_x_size = new_x_size - cdata->_x_size;
6851 pad_y_size = new_y_size - cdata->_y_size;
6854 if (!do_store_one(cdata, orig_image, 0, 0)) {
6856 <<
"Couldn't get image in rescale_texture()\n";
6862 new_image.copy_sub_image(orig_image, 0, new_y_size - orig_image.
get_y_size());
6864 do_clear_ram_image(cdata);
6865 cdata->_loaded_from_image =
false;
6866 cdata->inc_image_modified();
6867 if (!do_load_one(cdata, new_image, get_name(), 0, 0,
LoaderOptions())) {
6871 do_set_pad_size(cdata, pad_x_size, pad_y_size, 0);
6884make_copy_impl()
const {
6885 CDReader cdata(_cycler);
6886 return do_make_copy(cdata);
6893do_make_copy(
const CData *cdata)
const {
6895 CDWriter cdata_tex(tex->_cycler,
true);
6896 tex->do_assign(cdata_tex,
this, cdata);
6905do_assign(CData *cdata,
const Texture *copy,
const CData *cdata_copy) {
6906 cdata->do_assign(cdata_copy);
6913do_clear(CData *cdata) {
6916 CDReader cdata_tex(tex._cycler);
6917 do_assign(cdata, &tex, cdata_tex);
6919 cdata->inc_properties_modified();
6920 cdata->inc_image_modified();
6921 cdata->inc_simple_image_modified();
6928do_setup_texture(CData *cdata, Texture::TextureType texture_type,
6929 int x_size,
int y_size,
int z_size,
6930 Texture::ComponentType component_type,
6931 Texture::Format format) {
6932 switch (texture_type) {
6934 nassertv(y_size == 1 && z_size == 1);
6938 nassertv(z_size == 1);
6944 case TT_2d_texture_array:
6949 nassertv(x_size == y_size && z_size == 6);
6954 cdata->_default_sampler.set_wrap_u(SamplerState::WM_clamp);
6955 cdata->_default_sampler.set_wrap_v(SamplerState::WM_clamp);
6956 cdata->_default_sampler.set_wrap_w(SamplerState::WM_clamp);
6959 case TT_cube_map_array:
6961 nassertv(x_size == y_size && z_size % 6 == 0);
6963 cdata->_default_sampler.set_wrap_u(SamplerState::WM_clamp);
6964 cdata->_default_sampler.set_wrap_v(SamplerState::WM_clamp);
6965 cdata->_default_sampler.set_wrap_w(SamplerState::WM_clamp);
6968 case TT_buffer_texture:
6969 nassertv(y_size == 1 && z_size == 1);
6972 case TT_1d_texture_array:
6973 nassertv(z_size == 1);
6977 if (texture_type != TT_2d_texture) {
6978 do_clear_simple_ram_image(cdata);
6981 cdata->_texture_type = texture_type;
6982 cdata->_x_size = x_size;
6983 cdata->_y_size = y_size;
6984 cdata->_z_size = z_size;
6985 cdata->_num_views = 1;
6986 do_set_component_type(cdata, component_type);
6987 do_set_format(cdata, format);
6989 do_clear_ram_image(cdata);
6990 do_set_pad_size(cdata, 0, 0, 0);
6991 cdata->_orig_file_x_size = 0;
6992 cdata->_orig_file_y_size = 0;
6993 cdata->_loaded_from_image =
false;
6994 cdata->_loaded_from_txo =
false;
6995 cdata->_has_read_pages =
false;
6996 cdata->_has_read_mipmaps =
false;
7003do_set_format(CData *cdata, Texture::Format format) {
7004 if (format == cdata->_format) {
7007 cdata->_format = format;
7008 cdata->inc_properties_modified();
7010 switch (cdata->_format) {
7012 case F_depth_stencil:
7013 case F_depth_component:
7014 case F_depth_component16:
7015 case F_depth_component24:
7016 case F_depth_component32:
7028 cdata->_num_components = 1;
7031 case F_luminance_alpha:
7032 case F_luminance_alphamask:
7034 case F_sluminance_alpha:
7040 cdata->_num_components = 2;
7056 cdata->_num_components = 3;
7072 cdata->_num_components = 4;
7081do_set_component_type(CData *cdata, Texture::ComponentType component_type) {
7082 cdata->_component_type = component_type;
7084 switch (component_type) {
7085 case T_unsigned_byte:
7087 cdata->_component_width = 1;
7090 case T_unsigned_short:
7093 cdata->_component_width = 2;
7097 case T_unsigned_int_24_8:
7099 case T_unsigned_int:
7100 cdata->_component_width = 4;
7109do_set_x_size(CData *cdata,
int x_size) {
7110 if (cdata->_x_size != x_size) {
7111 cdata->_x_size = x_size;
7112 cdata->inc_image_modified();
7113 do_clear_ram_image(cdata);
7114 do_set_pad_size(cdata, 0, 0, 0);
7122do_set_y_size(CData *cdata,
int y_size) {
7123 if (cdata->_y_size != y_size) {
7124 nassertv((cdata->_texture_type != Texture::TT_buffer_texture &&
7125 cdata->_texture_type != Texture::TT_1d_texture) || y_size == 1);
7126 cdata->_y_size = y_size;
7127 cdata->inc_image_modified();
7128 do_clear_ram_image(cdata);
7129 do_set_pad_size(cdata, 0, 0, 0);
7138do_set_z_size(CData *cdata,
int z_size) {
7139 if (cdata->_z_size != z_size) {
7140 nassertv((cdata->_texture_type == Texture::TT_3d_texture) ||
7141 (cdata->_texture_type == Texture::TT_cube_map && z_size == 6) ||
7142 (cdata->_texture_type == Texture::TT_cube_map_array && z_size % 6 == 0) ||
7143 (cdata->_texture_type == Texture::TT_2d_texture_array) || (z_size == 1));
7144 cdata->_z_size = z_size;
7145 cdata->inc_image_modified();
7146 do_clear_ram_image(cdata);
7147 do_set_pad_size(cdata, 0, 0, 0);
7155do_set_num_views(CData *cdata,
int num_views) {
7156 nassertv(num_views >= 1);
7157 if (cdata->_num_views != num_views) {
7158 cdata->_num_views = num_views;
7159 if (do_has_ram_image(cdata)) {
7160 cdata->inc_image_modified();
7161 do_clear_ram_image(cdata);
7163 do_set_pad_size(cdata, 0, 0, 0);
7171do_set_wrap_u(CData *cdata, SamplerState::WrapMode wrap) {
7172 if (cdata->_default_sampler.get_wrap_u() != wrap) {
7173 cdata->inc_properties_modified();
7174 cdata->_default_sampler.set_wrap_u(wrap);
7182do_set_wrap_v(CData *cdata, SamplerState::WrapMode wrap) {
7183 if (cdata->_default_sampler.get_wrap_v() != wrap) {
7184 cdata->inc_properties_modified();
7185 cdata->_default_sampler.set_wrap_v(wrap);
7193do_set_wrap_w(CData *cdata, SamplerState::WrapMode wrap) {
7194 if (cdata->_default_sampler.get_wrap_w() != wrap) {
7195 cdata->inc_properties_modified();
7196 cdata->_default_sampler.set_wrap_w(wrap);
7204do_set_minfilter(CData *cdata, SamplerState::FilterType filter) {
7205 if (cdata->_default_sampler.get_minfilter() != filter) {
7206 cdata->inc_properties_modified();
7207 cdata->_default_sampler.set_minfilter(filter);
7215do_set_magfilter(CData *cdata, SamplerState::FilterType filter) {
7216 if (cdata->_default_sampler.get_magfilter() != filter) {
7217 cdata->inc_properties_modified();
7218 cdata->_default_sampler.set_magfilter(filter);
7226do_set_anisotropic_degree(CData *cdata,
int anisotropic_degree) {
7227 if (cdata->_default_sampler.get_anisotropic_degree() != anisotropic_degree) {
7228 cdata->inc_properties_modified();
7229 cdata->_default_sampler.set_anisotropic_degree(anisotropic_degree);
7237do_set_border_color(CData *cdata,
const LColor &color) {
7238 if (cdata->_default_sampler.get_border_color() != color) {
7239 cdata->inc_properties_modified();
7240 cdata->_default_sampler.set_border_color(color);
7248do_set_compression(CData *cdata, Texture::CompressionMode compression) {
7249 if (cdata->_compression != compression) {
7250 cdata->inc_properties_modified();
7251 cdata->_compression = compression;
7253 if (do_has_ram_image(cdata)) {
7255 bool has_ram_image_compression = (cdata->_ram_image_compression != CM_off);
7270do_set_quality_level(CData *cdata, Texture::QualityLevel quality_level) {
7271 if (cdata->_quality_level != quality_level) {
7272 cdata->inc_properties_modified();
7273 cdata->_quality_level = quality_level;
7281do_has_compression(
const CData *cdata)
const {
7282 if (cdata->_compression == CM_default) {
7283 if (cdata->_texture_type != Texture::TT_buffer_texture) {
7284 return compressed_textures;
7289 return (cdata->_compression != CM_off);
7298do_has_ram_image(
const CData *cdata)
const {
7299 return !cdata->_ram_images.empty() && !cdata->_ram_images[0]._image.empty();
7307do_has_uncompressed_ram_image(
const CData *cdata)
const {
7308 return !cdata->_ram_images.empty() && !cdata->_ram_images[0]._image.empty() && cdata->_ram_image_compression == CM_off;
7315do_get_ram_image(CData *cdata) {
7316 if (!do_has_ram_image(cdata) && do_can_reload(cdata)) {
7317 do_reload_ram_image(cdata,
true);
7319 if (do_has_ram_image(cdata)) {
7323 cdata->inc_image_modified();
7324 cdata->inc_properties_modified();
7328 if (cdata->_ram_images.empty()) {
7332 return cdata->_ram_images[0]._image;
7339do_get_uncompressed_ram_image(CData *cdata) {
7340 if (!cdata->_ram_images.empty() && cdata->_ram_image_compression != CM_off) {
7343 if (do_uncompress_ram_image(cdata)) {
7344 if (gobj_cat.is_debug()) {
7346 <<
"Uncompressed " << get_name() <<
"\n";
7348 return cdata->_ram_images[0]._image;
7353 if ((!do_has_ram_image(cdata) || cdata->_ram_image_compression != CM_off) && do_can_reload(cdata)) {
7354 do_reload_ram_image(cdata,
false);
7357 if (!cdata->_ram_images.empty() && cdata->_ram_image_compression != CM_off) {
7359 if (do_uncompress_ram_image(cdata)) {
7361 <<
"Uncompressed " << get_name() <<
"\n";
7362 return cdata->_ram_images[0]._image;
7366 if (cdata->_ram_images.empty() || cdata->_ram_image_compression != CM_off) {
7370 return cdata->_ram_images[0]._image;
7399 string format =
upcase(requested_format);
7402 CPTA_uchar data = do_get_uncompressed_ram_image(cdata);
7403 if (data ==
nullptr) {
7404 gobj_cat.error() <<
"Couldn't find an uncompressed RAM image!\n";
7407 size_t imgsize = (size_t)cdata->_x_size * (
size_t)cdata->_y_size *
7408 (size_t)cdata->_z_size * (
size_t)cdata->_num_views;
7409 nassertr(cdata->_num_components > 0 && cdata->_num_components <= 4,
CPTA_uchar(get_class_type()));
7410 nassertr(data.size() == (
size_t)(cdata->_component_width * cdata->_num_components * imgsize),
CPTA_uchar(get_class_type()));
7413 if ((cdata->_num_components == 1 && format.size() == 1) ||
7414 (cdata->_num_components == 2 && format.size() == 2 && format.at(1) ==
'A' && format.at(0) !=
'A') ||
7415 (cdata->_num_components == 3 && format ==
"BGR") ||
7416 (cdata->_num_components == 4 && format ==
"BGRA")) {
7424 alpha = cdata->_num_components - 1;
7428 for (
size_t i = 0; i < format.size(); ++i) {
7429 if (format[i] !=
'B' && format[i] !=
'G' && format[i] !=
'R' &&
7430 format[i] !=
'A' && format[i] !=
'0' && format[i] !=
'1') {
7431 gobj_cat.error() <<
"Unexpected component character '"
7432 << format[i] <<
"', expected one of RGBA01!\n";
7438 PTA_uchar newdata = PTA_uchar::empty_array(imgsize * format.size() * cdata->_component_width, get_class_type());
7441 if (cdata->_component_width == 1) {
7442 if (format ==
"RGBA" && cdata->_num_components == 4) {
7443 const uint32_t *src = (
const uint32_t *)data.p();
7444 uint32_t *dst = (uint32_t *)newdata.p();
7446 for (
size_t p = 0; p < imgsize; ++p) {
7447 uint32_t v = *src++;
7448 *dst++ = ((v & 0xff00ff00u)) |
7449 ((v & 0x00ff0000u) >> 16) |
7450 ((v & 0x000000ffu) << 16);
7454 if (format ==
"RGB" && cdata->_num_components == 4) {
7455 const uint32_t *src = (
const uint32_t *)data.p();
7456 uint32_t *dst = (uint32_t *)newdata.p();
7460 int blocks = imgsize >> 2;
7461 for (
int i = 0; i < blocks; ++i) {
7462 uint32_t v0 = *src++;
7463 uint32_t v1 = *src++;
7464 uint32_t v2 = *src++;
7465 uint32_t v3 = *src++;
7466 *dst++ = ((v0 & 0x00ff0000u) >> 16) |
7467 ((v0 & 0x0000ff00u)) |
7468 ((v0 & 0x000000ffu) << 16) |
7469 ((v1 & 0x00ff0000u) << 8);
7470 *dst++ = ((v1 & 0x0000ff00u) >> 8) |
7471 ((v1 & 0x000000ffu) << 8) |
7472 ((v2 & 0x00ff0000u)) |
7473 ((v2 & 0x0000ff00u) << 16);
7474 *dst++ = ((v2 & 0x000000ffu)) |
7475 ((v3 & 0x00ff0000u) >> 8) |
7476 ((v3 & 0x0000ff00u) << 8) |
7477 ((v3 & 0x000000ffu) << 24);
7482 uint8_t *tail = (uint8_t *)dst;
7483 for (
int i = (imgsize & ~0x3); i < imgsize; ++i) {
7484 uint32_t v = *src++;
7485 *tail++ = (v & 0x00ff0000u) >> 16;
7486 *tail++ = (v & 0x0000ff00u) >> 8;
7487 *tail++ = (v & 0x000000ffu);
7491 if (format ==
"BGR" && cdata->_num_components == 4) {
7492 const uint32_t *src = (
const uint32_t *)data.p();
7493 uint32_t *dst = (uint32_t *)newdata.p();
7497 int blocks = imgsize >> 2;
7498 for (
int i = 0; i < blocks; ++i) {
7499 uint32_t v0 = *src++;
7500 uint32_t v1 = *src++;
7501 uint32_t v2 = *src++;
7502 uint32_t v3 = *src++;
7503 *dst++ = (v0 & 0x00ffffffu) | ((v1 & 0x000000ffu) << 24);
7504 *dst++ = ((v1 & 0x00ffff00u) >> 8) | ((v2 & 0x0000ffffu) << 16);
7505 *dst++ = ((v2 & 0x00ff0000u) >> 16) | ((v3 & 0x00ffffffu) << 8);
7510 uint8_t *tail = (uint8_t *)dst;
7511 for (
int i = (imgsize & ~0x3); i < imgsize; ++i) {
7512 uint32_t v = *src++;
7513 *tail++ = (v & 0x000000ffu);
7514 *tail++ = (v & 0x0000ff00u) >> 8;
7515 *tail++ = (v & 0x00ff0000u) >> 16;
7519 const uint8_t *src = (
const uint8_t *)data.p();
7520 uint8_t *dst = (uint8_t *)newdata.p();
7522 if (format ==
"RGB" && cdata->_num_components == 3) {
7523 for (
int i = 0; i < imgsize; ++i) {
7531 if (format ==
"A" && cdata->_num_components != 3) {
7533 for (
size_t p = 0; p < imgsize; ++p) {
7534 dst[p] = src[alpha];
7535 src += cdata->_num_components;
7540 for (
size_t p = 0; p < imgsize; ++p) {
7541 for (
size_t i = 0; i < format.size(); ++i) {
7542 if (format[i] ==
'B' || (cdata->_num_components <= 2 && format[i] !=
'A')) {
7544 }
else if (format[i] ==
'G') {
7546 }
else if (format[i] ==
'R') {
7548 }
else if (format[i] ==
'A') {
7550 *dst++ = src[alpha];
7554 }
else if (format[i] ==
'1') {
7560 src += cdata->_num_components;
7566 for (
size_t p = 0; p < imgsize; ++p) {
7567 for (
size_t i = 0; i < format.size(); ++i) {
7569 if (format[i] ==
'B' || (cdata->_num_components <= 2 && format[i] !=
'A')) {
7571 }
else if (format[i] ==
'G') {
7573 }
else if (format[i] ==
'R') {
7575 }
else if (format[i] ==
'A') {
7579 memset((
void*)(newdata + (p * format.size() + i) * cdata->_component_width), -1, cdata->_component_width);
7582 }
else if (format[i] ==
'1') {
7583 memset((
void*)(newdata + (p * format.size() + i) * cdata->_component_width), -1, cdata->_component_width);
7586 memset((
void*)(newdata + (p * format.size() + i) * cdata->_component_width), 0, cdata->_component_width);
7589 memcpy((
void*)(newdata + (p * format.size() + i) * cdata->_component_width),
7590 (
void*)(data + (p * cdata->_num_components + component) * cdata->_component_width),
7591 cdata->_component_width);
7601do_set_simple_ram_image(CData *cdata,
CPTA_uchar image,
int x_size,
int y_size) {
7602 nassertv(cdata->_texture_type == TT_2d_texture);
7603 size_t expected_page_size = (size_t)(x_size * y_size * 4);
7604 nassertv(image.size() == expected_page_size);
7606 cdata->_simple_x_size = x_size;
7607 cdata->_simple_y_size = y_size;
7609 cdata->_simple_ram_image._page_size = image.size();
7610 cdata->_simple_image_date_generated = (int32_t)time(
nullptr);
7611 cdata->inc_simple_image_modified();
7618do_get_expected_num_mipmap_levels(
const CData *cdata)
const {
7619 if (cdata->_texture_type == Texture::TT_buffer_texture) {
7622 int size = max(cdata->_x_size, cdata->_y_size);
7623 if (cdata->_texture_type == Texture::TT_3d_texture) {
7624 size = max(size, cdata->_z_size);
7638do_get_ram_mipmap_page_size(
const CData *cdata,
int n)
const {
7639 if (cdata->_ram_image_compression != CM_off) {
7640 if (n >= 0 && n < (
int)cdata->_ram_images.size()) {
7641 return cdata->_ram_images[n]._page_size;
7645 return do_get_expected_ram_mipmap_page_size(cdata, n);
7653do_get_expected_mipmap_x_size(
const CData *cdata,
int n)
const {
7654 int size = max(cdata->_x_size, 1);
7655 while (n > 0 && size > 1) {
7666do_get_expected_mipmap_y_size(
const CData *cdata,
int n)
const {
7667 int size = max(cdata->_y_size, 1);
7668 while (n > 0 && size > 1) {
7679do_get_expected_mipmap_z_size(
const CData *cdata,
int n)
const {
7683 if (cdata->_texture_type == Texture::TT_3d_texture) {
7684 int size = max(cdata->_z_size, 1);
7685 while (n > 0 && size > 1) {
7692 return cdata->_z_size;
7700do_clear_simple_ram_image(CData *cdata) {
7701 cdata->_simple_x_size = 0;
7702 cdata->_simple_y_size = 0;
7703 cdata->_simple_ram_image._image.clear();
7704 cdata->_simple_ram_image._page_size = 0;
7705 cdata->_simple_image_date_generated = 0;
7710 cdata->inc_simple_image_modified();
7717do_clear_ram_mipmap_images(CData *cdata) {
7718 if (!cdata->_ram_images.empty()) {
7719 cdata->_ram_images.erase(cdata->_ram_images.begin() + 1, cdata->_ram_images.end());
7729do_generate_ram_mipmap_images(CData *cdata,
bool allow_recompress) {
7730 nassertv(do_has_ram_image(cdata));
7732 if (do_get_expected_num_mipmap_levels(cdata) == 1) {
7737 RamImage orig_compressed_image;
7738 CompressionMode orig_compression_mode = CM_off;
7740 if (cdata->_ram_image_compression != CM_off) {
7744 orig_compressed_image = cdata->_ram_images[0];
7745 orig_compression_mode = cdata->_ram_image_compression;
7748 do_get_uncompressed_ram_image(cdata);
7750 if (cdata->_ram_image_compression != CM_off) {
7752 <<
"Cannot generate mipmap levels for image with compression "
7753 << cdata->_ram_image_compression <<
"\n";
7758 do_clear_ram_mipmap_images(cdata);
7760 if (gobj_cat.is_debug()) {
7762 <<
"Generating mipmap levels for " << *
this <<
"\n";
7765 if (cdata->_texture_type == Texture::TT_3d_texture && cdata->_z_size != 1) {
7767 int x_size = cdata->_x_size;
7768 int y_size = cdata->_y_size;
7769 int z_size = cdata->_z_size;
7771 while (x_size > 1 || y_size > 1 || z_size > 1) {
7772 cdata->_ram_images.push_back(RamImage());
7773 do_filter_3d_mipmap_level(cdata, cdata->_ram_images[n + 1], cdata->_ram_images[n],
7774 x_size, y_size, z_size);
7775 x_size = max(x_size >> 1, 1);
7776 y_size = max(y_size >> 1, 1);
7777 z_size = max(z_size >> 1, 1);
7783 int x_size = cdata->_x_size;
7784 int y_size = cdata->_y_size;
7786 while (x_size > 1 || y_size > 1) {
7787 cdata->_ram_images.push_back(RamImage());
7788 do_filter_2d_mipmap_pages(cdata, cdata->_ram_images[n + 1], cdata->_ram_images[n],
7790 x_size = max(x_size >> 1, 1);
7791 y_size = max(y_size >> 1, 1);
7796 if (orig_compression_mode != CM_off && allow_recompress) {
7802 nassertv(cdata->_ram_images.size() > 1);
7803 int l0_x_size = cdata->_x_size;
7804 int l0_y_size = cdata->_y_size;
7805 int l0_z_size = cdata->_z_size;
7806 cdata->_x_size = do_get_expected_mipmap_x_size(cdata, 1);
7807 cdata->_y_size = do_get_expected_mipmap_y_size(cdata, 1);
7808 cdata->_z_size = do_get_expected_mipmap_z_size(cdata, 1);
7809 RamImage uncompressed_image = cdata->_ram_images[0];
7810 cdata->_ram_images.erase(cdata->_ram_images.begin());
7812 bool success = do_compress_ram_image(cdata, orig_compression_mode, QL_default,
nullptr);
7815 if (gobj_cat.is_debug()) {
7817 <<
"Compressed " << get_name() <<
" generated mipmaps with "
7818 << cdata->_ram_image_compression <<
"\n";
7820 cdata->_ram_images.insert(cdata->_ram_images.begin(), orig_compressed_image);
7822 cdata->_ram_images.insert(cdata->_ram_images.begin(), uncompressed_image);
7824 cdata->_x_size = l0_x_size;
7825 cdata->_y_size = l0_y_size;
7826 cdata->_z_size = l0_z_size;
7834do_set_pad_size(CData *cdata,
int x,
int y,
int z) {
7835 if (x > cdata->_x_size) {
7838 if (y > cdata->_y_size) {
7841 if (z > cdata->_z_size) {
7845 cdata->_pad_x_size = x;
7846 cdata->_pad_y_size = y;
7847 cdata->_pad_z_size = z;
7856do_can_reload(
const CData *cdata)
const {
7857 return (cdata->_loaded_from_image && !cdata->_fullpath.empty());
7864do_reload(CData *cdata) {
7865 if (do_can_reload(cdata)) {
7866 do_clear_ram_image(cdata);
7867 do_reload_ram_image(cdata,
true);
7868 if (do_has_ram_image(cdata)) {
7870 cdata->inc_image_modified();
7886do_has_bam_rawdata(
const CData *cdata)
const {
7887 return do_has_ram_image(cdata);
7895do_get_bam_rawdata(CData *cdata) {
7896 do_get_ram_image(cdata);
7904convert_from_pnmimage(PTA_uchar &image,
size_t page_size,
7905 int row_stride,
int x,
int y,
int z,
7906 const PNMImage &pnmimage,
int num_components,
7907 int component_width) {
7911 int pixel_size = num_components * component_width;
7914 if (row_stride == 0) {
7915 row_stride = x_size;
7917 row_skip = (row_stride - x_size) * pixel_size;
7918 nassertv(row_skip >= 0);
7921 bool is_grayscale = (num_components == 1 || num_components == 2);
7922 bool has_alpha = (num_components == 2 || num_components == 4);
7923 bool img_has_alpha = pnmimage.
has_alpha();
7925 int idx = page_size * z;
7926 nassertv(idx + page_size <= image.size());
7927 unsigned char *p = &image[idx];
7929 if (x != 0 || y != 0) {
7930 p += (row_stride * y + x) * pixel_size;
7933 if (maxval == 255 && component_width == 1) {
7938 switch (num_components) {
7940 for (
int j = y_size-1; j >= 0; j--) {
7941 const xel *row = array + j * x_size;
7942 for (
int i = 0; i < x_size; i++) {
7943 *p++ = (uchar)PPM_GETB(row[i]);
7950 if (img_has_alpha) {
7952 for (
int j = y_size-1; j >= 0; j--) {
7953 const xel *row = array + j * x_size;
7954 const xelval *alpha_row = alpha + j * x_size;
7955 for (
int i = 0; i < x_size; i++) {
7956 *p++ = (uchar)PPM_GETB(row[i]);
7957 *p++ = (uchar)alpha_row[i];
7962 for (
int j = y_size-1; j >= 0; j--) {
7963 const xel *row = array + j * x_size;
7964 for (
int i = 0; i < x_size; i++) {
7965 *p++ = (uchar)PPM_GETB(row[i]);
7974 for (
int j = y_size-1; j >= 0; j--) {
7975 const xel *row = array + j * x_size;
7976 for (
int i = 0; i < x_size; i++) {
7977 *p++ = (uchar)PPM_GETB(row[i]);
7978 *p++ = (uchar)PPM_GETG(row[i]);
7979 *p++ = (uchar)PPM_GETR(row[i]);
7986 if (img_has_alpha) {
7988 for (
int j = y_size-1; j >= 0; j--) {
7989 const xel *row = array + j * x_size;
7990 const xelval *alpha_row = alpha + j * x_size;
7991 for (
int i = 0; i < x_size; i++) {
7992 *p++ = (uchar)PPM_GETB(row[i]);
7993 *p++ = (uchar)PPM_GETG(row[i]);
7994 *p++ = (uchar)PPM_GETR(row[i]);
7995 *p++ = (uchar)alpha_row[i];
8000 for (
int j = y_size-1; j >= 0; j--) {
8001 const xel *row = array + j * x_size;
8002 for (
int i = 0; i < x_size; i++) {
8003 *p++ = (uchar)PPM_GETB(row[i]);
8004 *p++ = (uchar)PPM_GETG(row[i]);
8005 *p++ = (uchar)PPM_GETR(row[i]);
8014 nassertv(num_components >= 1 && num_components <= 4);
8018 }
else if (maxval == 65535 && component_width == 2) {
8021 for (
int j = y_size-1; j >= 0; j--) {
8022 for (
int i = 0; i < x_size; i++) {
8028 store_unscaled_short(p, pnmimage.
get_red_val(i, j));
8031 if (img_has_alpha) {
8034 store_unscaled_short(p, 65535);
8041 }
else if (component_width == 1) {
8045 double scale = 255.0 / (double)maxval;
8047 for (
int j = y_size-1; j >= 0; j--) {
8048 for (
int i = 0; i < x_size; i++) {
8050 store_scaled_byte(p, pnmimage.
get_gray_val(i, j), scale);
8052 store_scaled_byte(p, pnmimage.
get_blue_val(i, j), scale);
8054 store_scaled_byte(p, pnmimage.
get_red_val(i, j), scale);
8057 if (img_has_alpha) {
8060 store_unscaled_byte(p, 255);
8070 double scale = 65535.0 / (double)maxval;
8072 for (
int j = y_size-1; j >= 0; j--) {
8073 for (
int i = 0; i < x_size; i++) {
8075 store_scaled_short(p, pnmimage.
get_gray_val(i, j), scale);
8077 store_scaled_short(p, pnmimage.
get_blue_val(i, j), scale);
8079 store_scaled_short(p, pnmimage.
get_red_val(i, j), scale);
8082 if (img_has_alpha) {
8085 store_unscaled_short(p, 65535);
8099convert_from_pfm(PTA_uchar &image,
size_t page_size,
int z,
8100 const PfmFile &pfm,
int num_components,
int component_width) {
8101 nassertv(component_width == 4);
8105 int idx = page_size * z;
8106 nassertv(idx + page_size <= image.size());
8107 PN_float32 *p = (PN_float32 *)&image[idx];
8109 switch (num_components) {
8112 for (
int j = y_size-1; j >= 0; j--) {
8113 for (
int i = 0; i < x_size; i++) {
8123 for (
int j = y_size-1; j >= 0; j--) {
8124 for (
int i = 0; i < x_size; i++) {
8136 for (
int j = y_size-1; j >= 0; j--) {
8137 for (
int i = 0; i < x_size; i++) {
8150 for (
int j = y_size-1; j >= 0; j--) {
8151 for (
int i = 0; i < x_size; i++) {
8163 nassert_raise(
"unexpected channel count");
8167 nassertv((
unsigned char *)p == &image[idx] + page_size);
8175convert_to_pnmimage(
PNMImage &pnmimage,
int x_size,
int y_size,
8176 int num_components, ComponentType component_type,
8177 bool is_srgb,
CPTA_uchar image,
size_t page_size,
int z) {
8178 xelval maxval = 0xff;
8179 if (component_type != T_unsigned_byte && component_type != T_byte) {
8182 ColorSpace color_space =
is_srgb ? CS_sRGB : CS_linear;
8183 pnmimage.
clear(x_size, y_size, num_components, maxval,
nullptr, color_space);
8187 int idx = page_size * z;
8188 nassertr(idx + page_size <= image.size(),
false);
8193 switch (component_type) {
8194 case T_unsigned_byte:
8196 const unsigned char *p = &image[idx];
8198 for (
int j = y_size-1; j >= 0; j--) {
8199 xel *row = array + j * x_size;
8200 xelval *alpha_row = alpha + j * x_size;
8201 for (
int i = 0; i < x_size; i++) {
8202 PPM_PUTB(row[i], *p++);
8203 alpha_row[i] = *p++;
8207 for (
int j = y_size-1; j >= 0; j--) {
8208 xel *row = array + j * x_size;
8209 for (
int i = 0; i < x_size; i++) {
8210 PPM_PUTB(row[i], *p++);
8214 nassertr(p == &image[idx] + page_size,
false);
8216 const unsigned char *p = &image[idx];
8218 for (
int j = y_size-1; j >= 0; j--) {
8219 xel *row = array + j * x_size;
8220 xelval *alpha_row = alpha + j * x_size;
8221 for (
int i = 0; i < x_size; i++) {
8222 PPM_PUTB(row[i], *p++);
8223 PPM_PUTG(row[i], *p++);
8224 PPM_PUTR(row[i], *p++);
8225 alpha_row[i] = *p++;
8229 for (
int j = y_size-1; j >= 0; j--) {
8230 xel *row = array + j * x_size;
8231 for (
int i = 0; i < x_size; i++) {
8232 PPM_PUTB(row[i], *p++);
8233 PPM_PUTG(row[i], *p++);
8234 PPM_PUTR(row[i], *p++);
8238 nassertr(p == &image[idx] + page_size,
false);
8242 case T_unsigned_short:
8244 const uint16_t *p = (
const uint16_t *)&image[idx];
8246 for (
int j = y_size-1; j >= 0; j--) {
8247 xel *row = array + j * x_size;
8248 xelval *alpha_row = alpha + j * x_size;
8249 for (
int i = 0; i < x_size; i++) {
8250 PPM_PUTB(row[i], *p++);
8251 if (!is_grayscale) {
8252 PPM_PUTG(row[i], *p++);
8253 PPM_PUTR(row[i], *p++);
8256 alpha_row[i] = *p++;
8260 nassertr((
const unsigned char *)p == &image[idx] + page_size,
false);
8264 case T_unsigned_int:
8266 const uint32_t *p = (
const uint32_t *)&image[idx];
8268 for (
int j = y_size-1; j >= 0; j--) {
8269 xel *row = array + j * x_size;
8270 xelval *alpha_row = alpha + j * x_size;
8271 for (
int i = 0; i < x_size; i++) {
8272 PPM_PUTB(row[i], (*p++) >> 16u);
8273 if (!is_grayscale) {
8274 PPM_PUTG(row[i], (*p++) >> 16u);
8275 PPM_PUTR(row[i], (*p++) >> 16u);
8278 alpha_row[i] = (*p++) >> 16u;
8282 nassertr((
const unsigned char *)p == &image[idx] + page_size,
false);
8288 const unsigned char *p = &image[idx];
8290 for (
int j = y_size-1; j >= 0; j--) {
8291 for (
int i = 0; i < x_size; i++) {
8292 pnmimage.
set_blue(i, j, get_half_float(p));
8293 if (!is_grayscale) {
8294 pnmimage.
set_green(i, j, get_half_float(p));
8295 pnmimage.
set_red(i, j, get_half_float(p));
8298 pnmimage.
set_alpha(i, j, get_half_float(p));
8302 nassertr(p == &image[idx] + page_size,
false);
8318convert_to_pfm(
PfmFile &pfm,
int x_size,
int y_size,
8319 int num_components,
int component_width,
8321 nassertr(component_width == 4,
false);
8322 pfm.
clear(x_size, y_size, num_components);
8324 int idx = page_size * z;
8325 nassertr(idx + page_size <= image.size(),
false);
8326 const PN_float32 *p = (
const PN_float32 *)&image[idx];
8328 switch (num_components) {
8330 for (
int j = y_size-1; j >= 0; j--) {
8331 for (
int i = 0; i < x_size; i++) {
8339 for (
int j = y_size-1; j >= 0; j--) {
8340 for (
int i = 0; i < x_size; i++) {
8350 for (
int j = y_size-1; j >= 0; j--) {
8351 for (
int i = 0; i < x_size; i++) {
8362 for (
int j = y_size-1; j >= 0; j--) {
8363 for (
int i = 0; i < x_size; i++) {
8374 nassert_raise(
"unexpected channel count");
8378 nassertr((
unsigned char *)p == &image[idx] + page_size,
false);
8386read_dds_level_bgr8(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
8388 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8389 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8391 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
8392 size_t row_bytes = x_size * 3;
8393 PTA_uchar image = PTA_uchar::empty_array(size);
8394 for (
int y = y_size - 1; y >= 0; --y) {
8395 unsigned char *p = image.p() + y * row_bytes;
8396 nassertr(p + row_bytes <= image.p() + size, PTA_uchar());
8397 in.read((
char *)p, row_bytes);
8407read_dds_level_rgb8(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
8409 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8410 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8412 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
8413 size_t row_bytes = x_size * 3;
8414 PTA_uchar image = PTA_uchar::empty_array(size);
8415 for (
int y = y_size - 1; y >= 0; --y) {
8416 unsigned char *p = image.p() + y * row_bytes;
8417 nassertr(p + row_bytes <= image.p() + size, PTA_uchar());
8418 in.read((
char *)p, row_bytes);
8421 for (
int x = 0; x < x_size; ++x) {
8422 unsigned char r = p[0];
8427 nassertr(p <= image.p() + size, PTA_uchar());
8437read_dds_level_abgr8(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
8439 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8440 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8442 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
8443 size_t row_bytes = x_size * 4;
8444 PTA_uchar image = PTA_uchar::empty_array(size);
8445 for (
int y = y_size - 1; y >= 0; --y) {
8446 unsigned char *p = image.p() + y * row_bytes;
8447 in.read((
char *)p, row_bytes);
8449 uint32_t *pw = (uint32_t *)p;
8450 for (
int x = 0; x < x_size; ++x) {
8452#ifdef WORDS_BIGENDIAN
8454 w = ((w & 0xff00) << 16) | ((w & 0xff000000U) >> 16) | (w & 0xff00ff);
8457 w = ((w & 0xff) << 16) | ((w & 0xff0000) >> 16) | (w & 0xff00ff00U);
8462 nassertr((
unsigned char *)pw <= image.p() + size, PTA_uchar());
8472read_dds_level_rgba8(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
8474 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8475 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8477 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
8478 size_t row_bytes = x_size * 4;
8479 PTA_uchar image = PTA_uchar::empty_array(size);
8480 for (
int y = y_size - 1; y >= 0; --y) {
8481 unsigned char *p = image.p() + y * row_bytes;
8482 nassertr(p + row_bytes <= image.p() + size, PTA_uchar());
8483 in.read((
char *)p, row_bytes);
8493read_dds_level_abgr16(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
8495 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8496 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8498 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
8499 size_t row_bytes = x_size * 8;
8500 PTA_uchar image = PTA_uchar::empty_array(size);
8501 for (
int y = y_size - 1; y >= 0; --y) {
8502 unsigned char *p = image.p() + y * row_bytes;
8503 in.read((
char *)p, row_bytes);
8505 uint16_t *pw = (uint16_t *)p;
8506 for (
int x = 0; x < x_size; ++x) {
8510 nassertr((
unsigned char *)pw <= image.p() + size, PTA_uchar());
8520read_dds_level_abgr32(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
8522 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8523 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8525 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
8526 size_t row_bytes = x_size * 16;
8527 nassertr(row_bytes * y_size == size, PTA_uchar());
8528 PTA_uchar image = PTA_uchar::empty_array(size);
8529 for (
int y = y_size - 1; y >= 0; --y) {
8530 unsigned char *p = image.p() + y * row_bytes;
8531 in.read((
char *)p, row_bytes);
8533 uint32_t *pw = (uint32_t *)p;
8534 for (
int x = 0; x < x_size; ++x) {
8538 nassertr((
unsigned char *)pw <= image.p() + size, PTA_uchar());
8548read_dds_level_raw(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
8549 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8550 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8552 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
8553 size_t row_bytes = x_size * cdata->_num_components * cdata->_component_width;
8554 nassertr(row_bytes * y_size == size, PTA_uchar());
8555 PTA_uchar image = PTA_uchar::empty_array(size);
8556 for (
int y = y_size - 1; y >= 0; --y) {
8557 unsigned char *p = image.p() + y * row_bytes;
8558 in.read((
char *)p, row_bytes);
8569read_dds_level_generic_uncompressed(
Texture *tex, CData *cdata,
const DDSHeader &header,
8570 int n, istream &in) {
8571 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8572 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8574 int pitch = (x_size * header.pf.rgb_bitcount) / 8;
8581 pitch = ((pitch + 3) / 4) * 4;
8582 if (header.dds_flags & DDSD_PITCH) {
8583 pitch = header.pitch;
8587 int bpp = header.pf.rgb_bitcount / 8;
8588 int skip_bytes = pitch - (bpp * x_size);
8589 nassertr(skip_bytes >= 0, PTA_uchar());
8591 unsigned int r_mask = header.pf.r_mask;
8592 unsigned int g_mask = header.pf.g_mask;
8593 unsigned int b_mask = header.pf.b_mask;
8594 unsigned int a_mask = header.pf.a_mask;
8605 unsigned int r_scale = 0;
8607 r_scale = 0xff000000 / (r_mask >> r_shift);
8609 unsigned int g_scale = 0;
8611 g_scale = 0xff000000 / (g_mask >> g_shift);
8613 unsigned int b_scale = 0;
8615 b_scale = 0xff000000 / (b_mask >> b_shift);
8617 unsigned int a_scale = 0;
8619 a_scale = 0xff000000 / (a_mask >> a_shift);
8622 bool add_alpha =
has_alpha(cdata->_format);
8624 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
8625 size_t row_bytes = x_size * cdata->_num_components;
8626 PTA_uchar image = PTA_uchar::empty_array(size);
8627 for (
int y = y_size - 1; y >= 0; --y) {
8628 unsigned char *p = image.p() + y * row_bytes;
8629 for (
int x = 0; x < x_size; ++x) {
8632 unsigned int pixel = 0;
8634 for (
int bi = 0; bi < bpp; ++bi) {
8635 unsigned int ch = (
unsigned char)in.get();
8636 pixel |= (ch << shift);
8641 unsigned int r = (((
pixel & r_mask) >> r_shift) * r_scale) >> 24;
8642 unsigned int g = (((
pixel & g_mask) >> g_shift) * g_scale) >> 24;
8643 unsigned int b = (((
pixel & b_mask) >> b_shift) * b_scale) >> 24;
8646 store_unscaled_byte(p, b);
8647 store_unscaled_byte(p, g);
8648 store_unscaled_byte(p, r);
8650 unsigned int a = (((
pixel & a_mask) >> a_shift) * a_scale) >> 24;
8651 store_unscaled_byte(p, a);
8654 nassertr(p <= image.p() + size, PTA_uchar());
8655 for (
int bi = 0; bi < skip_bytes; ++bi) {
8668read_dds_level_luminance_uncompressed(
Texture *tex, CData *cdata,
const DDSHeader &header,
8669 int n, istream &in) {
8670 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8671 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8673 int pitch = (x_size * header.pf.rgb_bitcount) / 8;
8680 pitch = ((pitch + 3) / 4) * 4;
8681 if (header.dds_flags & DDSD_PITCH) {
8682 pitch = header.pitch;
8686 int bpp = header.pf.rgb_bitcount / 8;
8687 int skip_bytes = pitch - (bpp * x_size);
8688 nassertr(skip_bytes >= 0, PTA_uchar());
8690 unsigned int r_mask = header.pf.r_mask;
8691 unsigned int a_mask = header.pf.a_mask;
8700 unsigned int r_scale = 0;
8702 r_scale = 0xff000000 / (r_mask >> r_shift);
8704 unsigned int a_scale = 0;
8706 a_scale = 0xff000000 / (a_mask >> a_shift);
8709 bool add_alpha =
has_alpha(cdata->_format);
8711 size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
8712 size_t row_bytes = x_size * cdata->_num_components;
8713 PTA_uchar image = PTA_uchar::empty_array(size);
8714 for (
int y = y_size - 1; y >= 0; --y) {
8715 unsigned char *p = image.p() + y * row_bytes;
8716 for (
int x = 0; x < x_size; ++x) {
8719 unsigned int pixel = 0;
8721 for (
int bi = 0; bi < bpp; ++bi) {
8722 unsigned int ch = (
unsigned char)in.get();
8723 pixel |= (ch << shift);
8727 unsigned int r = (((
pixel & r_mask) >> r_shift) * r_scale) >> 24;
8730 store_unscaled_byte(p, r);
8732 unsigned int a = (((
pixel & a_mask) >> a_shift) * a_scale) >> 24;
8733 store_unscaled_byte(p, a);
8736 nassertr(p <= image.p() + size, PTA_uchar());
8737 for (
int bi = 0; bi < skip_bytes; ++bi) {
8749read_dds_level_bc1(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
8750 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8751 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8753 static const int div = 4;
8754 static const int block_bytes = 8;
8758 int num_cols = max(div, x_size) / div;
8759 int num_rows = max(div, y_size) / div;
8760 int row_length = num_cols * block_bytes;
8761 int linear_size = row_length * num_rows;
8764 if (header.dds_flags & DDSD_LINEARSIZE) {
8765 nassertr(linear_size == (
int)header.pitch, PTA_uchar());
8769 PTA_uchar image = PTA_uchar::empty_array(linear_size);
8775 for (
int ri = num_rows - 1; ri >= 0; --ri) {
8776 unsigned char *p = image.p() + row_length * ri;
8777 in.read((
char *)p, row_length);
8779 for (
int ci = 0; ci < num_cols; ++ci) {
8782 uint32_t *cells = (uint32_t *)p;
8783 uint32_t w = cells[1];
8784 w = ((w & 0xff) << 24) | ((w & 0xff00) << 8) | ((w & 0xff0000) >> 8) | ((w & 0xff000000U) >> 24);
8791 }
else if (y_size >= 2) {
8793 unsigned char *p = image.p();
8794 in.read((
char *)p, row_length);
8796 for (
int ci = 0; ci < num_cols; ++ci) {
8797 uint32_t *cells = (uint32_t *)p;
8798 uint32_t w = cells[1];
8799 w = ((w & 0xff) << 8) | ((w & 0xff00) >> 8);
8805 }
else if (y_size >= 1) {
8807 unsigned char *p = image.p();
8808 in.read((
char *)p, row_length);
8818read_dds_level_bc2(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
8819 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8820 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8822 static const int div = 4;
8823 static const int block_bytes = 16;
8828 int num_cols = max(div, x_size) / div;
8829 int num_rows = max(div, y_size) / div;
8830 int row_length = num_cols * block_bytes;
8831 int linear_size = row_length * num_rows;
8834 if (header.dds_flags & DDSD_LINEARSIZE) {
8835 nassertr(linear_size == (
int)header.pitch, PTA_uchar());
8839 PTA_uchar image = PTA_uchar::empty_array(linear_size);
8845 for (
int ri = num_rows - 1; ri >= 0; --ri) {
8846 unsigned char *p = image.p() + row_length * ri;
8847 in.read((
char *)p, row_length);
8849 for (
int ci = 0; ci < num_cols; ++ci) {
8852 uint32_t *cells = (uint32_t *)p;
8855 uint32_t w0 = cells[0];
8856 uint32_t w1 = cells[1];
8857 w0 = ((w0 & 0xffff) << 16) | ((w0 & 0xffff0000U) >> 16);
8858 w1 = ((w1 & 0xffff) << 16) | ((w1 & 0xffff0000U) >> 16);
8864 uint32_t w = cells[3];
8865 w = ((w & 0xff) << 24) | ((w & 0xff00) << 8) | ((w & 0xff0000) >> 8) | ((w & 0xff000000U) >> 24);
8872 }
else if (y_size >= 2) {
8874 unsigned char *p = image.p();
8875 in.read((
char *)p, row_length);
8877 for (
int ci = 0; ci < num_cols; ++ci) {
8878 uint32_t *cells = (uint32_t *)p;
8880 uint32_t w0 = cells[0];
8881 w0 = ((w0 & 0xffff) << 16) | ((w0 & 0xffff0000U) >> 16);
8884 uint32_t w = cells[3];
8885 w = ((w & 0xff) << 8) | ((w & 0xff00) >> 8);
8891 }
else if (y_size >= 1) {
8893 unsigned char *p = image.p();
8894 in.read((
char *)p, row_length);
8904read_dds_level_bc3(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
8905 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
8906 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
8908 static const int div = 4;
8909 static const int block_bytes = 16;
8914 int num_cols = max(div, x_size) / div;
8915 int num_rows = max(div, y_size) / div;
8916 int row_length = num_cols * block_bytes;
8917 int linear_size = row_length * num_rows;
8920 if (header.dds_flags & DDSD_LINEARSIZE) {
8921 nassertr(linear_size == (
int)header.pitch, PTA_uchar());
8925 PTA_uchar image = PTA_uchar::empty_array(linear_size);
8931 for (
int ri = num_rows - 1; ri >= 0; --ri) {
8932 unsigned char *p = image.p() + row_length * ri;
8933 in.read((
char *)p, row_length);
8935 for (
int ci = 0; ci < num_cols; ++ci) {
8938 uint32_t *cells = (uint32_t *)p;
8942 unsigned char p2 = p[2];
8943 unsigned char p3 = p[3];
8944 unsigned char p4 = p[4];
8945 unsigned char p5 = p[5];
8946 unsigned char p6 = p[6];
8947 unsigned char p7 = p[7];
8949 p[2] = ((p7 & 0xf) << 4) | ((p6 & 0xf0) >> 4);
8950 p[3] = ((p5 & 0xf) << 4) | ((p7 & 0xf0) >> 4);
8951 p[4] = ((p6 & 0xf) << 4) | ((p5 & 0xf0) >> 4);
8952 p[5] = ((p4 & 0xf) << 4) | ((p3 & 0xf0) >> 4);
8953 p[6] = ((p2 & 0xf) << 4) | ((p4 & 0xf0) >> 4);
8954 p[7] = ((p3 & 0xf) << 4) | ((p2 & 0xf0) >> 4);
8958 uint32_t w = cells[3];
8959 w = ((w & 0xff) << 24) | ((w & 0xff00) << 8) | ((w & 0xff0000) >> 8) | ((w & 0xff000000U) >> 24);
8966 }
else if (y_size >= 2) {
8968 unsigned char *p = image.p();
8969 in.read((
char *)p, row_length);
8971 for (
int ci = 0; ci < num_cols; ++ci) {
8972 uint32_t *cells = (uint32_t *)p;
8974 unsigned char p2 = p[2];
8975 unsigned char p3 = p[3];
8976 unsigned char p4 = p[4];
8978 p[2] = ((p4 & 0xf) << 4) | ((p3 & 0xf0) >> 4);
8979 p[3] = ((p2 & 0xf) << 4) | ((p4 & 0xf0) >> 4);
8980 p[4] = ((p3 & 0xf) << 4) | ((p2 & 0xf0) >> 4);
8982 uint32_t w0 = cells[0];
8983 w0 = ((w0 & 0xffff) << 16) | ((w0 & 0xffff0000U) >> 16);
8986 uint32_t w = cells[3];
8987 w = ((w & 0xff) << 8) | ((w & 0xff00) >> 8);
8993 }
else if (y_size >= 1) {
8995 unsigned char *p = image.p();
8996 in.read((
char *)p, row_length);
9006read_dds_level_bc4(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
9007 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
9008 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
9010 static const int div = 4;
9011 static const int block_bytes = 8;
9015 int num_cols = max(div, x_size) / div;
9016 int num_rows = max(div, y_size) / div;
9017 int row_length = num_cols * block_bytes;
9018 int linear_size = row_length * num_rows;
9021 if (header.dds_flags & DDSD_LINEARSIZE) {
9022 nassertr(linear_size == (
int)header.pitch, PTA_uchar());
9026 PTA_uchar image = PTA_uchar::empty_array(linear_size);
9032 for (
int ri = num_rows - 1; ri >= 0; --ri) {
9033 unsigned char *p = image.p() + row_length * ri;
9034 in.read((
char *)p, row_length);
9036 for (
int ci = 0; ci < num_cols; ++ci) {
9041 unsigned char p2 = p[2];
9042 unsigned char p3 = p[3];
9043 unsigned char p4 = p[4];
9044 unsigned char p5 = p[5];
9045 unsigned char p6 = p[6];
9046 unsigned char p7 = p[7];
9048 p[2] = ((p7 & 0xf) << 4) | ((p6 & 0xf0) >> 4);
9049 p[3] = ((p5 & 0xf) << 4) | ((p7 & 0xf0) >> 4);
9050 p[4] = ((p6 & 0xf) << 4) | ((p5 & 0xf0) >> 4);
9051 p[5] = ((p4 & 0xf) << 4) | ((p3 & 0xf0) >> 4);
9052 p[6] = ((p2 & 0xf) << 4) | ((p4 & 0xf0) >> 4);
9053 p[7] = ((p3 & 0xf) << 4) | ((p2 & 0xf0) >> 4);
9059 }
else if (y_size >= 2) {
9061 unsigned char *p = image.p();
9062 in.read((
char *)p, row_length);
9064 for (
int ci = 0; ci < num_cols; ++ci) {
9065 unsigned char p2 = p[2];
9066 unsigned char p3 = p[3];
9067 unsigned char p4 = p[4];
9069 p[2] = ((p4 & 0xf) << 4) | ((p3 & 0xf0) >> 4);
9070 p[3] = ((p2 & 0xf) << 4) | ((p4 & 0xf0) >> 4);
9071 p[4] = ((p3 & 0xf) << 4) | ((p2 & 0xf0) >> 4);
9076 }
else if (y_size >= 1) {
9078 unsigned char *p = image.p();
9079 in.read((
char *)p, row_length);
9089read_dds_level_bc5(
Texture *tex, CData *cdata,
const DDSHeader &header,
int n, istream &in) {
9090 int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
9091 int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
9095 int num_cols = max(4, x_size) / 2;
9096 int num_rows = max(4, y_size) / 4;
9097 int row_length = num_cols * 8;
9098 int linear_size = row_length * num_rows;
9101 if (header.dds_flags & DDSD_LINEARSIZE) {
9102 nassertr(linear_size == (
int)header.pitch, PTA_uchar());
9106 PTA_uchar image = PTA_uchar::empty_array(linear_size);
9112 for (
int ri = num_rows - 1; ri >= 0; --ri) {
9113 unsigned char *p = image.p() + row_length * ri;
9114 in.read((
char *)p, row_length);
9116 for (
int ci = 0; ci < num_cols; ++ci) {
9121 unsigned char p2 = p[2];
9122 unsigned char p3 = p[3];
9123 unsigned char p4 = p[4];
9124 unsigned char p5 = p[5];
9125 unsigned char p6 = p[6];
9126 unsigned char p7 = p[7];
9128 p[2] = ((p7 & 0xf) << 4) | ((p6 & 0xf0) >> 4);
9129 p[3] = ((p5 & 0xf) << 4) | ((p7 & 0xf0) >> 4);
9130 p[4] = ((p6 & 0xf) << 4) | ((p5 & 0xf0) >> 4);
9131 p[5] = ((p4 & 0xf) << 4) | ((p3 & 0xf0) >> 4);
9132 p[6] = ((p2 & 0xf) << 4) | ((p4 & 0xf0) >> 4);
9133 p[7] = ((p3 & 0xf) << 4) | ((p2 & 0xf0) >> 4);
9139 }
else if (y_size >= 2) {
9141 unsigned char *p = image.p();
9142 in.read((
char *)p, row_length);
9144 for (
int ci = 0; ci < num_cols; ++ci) {
9145 unsigned char p2 = p[2];
9146 unsigned char p3 = p[3];
9147 unsigned char p4 = p[4];
9149 p[2] = ((p4 & 0xf) << 4) | ((p3 & 0xf0) >> 4);
9150 p[3] = ((p2 & 0xf) << 4) | ((p4 & 0xf0) >> 4);
9151 p[4] = ((p3 & 0xf) << 4) | ((p2 & 0xf0) >> 4);
9156 }
else if (y_size >= 1) {
9158 unsigned char *p = image.p();
9159 in.read((
char *)p, row_length);
9173 PreparedViews::iterator pvi;
9174 pvi = _prepared_views.find(prepared_objects);
9175 if (pvi != _prepared_views.end()) {
9176 Contexts &contexts = (*pvi).second;
9177 Contexts::iterator ci;
9178 ci = contexts.find(view);
9179 if (ci != contexts.end()) {
9183 if (contexts.empty()) {
9184 _prepared_views.erase(pvi);
9194consider_downgrade(
PNMImage &pnmimage,
int num_channels,
const string &name) {
9203 <<
"Downgrading " << name <<
" from "
9205 << num_channels <<
".\n";
9230 for (
int yi = 0; yi < a.
get_y_size(); ++yi) {
9231 const xel *a_row = a_array + yi * x_size;
9232 const xel *b_row = b_array + yi * x_size;
9233 const xelval *a_alpha_row = a_alpha + yi * x_size;
9234 const xelval *b_alpha_row = b_alpha + yi * x_size;
9235 for (
int xi = 0; xi < x_size; ++xi) {
9236 delta += abs(PPM_GETR(a_row[xi]) - PPM_GETR(b_row[xi]));
9237 delta += abs(PPM_GETG(a_row[xi]) - PPM_GETG(b_row[xi]));
9238 delta += abs(PPM_GETB(a_row[xi]) - PPM_GETB(b_row[xi]));
9239 delta += abs(a_alpha_row[xi] - b_alpha_row[xi]);
9244 return (average_delta <= simple_image_threshold);
9257do_filter_2d_mipmap_pages(
const CData *cdata,
9258 Texture::RamImage &to,
const Texture::RamImage &from,
9259 int x_size,
int y_size)
const {
9260 Filter2DComponent *filter_component;
9261 Filter2DComponent *filter_alpha;
9263 if (
is_srgb(cdata->_format)) {
9266 nassertv(cdata->_component_type == T_unsigned_byte);
9268 if (has_sse2_sRGB_encode()) {
9269 filter_component = &filter_2d_unsigned_byte_srgb_sse2;
9271 filter_component = &filter_2d_unsigned_byte_srgb;
9275 filter_alpha = &filter_2d_unsigned_byte;
9278 switch (cdata->_component_type) {
9279 case T_unsigned_byte:
9280 filter_component = &filter_2d_unsigned_byte;
9283 case T_unsigned_short:
9284 filter_component = &filter_2d_unsigned_short;
9288 filter_component = &filter_2d_float;
9293 <<
"Unable to generate mipmaps for 2D texture with component type "
9294 << cdata->_component_type <<
"!";
9297 filter_alpha = filter_component;
9300 size_t pixel_size = cdata->_num_components * cdata->_component_width;
9301 size_t row_size = (size_t)x_size * pixel_size;
9303 int to_x_size = max(x_size >> 1, 1);
9304 int to_y_size = max(y_size >> 1, 1);
9306 size_t to_row_size = (size_t)to_x_size * pixel_size;
9307 to._page_size = (size_t)to_y_size * to_row_size;
9308 to._image = PTA_uchar::empty_array(to._page_size * cdata->_z_size * cdata->_num_views, get_class_type());
9311 int num_color_components = cdata->_num_components;
9313 --num_color_components;
9316 int num_pages = cdata->_z_size * cdata->_num_views;
9317 for (
int z = 0; z < num_pages; ++z) {
9319 unsigned char *p = to._image.p() + z * to._page_size;
9320 nassertv(p <= to._image.p() + to._image.size() + to._page_size);
9321 const unsigned char *q = from._image.p() + z * from._page_size;
9322 nassertv(q <= from._image.p() + from._image.size() + from._page_size);
9325 for (y = 0; y < y_size - 1; y += 2) {
9327 nassertv(p == to._image.p() + z * to._page_size + (y / 2) * to_row_size);
9328 nassertv(q == from._image.p() + z * from._page_size + y * row_size);
9331 for (x = 0; x < x_size - 1; x += 2) {
9333 for (
int c = 0; c < num_color_components; ++c) {
9335 filter_component(p, q, pixel_size, row_size);
9338 filter_alpha(p, q, pixel_size, row_size);
9348 for (
int c = 0; c < num_color_components; ++c) {
9350 filter_component(p, q, 0, row_size);
9353 filter_alpha(p, q, 0, row_size);
9367 for (x = 0; x < x_size - 1; x += 2) {
9369 for (
int c = 0; c < num_color_components; ++c) {
9371 filter_component(p, q, pixel_size, 0);
9374 filter_alpha(p, q, pixel_size, 0);
9384 for (
int c = 0; c < num_color_components; ++c) {
9386 filter_component(p, q, 0, 0);
9389 filter_alpha(p, q, pixel_size, 0);
9394 nassertv(p == to._image.p() + (z + 1) * to._page_size);
9395 nassertv(q == from._image.p() + (z + 1) * from._page_size);
9409do_filter_3d_mipmap_level(
const CData *cdata,
9410 Texture::RamImage &to,
const Texture::RamImage &from,
9411 int x_size,
int y_size,
int z_size)
const {
9412 Filter3DComponent *filter_component;
9413 Filter3DComponent *filter_alpha;
9415 if (
is_srgb(cdata->_format)) {
9418 nassertv(cdata->_component_type == T_unsigned_byte);
9420 if (has_sse2_sRGB_encode()) {
9421 filter_component = &filter_3d_unsigned_byte_srgb_sse2;
9423 filter_component = &filter_3d_unsigned_byte_srgb;
9427 filter_alpha = &filter_3d_unsigned_byte;
9430 switch (cdata->_component_type) {
9431 case T_unsigned_byte:
9432 filter_component = &filter_3d_unsigned_byte;
9435 case T_unsigned_short:
9436 filter_component = &filter_3d_unsigned_short;
9440 filter_component = &filter_3d_float;
9445 <<
"Unable to generate mipmaps for 3D texture with component type "
9446 << cdata->_component_type <<
"!";
9449 filter_alpha = filter_component;
9452 size_t pixel_size = cdata->_num_components * cdata->_component_width;
9453 size_t row_size = (size_t)x_size * pixel_size;
9454 size_t page_size = (size_t)y_size * row_size;
9455 size_t view_size = (size_t)z_size * page_size;
9457 int to_x_size = max(x_size >> 1, 1);
9458 int to_y_size = max(y_size >> 1, 1);
9459 int to_z_size = max(z_size >> 1, 1);
9461 size_t to_row_size = (size_t)to_x_size * pixel_size;
9462 size_t to_page_size = (size_t)to_y_size * to_row_size;
9463 size_t to_view_size = (size_t)to_z_size * to_page_size;
9464 to._page_size = to_page_size;
9465 to._image = PTA_uchar::empty_array(to_page_size * to_z_size * cdata->_num_views, get_class_type());
9468 int num_color_components = cdata->_num_components;
9470 --num_color_components;
9473 for (
int view = 0; view < cdata->_num_views; ++view) {
9474 unsigned char *start_to = to._image.p() + view * to_view_size;
9475 const unsigned char *start_from = from._image.p() + view * view_size;
9476 nassertv(start_to + to_view_size <= to._image.p() + to._image.size());
9477 nassertv(start_from + view_size <= from._image.p() + from._image.size());
9478 unsigned char *p = start_to;
9479 const unsigned char *q = start_from;
9482 for (z = 0; z < z_size - 1; z += 2) {
9484 nassertv(p == start_to + (z / 2) * to_page_size);
9485 nassertv(q == start_from + z * page_size);
9488 for (y = 0; y < y_size - 1; y += 2) {
9490 nassertv(p == start_to + (z / 2) * to_page_size + (y / 2) * to_row_size);
9491 nassertv(q == start_from + z * page_size + y * row_size);
9494 for (x = 0; x < x_size - 1; x += 2) {
9496 for (
int c = 0; c < num_color_components; ++c) {
9498 filter_component(p, q, pixel_size, row_size, page_size);
9501 filter_alpha(p, q, pixel_size, row_size, page_size);
9511 for (
int c = 0; c < num_color_components; ++c) {
9513 filter_component(p, q, 0, row_size, page_size);
9516 filter_alpha(p, q, 0, row_size, page_size);
9530 for (x = 0; x < x_size - 1; x += 2) {
9532 for (
int c = 0; c < num_color_components; ++c) {
9534 filter_component(p, q, pixel_size, 0, page_size);
9537 filter_alpha(p, q, pixel_size, 0, page_size);
9547 for (
int c = 0; c < num_color_components; ++c) {
9549 filter_component(p, q, 0, 0, page_size);
9552 filter_alpha(p, q, 0, 0, page_size);
9566 for (y = 0; y < y_size - 1; y += 2) {
9568 nassertv(p == start_to + (y / 2) * to_row_size);
9569 nassertv(q == start_from + y * row_size);
9572 for (x = 0; x < x_size - 1; x += 2) {
9574 for (
int c = 0; c < num_color_components; ++c) {
9576 filter_component(p, q, pixel_size, row_size, 0);
9579 filter_alpha(p, q, pixel_size, row_size, 0);
9589 for (
int c = 0; c < num_color_components; ++c) {
9591 filter_component(p, q, 0, row_size, 0);
9594 filter_alpha(p, q, 0, row_size, 0);
9608 for (x = 0; x < x_size - 1; x += 2) {
9610 for (
int c = 0; c < num_color_components; ++c) {
9612 filter_component(p, q, pixel_size, 0, 0);
9615 filter_alpha(p, q, pixel_size, 0, 0);
9625 for (
int c = 0; c < num_color_components; ++c) {
9627 filter_component(p, q, 0, 0, 0);
9630 filter_alpha(p, q, 0, 0, 0);
9636 nassertv(p == start_to + to_z_size * to_page_size);
9637 nassertv(q == start_from + z_size * page_size);
9646filter_2d_unsigned_byte(
unsigned char *&p,
const unsigned char *&q,
9647 size_t pixel_size,
size_t row_size) {
9648 unsigned int result = ((
unsigned int)q[0] +
9649 (
unsigned int)q[pixel_size] +
9650 (
unsigned int)q[row_size] +
9651 (
unsigned int)q[pixel_size + row_size]) >> 2;
9652 *p = (
unsigned char)result;
9662filter_2d_unsigned_byte_srgb(
unsigned char *&p,
const unsigned char *&q,
9663 size_t pixel_size,
size_t row_size) {
9679filter_2d_unsigned_byte_srgb_sse2(
unsigned char *&p,
const unsigned char *&q,
9680 size_t pixel_size,
size_t row_size) {
9686 *p = encode_sRGB_uchar_sse2(result * 0.25f);
9696filter_2d_unsigned_short(
unsigned char *&p,
const unsigned char *&q,
9697 size_t pixel_size,
size_t row_size) {
9698 unsigned int result = ((
unsigned int)*(
unsigned short *)&q[0] +
9699 (
unsigned int)*(
unsigned short *)&q[pixel_size] +
9700 (
unsigned int)*(
unsigned short *)&q[row_size] +
9701 (
unsigned int)*(
unsigned short *)&q[pixel_size + row_size]) >> 2;
9702 store_unscaled_short(p, result);
9711filter_2d_float(
unsigned char *&p,
const unsigned char *&q,
9712 size_t pixel_size,
size_t row_size) {
9713 *(
float *)p = (*(
float *)&q[0] +
9714 *(
float *)&q[pixel_size] +
9715 *(
float *)&q[row_size] +
9716 *(
float *)&q[pixel_size + row_size]) / 4.0f;
9727filter_3d_unsigned_byte(
unsigned char *&p,
const unsigned char *&q,
9728 size_t pixel_size,
size_t row_size,
size_t page_size) {
9729 unsigned int result = ((
unsigned int)q[0] +
9730 (
unsigned int)q[pixel_size] +
9731 (
unsigned int)q[row_size] +
9732 (
unsigned int)q[pixel_size + row_size] +
9733 (
unsigned int)q[page_size] +
9734 (
unsigned int)q[pixel_size + page_size] +
9735 (
unsigned int)q[row_size + page_size] +
9736 (
unsigned int)q[pixel_size + row_size + page_size]) >> 3;
9737 *p = (
unsigned char)result;
9748filter_3d_unsigned_byte_srgb(
unsigned char *&p,
const unsigned char *&q,
9749 size_t pixel_size,
size_t row_size,
size_t page_size) {
9770filter_3d_unsigned_byte_srgb_sse2(
unsigned char *&p,
const unsigned char *&q,
9771 size_t pixel_size,
size_t row_size,
size_t page_size) {
9781 *p = encode_sRGB_uchar_sse2(result * 0.125f);
9792filter_3d_unsigned_short(
unsigned char *&p,
const unsigned char *&q,
9793 size_t pixel_size,
size_t row_size,
9795 unsigned int result = ((
unsigned int)*(
unsigned short *)&q[0] +
9796 (
unsigned int)*(
unsigned short *)&q[pixel_size] +
9797 (
unsigned int)*(
unsigned short *)&q[row_size] +
9798 (
unsigned int)*(
unsigned short *)&q[pixel_size + row_size] +
9799 (
unsigned int)*(
unsigned short *)&q[page_size] +
9800 (
unsigned int)*(
unsigned short *)&q[pixel_size + page_size] +
9801 (
unsigned int)*(
unsigned short *)&q[row_size + page_size] +
9802 (
unsigned int)*(
unsigned short *)&q[pixel_size + row_size + page_size]) >> 3;
9803 store_unscaled_short(p, result);
9813filter_3d_float(
unsigned char *&p,
const unsigned char *&q,
9814 size_t pixel_size,
size_t row_size,
size_t page_size) {
9815 *(
float *)p = (*(
float *)&q[0] +
9816 *(
float *)&q[pixel_size] +
9817 *(
float *)&q[row_size] +
9818 *(
float *)&q[pixel_size + row_size] +
9819 *(
float *)&q[page_size] +
9820 *(
float *)&q[pixel_size + page_size] +
9821 *(
float *)&q[row_size + page_size] +
9822 *(
float *)&q[pixel_size + row_size + page_size]) / 8.0f;
9831do_squish(CData *cdata, Texture::CompressionMode compression,
int squish_flags) {
9833 if (!do_has_all_ram_mipmap_images(cdata)) {
9836 do_generate_ram_mipmap_images(cdata,
false);
9839 RamImages compressed_ram_images;
9840 compressed_ram_images.reserve(cdata->_ram_images.size());
9841 for (
size_t n = 0; n < cdata->_ram_images.size(); ++n) {
9842 RamImage compressed_image;
9843 int x_size = do_get_expected_mipmap_x_size(cdata, n);
9844 int y_size = do_get_expected_mipmap_y_size(cdata, n);
9845 int num_pages = do_get_expected_mipmap_num_pages(cdata, n);
9846 int page_size = squish::GetStorageRequirements(x_size, y_size, squish_flags);
9847 int cell_size = squish::GetStorageRequirements(4, 4, squish_flags);
9849 compressed_image._page_size = page_size;
9850 compressed_image._image = PTA_uchar::empty_array(page_size * num_pages);
9851 for (
int z = 0; z < num_pages; ++z) {
9852 unsigned char *dest_page = compressed_image._image.p() + z * page_size;
9853 unsigned const char *source_page = cdata->_ram_images[n]._image.p() + z * cdata->_ram_images[n]._page_size;
9854 unsigned const char *source_page_end = source_page + cdata->_ram_images[n]._page_size;
9856 unsigned char *d = dest_page;
9857 for (
int y = 0; y < y_size; y += 4) {
9858 for (
int x = 0; x < x_size; x += 4) {
9859 unsigned char tb[16 * 4];
9861 unsigned char *t = tb;
9862 for (
int i = 0; i < 16; ++i) {
9865 unsigned const char *s = source_page + (yi * x_size + xi) * cdata->_num_components;
9866 if (s < source_page_end) {
9867 switch (cdata->_num_components) {
9900 squish::CompressMasked(tb, mask, d, squish_flags);
9906 compressed_ram_images.push_back(compressed_image);
9908 cdata->_ram_images.swap(compressed_ram_images);
9909 cdata->_ram_image_compression = compression;
9922do_unsquish(CData *cdata,
int squish_flags) {
9924 RamImages uncompressed_ram_images;
9925 uncompressed_ram_images.reserve(cdata->_ram_images.size());
9926 for (
size_t n = 0; n < cdata->_ram_images.size(); ++n) {
9927 RamImage uncompressed_image;
9928 int x_size = do_get_expected_mipmap_x_size(cdata, n);
9929 int y_size = do_get_expected_mipmap_y_size(cdata, n);
9930 int num_pages = do_get_expected_mipmap_num_pages(cdata, n);
9931 int page_size = squish::GetStorageRequirements(x_size, y_size, squish_flags);
9932 int cell_size = squish::GetStorageRequirements(4, 4, squish_flags);
9934 uncompressed_image._page_size = do_get_expected_ram_mipmap_page_size(cdata, n);
9935 uncompressed_image._image = PTA_uchar::empty_array(uncompressed_image._page_size * num_pages);
9936 for (
int z = 0; z < num_pages; ++z) {
9937 unsigned char *dest_page = uncompressed_image._image.p() + z * uncompressed_image._page_size;
9938 unsigned char *dest_page_end = dest_page + uncompressed_image._page_size;
9939 unsigned const char *source_page = cdata->_ram_images[n]._image.p() + z * page_size;
9941 unsigned const char *s = source_page;
9942 for (
int y = 0; y < y_size; y += 4) {
9943 for (
int x = 0; x < x_size; x += 4) {
9944 unsigned char tb[16 * 4];
9945 squish::Decompress(tb, s, squish_flags);
9948 unsigned char *t = tb;
9949 for (
int i = 0; i < 16; ++i) {
9952 unsigned char *d = dest_page + (yi * x_size + xi) * cdata->_num_components;
9953 if (d < dest_page_end) {
9954 switch (cdata->_num_components) {
9984 uncompressed_ram_images.push_back(uncompressed_image);
9986 cdata->_ram_images.swap(uncompressed_ram_images);
9987 cdata->_ram_image_compression = CM_off;
10012 bool has_rawdata =
false;
10013 do_write_datagram_header(cdata, manager, me, has_rawdata);
10014 do_write_datagram_body(cdata, manager, me);
10018 do_write_datagram_rawdata(cdata, manager, me);
10056do_write_datagram_header(CData *cdata,
BamWriter *manager,
Datagram &me,
bool &has_rawdata) {
10065 has_rawdata = (file_texture_mode == BamWriter::BTM_rawdata ||
10066 (cdata->_filename.empty() && do_has_bam_rawdata(cdata)));
10067 if (has_rawdata && !do_has_bam_rawdata(cdata)) {
10068 do_get_bam_rawdata(cdata);
10069 if (!do_has_bam_rawdata(cdata)) {
10071 has_rawdata =
false;
10077 Filename filename = cdata->_filename;
10078 Filename alpha_filename = cdata->_alpha_filename;
10082 switch (file_texture_mode) {
10083 case BamWriter::BTM_unchanged:
10084 case BamWriter::BTM_rawdata:
10087 case BamWriter::BTM_fullpath:
10088 filename = cdata->_fullpath;
10089 alpha_filename = cdata->_alpha_fullpath;
10092 case BamWriter::BTM_relative:
10093 filename = cdata->_fullpath;
10094 alpha_filename = cdata->_alpha_fullpath;
10099 if (gobj_cat.is_debug()) {
10101 <<
"Texture file " << cdata->_fullpath
10102 <<
" found as " << filename <<
"\n";
10107 if (gobj_cat.is_debug()) {
10109 <<
"Alpha image " << cdata->_alpha_fullpath
10110 <<
" found as " << alpha_filename <<
"\n";
10114 case BamWriter::BTM_basename:
10116 alpha_filename = cdata->_alpha_fullpath.
get_basename();
10121 <<
"Unsupported bam-texture-mode: " << (int)file_texture_mode <<
"\n";
10124 if (filename.empty()) {
10125 if (do_has_bam_rawdata(cdata) || cdata->_has_clear_color) {
10127 has_rawdata =
true;
10134 me.
add_uint8(cdata->_primary_file_num_channels);
10135 me.
add_uint8(cdata->_alpha_file_channel);
10139 cdata->_texture_type == TT_cube_map) {
10148 me.
add_bool(cdata->_has_read_mipmaps);
10159 cdata->_default_sampler.write_datagram(me);
10177 if (cdata->_texture_type == TT_buffer_texture) {
10182 me.
add_uint8(cdata->_auto_texture_scale);
10194 me.
add_int32(cdata->_simple_image_date_generated);
10195 me.
add_uint32(cdata->_simple_ram_image._image.size());
10196 me.
append_data(cdata->_simple_ram_image._image, cdata->_simple_ram_image._image.size());
10200 me.
add_bool(cdata->_has_clear_color);
10201 if (cdata->_has_clear_color) {
10202 cdata->_clear_color.write_datagram(me);
10227 me.
add_uint8(cdata->_ram_image_compression);
10229 if (cdata->_ram_images.empty() && cdata->_has_clear_color &&
10233 int image_size = do_get_expected_ram_image_size(cdata);
10235 me.
add_uint32(do_get_expected_ram_page_size(cdata));
10239 unsigned char pixel[16];
10240 const int pixel_size = do_get_clear_data(cdata,
pixel);
10241 nassertv(pixel_size > 0);
10243 for (
int i = 0; i < image_size; i += pixel_size) {
10247 me.
add_uint8(cdata->_ram_images.size());
10248 for (
size_t n = 0; n < cdata->_ram_images.size(); ++n) {
10249 me.
add_uint32(cdata->_ram_images[n]._page_size);
10250 me.
add_uint32(cdata->_ram_images[n]._image.size());
10251 me.
append_data(cdata->_ram_images[n]._image, cdata->_ram_images[n]._image.size());
10262 return dummy->make_this_from_bam(params);
10289 int primary_file_num_channels = scan.
get_uint8();
10290 int alpha_file_channel = scan.
get_uint8();
10291 bool has_rawdata = scan.
get_bool();
10292 TextureType texture_type = (TextureType)scan.
get_uint8();
10296 if (texture_type == TT_2d_texture_array) {
10297 texture_type = TT_cube_map;
10300 bool has_read_mipmaps =
false;
10302 has_read_mipmaps = scan.
get_bool();
10312 me->set_name(name);
10313 CDWriter cdata_me(me->_cycler,
true);
10314 cdata_me->_filename = filename;
10315 cdata_me->_alpha_filename = alpha_filename;
10316 cdata_me->_primary_file_num_channels = primary_file_num_channels;
10317 cdata_me->_alpha_file_channel = alpha_file_channel;
10318 cdata_me->_texture_type = texture_type;
10319 cdata_me->_has_read_mipmaps = has_read_mipmaps;
10322 me->do_fillin_body(cdata_me, scan, manager);
10323 me->do_fillin_rawdata(cdata_me, scan, manager);
10335 AutoTextureScale auto_texture_scale = ATS_unspecified;
10338 CDWriter cdata_dummy(dummy->_cycler,
true);
10339 dummy->do_fillin_body(cdata_dummy, scan, manager);
10340 auto_texture_scale = cdata_dummy->_auto_texture_scale;
10344 if (filename.empty()) {
10348 <<
"Cannot create texture '" << name <<
"' with no filename.\n";
10358 if (!alpha_filename.empty()) {
10365 options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_generate_mipmaps);
10369 switch (texture_type) {
10370 case TT_buffer_texture:
10371 case TT_1d_texture:
10372 case TT_2d_texture:
10373 case TT_1d_texture_array:
10378 if ((options.get_texture_flags() & LoaderOptions::TF_preload) == 0 &&
10379 (
has_simple_ram_image || (options.get_texture_flags() & LoaderOptions::TF_preload_simple) == 0)) {
10380 if (alpha_filename.empty()) {
10385 primary_file_num_channels,
10386 alpha_file_channel,
10398 Filename alpha_fullpath = alpha_filename;
10399 const DSearchPath &model_path = get_model_path();
10401 (alpha_fullpath.empty() || vfs->
resolve_filename(alpha_fullpath, model_path))) {
10403 me->set_name(name);
10406 CDWriter cdata_me(me->_cycler,
true);
10407 cdata_me->_filename = filename;
10408 cdata_me->_alpha_filename = alpha_filename;
10409 cdata_me->_fullpath = fullpath;
10410 cdata_me->_alpha_fullpath = alpha_fullpath;
10411 cdata_me->_primary_file_num_channels = primary_file_num_channels;
10412 cdata_me->_alpha_file_channel = alpha_file_channel;
10413 cdata_me->_texture_type = texture_type;
10414 cdata_me->_loaded_from_image =
true;
10415 cdata_me->_has_read_mipmaps = has_read_mipmaps;
10429 if (alpha_filename.empty()) {
10431 has_read_mipmaps, options);
10434 primary_file_num_channels,
10435 alpha_file_channel,
10436 has_read_mipmaps, options);
10440 case TT_3d_texture:
10444 case TT_2d_texture_array:
10445 case TT_cube_map_array:
10455 if (me !=
nullptr) {
10456 me->set_name(name);
10457 CDWriter cdata_me(me->_cycler,
true);
10458 me->do_fillin_from(cdata_me, dummy);
10475 cdata->_default_sampler.read_datagram(scan, manager);
10478 cdata->_compression = (CompressionMode)scan.
get_uint8();
10481 cdata->_quality_level = (QualityLevel)scan.
get_uint8();
10484 cdata->_format = (Format)scan.
get_uint8();
10485 cdata->_num_components = scan.
get_uint8();
10487 if (cdata->_texture_type == TT_buffer_texture) {
10488 cdata->_usage_hint = (GeomEnums::UsageHint)scan.
get_uint8();
10491 cdata->inc_properties_modified();
10493 cdata->_auto_texture_scale = ATS_unspecified;
10495 cdata->_auto_texture_scale = (AutoTextureScale)scan.
get_uint8();
10500 cdata->_orig_file_x_size = scan.
get_uint32();
10501 cdata->_orig_file_y_size = scan.
get_uint32();
10509 cdata->_simple_image_date_generated = scan.
get_int32();
10516 <<
"simple RAM image extends past end of datagram, is texture corrupt?\n";
10520 PTA_uchar image = PTA_uchar::empty_array(u_size, get_class_type());
10523 cdata->_simple_ram_image._image = image;
10524 cdata->_simple_ram_image._page_size = u_size;
10525 cdata->inc_simple_image_modified();
10529 cdata->_has_clear_color = scan.
get_bool();
10530 if (cdata->_has_clear_color) {
10531 cdata->_clear_color.read_datagram(scan);
10551 do_set_pad_size(cdata, 0, 0, 0);
10554 cdata->_num_views = 1;
10558 cdata->_component_type = (ComponentType)scan.
get_uint8();
10559 cdata->_component_width = scan.
get_uint8();
10560 cdata->_ram_image_compression = CM_off;
10562 cdata->_ram_image_compression = (CompressionMode)scan.
get_uint8();
10565 int num_ram_images = 1;
10570 cdata->_ram_images.clear();
10571 cdata->_ram_images.reserve(num_ram_images);
10572 for (
int n = 0; n < num_ram_images; ++n) {
10573 cdata->_ram_images.push_back(RamImage());
10576 cdata->_ram_images[n]._page_size = scan.
get_uint32();
10585 <<
"RAM image " << n <<
" extends past end of datagram, is texture corrupt?\n";
10589 PTA_uchar image = PTA_uchar::empty_array(u_size, get_class_type());
10592 cdata->_ram_images[n]._image = image;
10594 cdata->_loaded_from_image =
true;
10595 cdata->inc_image_modified();
10604do_fillin_from(CData *cdata,
const Texture *dummy) {
10611 CDReader cdata_dummy(dummy->_cycler);
10613 do_set_wrap_u(cdata, cdata_dummy->_default_sampler.get_wrap_u());
10614 do_set_wrap_v(cdata, cdata_dummy->_default_sampler.get_wrap_v());
10615 do_set_wrap_w(cdata, cdata_dummy->_default_sampler.get_wrap_w());
10616 do_set_border_color(cdata, cdata_dummy->_default_sampler.get_border_color());
10618 if (cdata_dummy->_default_sampler.get_minfilter() != SamplerState::FT_default) {
10619 do_set_minfilter(cdata, cdata_dummy->_default_sampler.get_minfilter());
10621 if (cdata_dummy->_default_sampler.get_magfilter() != SamplerState::FT_default) {
10622 do_set_magfilter(cdata, cdata_dummy->_default_sampler.get_magfilter());
10624 if (cdata_dummy->_default_sampler.get_anisotropic_degree() != 0) {
10625 do_set_anisotropic_degree(cdata, cdata_dummy->_default_sampler.get_anisotropic_degree());
10627 if (cdata_dummy->_compression != CM_default) {
10628 do_set_compression(cdata, cdata_dummy->_compression);
10630 if (cdata_dummy->_quality_level != QL_default) {
10631 do_set_quality_level(cdata, cdata_dummy->_quality_level);
10634 Format format = cdata_dummy->_format;
10635 int num_components = cdata_dummy->_num_components;
10637 if (num_components == cdata->_num_components) {
10641 do_set_format(cdata, format);
10644 if (!cdata_dummy->_simple_ram_image._image.empty()) {
10647 if (cdata->_simple_ram_image._image.empty() ||
10648 cdata_dummy->_simple_image_date_generated > cdata->_simple_image_date_generated) {
10649 do_set_simple_ram_image(cdata,
10650 cdata_dummy->_simple_ram_image._image,
10651 cdata_dummy->_simple_x_size,
10652 cdata_dummy->_simple_y_size);
10653 cdata->_simple_image_date_generated = cdata_dummy->_simple_image_date_generated;
10663 _primary_file_num_channels = 0;
10664 _alpha_file_channel = 0;
10665 _keep_ram_image =
true;
10666 _compression = CM_default;
10667 _auto_texture_scale = ATS_unspecified;
10668 _ram_image_compression = CM_off;
10669 _render_to_texture =
false;
10670 _match_framebuffer_format =
false;
10671 _post_load_store_cache =
false;
10672 _quality_level = QL_default;
10674 _texture_type = TT_2d_texture;
10679 _num_components = 3;
10680 _component_width = 1;
10682 _component_type = T_unsigned_byte;
10685 _usage_hint = GeomEnums::UH_unspecified;
10691 _orig_file_x_size = 0;
10692 _orig_file_y_size = 0;
10694 _loaded_from_image =
false;
10695 _loaded_from_txo =
false;
10696 _has_read_pages =
false;
10697 _has_read_mipmaps =
false;
10698 _num_mipmap_levels_read = 0;
10700 _simple_x_size = 0;
10701 _simple_y_size = 0;
10702 _simple_ram_image._page_size = 0;
10704 _has_clear_color =
false;
10711CData(
const Texture::CData ©) {
10712 _num_mipmap_levels_read = 0;
10713 _render_to_texture = copy._render_to_texture;
10714 _post_load_store_cache = copy._post_load_store_cache;
10718 _properties_modified = copy._properties_modified;
10719 _image_modified = copy._image_modified;
10720 _simple_image_modified = copy._simple_image_modified;
10728 return new CData(*
this);
10734void Texture::CData::
10735do_assign(
const Texture::CData *copy) {
10736 _filename = copy->_filename;
10737 _alpha_filename = copy->_alpha_filename;
10738 if (!copy->_fullpath.empty()) {
10741 _fullpath = copy->_fullpath;
10742 _alpha_fullpath = copy->_alpha_fullpath;
10744 _primary_file_num_channels = copy->_primary_file_num_channels;
10745 _alpha_file_channel = copy->_alpha_file_channel;
10746 _x_size = copy->_x_size;
10747 _y_size = copy->_y_size;
10748 _z_size = copy->_z_size;
10749 _num_views = copy->_num_views;
10750 _pad_x_size = copy->_pad_x_size;
10751 _pad_y_size = copy->_pad_y_size;
10752 _pad_z_size = copy->_pad_z_size;
10753 _orig_file_x_size = copy->_orig_file_x_size;
10754 _orig_file_y_size = copy->_orig_file_y_size;
10755 _num_components = copy->_num_components;
10756 _component_width = copy->_component_width;
10757 _texture_type = copy->_texture_type;
10758 _format = copy->_format;
10759 _component_type = copy->_component_type;
10760 _loaded_from_image = copy->_loaded_from_image;
10761 _loaded_from_txo = copy->_loaded_from_txo;
10762 _has_read_pages = copy->_has_read_pages;
10763 _has_read_mipmaps = copy->_has_read_mipmaps;
10764 _num_mipmap_levels_read = copy->_num_mipmap_levels_read;
10765 _default_sampler = copy->_default_sampler;
10766 _keep_ram_image = copy->_keep_ram_image;
10767 _compression = copy->_compression;
10768 _match_framebuffer_format = copy->_match_framebuffer_format;
10769 _quality_level = copy->_quality_level;
10770 _auto_texture_scale = copy->_auto_texture_scale;
10771 _ram_image_compression = copy->_ram_image_compression;
10772 _ram_images = copy->_ram_images;
10773 _simple_x_size = copy->_simple_x_size;
10774 _simple_y_size = copy->_simple_y_size;
10775 _simple_ram_image = copy->_simple_ram_image;
10782void Texture::CData::
10790int Texture::CData::
10799void Texture::CData::
10807operator << (ostream &out, Texture::TextureType tt) {
10815operator << (ostream &out, Texture::ComponentType ct) {
10823operator << (ostream &out, Texture::Format f) {
10831operator << (ostream &out, Texture::CompressionMode cm) {
10839operator << (ostream &out, Texture::QualityLevel tql) {
10847operator >> (istream &in, Texture::QualityLevel &tql) {
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void parse_params(const FactoryParams ¶ms, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This class represents a thread-safe handle to a promised future result of an asynchronous operation,...
An instance of this class is written to the front of a Bam or Txo file to make the file a cached inst...
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.
get_data
Returns a pointer to the data stored in the record, or NULL if there is no data.
set_data
Stores a new data object on the record.
This class maintains a cache of Bam and/or Txo objects generated from model files and texture images ...
get_cache_textures
Returns whether texture files (e.g.
bool store(BamCacheRecord *record)
Flushes a cache entry to disk.
static BamCache * get_global_ptr()
Returns a pointer to the global BamCache object, which is used automatically by the ModelPool and Tex...
get_cache_compressed_textures
Returns whether compressed texture files will be stored in the cache, as compressed txo files.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
void register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
bool resolve()
This may be called at any time during processing of the Bam file to resolve all the known pointers so...
bool init()
Initializes the BamReader prior to reading any objects from its source.
get_filename
If a BAM is a file, then the BamReader should contain the name of the file.
TypedWritable * read_object()
Reads a single object from the Bam file.
get_loader_options
Returns the LoaderOptions passed to the loader when the model was requested, if any.
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
get_file_texture_mode
Returns the BamTextureMode preference indicated by the Bam file currently being written.
get_filename
If a BAM is a file, then the BamWriter should contain the name of the file.
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being written.
get_active
Returns the active flag associated with this object.
get_resident
Returns the resident flag associated with this object.
get_data_size_bytes
Returns the number of bytes previously reported for the data object.
void notify_all()
Informs all of the other threads who are currently blocked on wait() that the relevant condition has ...
void wait()
Waits on the condition.
This class specializes ConfigVariable as an enumerated type.
int get_word(size_t n) const
Returns the variable's nth value.
std::string get_unique_value(size_t n) const
Returns the nth unique value of the variable.
size_t get_num_unique_values() const
Returns the number of unique values in the variable.
PointerToArray< Element > cast_non_const() const
Casts away the constness of the CPTA(Element), and returns an equivalent PTA(Element).
This collects together the pieces of data that are accumulated for each node while walking the scene ...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
This template class calls PipelineCycler::read() in the constructor and PipelineCycler::release_read(...
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
A single page of data maintained by a PipelineCycler.
This class stores a list of directories that can be searched, in order, to locate a particular file.
A class to retrieve the individual data elements previously stored in a Datagram.
uint8_t get_uint8()
Extracts an unsigned 8-bit integer.
vector_uchar extract_bytes(size_t size)
Extracts the indicated number of bytes in the datagram and returns them as a string.
uint32_t get_uint32()
Extracts an unsigned 32-bit integer.
bool get_bool()
Extracts a boolean value.
std::string get_string()
Extracts a variable-length string.
int32_t get_int32()
Extracts a signed 32-bit integer.
size_t get_remaining_size() const
Return the bytes left in the datagram.
This class can be used to write a binary file that consists of an arbitrary header followed by a numb...
bool open(const FileReference *file)
Opens the indicated filename for writing.
bool write_header(const vector_uchar &header)
Writes a sequence of bytes to the beginning of the datagram file.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
void add_uint32(uint32_t value)
Adds an unsigned 32-bit integer to the datagram.
void add_int16(int16_t value)
Adds a signed 16-bit integer to the datagram.
void add_int32(int32_t value)
Adds a signed 32-bit integer to the datagram.
void add_uint8(uint8_t value)
Adds an unsigned 8-bit integer to the datagram.
void add_bool(bool value)
Adds a boolean value to the datagram.
void append_data(const void *data, size_t size)
Appends some more raw data to the end of the datagram.
void add_string(const std::string &str)
Adds a variable-length string to the datagram.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
void register_factory(TypeHandle handle, CreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
The name of a file, such as a texture file or an Egg file.
std::string get_basename() const
Returns the basename part of the filename.
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 ...
bool has_hash() const
Returns true if the filename is indicated to be a filename pattern (that is, set_pattern(true) was ca...
void set_basename_wo_extension(const std::string &s)
Replaces the basename part of the filename, without the file extension.
int find_on_searchpath(const DSearchPath &searchpath)
Performs the reverse of the resolve_filename() operation: assuming that the current filename is fully...
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_wo_extension() const
Returns the basename part of the filename, without the file extension.
void make_absolute()
Converts the filename to a fully-qualified pathname from the root (if it is a relative pathname),...
static Filename pattern_filename(const std::string &filename)
Constructs a filename that represents a sequence of numbered files.
This class can be used to test for string matches against standard Unix- shell filename globbing conv...
bool matches(const std::string &candidate) const
Returns true if the candidate string matches the pattern, false otherwise.
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
static GraphicsStateGuardianBase * get_default_gsg()
Returns a pointer to the "default" GSG.
Encodes a string name in a hash table, mapping it to a pointer.
get_name
Returns the complete name represented by the InternalName and all of its parents.
Specifies parameters that may be passed to the loader.
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 ...
get_auto_texture_scale
See set_auto_texture_scale().
get_texture_num_views
See set_texture_num_views().
void unlock()
Alias for release() to match C++11 semantics.
void lock()
Alias for acquire() to match C++11 semantics.
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
A base class for all things which can have a name.
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
static PNMFileTypeRegistry * get_global_ptr()
Returns a pointer to the global PNMFileTypeRegistry object.
PNMFileType * get_type_from_extension(const std::string &filename) const
Tries to determine what the PNMFileType is likely to be for a particular image file based on its exte...
This is the base class of a family of classes that represent particular image file types that PNMImag...
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
void clear()
Frees all memory allocated for the image, and clears all its parameters (size, color,...
void set_read_size(int x_size, int y_size)
Specifies the size to we'd like to scale the image upon reading it.
xelval get_channel_val(int x, int y, int channel) const
Returns the nth 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.
void alpha_fill(float alpha=0.0)
Sets the entire alpha channel to the given level.
xelval get_green_val(int x, int y) const
Returns the green component color at the indicated pixel.
void set_green(int x, int y, float g)
Sets the green component color only at the indicated pixel.
float get_alpha(int x, int y) const
Returns the alpha component color at the indicated pixel.
float get_gray(int x, int y) const
Returns the gray component color at the indicated pixel.
void quick_filter_from(const PNMImage ©, int xborder=0, int yborder=0)
Resizes from the given image, with a fixed radius of 0.5.
void fill(float red, float green, float blue)
Sets the entire image (except the alpha channel) to the given color.
void set_num_channels(int num_channels)
Changes the number of channels associated with the image.
xelval get_alpha_val(int x, int y) const
Returns the alpha component color at the indicated pixel.
void set_red(int x, int y, float r)
Sets the red component color only at the indicated pixel.
void copy_header_from(const PNMImageHeader &header)
Copies just the header information into this image.
void take_from(PNMImage &orig)
Move the contents of the other image into this one, and empty the other image.
bool is_valid() const
Returns true if the image has been read in or correctly initialized with a height and width.
xelval get_blue_val(int x, int y) const
Returns the blue component color at the indicated pixel.
bool read(const Filename &filename, PNMFileType *type=nullptr, bool report_unknown_type=true)
Reads the indicated image filename.
xel * get_array()
Directly access the underlying PNMImage array.
xelval get_red_val(int x, int y) const
Returns the red component color at the indicated pixel.
int get_read_y_size() const
Returns the requested y_size of the image if set_read_size() has been called, or the image y_size oth...
xelval get_gray_val(int x, int y) const
Returns the gray component color at the indicated pixel.
void set_alpha(int x, int y, float a)
Sets the alpha component color only at the indicated pixel.
ColorSpace get_color_space() const
Returns the color space in which the image is encoded.
void add_alpha()
Adds an alpha channel to the image, if it does not already have one.
xelval * get_alpha_array()
Directly access the underlying PNMImage array of alpha values.
bool write(const Filename &filename, PNMFileType *type=nullptr) const
Writes the image to the indicated filename.
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...
This is an abstract base class that defines the interface for reading image files of various types.
virtual bool is_floating_point()
Returns true if this PNMFileType represents a floating-point image type, false if it is a normal,...
A lightweight class that represents a single element that may be timed and/or counted via stats.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Defines a pfm file, a 2-d table of floating-point numbers, either 3-component or 1-component,...
bool read(const Filename &fullpath)
Reads the PFM data from the indicated file, returning true on success, false on failure.
bool write(const Filename &fullpath)
Writes the PFM data to the indicated file, returning true on success, false on failure.
bool store(PNMImage &pnmimage) const
Copies the data to the indicated PNMImage, converting to RGB values.
void set_channel(int x, int y, int c, PN_float32 value)
Replaces the cth channel of the point value at the indicated point.
bool load(const PNMImage &pnmimage)
Fills the PfmFile with the data from the indicated PNMImage, converted to floating-point values.
PN_float32 get_channel(int x, int y, int c) const
Returns the cth channel of the point value at the indicated point.
void clear()
Eliminates all data in the file.
A table of objects that are saved within the graphics context for reference by handle later.
bool is_texture_queued(const Texture *tex) const
Returns true if the texture has been queued on this GSG, false otherwise.
TextureContext * prepare_texture_now(Texture *tex, int view, GraphicsStateGuardianBase *gsg)
Immediately creates a new TextureContext for the indicated texture and returns it.
bool dequeue_texture(Texture *tex)
Removes a texture from the queued list of textures to be prepared.
void release_texture(TextureContext *tc)
Indicates that a texture context, created by a previous call to prepare_texture(),...
void ref() const
Explicitly increments the reference count.
void local_object()
This function should be called, once, immediately after creating a new instance of some ReferenceCoun...
get_ref_count
Returns the current reference count.
virtual bool unref() const
Explicitly decrements the reference count.
Represents a set of settings that indicate how a texture is sampled.
get_minfilter
Returns the filter mode of the texture for minification.
get_wrap_v
Returns the wrap mode of the texture in the V direction.
get_anisotropic_degree
Returns the degree of anisotropic filtering that should be applied to the texture.
get_magfilter
Returns the filter mode of the texture for magnification.
get_wrap_w
Returns the wrap mode of the texture in the W direction.
get_wrap_u
Returns the wrap mode of the texture in the U direction.
get_border_color
Returns the solid color of the texture's border.
A class to read sequential binary data directly from an istream.
This is a special class object that holds all the information returned by a particular GSG to indicat...
bool was_image_modified() const
Returns true if the texture image has been modified since the last time mark_loaded() was called.
An instance of this object is returned by Texture::peek().
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...
static Texture * get_texture(const Filename &filename, int primary_file_num_channels=0, bool read_mipmaps=false)
Returns the texture that has already been previously loaded, or NULL otherwise.
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,...
static void add_texture(Texture *texture)
Adds the indicated already-loaded texture to the pool.
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.
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,...
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
CPTA_uchar get_ram_image_as(const std::string &requested_format)
Returns the uncompressed system-RAM image data associated with the texture.
static TextureType string_texture_type(const std::string &str)
Returns the TextureType corresponding to the indicated string word.
virtual void ensure_loader_type(const Filename &filename)
May be called prior to calling read_txo() or any bam-related Texture- creating callback,...
static PT(Texture) make_from_txo(std bool write_txo(std::ostream &out, const std::string &filename="") const
Writes the texture to a Panda texture object.
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.
static std::string format_component_type(ComponentType ct)
Returns the indicated ComponentType converted to a string word.
Texture(const std::string &name=std::string())
Constructs an empty texture.
bool get_resident(PreparedGraphicsObjects *prepared_objects) const
Returns true if this Texture is reported to be resident within graphics memory for the indicated GSG.
Texture * load_related(const InternalName *suffix) const
Loads a texture whose filename is derived by concatenating a suffix to the filename of this texture.
static CompressionMode string_compression_mode(const std::string &str)
Returns the CompressionMode value associated with the given string representation.
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...
static bool is_specific(CompressionMode compression)
Returns true if the indicated compression mode is one of the specific compression types,...
bool has_ram_image() const
Returns true if the Texture has its image contents available in main RAM, false if it exists only in ...
static std::string format_quality_level(QualityLevel tql)
Returns the indicated QualityLevel converted to a string word.
size_t estimate_texture_memory() const
Estimates the amount of texture memory that will be consumed by loading this texture.
bool read(const Filename &fullpath, const LoaderOptions &options=LoaderOptions())
Reads the named filename into the texture.
void consider_rescale(PNMImage &pnmimage)
Asks the PNMImage to change its scale when it reads the image, according to the whims of the Config....
get_texture_type
Returns the overall interpretation of the texture.
bool write(const Filename &fullpath)
Writes the texture to the named filename.
static bool has_binary_alpha(Format format)
Returns true if the indicated format includes a binary alpha only, false otherwise.
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...
static std::string format_compression_mode(CompressionMode cm)
Returns the indicated CompressionMode converted to a string word.
get_aux_data
Returns a record previously recorded via set_aux_data().
static bool is_srgb(Format format)
Returns true if the indicated format is in the sRGB color space, false otherwise.
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.
bool get_active(PreparedGraphicsObjects *prepared_objects) const
Returns true if this Texture was rendered in the most recent frame within the indicated GSG.
get_keep_ram_image
Returns the flag that indicates whether this Texture is eligible to have its main RAM copy of the tex...
bool read_dds(std::istream &in, const std::string &filename="", bool header_only=false)
Reads the texture from a DDS file object.
void generate_normalization_cube_map(int size)
Generates a special cube map image in the texture that can be used to apply bump mapping effects: for...
bool has_compression() const
Returns true if the texture indicates it wants to be compressed, either with CM_on or higher,...
static QualityLevel string_quality_level(const std::string &str)
Returns the QualityLevel value associated with the given string representation.
void generate_alpha_scale_map()
Generates a special 256x1 1-d texture that can be used to apply an arbitrary alpha scale to objects b...
bool read_txo(std::istream &in, const std::string &filename="")
Reads the texture from a Panda texture object.
static ComponentType string_component_type(const std::string &str)
Returns the ComponentType corresponding to the indicated string word.
static void register_with_read_factory()
Factory method to generate a Texture object.
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,...
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
static int up_to_power_2(int value)
Returns the smallest power of 2 greater than or equal to value.
static AutoTextureScale get_textures_power_2()
This flag returns ATS_none, ATS_up, or ATS_down and controls the scaling of textures in general.
get_auto_texture_scale
Returns the power-of-2 texture-scaling mode that will be applied to this particular texture when it i...
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...
virtual void write_datagram(BamWriter *manager, Datagram &me)
Function to write the important information in the particular object to a Datagram.
static int down_to_power_2(int value)
Returns the largest power of 2 less than or equal to value.
bool release(PreparedGraphicsObjects *prepared_objects)
Frees the texture context only on the indicated object, if it exists there.
virtual bool has_cull_callback() const
Should be overridden by derived classes to return true if cull_callback() has been defined.
bool uses_mipmaps() const
Returns true if the minfilter settings on this texture indicate the use of mipmapping,...
static std::string format_texture_type(TextureType tt)
Returns the indicated TextureType converted to a string word.
has_simple_ram_image
Returns true if the Texture has a "simple" image available in main RAM.
static bool is_integer(Format format)
Returns true if the indicated format is an integer format, false otherwise.
PTA_uchar modify_simple_ram_image()
Returns a modifiable pointer to the internal "simple" texture image.
void clear_ram_mipmap_image(int n)
Discards the current system-RAM image for the nth mipmap level.
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...
bool read_ktx(std::istream &in, const std::string &filename="", bool header_only=false)
Reads the texture from a KTX file object.
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,...
get_expected_ram_page_size
Returns the number of bytes that should be used per each Z page of the 3-d texture.
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...
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const
Returns true if the texture has already been prepared or enqueued for preparation on the indicated GS...
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...
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.
set_aux_data
Records an arbitrary object in the Texture, associated with a specified key.
void texture_uploaded()
This method is called by the GraphicsEngine at the beginning of the frame *after* a texture has been ...
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.
static bool has_alpha(Format format)
Returns true if the indicated format includes alpha, false otherwise.
get_num_loadable_ram_mipmap_images
Returns the number of contiguous mipmap levels that exist in RAM, up until the first gap in the seque...
void generate_simple_ram_image()
Computes the "simple" ram image by loading the main RAM image, if it is not already available,...
static Format string_format(const std::string &str)
Returns the Format corresponding to the indicated string word.
clear_aux_data
Removes a record previously recorded via set_aux_data().
int release_all()
Frees the context allocated on all objects for which the texture has been declared.
CPTA_uchar get_ram_mipmap_image(int n) const
Returns the system-RAM image data associated with the nth mipmap level, if present.
static std::string format_format(Format f)
Returns the indicated Format converted to a string word.
is_cacheable
Returns true if there is enough information in this Texture object to write it to the bam cache succe...
static bool is_unsigned(ComponentType ctype)
Returns true if the indicated component type is unsigned, false otherwise.
A thread; that is, a lightweight process.
static void consider_yield()
Possibly suspends the current thread for the rest of the current epoch, if it has run for enough this...
get_current_thread
Returns a pointer to the currently-executing Thread object.
TypeHandle is the identifier used to differentiate C++ class types.
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
A base class for things which need to inherit from both TypedObject and from ReferenceCount.
Base class for objects that can be written to and read from Bam files.
A hierarchy of directories and files that appears to be one continuous file system,...
static void close_write_file(std::ostream *stream)
Closes a file opened by a previous call to open_write_file().
Filename get_cwd() const
Returns the current directory name.
bool exists(const Filename &filename) const
Convenience function; returns true if the named file exists in the virtual file system hierarchy.
bool resolve_filename(Filename &filename, const DSearchPath &searchpath, const std::string &default_extension=std::string()) const
Searches the given search path for the filename.
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,...
static void close_read_file(std::istream *stream)
Closes a file opened by a previous call to open_read_file().
PointerTo< VirtualFile > get_file(const Filename &filename, bool status_only=false) const
Looks up the file by the indicated name in the file system.
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
The abstract base class for a file or directory within the VirtualFileSystem.
This is our own Panda specialization on the default STL map.
This is our own Panda specialization on the default STL vector.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
EXPCL_PANDA_PNMIMAGE unsigned char encode_sRGB_uchar(unsigned char val)
Encodes the linearized unsigned char value to an sRGB-encoded unsigned char value.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_lowest_on_bit(unsigned short x)
Returns the index of the lowest 1 bit in the word.
int get_next_higher_bit(unsigned short x)
Returns the smallest power of 2 greater than x.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
string upcase(const string &s)
Returns the input string with all lowercase letters converted to uppercase.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void release_read(const CycleData *pointer) const
Releases a pointer previously obtained via a call to read().
CycleDataType * write_upstream(bool force_to_0, Thread *current_thread)
See PipelineCyclerBase::write_upstream().
CycleDataType * elevate_read_upstream(const CycleDataType *pointer, bool force_to_0, Thread *current_thread)
See PipelineCyclerBase::elevate_read_upstream().
const CycleDataType * read(Thread *current_thread) const
See PipelineCyclerBase::read().
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.