3030
3131#include " portable_compressed_texture.h"
3232
33+ #include " core/config/project_settings.h"
3334#include " core/io/marshalls.h"
3435#include " scene/resources/bit_map.h"
36+ #include " scene/resources/compressed_texture.h"
3537
3638void PortableCompressedTexture2D::_set_data (const Vector<uint8_t > &p_data) {
3739 if (p_data.size () == 0 ) {
@@ -41,7 +43,8 @@ void PortableCompressedTexture2D::_set_data(const Vector<uint8_t> &p_data) {
4143 const uint8_t *data = p_data.ptr ();
4244 uint32_t data_size = p_data.size ();
4345 ERR_FAIL_COND (data_size < 20 );
44- compression_mode = CompressionMode (decode_uint32 (data + 0 ));
46+ compression_mode = CompressionMode (decode_uint16 (data));
47+ CompressedTexture2D::DataFormat data_format = CompressedTexture2D::DataFormat (decode_uint16 (data + 2 ));
4548 format = Image::Format (decode_uint32 (data + 4 ));
4649 uint32_t mipmap_count = decode_uint32 (data + 8 );
4750 size.width = decode_uint32 (data + 12 );
@@ -56,6 +59,16 @@ void PortableCompressedTexture2D::_set_data(const Vector<uint8_t> &p_data) {
5659 switch (compression_mode) {
5760 case COMPRESSION_MODE_LOSSLESS :
5861 case COMPRESSION_MODE_LOSSY : {
62+ ImageMemLoadFunc loader_func;
63+ if (data_format == CompressedTexture2D::DATA_FORMAT_UNDEFINED ) {
64+ loader_func = nullptr ;
65+ } else if (data_format == CompressedTexture2D::DATA_FORMAT_PNG ) {
66+ loader_func = Image::_png_mem_unpacker_func;
67+ } else if (data_format == CompressedTexture2D::DATA_FORMAT_WEBP ) {
68+ loader_func = Image::_webp_mem_loader_func;
69+ } else {
70+ ERR_FAIL ();
71+ }
5972 Vector<uint8_t > image_data;
6073
6174 ERR_FAIL_COND (data_size < 4 );
@@ -64,7 +77,9 @@ void PortableCompressedTexture2D::_set_data(const Vector<uint8_t> &p_data) {
6477 data += 4 ;
6578 data_size -= 4 ;
6679 ERR_FAIL_COND (mipsize < data_size);
67- Ref<Image> img = memnew (Image (data, data_size));
80+ Ref<Image> img = loader_func == nullptr
81+ ? memnew (Image (data, data_size))
82+ : Ref<Image>(loader_func (data, data_size));
6883 ERR_FAIL_COND (img->is_empty ());
6984 if (img->get_format () != format) { // May happen due to webp/png in the tiny mipmaps.
7085 img->convert (format);
@@ -99,6 +114,7 @@ void PortableCompressedTexture2D::_set_data(const Vector<uint8_t> &p_data) {
99114 }
100115
101116 image_stored = true ;
117+ size_override = size;
102118 RenderingServer::get_singleton ()->texture_set_size_override (texture, size_override.width , size_override.height );
103119 alpha_cache.unref ();
104120
@@ -122,7 +138,8 @@ void PortableCompressedTexture2D::create_from_image(const Ref<Image> &p_image, C
122138 Vector<uint8_t > buffer;
123139
124140 buffer.resize (20 );
125- encode_uint32 (p_compression_mode, buffer.ptrw ());
141+ encode_uint16 (p_compression_mode, buffer.ptrw ());
142+ encode_uint16 (CompressedTexture2D::DATA_FORMAT_UNDEFINED , buffer.ptrw () + 2 );
126143 encode_uint32 (p_image->get_format (), buffer.ptrw () + 4 );
127144 encode_uint32 (p_image->get_mipmap_count () + 1 , buffer.ptrw () + 8 );
128145 encode_uint32 (p_image->get_width (), buffer.ptrw () + 12 );
@@ -131,12 +148,22 @@ void PortableCompressedTexture2D::create_from_image(const Ref<Image> &p_image, C
131148 switch (p_compression_mode) {
132149 case COMPRESSION_MODE_LOSSLESS :
133150 case COMPRESSION_MODE_LOSSY : {
151+ bool lossless_force_png = GLOBAL_GET (" rendering/textures/lossless_compression/force_png" ) ||
152+ !Image::_webp_mem_loader_func; // WebP module disabled.
153+ bool use_webp = !lossless_force_png && p_image->get_width () <= 16383 && p_image->get_height () <= 16383 ; // WebP has a size limit.
134154 for (int i = 0 ; i < p_image->get_mipmap_count () + 1 ; i++) {
135155 Vector<uint8_t > data;
136156 if (p_compression_mode == COMPRESSION_MODE_LOSSY ) {
137157 data = Image::webp_lossy_packer (p_image->get_image_from_mipmap (i), p_lossy_quality);
158+ encode_uint16 (CompressedTexture2D::DATA_FORMAT_WEBP , buffer.ptrw () + 2 );
138159 } else {
139- data = Image::webp_lossless_packer (p_image->get_image_from_mipmap (i));
160+ if (use_webp) {
161+ data = Image::webp_lossless_packer (p_image->get_image_from_mipmap (i));
162+ encode_uint16 (CompressedTexture2D::DATA_FORMAT_WEBP , buffer.ptrw () + 2 );
163+ } else {
164+ data = Image::png_packer (p_image->get_image_from_mipmap (i));
165+ encode_uint16 (CompressedTexture2D::DATA_FORMAT_PNG , buffer.ptrw () + 2 );
166+ }
140167 }
141168 int data_len = data.size ();
142169 buffer.resize (buffer.size () + 4 );
@@ -145,6 +172,7 @@ void PortableCompressedTexture2D::create_from_image(const Ref<Image> &p_image, C
145172 }
146173 } break ;
147174 case COMPRESSION_MODE_BASIS_UNIVERSAL : {
175+ encode_uint16 (CompressedTexture2D::DATA_FORMAT_BASIS_UNIVERSAL , buffer.ptrw () + 2 );
148176 Image::UsedChannels uc = p_image->detect_used_channels (p_normal_map ? Image::COMPRESS_SOURCE_NORMAL : Image::COMPRESS_SOURCE_GENERIC );
149177 Vector<uint8_t > budata = Image::basis_universal_packer (p_image, uc);
150178 buffer.append_array (budata);
@@ -153,6 +181,7 @@ void PortableCompressedTexture2D::create_from_image(const Ref<Image> &p_image, C
153181 case COMPRESSION_MODE_S3TC :
154182 case COMPRESSION_MODE_ETC2 :
155183 case COMPRESSION_MODE_BPTC : {
184+ encode_uint16 (CompressedTexture2D::DATA_FORMAT_IMAGE , buffer.ptrw () + 2 );
156185 Ref<Image> copy = p_image->duplicate ();
157186 switch (p_compression_mode) {
158187 case COMPRESSION_MODE_S3TC :
0 commit comments