Add support for ASTC 6x6 and high quality compression profiles.
This commit is contained in:
@@ -32,6 +32,25 @@
|
||||
|
||||
#include "core/object/class_db.h"
|
||||
|
||||
static Image::CompressProfile _astc_format_to_compress_profile(Image::ASTCFormat p_format) {
|
||||
switch (p_format) {
|
||||
case Image::ASTC_FORMAT_4x4:
|
||||
return Image::COMPRESS_PROFILE_MAX_QUALITY;
|
||||
case Image::ASTC_FORMAT_8x8:
|
||||
return Image::COMPRESS_PROFILE_MAX_COMPRESSION;
|
||||
default:
|
||||
return Image::COMPRESS_PROFILE_AUTOMATIC;
|
||||
}
|
||||
}
|
||||
|
||||
Error Image::_compress_bind_compat_115003(CompressMode p_mode, CompressSource p_source, ASTCFormat p_format) {
|
||||
return compress(p_mode, p_source, _astc_format_to_compress_profile(p_format));
|
||||
}
|
||||
|
||||
Error Image::_compress_from_channels_compat_115003(CompressMode p_mode, UsedChannels p_channels, ASTCFormat p_format) {
|
||||
return compress_from_channels(p_mode, p_channels, _astc_format_to_compress_profile(p_format));
|
||||
}
|
||||
|
||||
Vector<uint8_t> Image::_save_exr_to_buffer_bind_compat_117800(bool p_grayscale) const {
|
||||
return save_exr_to_buffer(p_grayscale);
|
||||
}
|
||||
@@ -41,6 +60,8 @@ Error Image::_save_exr_bind_compat_117800(const String &p_path, bool p_grayscale
|
||||
}
|
||||
|
||||
void Image::_bind_compatibility_methods() {
|
||||
ClassDB::bind_compatibility_method(D_METHOD("compress", "mode", "source", "astc_format"), &Image::_compress_bind_compat_115003, DEFVAL(COMPRESS_SOURCE_GENERIC), DEFVAL(ASTC_FORMAT_4x4));
|
||||
ClassDB::bind_compatibility_method(D_METHOD("compress_from_channels", "mode", "channels", "astc_format"), &Image::_compress_from_channels_compat_115003, DEFVAL(ASTC_FORMAT_4x4));
|
||||
ClassDB::bind_compatibility_method(D_METHOD("save_exr", "path", "grayscale"), &Image::_save_exr_bind_compat_117800, DEFVAL(false));
|
||||
ClassDB::bind_compatibility_method(D_METHOD("save_exr_to_buffer", "grayscale"), &Image::_save_exr_to_buffer_bind_compat_117800, DEFVAL(false));
|
||||
}
|
||||
|
||||
+63
-25
@@ -88,6 +88,8 @@ const char *Image::format_names[Image::FORMAT_MAX] = {
|
||||
"RG16Int",
|
||||
"RGB16Int",
|
||||
"RGBA16Int",
|
||||
"ASTC_6x6",
|
||||
"ASTC_6x6_HDR",
|
||||
};
|
||||
|
||||
// External VRAM compression function pointers.
|
||||
@@ -96,7 +98,7 @@ void (*Image::_image_compress_bc_func)(Image *, Image::UsedChannels) = nullptr;
|
||||
void (*Image::_image_compress_bptc_func)(Image *, Image::UsedChannels, Image::BPTCFormat) = nullptr;
|
||||
void (*Image::_image_compress_etc1_func)(Image *) = nullptr;
|
||||
void (*Image::_image_compress_etc2_func)(Image *, Image::UsedChannels) = nullptr;
|
||||
void (*Image::_image_compress_astc_func)(Image *, Image::ASTCFormat) = nullptr;
|
||||
void (*Image::_image_compress_astc_func)(Image *, Image::UsedChannels, Image::CompressProfile) = nullptr;
|
||||
|
||||
Error (*Image::_image_compress_bptc_rd_func)(Image *, Image::UsedChannels, Image::BPTCFormat) = nullptr;
|
||||
Error (*Image::_image_compress_bc_rd_func)(Image *, Image::UsedChannels) = nullptr;
|
||||
@@ -207,6 +209,10 @@ int Image::get_format_pixel_size(Format p_format) {
|
||||
return 1;
|
||||
case FORMAT_ASTC_4x4_HDR:
|
||||
return 1;
|
||||
case FORMAT_ASTC_6x6:
|
||||
return 1;
|
||||
case FORMAT_ASTC_6x6_HDR:
|
||||
return 1;
|
||||
case FORMAT_ASTC_8x8:
|
||||
return 1;
|
||||
case FORMAT_ASTC_8x8_HDR:
|
||||
@@ -233,6 +239,27 @@ int Image::get_format_pixel_size(Format p_format) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t Image::get_format_pixels_shifted(Format p_format, uint64_t p_pixels) {
|
||||
switch (p_format) {
|
||||
case FORMAT_ASTC_8x8:
|
||||
case FORMAT_ASTC_8x8_HDR:
|
||||
return p_pixels >> 2;
|
||||
case FORMAT_ASTC_6x6:
|
||||
case FORMAT_ASTC_6x6_HDR:
|
||||
return (p_pixels * 4) / 9;
|
||||
case FORMAT_DXT1:
|
||||
case FORMAT_RGTC_R:
|
||||
case FORMAT_ETC:
|
||||
case FORMAT_ETC2_R11:
|
||||
case FORMAT_ETC2_R11S:
|
||||
case FORMAT_ETC2_RGB8:
|
||||
case FORMAT_ETC2_RGB8A1:
|
||||
return p_pixels >> 1;
|
||||
default:
|
||||
return p_pixels;
|
||||
}
|
||||
}
|
||||
|
||||
void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) {
|
||||
switch (p_format) {
|
||||
case FORMAT_DXT1:
|
||||
@@ -270,6 +297,11 @@ void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) {
|
||||
r_w = 4;
|
||||
r_h = 4;
|
||||
} break;
|
||||
case FORMAT_ASTC_6x6:
|
||||
case FORMAT_ASTC_6x6_HDR: {
|
||||
r_w = 6;
|
||||
r_h = 6;
|
||||
} break;
|
||||
case FORMAT_ASTC_8x8:
|
||||
case FORMAT_ASTC_8x8_HDR: {
|
||||
r_w = 8;
|
||||
@@ -282,16 +314,6 @@ void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) {
|
||||
}
|
||||
}
|
||||
|
||||
int Image::get_format_pixel_rshift(Format p_format) {
|
||||
if (p_format == FORMAT_ASTC_8x8) {
|
||||
return 2;
|
||||
} else if (p_format == FORMAT_DXT1 || p_format == FORMAT_RGTC_R || p_format == FORMAT_ETC || p_format == FORMAT_ETC2_R11 || p_format == FORMAT_ETC2_R11S || p_format == FORMAT_ETC2_RGB8 || p_format == FORMAT_ETC2_RGB8A1) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int Image::get_format_block_size(Format p_format) {
|
||||
switch (p_format) {
|
||||
case FORMAT_DXT1:
|
||||
@@ -324,6 +346,10 @@ int Image::get_format_block_size(Format p_format) {
|
||||
case FORMAT_ASTC_4x4_HDR: {
|
||||
return 4;
|
||||
}
|
||||
case FORMAT_ASTC_6x6:
|
||||
case FORMAT_ASTC_6x6_HDR: {
|
||||
return 6;
|
||||
}
|
||||
case FORMAT_ASTC_8x8:
|
||||
case FORMAT_ASTC_8x8_HDR: {
|
||||
return 8;
|
||||
@@ -341,7 +367,6 @@ void Image::_get_mipmap_offset_and_size(int p_mipmap, int64_t &r_offset, int &r_
|
||||
int64_t ofs = 0;
|
||||
|
||||
int pixel_size = get_format_pixel_size(format);
|
||||
int pixel_rshift = get_format_pixel_rshift(format);
|
||||
int block = get_format_block_size(format);
|
||||
int minw, minh;
|
||||
get_format_min_pixel_size(format, minw, minh);
|
||||
@@ -353,7 +378,7 @@ void Image::_get_mipmap_offset_and_size(int p_mipmap, int64_t &r_offset, int &r_
|
||||
int64_t s = bw * bh;
|
||||
|
||||
s *= pixel_size;
|
||||
s >>= pixel_rshift;
|
||||
s = get_format_pixels_shifted(format, s);
|
||||
ofs += s;
|
||||
w = MAX(minw, w >> 1);
|
||||
h = MAX(minh, h >> 1);
|
||||
@@ -1908,7 +1933,6 @@ int64_t Image::_get_dst_image_size(int p_width, int p_height, Format p_format, i
|
||||
int mm = 0;
|
||||
|
||||
int pixsize = get_format_pixel_size(p_format);
|
||||
int pixshift = get_format_pixel_rshift(p_format);
|
||||
int block = get_format_block_size(p_format);
|
||||
|
||||
// Technically, you can still compress up to 1 px no matter the format, so commenting this.
|
||||
@@ -1923,7 +1947,7 @@ int64_t Image::_get_dst_image_size(int p_width, int p_height, Format p_format, i
|
||||
int64_t s = bw * bh;
|
||||
|
||||
s *= pixsize;
|
||||
s >>= pixshift;
|
||||
s = get_format_pixels_shifted(p_format, s);
|
||||
|
||||
size += s;
|
||||
|
||||
@@ -2909,7 +2933,7 @@ bool Image::is_compressed() const {
|
||||
}
|
||||
|
||||
bool Image::is_format_compressed(Format p_format) {
|
||||
return p_format > FORMAT_RGBE9995 && p_format < FORMAT_R16;
|
||||
return (p_format >= FORMAT_DXT1 && p_format <= FORMAT_ASTC_8x8_HDR) || (p_format >= FORMAT_ASTC_6x6 && p_format <= FORMAT_ASTC_6x6_HDR);
|
||||
}
|
||||
|
||||
Error Image::decompress() {
|
||||
@@ -2921,7 +2945,7 @@ Error Image::decompress() {
|
||||
_image_decompress_etc1(this);
|
||||
} else if (format >= FORMAT_ETC2_R11 && format <= FORMAT_ETC2_RA_AS_RG && _image_decompress_etc2) {
|
||||
_image_decompress_etc2(this);
|
||||
} else if (format >= FORMAT_ASTC_4x4 && format <= FORMAT_ASTC_8x8_HDR && _image_decompress_astc) {
|
||||
} else if (((format >= FORMAT_ASTC_4x4 && format <= FORMAT_ASTC_8x8_HDR) || (format >= FORMAT_ASTC_6x6 && format <= FORMAT_ASTC_6x6_HDR)) && _image_decompress_astc) {
|
||||
_image_decompress_astc(this);
|
||||
} else {
|
||||
return ERR_UNAVAILABLE;
|
||||
@@ -2942,17 +2966,17 @@ bool Image::can_decompress(const String &p_format_tag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Error Image::compress(CompressMode p_mode, CompressSource p_source, ASTCFormat p_astc_format) {
|
||||
Error Image::compress(CompressMode p_mode, CompressSource p_source, CompressProfile p_profile) {
|
||||
ERR_FAIL_INDEX_V_MSG(p_mode, COMPRESS_MAX, ERR_INVALID_PARAMETER, "Invalid compress mode.");
|
||||
ERR_FAIL_INDEX_V_MSG(p_source, COMPRESS_SOURCE_MAX, ERR_INVALID_PARAMETER, "Invalid compress source.");
|
||||
return compress_from_channels(p_mode, detect_used_channels(p_source), p_astc_format);
|
||||
return compress_from_channels(p_mode, detect_used_channels(p_source), p_profile);
|
||||
}
|
||||
|
||||
Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, ASTCFormat p_astc_format) {
|
||||
return _compress_from_channels(p_mode, p_channels, p_astc_format, BPTC_DETECT);
|
||||
Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, CompressProfile p_profile) {
|
||||
return _compress_from_channels(p_mode, p_channels, p_profile, BPTC_DETECT);
|
||||
}
|
||||
|
||||
Error Image::_compress_from_channels(CompressMode p_mode, UsedChannels p_channels, ASTCFormat p_astc_format, BPTCFormat p_bptc_format) {
|
||||
Error Image::_compress_from_channels(CompressMode p_mode, UsedChannels p_channels, CompressProfile p_profile, BPTCFormat p_bptc_format) {
|
||||
ERR_FAIL_COND_V(data.is_empty(), ERR_INVALID_DATA);
|
||||
|
||||
// RenderingDevice only.
|
||||
@@ -3004,7 +3028,7 @@ Error Image::_compress_from_channels(CompressMode p_mode, UsedChannels p_channel
|
||||
} break;
|
||||
case COMPRESS_ASTC: {
|
||||
ERR_FAIL_NULL_V(_image_compress_astc_func, ERR_UNAVAILABLE);
|
||||
_image_compress_astc_func(this, p_astc_format);
|
||||
_image_compress_astc_func(this, p_channels, p_profile);
|
||||
} break;
|
||||
case COMPRESS_MAX: {
|
||||
ERR_FAIL_V(ERR_INVALID_PARAMETER);
|
||||
@@ -3895,8 +3919,8 @@ void Image::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("is_invisible"), &Image::is_invisible);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("detect_used_channels", "source"), &Image::detect_used_channels, DEFVAL(COMPRESS_SOURCE_GENERIC));
|
||||
ClassDB::bind_method(D_METHOD("compress", "mode", "source", "astc_format"), &Image::compress, DEFVAL(COMPRESS_SOURCE_GENERIC), DEFVAL(ASTC_FORMAT_4x4));
|
||||
ClassDB::bind_method(D_METHOD("compress_from_channels", "mode", "channels", "astc_format"), &Image::compress_from_channels, DEFVAL(ASTC_FORMAT_4x4));
|
||||
ClassDB::bind_method(D_METHOD("compress", "mode", "source", "profile"), &Image::compress, DEFVAL(COMPRESS_SOURCE_GENERIC), DEFVAL(COMPRESS_PROFILE_AUTOMATIC));
|
||||
ClassDB::bind_method(D_METHOD("compress_from_channels", "mode", "channels", "profile"), &Image::compress_from_channels, DEFVAL(COMPRESS_PROFILE_AUTOMATIC));
|
||||
ClassDB::bind_method(D_METHOD("decompress"), &Image::decompress);
|
||||
ClassDB::bind_method(D_METHOD("is_compressed"), &Image::is_compressed);
|
||||
|
||||
@@ -3999,6 +4023,8 @@ void Image::_bind_methods() {
|
||||
BIND_ENUM_CONSTANT(FORMAT_RG16I);
|
||||
BIND_ENUM_CONSTANT(FORMAT_RGB16I);
|
||||
BIND_ENUM_CONSTANT(FORMAT_RGBA16I);
|
||||
BIND_ENUM_CONSTANT(FORMAT_ASTC_6x6);
|
||||
BIND_ENUM_CONSTANT(FORMAT_ASTC_6x6_HDR);
|
||||
BIND_ENUM_CONSTANT(FORMAT_MAX);
|
||||
|
||||
BIND_ENUM_CONSTANT(INTERPOLATE_NEAREST);
|
||||
@@ -4029,8 +4055,16 @@ void Image::_bind_methods() {
|
||||
BIND_ENUM_CONSTANT(COMPRESS_SOURCE_SRGB);
|
||||
BIND_ENUM_CONSTANT(COMPRESS_SOURCE_NORMAL);
|
||||
|
||||
BIND_ENUM_CONSTANT(COMPRESS_PROFILE_AUTOMATIC);
|
||||
BIND_ENUM_CONSTANT(COMPRESS_PROFILE_MAX_QUALITY);
|
||||
BIND_ENUM_CONSTANT(COMPRESS_PROFILE_COMPRESSED);
|
||||
BIND_ENUM_CONSTANT(COMPRESS_PROFILE_MAX_COMPRESSION);
|
||||
BIND_ENUM_CONSTANT(COMPRESS_PROFILE_MAX);
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
BIND_ENUM_CONSTANT(ASTC_FORMAT_4x4);
|
||||
BIND_ENUM_CONSTANT(ASTC_FORMAT_8x8);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Image::normal_map_to_xy() {
|
||||
@@ -4408,6 +4442,10 @@ uint32_t Image::get_format_component_mask(Format p_format) {
|
||||
return rgba;
|
||||
case FORMAT_ASTC_4x4_HDR:
|
||||
return rgba;
|
||||
case FORMAT_ASTC_6x6:
|
||||
return rgba;
|
||||
case FORMAT_ASTC_6x6_HDR:
|
||||
return rgba;
|
||||
case FORMAT_ASTC_8x8:
|
||||
return rgba;
|
||||
case FORMAT_ASTC_8x8_HDR:
|
||||
|
||||
+24
-6
@@ -119,6 +119,8 @@ public:
|
||||
FORMAT_RG16I,
|
||||
FORMAT_RGB16I,
|
||||
FORMAT_RGBA16I,
|
||||
FORMAT_ASTC_6x6,
|
||||
FORMAT_ASTC_6x6_HDR,
|
||||
FORMAT_MAX
|
||||
};
|
||||
|
||||
@@ -144,11 +146,13 @@ public:
|
||||
USED_CHANNELS_RGBA,
|
||||
};
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
// ASTC supports block formats other than 4x4.
|
||||
enum ASTCFormat {
|
||||
ASTC_FORMAT_4x4,
|
||||
ASTC_FORMAT_8x8,
|
||||
};
|
||||
#endif
|
||||
|
||||
enum BPTCFormat {
|
||||
BPTC_DETECT,
|
||||
@@ -190,6 +194,14 @@ public:
|
||||
COMPRESS_SOURCE_MAX,
|
||||
};
|
||||
|
||||
enum CompressProfile {
|
||||
COMPRESS_PROFILE_AUTOMATIC,
|
||||
COMPRESS_PROFILE_MAX_QUALITY,
|
||||
COMPRESS_PROFILE_COMPRESSED,
|
||||
COMPRESS_PROFILE_MAX_COMPRESSION,
|
||||
COMPRESS_PROFILE_MAX
|
||||
};
|
||||
|
||||
enum AlphaMode {
|
||||
ALPHA_NONE,
|
||||
ALPHA_BIT,
|
||||
@@ -233,7 +245,7 @@ public:
|
||||
static void (*_image_compress_bptc_func)(Image *, UsedChannels p_channels, BPTCFormat p_bptc_format);
|
||||
static void (*_image_compress_etc1_func)(Image *);
|
||||
static void (*_image_compress_etc2_func)(Image *, UsedChannels p_channels);
|
||||
static void (*_image_compress_astc_func)(Image *, ASTCFormat p_format);
|
||||
static void (*_image_compress_astc_func)(Image *, UsedChannels p_channels, CompressProfile p_profile);
|
||||
|
||||
static Error (*_image_compress_bptc_rd_func)(Image *, UsedChannels p_channels, BPTCFormat p_bptc_format);
|
||||
static Error (*_image_compress_bc_rd_func)(Image *, UsedChannels p_channels);
|
||||
@@ -264,8 +276,11 @@ protected:
|
||||
static void _bind_methods();
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
Error _compress_bind_compat_115003(CompressMode p_mode, CompressSource p_source, ASTCFormat p_format);
|
||||
Error _compress_from_channels_compat_115003(CompressMode p_mode, UsedChannels p_channels, ASTCFormat p_format);
|
||||
Vector<uint8_t> _save_exr_to_buffer_bind_compat_117800(bool p_grayscale = false) const;
|
||||
Error _save_exr_bind_compat_117800(const String &p_path, bool p_grayscale = false) const;
|
||||
|
||||
static void _bind_compatibility_methods();
|
||||
#endif
|
||||
|
||||
@@ -393,7 +408,7 @@ public:
|
||||
bool is_invisible() const;
|
||||
|
||||
static int get_format_pixel_size(Format p_format);
|
||||
static int get_format_pixel_rshift(Format p_format);
|
||||
static uint64_t get_format_pixels_shifted(Format p_format, uint64_t p_pixels);
|
||||
static int get_format_block_size(Format p_format);
|
||||
static void get_format_min_pixel_size(Format p_format, int &r_w, int &r_h);
|
||||
|
||||
@@ -403,10 +418,9 @@ public:
|
||||
static int64_t get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap);
|
||||
static int64_t get_image_mipmap_offset_and_dimensions(int p_width, int p_height, Format p_format, int p_mipmap, int &r_w, int &r_h);
|
||||
|
||||
Error compress(CompressMode p_mode, CompressSource p_source = COMPRESS_SOURCE_GENERIC, ASTCFormat p_astc_format = ASTC_FORMAT_4x4);
|
||||
Error compress_from_channels(CompressMode p_mode, UsedChannels p_channels, ASTCFormat p_astc_format = ASTC_FORMAT_4x4);
|
||||
Error _compress_from_channels(CompressMode p_mode, UsedChannels p_channels, ASTCFormat p_astc_format, BPTCFormat p_bptc_format);
|
||||
|
||||
Error compress(CompressMode p_mode, CompressSource p_source = COMPRESS_SOURCE_GENERIC, CompressProfile p_profile = COMPRESS_PROFILE_AUTOMATIC);
|
||||
Error compress_from_channels(CompressMode p_mode, UsedChannels p_channels, CompressProfile p_profile = COMPRESS_PROFILE_AUTOMATIC);
|
||||
Error _compress_from_channels(CompressMode p_mode, UsedChannels p_channels, CompressProfile p_profile, BPTCFormat p_bptc_format);
|
||||
Error decompress();
|
||||
bool is_compressed() const;
|
||||
static bool is_format_compressed(Format p_format);
|
||||
@@ -481,4 +495,8 @@ VARIANT_ENUM_CAST(Image::CompressSource)
|
||||
VARIANT_ENUM_CAST(Image::UsedChannels)
|
||||
VARIANT_ENUM_CAST(Image::AlphaMode)
|
||||
VARIANT_ENUM_CAST(Image::RoughnessChannel)
|
||||
VARIANT_ENUM_CAST(Image::CompressProfile)
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
VARIANT_ENUM_CAST(Image::ASTCFormat)
|
||||
#endif
|
||||
|
||||
+27
-6
@@ -79,11 +79,11 @@
|
||||
<return type="int" enum="Error" />
|
||||
<param index="0" name="mode" type="int" enum="Image.CompressMode" />
|
||||
<param index="1" name="source" type="int" enum="Image.CompressSource" default="0" />
|
||||
<param index="2" name="astc_format" type="int" enum="Image.ASTCFormat" default="0" />
|
||||
<param index="2" name="profile" type="int" enum="Image.CompressProfile" default="0" />
|
||||
<description>
|
||||
Compresses the image with a VRAM-compressed format to use less memory. Can not directly access pixel data while the image is compressed. Returns error if the chosen compression mode is not available.
|
||||
The [param source] parameter helps to pick the best compression method for DXT and ETC2 formats. It is ignored for ASTC compression.
|
||||
The [param astc_format] parameter is only taken into account when using ASTC compression; it is ignored for all other formats.
|
||||
The [param profile] lets the user pick whether the compression should prioritize quality or a smaller size. Only ASTC compression uses this currently.
|
||||
[b]Note:[/b] [method compress] is only supported in editor builds. When run in an exported project, this method always returns [constant ERR_UNAVAILABLE].
|
||||
</description>
|
||||
</method>
|
||||
@@ -91,11 +91,11 @@
|
||||
<return type="int" enum="Error" />
|
||||
<param index="0" name="mode" type="int" enum="Image.CompressMode" />
|
||||
<param index="1" name="channels" type="int" enum="Image.UsedChannels" />
|
||||
<param index="2" name="astc_format" type="int" enum="Image.ASTCFormat" default="0" />
|
||||
<param index="2" name="profile" type="int" enum="Image.CompressProfile" default="0" />
|
||||
<description>
|
||||
Compresses the image with a VRAM-compressed format to use less memory. Can not directly access pixel data while the image is compressed. Returns error if the chosen compression mode is not available.
|
||||
This is an alternative to [method compress] that lets the user supply the channels used in order for the compressor to pick the best DXT and ETC2 formats. For other formats (non DXT or ETC2), this argument is ignored.
|
||||
The [param astc_format] parameter is only taken into account when using ASTC compression; it is ignored for all other formats.
|
||||
This is an alternative to [method compress] that lets the user supply the channels used in order for the compressor to pick the best DXT, ETC2, and ASTC formats. For other formats (non DXT, ETC2, or ASTC), this argument is ignored.
|
||||
The [param profile] lets the user pick whether the compression should prioritize quality or a smaller size. Only ASTC compression uses this currently.
|
||||
[b]Note:[/b] [method compress_from_channels] is only supported in editor builds. When run in an exported project, this method always returns [constant ERR_UNAVAILABLE].
|
||||
</description>
|
||||
</method>
|
||||
@@ -815,7 +815,13 @@
|
||||
[b]Note:[/b] When used in a shader, the texture requires usage of [code]usampler[/code] samplers. Additionally, it only supports nearest-neighbor filtering under the Compatibility renderer.
|
||||
[b]Note:[/b] When sampling using [method Image.get_pixel], returned [Color]s have to be divided by [code]65535[/code] to get the correct color value.
|
||||
</constant>
|
||||
<constant name="FORMAT_MAX" value="47" enum="Format">
|
||||
<constant name="FORMAT_ASTC_6x6" value="47" enum="Format">
|
||||
[url=https://en.wikipedia.org/wiki/Adaptive_scalable_texture_compression]Adaptive Scalable Texture Compression[/url]. This implements the 6×6 (medium quality) mode.
|
||||
</constant>
|
||||
<constant name="FORMAT_ASTC_6x6_HDR" value="48" enum="Format">
|
||||
Same format as [constant FORMAT_ASTC_6x6], but with the hint to let the GPU know it is used for HDR.
|
||||
</constant>
|
||||
<constant name="FORMAT_MAX" value="49" enum="Format">
|
||||
Represents the size of the [enum Format] enum.
|
||||
</constant>
|
||||
<constant name="INTERPOLATE_NEAREST" value="0" enum="Interpolation">
|
||||
@@ -891,6 +897,21 @@
|
||||
<constant name="COMPRESS_SOURCE_NORMAL" value="2" enum="CompressSource">
|
||||
Source texture (before compression) is a normal texture (e.g. it can be compressed into two channels).
|
||||
</constant>
|
||||
<constant name="COMPRESS_PROFILE_AUTOMATIC" value="0" enum="CompressProfile">
|
||||
Automatically adjusts the quality level based on the number of unique color channels present in the image. For ASTC, this corresponds to picking 8x8 when only one channel is detected (R, L), 6x6 when two channels are detected (RG, LA), and 4x4 in all other cases.
|
||||
</constant>
|
||||
<constant name="COMPRESS_PROFILE_MAX_QUALITY" value="1" enum="CompressProfile">
|
||||
Prioritizes highest quality over compression. For ASTC, this corresponds to using a 4x4 block size.
|
||||
</constant>
|
||||
<constant name="COMPRESS_PROFILE_COMPRESSED" value="2" enum="CompressProfile">
|
||||
Prioritizes some compression over quality. For ASTC, this corresponds to using a 6x6 block size.
|
||||
</constant>
|
||||
<constant name="COMPRESS_PROFILE_MAX_COMPRESSION" value="3" enum="CompressProfile">
|
||||
Prioritizes highest compression over quality. For ASTC, this corresponds to using an 8x8 block size.
|
||||
</constant>
|
||||
<constant name="COMPRESS_PROFILE_MAX" value="4" enum="CompressProfile">
|
||||
Represents the size of the [enum CompressProfile] enum.
|
||||
</constant>
|
||||
<constant name="ASTC_FORMAT_4x4" value="0" enum="ASTCFormat">
|
||||
Hint to indicate that the high quality 4×4 ASTC compression format should be used.
|
||||
</constant>
|
||||
|
||||
@@ -28,6 +28,14 @@
|
||||
If [code]false[/code], uses the faster but lower-quality S3TC compression on desktop platforms and ETC2 on mobile/web platforms. When using S3TC, DXT1 (BC1) is used for opaque textures and DXT5 (BC3) is used for transparent or normal map (RGTC) textures.
|
||||
BPTC and ASTC support VRAM compression for HDR textures, but S3TC and ETC2 do not (see [member compress/hdr_compression]).
|
||||
</member>
|
||||
<member name="compress/high_quality_mode" type="int" setter="" getter="" default="0">
|
||||
Controls the priorities of the VRAM compression when [member compress/high_quality] is enabled.
|
||||
[b]Automatic:[/b] Automatically adjusts the quality level based on the number of unique color channels present in the image. For ASTC, this corresponds to picking 8x8 when only one channel is detected (R, L), 6x6 when two channels are detected (RG, LA), and 4x4 in all other cases.
|
||||
[b]Max Quality:[/b] Prioritizes highest quality over compression. For ASTC, this corresponds to using a 4x4 block size.
|
||||
[b]Compressed:[/b] Prioritizes some compression over quality. For ASTC, this corresponds to using a 6x6 block size.
|
||||
[b]Max Compression:[/b] Prioritizes highest compression over quality. For ASTC, this corresponds to using an 8x8 block size.
|
||||
[b]Note:[/b] Currently, only the ASTC compressor uses this setting. Other compressors will ignore it.
|
||||
</member>
|
||||
<member name="compress/lossy_quality" type="float" setter="" getter="" default="0.7">
|
||||
The quality to use when using the [b]Lossy[/b] compression mode. Higher values result in better quality, at the cost of larger file sizes. Lossy quality does not affect memory usage of the imported texture, only its file size on disk.
|
||||
</member>
|
||||
|
||||
@@ -27,6 +27,14 @@
|
||||
If [code]false[/code], uses the faster but lower-quality S3TC compression on desktop platforms and ETC2 on mobile/web platforms. When using S3TC, DXT1 (BC1) is used for opaque textures and DXT5 (BC3) is used for transparent or normal map (RGTC) textures.
|
||||
BPTC and ASTC support VRAM compression for HDR textures, but S3TC and ETC2 do not (see [member compress/hdr_compression]).
|
||||
</member>
|
||||
<member name="compress/high_quality_mode" type="int" setter="" getter="" default="0">
|
||||
Controls the priorities of the VRAM compression when [member compress/high_quality] is enabled.
|
||||
[b]Automatic:[/b] Automatically adjusts the quality level based on the number of unique color channels present in the image. For ASTC, this corresponds to picking 8x8 when only one channel is detected (R, L), 6x6 when two channels are detected (RG, LA), and 4x4 in all other cases.
|
||||
[b]Max Quality:[/b] Prioritizes highest quality over compression. For ASTC, this corresponds to using a 4x4 block size.
|
||||
[b]Compressed:[/b] Prioritizes some compression over quality. For ASTC, this corresponds to using a 6x6 block size.
|
||||
[b]Max Compression:[/b] Prioritizes highest compression over quality. For ASTC, this corresponds to using an 8x8 block size.
|
||||
[b]Note:[/b] Currently, only the ASTC compressor uses this setting. Other compressors will ignore it.
|
||||
</member>
|
||||
<member name="compress/lossy_quality" type="float" setter="" getter="" default="0.7">
|
||||
The quality to use when using the [b]Lossy[/b] compression mode. Higher values result in better quality, at the cost of larger file sizes. Lossy quality does not affect memory usage of the imported texture, only its file size on disk.
|
||||
</member>
|
||||
|
||||
@@ -941,6 +941,26 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
|
||||
need_decompress = true;
|
||||
}
|
||||
} break;
|
||||
case Image::FORMAT_ASTC_6x6: {
|
||||
if (config->astc_supported) {
|
||||
r_gl_internal_format = _EXT_COMPRESSED_RGBA_ASTC_6x6_KHR;
|
||||
r_gl_format = GL_RGBA;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
r_compressed = true;
|
||||
} else {
|
||||
need_decompress = true;
|
||||
}
|
||||
} break;
|
||||
case Image::FORMAT_ASTC_6x6_HDR: {
|
||||
if (config->astc_hdr_supported) {
|
||||
r_gl_internal_format = _EXT_COMPRESSED_RGBA_ASTC_6x6_KHR;
|
||||
r_gl_format = GL_RGBA;
|
||||
r_gl_type = GL_UNSIGNED_BYTE;
|
||||
r_compressed = true;
|
||||
} else {
|
||||
need_decompress = true;
|
||||
}
|
||||
} break;
|
||||
case Image::FORMAT_ASTC_8x8: {
|
||||
if (config->astc_supported) {
|
||||
r_gl_internal_format = _EXT_COMPRESSED_RGBA_ASTC_8x8_KHR;
|
||||
|
||||
@@ -582,7 +582,6 @@ Vector<uint8_t> RenderingDeviceDriverMetal::texture_get_data(TextureID p_texture
|
||||
image_data.resize(tight_mip_size);
|
||||
|
||||
uint32_t pixel_size = get_image_format_pixel_size(tex_format);
|
||||
uint32_t pixel_rshift = get_compressed_image_format_pixel_rshift(tex_format);
|
||||
uint32_t blockw = 0, blockh = 0;
|
||||
get_compressed_image_format_block_dimensions(tex_format, blockw, blockh);
|
||||
|
||||
@@ -592,7 +591,7 @@ Vector<uint8_t> RenderingDeviceDriverMetal::texture_get_data(TextureID p_texture
|
||||
uint32_t bw = STEPIFY(tex_w, blockw);
|
||||
uint32_t bh = STEPIFY(tex_h, blockh);
|
||||
|
||||
uint32_t bytes_per_row = (bw * pixel_size) >> pixel_rshift;
|
||||
uint32_t bytes_per_row = get_compressed_image_format_pixels_shifted(tex_format, bw * pixel_size);
|
||||
uint32_t bytes_per_img = bytes_per_row * bh;
|
||||
uint32_t mip_size = bytes_per_img * tex_d;
|
||||
|
||||
|
||||
@@ -119,6 +119,9 @@ String ResourceImporterLayeredTexture::get_resource_type() const {
|
||||
}
|
||||
|
||||
bool ResourceImporterLayeredTexture::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const {
|
||||
if (p_option == "compress/high_quality_mode") {
|
||||
return bool(p_options["compress/high_quality"]);
|
||||
}
|
||||
if (p_option == "compress/lossy_quality" && p_options.has("compress/mode")) {
|
||||
return int(p_options["compress/mode"]) == COMPRESS_LOSSY;
|
||||
}
|
||||
@@ -142,7 +145,8 @@ String ResourceImporterLayeredTexture::get_preset_name(int p_idx) const {
|
||||
|
||||
void ResourceImporterLayeredTexture::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const {
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/mode", PROPERTY_HINT_ENUM, "Lossless,Lossy,VRAM Compressed,VRAM Uncompressed,Basis Universal", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 1));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress/high_quality"), false));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress/high_quality", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/high_quality_mode", PROPERTY_HINT_ENUM, "Automatic,Max Quality,Compressed,Max Compression"), 0));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "compress/lossy_quality", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.7));
|
||||
|
||||
Image::BasisUniversalPackerParams basisu_params;
|
||||
@@ -167,7 +171,7 @@ void ResourceImporterLayeredTexture::get_import_options(const String &p_path, Li
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceImporterLayeredTexture::_save_tex(Vector<Ref<Image>> p_images, const String &p_to_path, int p_compress_mode, float p_lossy, const Image::BasisUniversalPackerParams &p_basisu_params, Image::CompressMode p_vram_compression, Image::CompressSource p_csource, Image::UsedChannels used_channels, bool p_mipmaps, bool p_force_po2, Image::BPTCFormat p_bptc_format) {
|
||||
void ResourceImporterLayeredTexture::_save_tex(Vector<Ref<Image>> p_images, const String &p_to_path, int p_compress_mode, float p_lossy, const Image::BasisUniversalPackerParams &p_basisu_params, Image::CompressMode p_vram_compression, Image::CompressProfile p_vram_compression_profile, Image::CompressSource p_csource, Image::UsedChannels used_channels, bool p_mipmaps, bool p_force_po2, Image::BPTCFormat p_bptc_format) {
|
||||
Vector<Ref<Image>> mipmap_images; //for 3D
|
||||
|
||||
if (mode == MODE_3D) {
|
||||
@@ -287,11 +291,11 @@ void ResourceImporterLayeredTexture::_save_tex(Vector<Ref<Image>> p_images, cons
|
||||
}
|
||||
|
||||
for (int i = 0; i < p_images.size(); i++) {
|
||||
ResourceImporterTexture::save_to_ctex_format(f, p_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy, p_basisu_params, p_bptc_format);
|
||||
ResourceImporterTexture::save_to_ctex_format(f, p_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_vram_compression_profile, p_lossy, p_basisu_params, p_bptc_format);
|
||||
}
|
||||
|
||||
for (int i = 0; i < mipmap_images.size(); i++) {
|
||||
ResourceImporterTexture::save_to_ctex_format(f, mipmap_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy, p_basisu_params, p_bptc_format);
|
||||
ResourceImporterTexture::save_to_ctex_format(f, mipmap_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_vram_compression_profile, p_lossy, p_basisu_params, p_bptc_format);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,6 +303,7 @@ Error ResourceImporterLayeredTexture::import(ResourceUID::ID p_source_id, const
|
||||
int compress_mode = p_options["compress/mode"];
|
||||
float lossy = p_options["compress/lossy_quality"];
|
||||
bool high_quality = p_options["compress/high_quality"];
|
||||
int high_quality_mode = p_options["compress/high_quality_mode"];
|
||||
int hdr_compression = p_options["compress/hdr_compression"];
|
||||
bool mipmaps = p_options["mipmaps/generate"];
|
||||
|
||||
@@ -406,6 +411,7 @@ Error ResourceImporterLayeredTexture::import(ResourceUID::ID p_source_id, const
|
||||
texture_import->mipmaps = mipmaps;
|
||||
texture_import->used_channels = used_channels;
|
||||
texture_import->high_quality = high_quality;
|
||||
texture_import->compression_profile = (Image::CompressProfile)(high_quality_mode);
|
||||
|
||||
texture_import->basisu_params = basisu_params;
|
||||
|
||||
@@ -504,7 +510,7 @@ void ResourceImporterLayeredTexture::_check_compress_ctex(const String &p_source
|
||||
if (r_texture_import->compress_mode != COMPRESS_VRAM_COMPRESSED) {
|
||||
// Import normally.
|
||||
_save_tex(*r_texture_import->slices, r_texture_import->save_path + "." + extension, r_texture_import->compress_mode, r_texture_import->lossy, r_texture_import->basisu_params,
|
||||
Image::COMPRESS_S3TC /* IGNORED */, *r_texture_import->csource, r_texture_import->used_channels, r_texture_import->mipmaps, false, Image::BPTC_DETECT);
|
||||
Image::COMPRESS_S3TC /* IGNORED */, Image::COMPRESS_PROFILE_AUTOMATIC /* IGNORED */, *r_texture_import->csource, r_texture_import->used_channels, r_texture_import->mipmaps, false, Image::BPTC_DETECT);
|
||||
return;
|
||||
}
|
||||
// Must import in all formats, in order of priority (so platform chooses the best supported one. IE, etc2 over etc).
|
||||
@@ -560,7 +566,7 @@ void ResourceImporterLayeredTexture::_check_compress_ctex(const String &p_source
|
||||
|
||||
if (use_uncompressed) {
|
||||
_save_tex(*r_texture_import->slices, r_texture_import->save_path + "." + extension, COMPRESS_VRAM_UNCOMPRESSED, r_texture_import->lossy, r_texture_import->basisu_params,
|
||||
Image::COMPRESS_S3TC /* IGNORED */, *r_texture_import->csource, r_texture_import->used_channels, r_texture_import->mipmaps, false, Image::BPTC_DETECT);
|
||||
Image::COMPRESS_S3TC /* IGNORED */, Image::COMPRESS_PROFILE_AUTOMATIC /* IGNORED */, *r_texture_import->csource, r_texture_import->used_channels, r_texture_import->mipmaps, false, Image::BPTC_DETECT);
|
||||
} else {
|
||||
if (can_s3tc_bptc) {
|
||||
Image::CompressMode image_compress_mode;
|
||||
@@ -574,7 +580,7 @@ void ResourceImporterLayeredTexture::_check_compress_ctex(const String &p_source
|
||||
image_compress_mode = Image::COMPRESS_S3TC;
|
||||
image_compress_format = "s3tc";
|
||||
}
|
||||
_save_tex(*r_texture_import->slices, r_texture_import->save_path + "." + image_compress_format + "." + extension, r_texture_import->compress_mode, r_texture_import->lossy, r_texture_import->basisu_params, image_compress_mode, *r_texture_import->csource, r_texture_import->used_channels, r_texture_import->mipmaps, true, image_bptc_format);
|
||||
_save_tex(*r_texture_import->slices, r_texture_import->save_path + "." + image_compress_format + "." + extension, r_texture_import->compress_mode, r_texture_import->lossy, r_texture_import->basisu_params, image_compress_mode, r_texture_import->compression_profile, *r_texture_import->csource, r_texture_import->used_channels, r_texture_import->mipmaps, true, image_bptc_format);
|
||||
r_texture_import->platform_variants->push_back(image_compress_format);
|
||||
}
|
||||
|
||||
@@ -588,7 +594,7 @@ void ResourceImporterLayeredTexture::_check_compress_ctex(const String &p_source
|
||||
image_compress_mode = Image::COMPRESS_ETC2;
|
||||
image_compress_format = "etc2";
|
||||
}
|
||||
_save_tex(*r_texture_import->slices, r_texture_import->save_path + "." + image_compress_format + "." + extension, r_texture_import->compress_mode, r_texture_import->lossy, r_texture_import->basisu_params, image_compress_mode, *r_texture_import->csource, r_texture_import->used_channels, r_texture_import->mipmaps, true, Image::BPTC_DETECT);
|
||||
_save_tex(*r_texture_import->slices, r_texture_import->save_path + "." + image_compress_format + "." + extension, r_texture_import->compress_mode, r_texture_import->lossy, r_texture_import->basisu_params, image_compress_mode, r_texture_import->compression_profile, *r_texture_import->csource, r_texture_import->used_channels, r_texture_import->mipmaps, true, Image::BPTC_DETECT);
|
||||
r_texture_import->platform_variants->push_back(image_compress_format);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ public:
|
||||
int hdr_compression = 0;
|
||||
bool mipmaps = true;
|
||||
bool high_quality = false;
|
||||
Image::CompressProfile compression_profile = Image::COMPRESS_PROFILE_AUTOMATIC;
|
||||
Image::UsedChannels used_channels = Image::USED_CHANNELS_RGBA;
|
||||
};
|
||||
|
||||
@@ -111,7 +112,7 @@ public:
|
||||
virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override;
|
||||
virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override;
|
||||
|
||||
void _save_tex(Vector<Ref<Image>> p_images, const String &p_to_path, int p_compress_mode, float p_lossy, const Image::BasisUniversalPackerParams &p_basisu_params, Image::CompressMode p_vram_compression, Image::CompressSource p_csource, Image::UsedChannels used_channels, bool p_mipmaps, bool p_force_po2, Image::BPTCFormat p_bptc_format);
|
||||
void _save_tex(Vector<Ref<Image>> p_images, const String &p_to_path, int p_compress_mode, float p_lossy, const Image::BasisUniversalPackerParams &p_basisu_params, Image::CompressMode p_vram_compression, Image::CompressProfile p_vram_compression_profile, Image::CompressSource p_csource, Image::UsedChannels used_channels, bool p_mipmaps, bool p_force_po2, Image::BPTCFormat p_bptc_format);
|
||||
|
||||
virtual Error import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override;
|
||||
|
||||
|
||||
@@ -180,7 +180,9 @@ String ResourceImporterTexture::get_resource_type() const {
|
||||
}
|
||||
|
||||
bool ResourceImporterTexture::get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const {
|
||||
if (p_option == "compress/high_quality" || p_option == "compress/hdr_compression") {
|
||||
if (p_option == "compress/high_quality_mode") {
|
||||
return bool(p_options["compress/high_quality"]);
|
||||
} else if (p_option == "compress/high_quality" || p_option == "compress/hdr_compression") {
|
||||
int compress_mode = int(p_options["compress/mode"]);
|
||||
if (compress_mode != COMPRESS_VRAM_COMPRESSED) {
|
||||
return false;
|
||||
@@ -230,7 +232,8 @@ String ResourceImporterTexture::get_preset_name(int p_idx) const {
|
||||
|
||||
void ResourceImporterTexture::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const {
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/mode", PROPERTY_HINT_ENUM, "Lossless,Lossy,VRAM Compressed,VRAM Uncompressed,Basis Universal", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), p_preset == PRESET_3D ? 2 : 0));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress/high_quality"), false));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress/high_quality", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/high_quality_mode", PROPERTY_HINT_ENUM, "Automatic,Max Quality,Compressed,Max Compression"), 0));
|
||||
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "compress/lossy_quality", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.7));
|
||||
|
||||
Image::BasisUniversalPackerParams basisu_params;
|
||||
@@ -269,7 +272,7 @@ void ResourceImporterTexture::get_import_options(const String &p_path, List<Impo
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceImporterTexture::save_to_ctex_format(Ref<FileAccess> f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality, const Image::BasisUniversalPackerParams &p_basisu_params, Image::BPTCFormat p_bptc_format) {
|
||||
void ResourceImporterTexture::save_to_ctex_format(Ref<FileAccess> f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, Image::CompressProfile p_compress_profile, float p_lossy_quality, const Image::BasisUniversalPackerParams &p_basisu_params, Image::BPTCFormat p_bptc_format) {
|
||||
switch (p_compress_mode) {
|
||||
case COMPRESS_LOSSLESS: {
|
||||
bool lossless_force_png = GLOBAL_GET("rendering/textures/lossless_compression/force_png") || !Image::_webp_mem_loader_func; // WebP module disabled or png is forced.
|
||||
@@ -314,7 +317,7 @@ void ResourceImporterTexture::save_to_ctex_format(Ref<FileAccess> f, const Ref<I
|
||||
} break;
|
||||
case COMPRESS_VRAM_COMPRESSED: {
|
||||
Ref<Image> image = p_image->duplicate();
|
||||
image->_compress_from_channels(p_compress_format, p_channels, Image::ASTC_FORMAT_4x4, p_bptc_format);
|
||||
image->_compress_from_channels(p_compress_format, p_channels, p_compress_profile, p_bptc_format);
|
||||
|
||||
f->store_32(CompressedTexture2D::DATA_FORMAT_IMAGE);
|
||||
f->store_16(image->get_width());
|
||||
@@ -349,7 +352,7 @@ void ResourceImporterTexture::save_to_ctex_format(Ref<FileAccess> f, const Ref<I
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceImporterTexture::_save_ctex(const Ref<Image> &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, const Image::BasisUniversalPackerParams &p_basisu_params, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_roughness, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref<Image> &p_normal, Image::RoughnessChannel p_roughness_channel) {
|
||||
void ResourceImporterTexture::_save_ctex(const Ref<Image> &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, const Image::BasisUniversalPackerParams &p_basisu_params, Image::CompressMode p_vram_compression, Image::CompressProfile p_vram_compression_profile, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_roughness, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref<Image> &p_normal, Image::RoughnessChannel p_roughness_channel) {
|
||||
Ref<FileAccess> f = FileAccess::open(p_to_path, FileAccess::WRITE);
|
||||
ERR_FAIL_COND(f.is_null());
|
||||
|
||||
@@ -429,7 +432,7 @@ void ResourceImporterTexture::_save_ctex(const Ref<Image> &p_image, const String
|
||||
used_channels = image->detect_used_channels(comp_source);
|
||||
}
|
||||
|
||||
save_to_ctex_format(f, image, p_compress_mode, used_channels, p_vram_compression, p_lossy_quality, p_basisu_params, Image::BPTC_DETECT);
|
||||
save_to_ctex_format(f, image, p_compress_mode, used_channels, p_vram_compression, p_vram_compression_profile, p_lossy_quality, p_basisu_params, Image::BPTC_DETECT);
|
||||
}
|
||||
|
||||
void ResourceImporterTexture::_save_editor_meta(const Dictionary &p_metadata, const String &p_to_path) {
|
||||
@@ -707,6 +710,7 @@ Error ResourceImporterTexture::import(ResourceUID::ID p_source_id, const String
|
||||
const int normal = p_options["compress/normal_map"];
|
||||
const int hdr_compression = p_options["compress/hdr_compression"];
|
||||
const int high_quality = p_options["compress/high_quality"];
|
||||
const int high_quality_mode = p_options["compress/high_quality_mode"];
|
||||
|
||||
// Mipmaps.
|
||||
const bool mipmaps = p_options["mipmaps/generate"];
|
||||
@@ -926,12 +930,13 @@ Error ResourceImporterTexture::import(ResourceUID::ID p_source_id, const String
|
||||
}
|
||||
|
||||
if (force_uncompressed) {
|
||||
_save_ctex(image, p_save_path + ".ctex", COMPRESS_VRAM_UNCOMPRESSED, lossy, basisu_params, Image::COMPRESS_S3TC /* This is ignored. */,
|
||||
_save_ctex(image, p_save_path + ".ctex", COMPRESS_VRAM_UNCOMPRESSED, lossy, basisu_params, Image::COMPRESS_S3TC /* This is ignored. */, Image::COMPRESS_PROFILE_AUTOMATIC /* This is ignored. */,
|
||||
mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel);
|
||||
} else {
|
||||
if (can_s3tc_bptc) {
|
||||
Image::CompressMode image_compress_mode;
|
||||
String image_compress_format;
|
||||
Image::CompressProfile image_compress_profile = (Image::CompressProfile)(high_quality_mode);
|
||||
if (high_quality || is_hdr) {
|
||||
image_compress_mode = Image::COMPRESS_BPTC;
|
||||
image_compress_format = "bptc";
|
||||
@@ -940,7 +945,7 @@ Error ResourceImporterTexture::import(ResourceUID::ID p_source_id, const String
|
||||
image_compress_format = "s3tc";
|
||||
}
|
||||
|
||||
_save_ctex(image, p_save_path + "." + image_compress_format + ".ctex", compress_mode, lossy, basisu_params, image_compress_mode, mipmaps,
|
||||
_save_ctex(image, p_save_path + "." + image_compress_format + ".ctex", compress_mode, lossy, basisu_params, image_compress_mode, image_compress_profile, mipmaps,
|
||||
stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel);
|
||||
r_platform_variants->push_back(image_compress_format);
|
||||
}
|
||||
@@ -948,6 +953,7 @@ Error ResourceImporterTexture::import(ResourceUID::ID p_source_id, const String
|
||||
if (can_etc2_astc) {
|
||||
Image::CompressMode image_compress_mode;
|
||||
String image_compress_format;
|
||||
Image::CompressProfile image_compress_profile = (Image::CompressProfile)(high_quality_mode);
|
||||
if (high_quality || is_hdr) {
|
||||
image_compress_mode = Image::COMPRESS_ASTC;
|
||||
image_compress_format = "astc";
|
||||
@@ -956,19 +962,19 @@ Error ResourceImporterTexture::import(ResourceUID::ID p_source_id, const String
|
||||
image_compress_format = "etc2";
|
||||
}
|
||||
|
||||
_save_ctex(image, p_save_path + "." + image_compress_format + ".ctex", compress_mode, lossy, basisu_params, image_compress_mode, mipmaps, stream, detect_3d,
|
||||
_save_ctex(image, p_save_path + "." + image_compress_format + ".ctex", compress_mode, lossy, basisu_params, image_compress_mode, image_compress_profile, mipmaps, stream, detect_3d,
|
||||
detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel);
|
||||
r_platform_variants->push_back(image_compress_format);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Import normally.
|
||||
_save_ctex(image, p_save_path + ".ctex", compress_mode, lossy, basisu_params, Image::COMPRESS_S3TC /* This is ignored. */,
|
||||
_save_ctex(image, p_save_path + ".ctex", compress_mode, lossy, basisu_params, Image::COMPRESS_S3TC /* This is ignored. */, Image::COMPRESS_PROFILE_AUTOMATIC /* This is ignored. */,
|
||||
mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel);
|
||||
}
|
||||
|
||||
if (editor_image.is_valid()) {
|
||||
_save_ctex(editor_image, p_save_path + ".editor.ctex", compress_mode, lossy, basisu_params, Image::COMPRESS_S3TC /* This is ignored. */,
|
||||
_save_ctex(editor_image, p_save_path + ".editor.ctex", compress_mode, lossy, basisu_params, Image::COMPRESS_S3TC /* This is ignored. */, Image::COMPRESS_PROFILE_AUTOMATIC /* This is ignored. */,
|
||||
mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel);
|
||||
|
||||
// Generate and save editor-specific metadata, which we cannot save to the .import file.
|
||||
|
||||
@@ -86,7 +86,7 @@ protected:
|
||||
static ResourceImporterTexture *singleton;
|
||||
static const char *compression_formats[];
|
||||
|
||||
void _save_ctex(const Ref<Image> &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, const Image::BasisUniversalPackerParams &p_basisu_params, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_srgb, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref<Image> &p_normal, Image::RoughnessChannel p_roughness_channel);
|
||||
void _save_ctex(const Ref<Image> &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, const Image::BasisUniversalPackerParams &p_basisu_params, Image::CompressMode p_vram_compression, Image::CompressProfile p_vram_compression_profile, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_srgb, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref<Image> &p_normal, Image::RoughnessChannel p_roughness_channel);
|
||||
void _save_editor_meta(const Dictionary &p_metadata, const String &p_to_path);
|
||||
Dictionary _load_editor_meta(const String &p_to_path) const;
|
||||
|
||||
@@ -95,7 +95,7 @@ protected:
|
||||
static inline void _invert_y_channel(Ref<Image> &r_image);
|
||||
|
||||
public:
|
||||
static void save_to_ctex_format(Ref<FileAccess> f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality, const Image::BasisUniversalPackerParams &p_basisu_params, Image::BPTCFormat p_bptc_format);
|
||||
static void save_to_ctex_format(Ref<FileAccess> f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, Image::CompressProfile p_compress_profile, float p_lossy_quality, const Image::BasisUniversalPackerParams &p_basisu_params, Image::BPTCFormat p_bptc_format);
|
||||
|
||||
static ResourceImporterTexture *get_singleton() { return singleton; }
|
||||
virtual String get_importer_name() const override;
|
||||
|
||||
@@ -195,8 +195,8 @@ void TexturePreview::_update_metadata_label_text() {
|
||||
if (format != Image::FORMAT_MAX) {
|
||||
// Avoid signed integer overflow that could occur with huge texture sizes by casting everything to uint64_t.
|
||||
uint64_t memory = uint64_t(resolution.x) * uint64_t(resolution.y) * uint64_t(Image::get_format_pixel_size(format));
|
||||
// Handle VRAM-compressed formats that are stored with 4 bpp.
|
||||
memory >>= Image::get_format_pixel_rshift(format);
|
||||
// Handle VRAM-compressed formats.
|
||||
memory = Image::get_format_pixels_shifted(format, memory);
|
||||
|
||||
float mipmaps_multiplier = 1.0;
|
||||
float mipmap_increase = 0.25;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
GH-115003
|
||||
---------
|
||||
Validate extension JSON: Error: Field 'classes/Image/methods/compress/arguments/2': default_value changed value in new API, from "0" to "1".
|
||||
Validate extension JSON: Error: Field 'classes/Image/methods/compress/arguments/2': type changed value in new API, from "enum::Image.ASTCFormat" to "enum::Image.CompressProfile".
|
||||
Validate extension JSON: Error: Field 'classes/Image/methods/compress_from_channels/arguments/2': default_value changed value in new API, from "0" to "1".
|
||||
Validate extension JSON: Error: Field 'classes/Image/methods/compress_from_channels/arguments/2': type changed value in new API, from "enum::Image.ASTCFormat" to "enum::Image.CompressProfile".
|
||||
|
||||
The ASTCFormat argument has been changed to a more abstract parameter that can be used by more compressors.
|
||||
Compatibility methods have been registered.
|
||||
@@ -36,7 +36,22 @@
|
||||
#include <astcenc.h>
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
void _compress_astc(Image *r_img, Image::ASTCFormat p_format) {
|
||||
Image::CompressProfile _pick_profile_from_channels(Image::UsedChannels p_channels) {
|
||||
switch (p_channels) {
|
||||
case Image::USED_CHANNELS_L:
|
||||
case Image::USED_CHANNELS_R:
|
||||
return Image::COMPRESS_PROFILE_MAX_COMPRESSION;
|
||||
case Image::USED_CHANNELS_LA:
|
||||
case Image::USED_CHANNELS_RG:
|
||||
return Image::COMPRESS_PROFILE_COMPRESSED;
|
||||
case Image::USED_CHANNELS_RGB:
|
||||
case Image::USED_CHANNELS_RGBA:
|
||||
default:
|
||||
return Image::COMPRESS_PROFILE_MAX_QUALITY;
|
||||
}
|
||||
}
|
||||
|
||||
void _compress_astc(Image *r_img, Image::UsedChannels p_channels, Image::CompressProfile p_profile) {
|
||||
const uint64_t start_time = OS::get_singleton()->get_ticks_msec();
|
||||
|
||||
if (r_img->is_compressed()) {
|
||||
@@ -58,23 +73,27 @@ void _compress_astc(Image *r_img, Image::ASTCFormat p_format) {
|
||||
const astcenc_profile profile = is_hdr ? ASTCENC_PRF_HDR : ASTCENC_PRF_LDR;
|
||||
|
||||
Image::Format target_format = Image::FORMAT_MAX;
|
||||
unsigned int block_x = 4;
|
||||
unsigned int block_y = 4;
|
||||
unsigned int block_x = 1, block_y = 1;
|
||||
if (p_profile == Image::COMPRESS_PROFILE_AUTOMATIC) {
|
||||
// Automatic profile will automatically pick one of the other profiles based on the amount of channels currently in use.
|
||||
p_profile = _pick_profile_from_channels(p_channels);
|
||||
}
|
||||
|
||||
if (p_format == Image::ASTCFormat::ASTC_FORMAT_4x4) {
|
||||
if (is_hdr) {
|
||||
target_format = Image::FORMAT_ASTC_4x4_HDR;
|
||||
} else {
|
||||
target_format = Image::FORMAT_ASTC_4x4;
|
||||
}
|
||||
} else if (p_format == Image::ASTCFormat::ASTC_FORMAT_8x8) {
|
||||
if (is_hdr) {
|
||||
target_format = Image::FORMAT_ASTC_8x8_HDR;
|
||||
} else {
|
||||
target_format = Image::FORMAT_ASTC_8x8;
|
||||
}
|
||||
block_x = 8;
|
||||
block_y = 8;
|
||||
switch (p_profile) {
|
||||
case Image::COMPRESS_PROFILE_MAX_QUALITY:
|
||||
target_format = is_hdr ? Image::FORMAT_ASTC_4x4_HDR : Image::FORMAT_ASTC_4x4;
|
||||
block_x = block_y = 4;
|
||||
break;
|
||||
case Image::COMPRESS_PROFILE_COMPRESSED:
|
||||
target_format = is_hdr ? Image::FORMAT_ASTC_6x6_HDR : Image::FORMAT_ASTC_6x6;
|
||||
block_x = block_y = 6;
|
||||
break;
|
||||
case Image::COMPRESS_PROFILE_MAX_COMPRESSION:
|
||||
target_format = is_hdr ? Image::FORMAT_ASTC_8x8_HDR : Image::FORMAT_ASTC_8x8;
|
||||
block_x = block_y = 8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Compress image data and (if required) mipmaps.
|
||||
@@ -195,6 +214,16 @@ void _decompress_astc(Image *r_img) {
|
||||
block_y = 4;
|
||||
is_hdr = true;
|
||||
} break;
|
||||
case Image::FORMAT_ASTC_6x6: {
|
||||
block_x = 6;
|
||||
block_y = 6;
|
||||
is_hdr = false;
|
||||
} break;
|
||||
case Image::FORMAT_ASTC_6x6_HDR: {
|
||||
block_x = 6;
|
||||
block_y = 6;
|
||||
is_hdr = true;
|
||||
} break;
|
||||
case Image::FORMAT_ASTC_8x8: {
|
||||
block_x = 8;
|
||||
block_y = 8;
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include "core/io/image.h"
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
void _compress_astc(Image *r_img, Image::ASTCFormat p_format);
|
||||
void _compress_astc(Image *r_img, Image::UsedChannels p_channels, Image::CompressProfile p_profile);
|
||||
#endif
|
||||
|
||||
void _decompress_astc(Image *r_img);
|
||||
|
||||
@@ -199,7 +199,6 @@ void image_compress_cvtt(Image *p_image, Image::UsedChannels p_channels, Image::
|
||||
int64_t target_size = Image::get_image_data_size(w, h, target_format, p_image->has_mipmaps());
|
||||
int mm_count = p_image->has_mipmaps() ? Image::get_image_required_mipmaps(w, h, target_format) : 0;
|
||||
data.resize(target_size);
|
||||
int shift = Image::get_format_pixel_rshift(target_format);
|
||||
|
||||
uint8_t *wb = data.ptrw();
|
||||
|
||||
@@ -282,7 +281,7 @@ void image_compress_cvtt(Image *p_image, Image::UsedChannels p_channels, Image::
|
||||
out_bytes += 16 * (bw / 4);
|
||||
}
|
||||
|
||||
dst_ofs += (MAX(4, bw) * MAX(4, bh)) >> shift;
|
||||
dst_ofs += Image::get_format_pixels_shifted(target_format, MAX(4, bw) * MAX(4, bh));
|
||||
}
|
||||
|
||||
const CVTTCompressionRowTask *tasks_rb = tasks.ptr();
|
||||
|
||||
@@ -267,6 +267,12 @@ static Ref<Image> load_from_file_access(Ref<FileAccess> f, Error *r_error) {
|
||||
case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
|
||||
format = Image::FORMAT_ASTC_4x4_HDR;
|
||||
break;
|
||||
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
|
||||
format = Image::FORMAT_ASTC_6x6;
|
||||
break;
|
||||
case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
|
||||
format = Image::FORMAT_ASTC_6x6_HDR;
|
||||
break;
|
||||
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
|
||||
format = Image::FORMAT_ASTC_8x8;
|
||||
break;
|
||||
@@ -487,6 +493,12 @@ static Ref<Image> load_from_file_access(Ref<FileAccess> f, Error *r_error) {
|
||||
case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
|
||||
format = Image::FORMAT_ASTC_4x4_HDR;
|
||||
break;
|
||||
case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
|
||||
format = Image::FORMAT_ASTC_6x6;
|
||||
break;
|
||||
case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
|
||||
format = Image::FORMAT_ASTC_6x6_HDR;
|
||||
break;
|
||||
case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
|
||||
format = Image::FORMAT_ASTC_8x8;
|
||||
break;
|
||||
@@ -511,7 +523,6 @@ static Ref<Image> load_from_file_access(Ref<FileAccess> f, Error *r_error) {
|
||||
// KTX use 4-bytes padding, don't use mipmaps if padding is effective
|
||||
// TODO: unpad dynamically
|
||||
int pixel_size = Image::get_format_pixel_size(format);
|
||||
int pixel_rshift = Image::get_format_pixel_rshift(format);
|
||||
int block = Image::get_format_block_size(format);
|
||||
int minw, minh;
|
||||
Image::get_format_min_pixel_size(format, minw, minh);
|
||||
@@ -523,7 +534,7 @@ static Ref<Image> load_from_file_access(Ref<FileAccess> f, Error *r_error) {
|
||||
size_t bh = h % block != 0 ? h + (block - h % block) : h;
|
||||
size_t s = bw * bh;
|
||||
s *= pixel_size;
|
||||
s >>= pixel_rshift;
|
||||
s = Image::get_format_pixels_shifted(format, s);
|
||||
if (mip_size != static_cast<ktx_size_t>(s)) {
|
||||
if (!i) {
|
||||
ktxTexture_Destroy(ktx_texture);
|
||||
|
||||
@@ -47,7 +47,7 @@ static PortableCompressedTexture2D::CompressionMode get_expected_compression_mod
|
||||
return PortableCompressedTexture2D::COMPRESSION_MODE_ETC2;
|
||||
} else if (format >= Image::FORMAT_BPTC_RGBA && format <= Image::FORMAT_BPTC_RGBFU) {
|
||||
return PortableCompressedTexture2D::COMPRESSION_MODE_BPTC;
|
||||
} else if (format >= Image::FORMAT_ASTC_4x4 && format <= Image::FORMAT_ASTC_8x8_HDR) {
|
||||
} else if ((format >= Image::FORMAT_ASTC_4x4 && format <= Image::FORMAT_ASTC_8x8_HDR) || (format >= Image::FORMAT_ASTC_6x6 && format <= Image::FORMAT_ASTC_6x6_HDR)) {
|
||||
return PortableCompressedTexture2D::COMPRESSION_MODE_ASTC;
|
||||
}
|
||||
ERR_FAIL_V(PortableCompressedTexture2D::COMPRESSION_MODE_LOSSLESS);
|
||||
|
||||
@@ -1589,6 +1589,14 @@ RID TextureStorage::texture_create_from_native_handle(RSE::TextureType p_type, I
|
||||
format = RD::DATA_FORMAT_ASTC_4x4_SFLOAT_BLOCK;
|
||||
break;
|
||||
|
||||
case Image::FORMAT_ASTC_6x6:
|
||||
format = RD::DATA_FORMAT_ASTC_6x6_UNORM_BLOCK;
|
||||
break;
|
||||
|
||||
case Image::FORMAT_ASTC_6x6_HDR:
|
||||
format = RD::DATA_FORMAT_ASTC_6x6_SFLOAT_BLOCK;
|
||||
break;
|
||||
|
||||
case Image::FORMAT_ASTC_8x8:
|
||||
format = RD::DATA_FORMAT_ASTC_8x8_UNORM_BLOCK;
|
||||
break;
|
||||
@@ -2720,6 +2728,38 @@ Ref<Image> TextureStorage::_validate_texture_format(const Ref<Image> &p_image, T
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
|
||||
|
||||
} break; // astc 4x4 HDR
|
||||
case Image::FORMAT_ASTC_6x6: {
|
||||
if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ASTC_6x6_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
|
||||
r_format.format = RD::DATA_FORMAT_ASTC_6x6_UNORM_BLOCK;
|
||||
r_format.format_srgb = RD::DATA_FORMAT_ASTC_6x6_SRGB_BLOCK;
|
||||
} else {
|
||||
//not supported, reconvert
|
||||
image->decompress();
|
||||
r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
|
||||
r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
|
||||
image->convert(Image::FORMAT_RGBA8);
|
||||
}
|
||||
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
|
||||
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
|
||||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
|
||||
|
||||
} break; // astc 6x6
|
||||
case Image::FORMAT_ASTC_6x6_HDR: {
|
||||
if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ASTC_6x6_SFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
|
||||
r_format.format = RD::DATA_FORMAT_ASTC_6x6_SFLOAT_BLOCK;
|
||||
} else {
|
||||
//not supported, reconvert
|
||||
image->decompress();
|
||||
r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
image->convert(Image::FORMAT_RGBAH);
|
||||
}
|
||||
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
|
||||
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
|
||||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
|
||||
|
||||
} break; // astc 8x8 HDR
|
||||
case Image::FORMAT_ASTC_8x8: {
|
||||
if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ASTC_8x8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
|
||||
r_format.format = RD::DATA_FORMAT_ASTC_8x8_UNORM_BLOCK;
|
||||
@@ -3209,6 +3249,31 @@ void TextureStorage::_texture_format_from_rd(RD::DataFormat p_rd_format, Texture
|
||||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
|
||||
} break; // astc 4x4
|
||||
case RD::DATA_FORMAT_ASTC_6x6_UNORM_BLOCK: {
|
||||
r_format.image_format = Image::FORMAT_ASTC_6x6;
|
||||
r_format.rd_format = RD::DATA_FORMAT_ASTC_6x6_UNORM_BLOCK;
|
||||
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
|
||||
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
|
||||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
|
||||
} break;
|
||||
case RD::DATA_FORMAT_ASTC_6x6_SRGB_BLOCK: {
|
||||
r_format.image_format = Image::FORMAT_ASTC_6x6;
|
||||
r_format.rd_format = RD::DATA_FORMAT_ASTC_6x6_UNORM_BLOCK;
|
||||
r_format.rd_format_srgb = RD::DATA_FORMAT_ASTC_6x6_SRGB_BLOCK;
|
||||
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
|
||||
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
|
||||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
|
||||
} break;
|
||||
case RD::DATA_FORMAT_ASTC_6x6_SFLOAT_BLOCK: {
|
||||
r_format.image_format = Image::FORMAT_ASTC_6x6_HDR;
|
||||
r_format.rd_format = RD::DATA_FORMAT_ASTC_6x6_SFLOAT_BLOCK;
|
||||
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R;
|
||||
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G;
|
||||
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
|
||||
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A;
|
||||
} break; // astc 8x8
|
||||
case RD::DATA_FORMAT_ASTC_8x8_UNORM_BLOCK: {
|
||||
// Q: Do we do as we do below, just create the sRGB variant?
|
||||
r_format.image_format = Image::FORMAT_ASTC_8x8;
|
||||
|
||||
@@ -2122,7 +2122,6 @@ Error RenderingDevice::_texture_initialize(RID p_texture, uint32_t p_layer, cons
|
||||
get_compressed_image_format_block_dimensions(texture->format, block_w, block_h);
|
||||
|
||||
uint32_t pixel_size = get_image_format_pixel_size(texture->format);
|
||||
uint32_t pixel_rshift = get_compressed_image_format_pixel_rshift(texture->format);
|
||||
uint32_t block_size = get_compressed_image_format_block_byte_size(texture->format);
|
||||
|
||||
// The algorithm operates on two passes, one to figure out the total size the staging buffer will require to allocate and another one where the copy is actually performed.
|
||||
@@ -2180,11 +2179,10 @@ Error RenderingDevice::_texture_initialize(RID p_texture, uint32_t p_layer, cons
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t pitch = (width * pixel_size * block_w) >> pixel_rshift;
|
||||
uint32_t pitch = get_compressed_image_format_pixels_shifted(texture->format, width * pixel_size * block_w);
|
||||
uint32_t pitch_step = driver->api_trait_get(RDD::API_TRAIT_TEXTURE_DATA_ROW_PITCH_STEP);
|
||||
pitch = STEPIFY(pitch, pitch_step);
|
||||
uint32_t to_allocate = pitch * height;
|
||||
to_allocate >>= pixel_rshift;
|
||||
uint32_t to_allocate = get_compressed_image_format_pixels_shifted(texture->format, pitch * height);
|
||||
|
||||
if (copy_pass) {
|
||||
const uint8_t *read_ptr_mipmap_layer = read_ptr_mipmap + (tight_mip_size / depth) * z;
|
||||
@@ -2282,7 +2280,6 @@ Error RenderingDevice::texture_update(RID p_texture, uint32_t p_layer, const Vec
|
||||
get_compressed_image_format_block_dimensions(texture->format, block_w, block_h);
|
||||
|
||||
uint32_t pixel_size = get_image_format_pixel_size(texture->format);
|
||||
uint32_t pixel_rshift = get_compressed_image_format_pixel_rshift(texture->format);
|
||||
uint32_t block_size = get_compressed_image_format_block_byte_size(texture->format);
|
||||
|
||||
uint32_t region_size = texture_upload_region_size_px;
|
||||
@@ -2317,7 +2314,7 @@ Error RenderingDevice::texture_update(RID p_texture, uint32_t p_layer, const Vec
|
||||
uint32_t region_logic_w = MIN(region_size, logic_width - x);
|
||||
uint32_t region_logic_h = MIN(region_size, logic_height - y);
|
||||
|
||||
uint32_t region_pitch = (region_w * pixel_size * block_w) >> pixel_rshift;
|
||||
uint32_t region_pitch = get_compressed_image_format_pixels_shifted(texture->format, region_w * pixel_size * block_w);
|
||||
uint32_t pitch_step = driver->api_trait_get(RDD::API_TRAIT_TEXTURE_DATA_ROW_PITCH_STEP);
|
||||
region_pitch = STEPIFY(region_pitch, pitch_step);
|
||||
uint32_t to_allocate = region_pitch * region_h;
|
||||
@@ -2811,10 +2808,8 @@ Error RenderingDevice::texture_get_data_async(RID p_texture, uint32_t p_layer, c
|
||||
uint32_t block_w, block_h;
|
||||
get_compressed_image_format_block_dimensions(tex->format, block_w, block_h);
|
||||
|
||||
uint32_t pixel_size = get_image_format_pixel_size(tex->format);
|
||||
uint32_t pixel_rshift = get_compressed_image_format_pixel_rshift(tex->format);
|
||||
|
||||
uint32_t w, h, d;
|
||||
uint32_t pixel_size = get_image_format_pixel_size(tex->format);
|
||||
uint32_t required_align = driver->api_trait_get(RDD::API_TRAIT_TEXTURE_TRANSFER_ALIGNMENT);
|
||||
uint32_t pitch_step = driver->api_trait_get(RDD::API_TRAIT_TEXTURE_DATA_ROW_PITCH_STEP);
|
||||
uint32_t region_size = texture_download_region_size_px;
|
||||
@@ -2837,7 +2832,7 @@ Error RenderingDevice::texture_get_data_async(RID p_texture, uint32_t p_layer, c
|
||||
|
||||
uint32_t region_logic_w = MIN(region_size, logic_w - x);
|
||||
uint32_t region_logic_h = MIN(region_size, logic_h - y);
|
||||
uint32_t region_pitch = (region_w * pixel_size * block_w) >> pixel_rshift;
|
||||
uint32_t region_pitch = get_compressed_image_format_pixels_shifted(tex->format, region_w * pixel_size * block_w);
|
||||
region_pitch = STEPIFY(region_pitch, pitch_step);
|
||||
|
||||
uint32_t to_allocate = region_pitch * region_h;
|
||||
|
||||
@@ -587,6 +587,12 @@ void RenderingDeviceCommons::get_compressed_image_format_block_dimensions(DataFo
|
||||
r_w = 4;
|
||||
r_h = 4;
|
||||
} break;
|
||||
case DATA_FORMAT_ASTC_6x6_UNORM_BLOCK:
|
||||
case DATA_FORMAT_ASTC_6x6_SRGB_BLOCK:
|
||||
case DATA_FORMAT_ASTC_6x6_SFLOAT_BLOCK: {
|
||||
r_w = 6;
|
||||
r_h = 6;
|
||||
} break;
|
||||
case DATA_FORMAT_ASTC_5x4_UNORM_BLOCK: // Unsupported
|
||||
case DATA_FORMAT_ASTC_5x4_SRGB_BLOCK:
|
||||
case DATA_FORMAT_ASTC_5x4_SFLOAT_BLOCK:
|
||||
@@ -596,9 +602,6 @@ void RenderingDeviceCommons::get_compressed_image_format_block_dimensions(DataFo
|
||||
case DATA_FORMAT_ASTC_6x5_UNORM_BLOCK:
|
||||
case DATA_FORMAT_ASTC_6x5_SRGB_BLOCK:
|
||||
case DATA_FORMAT_ASTC_6x5_SFLOAT_BLOCK:
|
||||
case DATA_FORMAT_ASTC_6x6_UNORM_BLOCK:
|
||||
case DATA_FORMAT_ASTC_6x6_SRGB_BLOCK:
|
||||
case DATA_FORMAT_ASTC_6x6_SFLOAT_BLOCK:
|
||||
case DATA_FORMAT_ASTC_8x5_UNORM_BLOCK:
|
||||
case DATA_FORMAT_ASTC_8x5_SRGB_BLOCK:
|
||||
case DATA_FORMAT_ASTC_8x5_SFLOAT_BLOCK:
|
||||
@@ -731,7 +734,7 @@ uint32_t RenderingDeviceCommons::get_compressed_image_format_block_byte_size(Dat
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t RenderingDeviceCommons::get_compressed_image_format_pixel_rshift(DataFormat p_format) {
|
||||
uint32_t RenderingDeviceCommons::get_compressed_image_format_pixels_shifted(DataFormat p_format, uint32_t p_pixels) {
|
||||
switch (p_format) {
|
||||
case DATA_FORMAT_BC1_RGB_UNORM_BLOCK: // These formats are half byte size, so rshift is 1.
|
||||
case DATA_FORMAT_BC1_RGB_SRGB_BLOCK:
|
||||
@@ -745,17 +748,18 @@ uint32_t RenderingDeviceCommons::get_compressed_image_format_pixel_rshift(DataFo
|
||||
case DATA_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
|
||||
case DATA_FORMAT_EAC_R11_UNORM_BLOCK:
|
||||
case DATA_FORMAT_EAC_R11_SNORM_BLOCK:
|
||||
return 1;
|
||||
return (p_pixels >> 1);
|
||||
case DATA_FORMAT_ASTC_6x6_SRGB_BLOCK:
|
||||
case DATA_FORMAT_ASTC_6x6_UNORM_BLOCK:
|
||||
case DATA_FORMAT_ASTC_6x6_SFLOAT_BLOCK:
|
||||
return (p_pixels * 4) / 9;
|
||||
case DATA_FORMAT_ASTC_8x8_SRGB_BLOCK:
|
||||
case DATA_FORMAT_ASTC_8x8_UNORM_BLOCK:
|
||||
case DATA_FORMAT_ASTC_8x8_SFLOAT_BLOCK: {
|
||||
return 2;
|
||||
}
|
||||
default: {
|
||||
}
|
||||
case DATA_FORMAT_ASTC_8x8_SFLOAT_BLOCK:
|
||||
return (p_pixels >> 2);
|
||||
default:
|
||||
return p_pixels;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t RenderingDeviceCommons::get_image_format_required_size(DataFormat p_format, uint32_t p_width, uint32_t p_height, uint32_t p_depth, uint32_t p_mipmaps, uint32_t *r_blockw, uint32_t *r_blockh, uint32_t *r_depth) {
|
||||
@@ -767,7 +771,6 @@ uint32_t RenderingDeviceCommons::get_image_format_required_size(DataFormat p_for
|
||||
uint32_t size = 0;
|
||||
|
||||
uint32_t pixel_size = get_image_format_pixel_size(p_format);
|
||||
uint32_t pixel_rshift = get_compressed_image_format_pixel_rshift(p_format);
|
||||
uint32_t blockw = 0;
|
||||
uint32_t blockh = 0;
|
||||
get_compressed_image_format_block_dimensions(p_format, blockw, blockh);
|
||||
@@ -779,7 +782,7 @@ uint32_t RenderingDeviceCommons::get_image_format_required_size(DataFormat p_for
|
||||
uint32_t s = bw * bh;
|
||||
|
||||
s *= pixel_size;
|
||||
s >>= pixel_rshift;
|
||||
s = get_compressed_image_format_pixels_shifted(p_format, s);
|
||||
size += s * d;
|
||||
if (r_blockw) {
|
||||
*r_blockw = bw;
|
||||
|
||||
@@ -1078,7 +1078,7 @@ protected:
|
||||
|
||||
static void get_compressed_image_format_block_dimensions(DataFormat p_format, uint32_t &r_w, uint32_t &r_h);
|
||||
uint32_t get_compressed_image_format_block_byte_size(DataFormat p_format) const;
|
||||
static uint32_t get_compressed_image_format_pixel_rshift(DataFormat p_format);
|
||||
static uint32_t get_compressed_image_format_pixels_shifted(DataFormat p_format, uint32_t p_pixels);
|
||||
static uint32_t get_image_format_required_size(DataFormat p_format, uint32_t p_width, uint32_t p_height, uint32_t p_depth, uint32_t p_mipmaps, uint32_t *r_blockw = nullptr, uint32_t *r_blockh = nullptr, uint32_t *r_depth = nullptr);
|
||||
static uint32_t get_image_required_mipmaps(uint32_t p_width, uint32_t p_height, uint32_t p_depth);
|
||||
static bool format_has_depth(DataFormat p_format);
|
||||
|
||||
Reference in New Issue
Block a user