|
@@ -30,8 +30,10 @@
|
|
|
|
|
|
#include "portable_compressed_texture.h"
|
|
#include "portable_compressed_texture.h"
|
|
|
|
|
|
|
|
+#include "core/config/project_settings.h"
|
|
#include "core/io/marshalls.h"
|
|
#include "core/io/marshalls.h"
|
|
#include "scene/resources/bit_map.h"
|
|
#include "scene/resources/bit_map.h"
|
|
|
|
+#include "scene/resources/compressed_texture.h"
|
|
|
|
|
|
void PortableCompressedTexture2D::_set_data(const Vector<uint8_t> &p_data) {
|
|
void PortableCompressedTexture2D::_set_data(const Vector<uint8_t> &p_data) {
|
|
if (p_data.size() == 0) {
|
|
if (p_data.size() == 0) {
|
|
@@ -41,7 +43,8 @@ void PortableCompressedTexture2D::_set_data(const Vector<uint8_t> &p_data) {
|
|
const uint8_t *data = p_data.ptr();
|
|
const uint8_t *data = p_data.ptr();
|
|
uint32_t data_size = p_data.size();
|
|
uint32_t data_size = p_data.size();
|
|
ERR_FAIL_COND(data_size < 20);
|
|
ERR_FAIL_COND(data_size < 20);
|
|
- compression_mode = CompressionMode(decode_uint32(data + 0));
|
|
|
|
|
|
+ compression_mode = CompressionMode(decode_uint16(data));
|
|
|
|
+ CompressedTexture2D::DataFormat data_format = CompressedTexture2D::DataFormat(decode_uint16(data + 2));
|
|
format = Image::Format(decode_uint32(data + 4));
|
|
format = Image::Format(decode_uint32(data + 4));
|
|
uint32_t mipmap_count = decode_uint32(data + 8);
|
|
uint32_t mipmap_count = decode_uint32(data + 8);
|
|
size.width = decode_uint32(data + 12);
|
|
size.width = decode_uint32(data + 12);
|
|
@@ -56,6 +59,16 @@ void PortableCompressedTexture2D::_set_data(const Vector<uint8_t> &p_data) {
|
|
switch (compression_mode) {
|
|
switch (compression_mode) {
|
|
case COMPRESSION_MODE_LOSSLESS:
|
|
case COMPRESSION_MODE_LOSSLESS:
|
|
case COMPRESSION_MODE_LOSSY: {
|
|
case COMPRESSION_MODE_LOSSY: {
|
|
|
|
+ ImageMemLoadFunc loader_func;
|
|
|
|
+ if (data_format == CompressedTexture2D::DATA_FORMAT_UNDEFINED) {
|
|
|
|
+ loader_func = nullptr;
|
|
|
|
+ } else if (data_format == CompressedTexture2D::DATA_FORMAT_PNG) {
|
|
|
|
+ loader_func = Image::_png_mem_unpacker_func;
|
|
|
|
+ } else if (data_format == CompressedTexture2D::DATA_FORMAT_WEBP) {
|
|
|
|
+ loader_func = Image::_webp_mem_loader_func;
|
|
|
|
+ } else {
|
|
|
|
+ ERR_FAIL();
|
|
|
|
+ }
|
|
Vector<uint8_t> image_data;
|
|
Vector<uint8_t> image_data;
|
|
|
|
|
|
ERR_FAIL_COND(data_size < 4);
|
|
ERR_FAIL_COND(data_size < 4);
|
|
@@ -64,7 +77,9 @@ void PortableCompressedTexture2D::_set_data(const Vector<uint8_t> &p_data) {
|
|
data += 4;
|
|
data += 4;
|
|
data_size -= 4;
|
|
data_size -= 4;
|
|
ERR_FAIL_COND(mipsize < data_size);
|
|
ERR_FAIL_COND(mipsize < data_size);
|
|
- Ref<Image> img = memnew(Image(data, data_size));
|
|
|
|
|
|
+ Ref<Image> img = loader_func == nullptr
|
|
|
|
+ ? memnew(Image(data, data_size))
|
|
|
|
+ : Ref<Image>(loader_func(data, data_size));
|
|
ERR_FAIL_COND(img->is_empty());
|
|
ERR_FAIL_COND(img->is_empty());
|
|
if (img->get_format() != format) { // May happen due to webp/png in the tiny mipmaps.
|
|
if (img->get_format() != format) { // May happen due to webp/png in the tiny mipmaps.
|
|
img->convert(format);
|
|
img->convert(format);
|
|
@@ -99,6 +114,7 @@ void PortableCompressedTexture2D::_set_data(const Vector<uint8_t> &p_data) {
|
|
}
|
|
}
|
|
|
|
|
|
image_stored = true;
|
|
image_stored = true;
|
|
|
|
+ size_override = size;
|
|
RenderingServer::get_singleton()->texture_set_size_override(texture, size_override.width, size_override.height);
|
|
RenderingServer::get_singleton()->texture_set_size_override(texture, size_override.width, size_override.height);
|
|
alpha_cache.unref();
|
|
alpha_cache.unref();
|
|
|
|
|
|
@@ -122,7 +138,8 @@ void PortableCompressedTexture2D::create_from_image(const Ref<Image> &p_image, C
|
|
Vector<uint8_t> buffer;
|
|
Vector<uint8_t> buffer;
|
|
|
|
|
|
buffer.resize(20);
|
|
buffer.resize(20);
|
|
- encode_uint32(p_compression_mode, buffer.ptrw());
|
|
|
|
|
|
+ encode_uint16(p_compression_mode, buffer.ptrw());
|
|
|
|
+ encode_uint16(CompressedTexture2D::DATA_FORMAT_UNDEFINED, buffer.ptrw() + 2);
|
|
encode_uint32(p_image->get_format(), buffer.ptrw() + 4);
|
|
encode_uint32(p_image->get_format(), buffer.ptrw() + 4);
|
|
encode_uint32(p_image->get_mipmap_count() + 1, buffer.ptrw() + 8);
|
|
encode_uint32(p_image->get_mipmap_count() + 1, buffer.ptrw() + 8);
|
|
encode_uint32(p_image->get_width(), buffer.ptrw() + 12);
|
|
encode_uint32(p_image->get_width(), buffer.ptrw() + 12);
|
|
@@ -131,12 +148,22 @@ void PortableCompressedTexture2D::create_from_image(const Ref<Image> &p_image, C
|
|
switch (p_compression_mode) {
|
|
switch (p_compression_mode) {
|
|
case COMPRESSION_MODE_LOSSLESS:
|
|
case COMPRESSION_MODE_LOSSLESS:
|
|
case COMPRESSION_MODE_LOSSY: {
|
|
case COMPRESSION_MODE_LOSSY: {
|
|
|
|
+ bool lossless_force_png = GLOBAL_GET("rendering/textures/lossless_compression/force_png") ||
|
|
|
|
+ !Image::_webp_mem_loader_func; // WebP module disabled.
|
|
|
|
+ bool use_webp = !lossless_force_png && p_image->get_width() <= 16383 && p_image->get_height() <= 16383; // WebP has a size limit.
|
|
for (int i = 0; i < p_image->get_mipmap_count() + 1; i++) {
|
|
for (int i = 0; i < p_image->get_mipmap_count() + 1; i++) {
|
|
Vector<uint8_t> data;
|
|
Vector<uint8_t> data;
|
|
if (p_compression_mode == COMPRESSION_MODE_LOSSY) {
|
|
if (p_compression_mode == COMPRESSION_MODE_LOSSY) {
|
|
data = Image::webp_lossy_packer(p_image->get_image_from_mipmap(i), p_lossy_quality);
|
|
data = Image::webp_lossy_packer(p_image->get_image_from_mipmap(i), p_lossy_quality);
|
|
|
|
+ encode_uint16(CompressedTexture2D::DATA_FORMAT_WEBP, buffer.ptrw() + 2);
|
|
} else {
|
|
} else {
|
|
- data = Image::webp_lossless_packer(p_image->get_image_from_mipmap(i));
|
|
|
|
|
|
+ if (use_webp) {
|
|
|
|
+ data = Image::webp_lossless_packer(p_image->get_image_from_mipmap(i));
|
|
|
|
+ encode_uint16(CompressedTexture2D::DATA_FORMAT_WEBP, buffer.ptrw() + 2);
|
|
|
|
+ } else {
|
|
|
|
+ data = Image::png_packer(p_image->get_image_from_mipmap(i));
|
|
|
|
+ encode_uint16(CompressedTexture2D::DATA_FORMAT_PNG, buffer.ptrw() + 2);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
int data_len = data.size();
|
|
int data_len = data.size();
|
|
buffer.resize(buffer.size() + 4);
|
|
buffer.resize(buffer.size() + 4);
|
|
@@ -145,6 +172,7 @@ void PortableCompressedTexture2D::create_from_image(const Ref<Image> &p_image, C
|
|
}
|
|
}
|
|
} break;
|
|
} break;
|
|
case COMPRESSION_MODE_BASIS_UNIVERSAL: {
|
|
case COMPRESSION_MODE_BASIS_UNIVERSAL: {
|
|
|
|
+ encode_uint16(CompressedTexture2D::DATA_FORMAT_BASIS_UNIVERSAL, buffer.ptrw() + 2);
|
|
Image::UsedChannels uc = p_image->detect_used_channels(p_normal_map ? Image::COMPRESS_SOURCE_NORMAL : Image::COMPRESS_SOURCE_GENERIC);
|
|
Image::UsedChannels uc = p_image->detect_used_channels(p_normal_map ? Image::COMPRESS_SOURCE_NORMAL : Image::COMPRESS_SOURCE_GENERIC);
|
|
Vector<uint8_t> budata = Image::basis_universal_packer(p_image, uc);
|
|
Vector<uint8_t> budata = Image::basis_universal_packer(p_image, uc);
|
|
buffer.append_array(budata);
|
|
buffer.append_array(budata);
|
|
@@ -153,6 +181,7 @@ void PortableCompressedTexture2D::create_from_image(const Ref<Image> &p_image, C
|
|
case COMPRESSION_MODE_S3TC:
|
|
case COMPRESSION_MODE_S3TC:
|
|
case COMPRESSION_MODE_ETC2:
|
|
case COMPRESSION_MODE_ETC2:
|
|
case COMPRESSION_MODE_BPTC: {
|
|
case COMPRESSION_MODE_BPTC: {
|
|
|
|
+ encode_uint16(CompressedTexture2D::DATA_FORMAT_IMAGE, buffer.ptrw() + 2);
|
|
Ref<Image> copy = p_image->duplicate();
|
|
Ref<Image> copy = p_image->duplicate();
|
|
switch (p_compression_mode) {
|
|
switch (p_compression_mode) {
|
|
case COMPRESSION_MODE_S3TC:
|
|
case COMPRESSION_MODE_S3TC:
|