Remove support for PVRTC texture encoding and decoding

On the only platform where PVRTC is supported (iOS),
ETC2 generally supersedes PVRTC in every possible way. The increased
memory usage is not really a problem thanks to modern iOS' devices
processing power being higher than its Android counterparts.
This commit is contained in:
Hugo Locurcio 2021-12-29 02:06:12 +01:00
parent 472b5b1167
commit 40be15920f
No known key found for this signature in database
GPG key ID: 39E8F8BE30B0A49C
50 changed files with 34 additions and 2872 deletions

View file

@ -374,11 +374,6 @@ Copyright: 1997-2021, University of Cambridge
2009-2021, Zoltan Herczeg
License: BSD-3-clause
Files: ./thirdparty/pvrtccompressor/
Comment: PvrTcCompressor
Copyright: 2014, Jeffrey Lim.
License: BSD-3-clause
Files: ./thirdparty/recastnavigation/
Comment: Recast
Copyright: 2009, Mikko Mononen

View file

@ -65,10 +65,6 @@ const char *Image::format_names[Image::FORMAT_MAX] = {
"BPTC_RGBA",
"BPTC_RGBF",
"BPTC_RGBFU",
"PVRTC1_2", //pvrtc
"PVRTC1_2A",
"PVRTC1_4",
"PVRTC1_4A",
"ETC", //etc1
"ETC2_R11", //etc2
"ETC2_R11S", //signed", NOT srgb.
@ -148,14 +144,6 @@ int Image::get_format_pixel_size(Format p_format) {
return 1; //float /
case FORMAT_BPTC_RGBFU:
return 1; //unsigned float
case FORMAT_PVRTC1_2:
return 1; //pvrtc
case FORMAT_PVRTC1_2A:
return 1;
case FORMAT_PVRTC1_4:
return 1;
case FORMAT_PVRTC1_4A:
return 1;
case FORMAT_ETC:
return 1; //etc1
case FORMAT_ETC2_R11:
@ -193,16 +181,6 @@ 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_PVRTC1_2:
case FORMAT_PVRTC1_2A: {
r_w = 16;
r_h = 8;
} break;
case FORMAT_PVRTC1_4A:
case FORMAT_PVRTC1_4: {
r_w = 8;
r_h = 8;
} break;
case FORMAT_ETC: {
r_w = 4;
r_h = 4;
@ -235,10 +213,8 @@ 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_DXT1 || p_format == FORMAT_RGTC_R || p_format == FORMAT_PVRTC1_4 || p_format == FORMAT_PVRTC1_4A || p_format == FORMAT_ETC || p_format == FORMAT_ETC2_R11 || p_format == FORMAT_ETC2_R11S || p_format == FORMAT_ETC2_RGB8 || p_format == FORMAT_ETC2_RGB8A1) {
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 if (p_format == FORMAT_PVRTC1_2 || p_format == FORMAT_PVRTC1_2A) {
return 2;
} else {
return 0;
}
@ -254,14 +230,6 @@ int Image::get_format_block_size(Format p_format) {
return 4;
}
case FORMAT_PVRTC1_2:
case FORMAT_PVRTC1_2A: {
return 4;
}
case FORMAT_PVRTC1_4A:
case FORMAT_PVRTC1_4: {
return 4;
}
case FORMAT_ETC: {
return 4;
}
@ -2222,8 +2190,6 @@ bool Image::is_invisible() const {
} break;
case FORMAT_PVRTC1_2A:
case FORMAT_PVRTC1_4A:
case FORMAT_DXT3:
case FORMAT_DXT5: {
detected = true;
@ -2264,8 +2230,6 @@ Image::AlphaMode Image::detect_alpha() const {
}
} break;
case FORMAT_PVRTC1_2A:
case FORMAT_PVRTC1_4A:
case FORMAT_DXT3:
case FORMAT_DXT5: {
detected = true;
@ -2361,8 +2325,6 @@ Error Image::decompress() {
_image_decompress_bc(this);
} else if (format >= FORMAT_BPTC_RGBA && format <= FORMAT_BPTC_RGBFU && _image_decompress_bptc) {
_image_decompress_bptc(this);
} else if (format >= FORMAT_PVRTC1_2 && format <= FORMAT_PVRTC1_4A && _image_decompress_pvrtc) {
_image_decompress_pvrtc(this);
} else if (format == FORMAT_ETC && _image_decompress_etc1) {
_image_decompress_etc1(this);
} else if (format >= FORMAT_ETC2_R11 && format <= FORMAT_ETC2_RA_AS_RG && _image_decompress_etc2) {
@ -2385,10 +2347,6 @@ Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels
ERR_FAIL_COND_V(!_image_compress_bc_func, ERR_UNAVAILABLE);
_image_compress_bc_func(this, p_lossy_quality, p_channels);
} break;
case COMPRESS_PVRTC1_4: {
ERR_FAIL_COND_V(!_image_compress_pvrtc1_4bpp_func, ERR_UNAVAILABLE);
_image_compress_pvrtc1_4bpp_func(this);
} break;
case COMPRESS_ETC: {
ERR_FAIL_COND_V(!_image_compress_etc1_func, ERR_UNAVAILABLE);
_image_compress_etc1_func(this, p_lossy_quality);
@ -2752,10 +2710,8 @@ ImageMemLoadFunc Image::_bmp_mem_loader_func = nullptr;
void (*Image::_image_compress_bc_func)(Image *, float, Image::UsedChannels) = nullptr;
void (*Image::_image_compress_bptc_func)(Image *, float, Image::UsedChannels) = nullptr;
void (*Image::_image_compress_pvrtc1_4bpp_func)(Image *) = nullptr;
void (*Image::_image_compress_etc1_func)(Image *, float) = nullptr;
void (*Image::_image_compress_etc2_func)(Image *, float, Image::UsedChannels) = nullptr;
void (*Image::_image_decompress_pvrtc)(Image *) = nullptr;
void (*Image::_image_decompress_bc)(Image *) = nullptr;
void (*Image::_image_decompress_bptc)(Image *) = nullptr;
void (*Image::_image_decompress_etc1)(Image *) = nullptr;
@ -3238,10 +3194,6 @@ void Image::_bind_methods() {
BIND_ENUM_CONSTANT(FORMAT_BPTC_RGBA); //btpc bc6h
BIND_ENUM_CONSTANT(FORMAT_BPTC_RGBF); //float /
BIND_ENUM_CONSTANT(FORMAT_BPTC_RGBFU); //unsigned float
BIND_ENUM_CONSTANT(FORMAT_PVRTC1_2); //pvrtc
BIND_ENUM_CONSTANT(FORMAT_PVRTC1_2A);
BIND_ENUM_CONSTANT(FORMAT_PVRTC1_4);
BIND_ENUM_CONSTANT(FORMAT_PVRTC1_4A);
BIND_ENUM_CONSTANT(FORMAT_ETC); //etc1
BIND_ENUM_CONSTANT(FORMAT_ETC2_R11); //etc2
BIND_ENUM_CONSTANT(FORMAT_ETC2_R11S); //signed ); NOT srgb.
@ -3265,7 +3217,6 @@ void Image::_bind_methods() {
BIND_ENUM_CONSTANT(ALPHA_BLEND);
BIND_ENUM_CONSTANT(COMPRESS_S3TC);
BIND_ENUM_CONSTANT(COMPRESS_PVRTC1_4);
BIND_ENUM_CONSTANT(COMPRESS_ETC);
BIND_ENUM_CONSTANT(COMPRESS_ETC2);
BIND_ENUM_CONSTANT(COMPRESS_BPTC);

View file

@ -89,10 +89,6 @@ public:
FORMAT_BPTC_RGBA, //btpc bc7
FORMAT_BPTC_RGBF, //float bc6h
FORMAT_BPTC_RGBFU, //unsigned float bc6hu
FORMAT_PVRTC1_2, //pvrtc1
FORMAT_PVRTC1_2A,
FORMAT_PVRTC1_4,
FORMAT_PVRTC1_4A,
FORMAT_ETC, //etc1
FORMAT_ETC2_R11, //etc2
FORMAT_ETC2_R11S, //signed, NOT srgb.
@ -136,11 +132,9 @@ public:
static void (*_image_compress_bc_func)(Image *, float, UsedChannels p_channels);
static void (*_image_compress_bptc_func)(Image *, float p_lossy_quality, UsedChannels p_channels);
static void (*_image_compress_pvrtc1_4bpp_func)(Image *);
static void (*_image_compress_etc1_func)(Image *, float);
static void (*_image_compress_etc2_func)(Image *, float, UsedChannels p_channels);
static void (*_image_decompress_pvrtc)(Image *);
static void (*_image_decompress_bc)(Image *);
static void (*_image_decompress_bptc)(Image *);
static void (*_image_decompress_etc1)(Image *);
@ -332,7 +326,6 @@ public:
enum CompressMode {
COMPRESS_S3TC,
COMPRESS_PVRTC1_4,
COMPRESS_ETC,
COMPRESS_ETC2,
COMPRESS_BPTC,

View file

@ -135,7 +135,7 @@
<return type="int" enum="Error" />
<description>
Decompresses the image if it is VRAM compressed in a supported format. Returns [constant OK] if the format is supported, otherwise [constant ERR_UNAVAILABLE].
[b]Note:[/b] The following formats can be decompressed: DXT, RGTC, BPTC, PVRTC1. The formats ETC1 and ETC2 are not supported.
[b]Note:[/b] The following formats can be decompressed: DXT, RGTC, BPTC. The formats ETC1 and ETC2 are not supported.
</description>
</method>
<method name="detect_alpha" qualifiers="const">
@ -543,52 +543,38 @@
<constant name="FORMAT_BPTC_RGBFU" value="24" enum="Format">
Texture format that uses [url=https://www.khronos.org/opengl/wiki/BPTC_Texture_Compression]BPTC[/url] compression with unsigned floating-point RGB components.
</constant>
<constant name="FORMAT_PVRTC1_2" value="25" enum="Format">
Texture format used on PowerVR-supported mobile platforms, uses 2-bit color depth with no alpha. More information can be found [url=https://en.wikipedia.org/wiki/PVRTC]here[/url].
[b]Note:[/b] When creating an [ImageTexture], an sRGB to linear color space conversion is performed.
</constant>
<constant name="FORMAT_PVRTC1_2A" value="26" enum="Format">
Same as [constant FORMAT_PVRTC1_2], but with an alpha component.
</constant>
<constant name="FORMAT_PVRTC1_4" value="27" enum="Format">
Texture format used on PowerVR-supported mobile platforms, uses 4-bit color depth with no alpha. More information can be found [url=https://en.wikipedia.org/wiki/PVRTC]here[/url].
[b]Note:[/b] When creating an [ImageTexture], an sRGB to linear color space conversion is performed.
</constant>
<constant name="FORMAT_PVRTC1_4A" value="28" enum="Format">
Same as [constant FORMAT_PVRTC1_4], but with an alpha component.
</constant>
<constant name="FORMAT_ETC" value="29" enum="Format">
<constant name="FORMAT_ETC" value="25" enum="Format">
[url=https://en.wikipedia.org/wiki/Ericsson_Texture_Compression#ETC1]Ericsson Texture Compression format 1[/url], also referred to as "ETC1", and is part of the OpenGL ES graphics standard. This format cannot store an alpha channel.
</constant>
<constant name="FORMAT_ETC2_R11" value="30" enum="Format">
<constant name="FORMAT_ETC2_R11" value="26" enum="Format">
[url=https://en.wikipedia.org/wiki/Ericsson_Texture_Compression#ETC2_and_EAC]Ericsson Texture Compression format 2[/url] ([code]R11_EAC[/code] variant), which provides one channel of unsigned data.
</constant>
<constant name="FORMAT_ETC2_R11S" value="31" enum="Format">
<constant name="FORMAT_ETC2_R11S" value="27" enum="Format">
[url=https://en.wikipedia.org/wiki/Ericsson_Texture_Compression#ETC2_and_EAC]Ericsson Texture Compression format 2[/url] ([code]SIGNED_R11_EAC[/code] variant), which provides one channel of signed data.
</constant>
<constant name="FORMAT_ETC2_RG11" value="32" enum="Format">
<constant name="FORMAT_ETC2_RG11" value="28" enum="Format">
[url=https://en.wikipedia.org/wiki/Ericsson_Texture_Compression#ETC2_and_EAC]Ericsson Texture Compression format 2[/url] ([code]RG11_EAC[/code] variant), which provides two channels of unsigned data.
</constant>
<constant name="FORMAT_ETC2_RG11S" value="33" enum="Format">
<constant name="FORMAT_ETC2_RG11S" value="29" enum="Format">
[url=https://en.wikipedia.org/wiki/Ericsson_Texture_Compression#ETC2_and_EAC]Ericsson Texture Compression format 2[/url] ([code]SIGNED_RG11_EAC[/code] variant), which provides two channels of signed data.
</constant>
<constant name="FORMAT_ETC2_RGB8" value="34" enum="Format">
<constant name="FORMAT_ETC2_RGB8" value="30" enum="Format">
[url=https://en.wikipedia.org/wiki/Ericsson_Texture_Compression#ETC2_and_EAC]Ericsson Texture Compression format 2[/url] ([code]RGB8[/code] variant), which is a follow-up of ETC1 and compresses RGB888 data.
[b]Note:[/b] When creating an [ImageTexture], an sRGB to linear color space conversion is performed.
</constant>
<constant name="FORMAT_ETC2_RGBA8" value="35" enum="Format">
<constant name="FORMAT_ETC2_RGBA8" value="31" enum="Format">
[url=https://en.wikipedia.org/wiki/Ericsson_Texture_Compression#ETC2_and_EAC]Ericsson Texture Compression format 2[/url] ([code]RGBA8[/code]variant), which compresses RGBA8888 data with full alpha support.
[b]Note:[/b] When creating an [ImageTexture], an sRGB to linear color space conversion is performed.
</constant>
<constant name="FORMAT_ETC2_RGB8A1" value="36" enum="Format">
<constant name="FORMAT_ETC2_RGB8A1" value="32" enum="Format">
[url=https://en.wikipedia.org/wiki/Ericsson_Texture_Compression#ETC2_and_EAC]Ericsson Texture Compression format 2[/url] ([code]RGB8_PUNCHTHROUGH_ALPHA1[/code] variant), which compresses RGBA data to make alpha either fully transparent or fully opaque.
[b]Note:[/b] When creating an [ImageTexture], an sRGB to linear color space conversion is performed.
</constant>
<constant name="FORMAT_ETC2_RA_AS_RG" value="37" enum="Format">
<constant name="FORMAT_ETC2_RA_AS_RG" value="33" enum="Format">
</constant>
<constant name="FORMAT_DXT5_RA_AS_RG" value="38" enum="Format">
<constant name="FORMAT_DXT5_RA_AS_RG" value="34" enum="Format">
</constant>
<constant name="FORMAT_MAX" value="39" enum="Format">
<constant name="FORMAT_MAX" value="35" enum="Format">
Represents the size of the [enum Format] enum.
</constant>
<constant name="INTERPOLATE_NEAREST" value="0" enum="Interpolation">
@ -622,16 +608,13 @@
<constant name="COMPRESS_S3TC" value="0" enum="CompressMode">
Use S3TC compression.
</constant>
<constant name="COMPRESS_PVRTC1_4" value="1" enum="CompressMode">
Use PVRTC1 4-bpp compression.
</constant>
<constant name="COMPRESS_ETC" value="2" enum="CompressMode">
<constant name="COMPRESS_ETC" value="1" enum="CompressMode">
Use ETC compression.
</constant>
<constant name="COMPRESS_ETC2" value="3" enum="CompressMode">
<constant name="COMPRESS_ETC2" value="2" enum="CompressMode">
Use ETC2 compression.
</constant>
<constant name="COMPRESS_BPTC" value="4" enum="CompressMode">
<constant name="COMPRESS_BPTC" value="3" enum="CompressMode">
Use BPTC compression.
</constant>
<constant name="USED_CHANNELS_L" value="0" enum="UsedChannels">

View file

@ -1889,10 +1889,6 @@
If [code]true[/code], the texture importer will import VRAM-compressed textures using the Ericsson Texture Compression 2 algorithm. This texture compression algorithm is only supported when using the Vulkan renderer.
[b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]).
</member>
<member name="rendering/textures/vram_compression/import_pvrtc" type="bool" setter="" getter="" default="false">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the PowerVR Texture Compression algorithm. This texture compression algorithm is only supported on iOS.
[b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]).
</member>
<member name="rendering/textures/vram_compression/import_s3tc" type="bool" setter="" getter="" default="true">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the S3 Texture Compression algorithm. This algorithm is only supported on desktop platforms and consoles.
[b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]).

View file

@ -7,7 +7,7 @@
<tutorials>
</tutorials>
<members>
<member name="format_override" type="int" setter="set_format_override" getter="get_format_override" enum="RenderingDevice.DataFormat" default="226">
<member name="format_override" type="int" setter="set_format_override" getter="get_format_override" enum="RenderingDevice.DataFormat" default="218">
</member>
<member name="swizzle_a" type="int" setter="set_swizzle_a" getter="get_swizzle_a" enum="RenderingDevice.TextureSwizzle" default="6">
</member>

View file

@ -7,7 +7,7 @@
<tutorials>
</tutorials>
<members>
<member name="format" type="int" setter="set_format" getter="get_format" enum="RenderingDevice.DataFormat" default="226">
<member name="format" type="int" setter="set_format" getter="get_format" enum="RenderingDevice.DataFormat" default="218">
</member>
<member name="frequency" type="int" setter="set_frequency" getter="get_frequency" enum="RenderingDevice.VertexFrequency" default="0">
</member>

View file

@ -1135,23 +1135,7 @@
</constant>
<constant name="DATA_FORMAT_G16_B16_R16_3PLANE_444_UNORM" value="217" enum="DataFormat">
</constant>
<constant name="DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG" value="218" enum="DataFormat">
</constant>
<constant name="DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG" value="219" enum="DataFormat">
</constant>
<constant name="DATA_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG" value="220" enum="DataFormat">
</constant>
<constant name="DATA_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG" value="221" enum="DataFormat">
</constant>
<constant name="DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG" value="222" enum="DataFormat">
</constant>
<constant name="DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG" value="223" enum="DataFormat">
</constant>
<constant name="DATA_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG" value="224" enum="DataFormat">
</constant>
<constant name="DATA_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG" value="225" enum="DataFormat">
</constant>
<constant name="DATA_FORMAT_MAX" value="226" enum="DataFormat">
<constant name="DATA_FORMAT_MAX" value="218" enum="DataFormat">
</constant>
<constant name="TEXTURE_TYPE_1D" value="0" enum="TextureType">
</constant>

View file

@ -1334,7 +1334,7 @@
<return type="bool" />
<argument index="0" name="feature" type="String" />
<description>
Returns [code]true[/code] if the OS supports a certain feature. Features might be [code]s3tc[/code], [code]etc[/code], [code]etc2[/code] and [code]pvrtc[/code].
Returns [code]true[/code] if the OS supports a certain feature. Features might be [code]s3tc[/code], [code]etc[/code], and [code]etc2[/code].
</description>
</method>
<method name="instance_attach_object_instance_id">

View file

@ -55,16 +55,6 @@ GLuint RasterizerStorageGLES3::system_fbo = 0;
#define _EXT_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE
#define _EXT_ETC1_RGB8_OES 0x8D64
#define _EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
#define _EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
#define _EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
#define _EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
#define _EXT_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT 0x8A54
#define _EXT_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT 0x8A55
#define _EXT_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT 0x8A56
#define _EXT_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT 0x8A57
#define _EXT_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C
#define _EXT_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D
#define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
@ -312,57 +302,6 @@ Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_
need_decompress = true;
}
} break;
case Image::FORMAT_PVRTC1_2: {
if (config.pvrtc_supported) {
r_gl_internal_format = _EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
//r_srgb = true;
} else {
need_decompress = true;
}
} break;
case Image::FORMAT_PVRTC1_2A: {
if (config.pvrtc_supported) {
r_gl_internal_format = _EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
//r_srgb = true;
} else {
need_decompress = true;
}
} break;
case Image::FORMAT_PVRTC1_4: {
if (config.pvrtc_supported) {
r_gl_internal_format = _EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
//r_srgb = true;
} else {
need_decompress = true;
}
} break;
case Image::FORMAT_PVRTC1_4A: {
if (config.pvrtc_supported) {
r_gl_internal_format = _EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
//r_srgb = true;
} else {
need_decompress = true;
}
} break;
case Image::FORMAT_ETC: {
if (config.etc_supported) {
r_gl_internal_format = _EXT_ETC1_RGB8_OES;
@ -4085,17 +4024,17 @@ bool RasterizerStorageGLES3::free(RID p_rid) {
}
bool RasterizerStorageGLES3::has_os_feature(const String &p_feature) const {
if (p_feature == "pvrtc")
return config.pvrtc_supported;
if (p_feature == "s3tc")
if (p_feature == "s3tc") {
return config.s3tc_supported;
}
if (p_feature == "etc")
if (p_feature == "etc") {
return config.etc_supported;
}
if (p_feature == "skinning_fallback")
if (p_feature == "skinning_fallback") {
return config.use_skeleton_software;
}
return false;
}
@ -4220,7 +4159,6 @@ void RasterizerStorageGLES3::initialize() {
#ifdef GLES_OVER_GL
config.float_texture_supported = true;
config.s3tc_supported = true;
config.pvrtc_supported = false;
config.etc_supported = false;
config.support_npot_repeat_mipmap = true;
config.depth_buffer_internalformat = GL_DEPTH_COMPONENT24;
@ -4228,7 +4166,6 @@ void RasterizerStorageGLES3::initialize() {
config.float_texture_supported = config.extensions.has("GL_ARB_texture_float") || config.extensions.has("GL_OES_texture_float");
config.s3tc_supported = config.extensions.has("GL_EXT_texture_compression_s3tc") || config.extensions.has("WEBGL_compressed_texture_s3tc");
config.etc_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture") || config.extensions.has("WEBGL_compressed_texture_etc1");
config.pvrtc_supported = config.extensions.has("GL_IMG_texture_compression_pvrtc") || config.extensions.has("WEBGL_compressed_texture_pvrtc");
config.support_npot_repeat_mipmap = config.extensions.has("GL_OES_texture_npot");
#ifdef JAVASCRIPT_ENABLED
@ -4297,7 +4234,6 @@ void RasterizerStorageGLES3::initialize() {
config.etc_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture");
config.latc_supported = config.extensions.has("GL_EXT_texture_compression_latc");
config.bptc_supported = config.extensions.has("GL_ARB_texture_compression_bptc");
config.pvrtc_supported = config.extensions.has("GL_IMG_texture_compression_pvrtc");
config.rgtc_supported = config.extensions.has("GL_EXT_texture_compression_rgtc") || config.extensions.has("GL_ARB_texture_compression_rgtc") || config.extensions.has("EXT_texture_compression_rgtc");
config.bptc_supported = config.extensions.has("GL_ARB_texture_compression_bptc") || config.extensions.has("EXT_texture_compression_bptc");
config.srgb_decode_supported = config.extensions.has("GL_EXT_texture_sRGB_decode");

View file

@ -79,7 +79,6 @@ public:
bool bptc_supported;
bool etc_supported;
bool etc2_supported;
bool pvrtc_supported;
bool srgb_decode_supported;
bool keep_original_textures;

View file

@ -387,14 +387,6 @@ const VkFormat RenderingDeviceVulkan::vulkan_formats[RenderingDevice::DATA_FORMA
VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM,
VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,
VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM,
VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG,
VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG,
VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG,
VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG,
VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG,
VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG,
VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG,
VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG,
};
const char *RenderingDeviceVulkan::named_formats[RenderingDevice::DATA_FORMAT_MAX] = {
@ -616,14 +608,6 @@ const char *RenderingDeviceVulkan::named_formats[RenderingDevice::DATA_FORMAT_MA
"G16_B16_R16_3Plane_422_Unorm",
"G16_B16R16_2Plane_422_Unorm",
"G16_B16_R16_3Plane_444_Unorm",
"Pvrtc1_2Bpp_Unorm_Block_Img",
"Pvrtc1_4Bpp_Unorm_Block_Img",
"Pvrtc2_2Bpp_Unorm_Block_Img",
"Pvrtc2_4Bpp_Unorm_Block_Img",
"Pvrtc1_2Bpp_Srgb_Block_Img",
"Pvrtc1_4Bpp_Srgb_Block_Img",
"Pvrtc2_2Bpp_Srgb_Block_Img",
"Pvrtc2_4Bpp_Srgb_Block_Img"
};
int RenderingDeviceVulkan::get_format_vertex_size(DataFormat p_format) {
@ -970,15 +954,6 @@ uint32_t RenderingDeviceVulkan::get_image_format_pixel_size(DataFormat p_format)
case DATA_FORMAT_G16_B16R16_2PLANE_422_UNORM:
case DATA_FORMAT_G16_B16_R16_3PLANE_444_UNORM:
return 8;
case DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG:
case DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG:
case DATA_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG:
case DATA_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG:
case DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG:
case DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG:
case DATA_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG:
case DATA_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG:
return 1;
default: {
ERR_PRINT("Format not handled, bug");
}
@ -1048,20 +1023,6 @@ void RenderingDeviceVulkan::get_compressed_image_format_block_dimensions(DataFor
r_w = 4;
r_h = 4;
return;
case DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG:
case DATA_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG:
case DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG:
case DATA_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG:
r_w = 4;
r_h = 4;
return;
case DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG:
case DATA_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG:
case DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG:
case DATA_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG:
r_w = 8;
r_h = 4;
return;
default: {
r_w = 1;
r_h = 1;
@ -1138,15 +1099,6 @@ uint32_t RenderingDeviceVulkan::get_compressed_image_format_block_byte_size(Data
case DATA_FORMAT_ASTC_12x12_UNORM_BLOCK:
case DATA_FORMAT_ASTC_12x12_SRGB_BLOCK:
return 8; //wrong
case DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG:
case DATA_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG:
case DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG:
case DATA_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG:
case DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG:
case DATA_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG:
case DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG:
case DATA_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG:
return 8; //what varies is resolution
default: {
}
}
@ -1167,16 +1119,7 @@ uint32_t RenderingDeviceVulkan::get_compressed_image_format_pixel_rshift(DataFor
case DATA_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
case DATA_FORMAT_EAC_R11_UNORM_BLOCK:
case DATA_FORMAT_EAC_R11_SNORM_BLOCK:
case DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG:
case DATA_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG:
case DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG:
case DATA_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG:
return 1;
case DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG: //these formats are quarter byte size, so rshift is 1
case DATA_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG:
case DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG:
case DATA_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG:
return 2;
default: {
}
}

View file

@ -1501,36 +1501,12 @@ void EditorExport::add_export_preset(const Ref<EditorExportPreset> &p_preset, in
}
String EditorExportPlatform::test_etc2() const {
// String driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name");
// bool etc_supported = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc");
// bool etc2_supported = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc2");
String driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name");
bool etc_supported = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc");
bool etc2_supported = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc2");
const bool etc2_supported = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc2");
if (driver == "opengl3" && !etc_supported) {
return TTR("Target platform requires 'ETC' texture compression for OpenGL. Enable 'Import Etc' in Project Settings.");
} else if (driver == "vulkan" && !etc2_supported) {
// FIXME: Review if this is true for Vulkan.
return TTR("Target platform requires 'ETC2' texture compression for Vulkan. Enable 'Import Etc 2' in Project Settings.");
if (!etc2_supported) {
return TTR("Target platform requires 'ETC2' texture compression. Enable 'Import Etc 2' in Project Settings.");
}
return String();
}
String EditorExportPlatform::test_etc2_or_pvrtc() const {
String driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name");
bool etc2_supported = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc2");
bool pvrtc_supported = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_pvrtc");
// String driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name");
// bool etc2_supported = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc2");
// bool pvrtc_supported = ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_pvrtc");
if (driver == "opengl3" && !pvrtc_supported) {
return TTR("Target platform requires 'PVRTC' texture compression for OpenGL. Enable 'Import Pvrtc' in Project Settings.");
} else if (driver == "vulkan" && !etc2_supported && !pvrtc_supported) {
// FIXME: Review if this is true for Vulkan.
return TTR("Target platform requires 'ETC2' or 'PVRTC' texture compression for Vulkan. Enable 'Import Etc 2' or 'Import Pvrtc' in Project Settings.");
}
return String();
}

View file

@ -269,8 +269,7 @@ public:
virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) { return OK; }
virtual Ref<Texture2D> get_run_icon() const { return get_logo(); }
String test_etc2() const; //generic test for etc2 since most platforms use it
String test_etc2_or_pvrtc() const; // test for etc2 or pvrtc support for iOS
String test_etc2() const;
virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const = 0;
virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const = 0;

View file

@ -450,12 +450,6 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const
formats_imported.push_back("etc2");
}
if (ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_pvrtc")) {
_save_tex(slices, p_save_path + ".etc2." + extension, compress_mode, lossy, Image::COMPRESS_ETC2, csource, used_channels, mipmaps, true);
r_platform_variants->push_back("pvrtc");
formats_imported.push_back("pvrtc");
}
if (!ok_on_pc) {
EditorNode::add_io_error("Warning, no suitable PC VRAM compression enabled in Project Settings. This texture will not display correctly on PC.");
}
@ -481,7 +475,6 @@ const char *ResourceImporterLayeredTexture::compression_formats[] = {
"s3tc",
"etc",
"etc2",
"pvrtc",
nullptr
};
String ResourceImporterLayeredTexture::get_import_settings_string() const {

View file

@ -556,12 +556,6 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
formats_imported.push_back("etc");
}
if (ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_pvrtc")) {
_save_stex(image, p_save_path + ".pvrtc.stex", compress_mode, lossy, Image::COMPRESS_PVRTC1_4, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel);
r_platform_variants->push_back("pvrtc");
formats_imported.push_back("pvrtc");
}
if (!ok_on_pc) {
EditorNode::add_io_error("Warning, no suitable PC VRAM compression enabled in Project Settings. This texture will not display correctly on PC.");
}
@ -586,7 +580,6 @@ const char *ResourceImporterTexture::compression_formats[] = {
"s3tc",
"etc",
"etc2",
"pvrtc",
nullptr
};
String ResourceImporterTexture::get_import_settings_string() const {

View file

@ -215,7 +215,6 @@ void ProjectSettingsEditor::_add_feature_overrides() {
presets.insert("s3tc");
presets.insert("etc");
presets.insert("etc2");
presets.insert("pvrtc");
presets.insert("debug");
presets.insert("release");
presets.insert("editor");

View file

@ -1,38 +0,0 @@
#!/usr/bin/env python
Import("env")
Import("env_modules")
env_pvr = env_modules.Clone()
# Thirdparty source files
thirdparty_obj = []
# Not unbundled so far since not widespread as shared library
thirdparty_dir = "#thirdparty/pvrtccompressor/"
thirdparty_sources = [
"BitScale.cpp",
"MortonTable.cpp",
"PvrTcDecoder.cpp",
"PvrTcEncoder.cpp",
"PvrTcPacket.cpp",
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
env_pvr.Prepend(CPPPATH=[thirdparty_dir])
env_thirdparty = env_pvr.Clone()
env_thirdparty.disable_warnings()
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_sources)
env.modules_sources += thirdparty_obj
# Godot source files
module_obj = []
env_pvr.add_source_files(module_obj, "*.cpp")
env.modules_sources += module_obj
# Needed to force rebuilding the module files when the thirdparty library is updated.
env.Depends(module_obj, thirdparty_obj)

View file

@ -1,6 +0,0 @@
def can_build(env, platform):
return True
def configure(env):
pass

View file

@ -1,88 +0,0 @@
/*************************************************************************/
/* image_compress_pvrtc.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "image_compress_pvrtc.h"
#include "core/io/image.h"
#include "core/object/ref_counted.h"
#include <PvrTcEncoder.h>
#include <RgbaBitmap.h>
static void _compress_pvrtc1_4bpp(Image *p_img) {
Ref<Image> img = p_img->duplicate();
bool make_mipmaps = false;
if (!img->is_size_po2() || img->get_width() != img->get_height()) {
make_mipmaps = img->has_mipmaps();
img->resize_to_po2(true);
// Resizing can fail for some formats
if (!img->is_size_po2() || img->get_width() != img->get_height()) {
ERR_FAIL_MSG("Failed to resize the image for compression.");
}
}
img->convert(Image::FORMAT_RGBA8);
if (!img->has_mipmaps() && make_mipmaps) {
img->generate_mipmaps();
}
bool use_alpha = img->detect_alpha();
Ref<Image> new_img;
new_img.instantiate();
new_img->create(img->get_width(), img->get_height(), img->has_mipmaps(), use_alpha ? Image::FORMAT_PVRTC1_4A : Image::FORMAT_PVRTC1_4);
Vector<uint8_t> data = new_img->get_data();
{
uint8_t *wr = data.ptrw();
const uint8_t *r = img->get_data().ptr();
for (int i = 0; i <= new_img->get_mipmap_count(); i++) {
int ofs, size, w, h;
img->get_mipmap_offset_size_and_dimensions(i, ofs, size, w, h);
Javelin::RgbaBitmap bm(w, h);
void *dst = (void *)bm.GetData();
memcpy(dst, &r[ofs], size);
Javelin::ColorRgba<unsigned char> *dp = bm.GetData();
for (int j = 0; j < size / 4; j++) {
// Red and blue colors are swapped.
SWAP(dp[j].r, dp[j].b);
}
new_img->get_mipmap_offset_size_and_dimensions(i, ofs, size, w, h);
Javelin::PvrTcEncoder::EncodeRgba4Bpp(&wr[ofs], bm);
}
}
p_img->create(new_img->get_width(), new_img->get_height(), new_img->has_mipmaps(), new_img->get_format(), data);
}
void _register_pvrtc_compress_func() {
Image::_image_compress_pvrtc1_4bpp_func = _compress_pvrtc1_4bpp;
}

View file

@ -1,36 +0,0 @@
/*************************************************************************/
/* image_compress_pvrtc.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef IMAGE_COMPRESS_PVRTC_H
#define IMAGE_COMPRESS_PVRTC_H
void _register_pvrtc_compress_func();
#endif // IMAGE_COMPRESS_PVRTC_H

View file

@ -1,48 +0,0 @@
/*************************************************************************/
/* register_types.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "register_types.h"
#include "image_compress_pvrtc.h"
#include "texture_loader_pvr.h"
static Ref<ResourceFormatPVR> resource_loader_pvr;
void register_pvr_types() {
resource_loader_pvr.instantiate();
ResourceLoader::add_resource_format_loader(resource_loader_pvr);
_register_pvrtc_compress_func();
}
void unregister_pvr_types() {
ResourceLoader::remove_resource_format_loader(resource_loader_pvr);
resource_loader_pvr.unref();
}

View file

@ -1,37 +0,0 @@
/*************************************************************************/
/* register_types.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef PVR_REGISTER_TYPES_H
#define PVR_REGISTER_TYPES_H
void register_pvr_types();
void unregister_pvr_types();
#endif // PVR_REGISTER_TYPES_H

View file

@ -1,608 +0,0 @@
/*************************************************************************/
/* texture_loader_pvr.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "texture_loader_pvr.h"
#include "core/io/file_access.h"
static void _pvrtc_decompress(Image *p_img);
enum PVRFLags {
PVR_HAS_MIPMAPS = 0x00000100,
PVR_TWIDDLED = 0x00000200,
PVR_NORMAL_MAP = 0x00000400,
PVR_BORDER = 0x00000800,
PVR_CUBE_MAP = 0x00001000,
PVR_FALSE_MIPMAPS = 0x00002000,
PVR_VOLUME_TEXTURES = 0x00004000,
PVR_HAS_ALPHA = 0x00008000,
PVR_VFLIP = 0x00010000
};
RES ResourceFormatPVR::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
if (r_error) {
*r_error = ERR_CANT_OPEN;
}
Error err;
FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
if (!f) {
return RES();
}
FileAccessRef faref(f);
ERR_FAIL_COND_V(err, RES());
if (r_error) {
*r_error = ERR_FILE_CORRUPT;
}
uint32_t hsize = f->get_32();
ERR_FAIL_COND_V(hsize != 52, RES());
uint32_t height = f->get_32();
uint32_t width = f->get_32();
uint32_t mipmaps = f->get_32();
uint32_t flags = f->get_32();
uint32_t surfsize = f->get_32();
f->seek(f->get_position() + 20); // bpp, rmask, gmask, bmask, amask
uint8_t pvrid[5] = { 0, 0, 0, 0, 0 };
f->get_buffer(pvrid, 4);
ERR_FAIL_COND_V(String((char *)pvrid) != "PVR!", RES());
f->get_32(); // surfcount
/*
print_line("height: "+itos(height));
print_line("width: "+itos(width));
print_line("mipmaps: "+itos(mipmaps));
print_line("flags: "+itos(flags));
print_line("surfsize: "+itos(surfsize));
print_line("bpp: "+itos(bpp));
print_line("rmask: "+itos(rmask));
print_line("gmask: "+itos(gmask));
print_line("bmask: "+itos(bmask));
print_line("amask: "+itos(amask));
print_line("surfcount: "+itos(surfcount));
*/
Vector<uint8_t> data;
data.resize(surfsize);
ERR_FAIL_COND_V(data.size() == 0, RES());
uint8_t *w = data.ptrw();
f->get_buffer(&w[0], surfsize);
err = f->get_error();
ERR_FAIL_COND_V(err != OK, RES());
Image::Format format = Image::FORMAT_MAX;
switch (flags & 0xFF) {
case 0x18:
case 0xC:
format = (flags & PVR_HAS_ALPHA) ? Image::FORMAT_PVRTC1_2A : Image::FORMAT_PVRTC1_2;
break;
case 0x19:
case 0xD:
format = (flags & PVR_HAS_ALPHA) ? Image::FORMAT_PVRTC1_4A : Image::FORMAT_PVRTC1_4;
break;
case 0x16:
format = Image::FORMAT_L8;
break;
case 0x17:
format = Image::FORMAT_LA8;
break;
case 0x20:
case 0x80:
case 0x81:
format = Image::FORMAT_DXT1;
break;
case 0x21:
case 0x22:
case 0x82:
case 0x83:
format = Image::FORMAT_DXT3;
break;
case 0x23:
case 0x24:
case 0x84:
case 0x85:
format = Image::FORMAT_DXT5;
break;
case 0x4:
case 0x15:
format = Image::FORMAT_RGB8;
break;
case 0x5:
case 0x12:
format = Image::FORMAT_RGBA8;
break;
case 0x36:
format = Image::FORMAT_ETC;
break;
default:
ERR_FAIL_V_MSG(RES(), "Unsupported format in PVR texture: " + itos(flags & 0xFF) + ".");
}
Ref<Image> image = memnew(Image(width, height, mipmaps, format, data));
ERR_FAIL_COND_V(image->is_empty(), RES());
Ref<ImageTexture> texture = memnew(ImageTexture);
texture->create_from_image(image);
if (r_error) {
*r_error = OK;
}
return texture;
}
void ResourceFormatPVR::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("pvr");
}
bool ResourceFormatPVR::handles_type(const String &p_type) const {
return ClassDB::is_parent_class(p_type, "Texture2D");
}
String ResourceFormatPVR::get_resource_type(const String &p_path) const {
if (p_path.get_extension().to_lower() == "pvr") {
return "Texture2D";
}
return "";
}
ResourceFormatPVR::ResourceFormatPVR() {
Image::_image_decompress_pvrtc = _pvrtc_decompress;
}
/////////////////////////////////////////////////////////
//PVRTC decompressor, Based on PVRTC decompressor by IMGTEC.
/////////////////////////////////////////////////////////
#define PT_INDEX 2
#define BLK_Y_SIZE 4
#define BLK_X_MAX 8
#define BLK_X_2BPP 8
#define BLK_X_4BPP 4
#define WRAP_COORD(Val, Size) ((Val) & ((Size)-1))
/*
Define an expression to either wrap or clamp large or small vals to the
legal coordinate range
*/
#define LIMIT_COORD(Val, Size, p_tiled) \
((p_tiled) ? WRAP_COORD((Val), (Size)) : CLAMP((Val), 0, (Size)-1))
struct PVRTCBlock {
//blocks are 64 bits
uint32_t data[2] = {};
};
_FORCE_INLINE_ bool is_po2(uint32_t p_input) {
if (p_input == 0) {
return false;
}
uint32_t minus1 = p_input - 1;
return ((p_input | minus1) == (p_input ^ minus1)) ? true : false;
}
static void unpack_5554(const PVRTCBlock *p_block, int p_ab_colors[2][4]) {
uint32_t raw_bits[2];
raw_bits[0] = p_block->data[1] & (0xFFFE);
raw_bits[1] = p_block->data[1] >> 16;
for (int i = 0; i < 2; i++) {
if (raw_bits[i] & (1 << 15)) {
p_ab_colors[i][0] = (raw_bits[i] >> 10) & 0x1F;
p_ab_colors[i][1] = (raw_bits[i] >> 5) & 0x1F;
p_ab_colors[i][2] = raw_bits[i] & 0x1F;
if (i == 0) {
p_ab_colors[0][2] |= p_ab_colors[0][2] >> 4;
}
p_ab_colors[i][3] = 0xF;
} else {
p_ab_colors[i][0] = (raw_bits[i] >> (8 - 1)) & 0x1E;
p_ab_colors[i][1] = (raw_bits[i] >> (4 - 1)) & 0x1E;
p_ab_colors[i][0] |= p_ab_colors[i][0] >> 4;
p_ab_colors[i][1] |= p_ab_colors[i][1] >> 4;
p_ab_colors[i][2] = (raw_bits[i] & 0xF) << 1;
if (i == 0) {
p_ab_colors[0][2] |= p_ab_colors[0][2] >> 3;
} else {
p_ab_colors[0][2] |= p_ab_colors[0][2] >> 4;
}
p_ab_colors[i][3] = (raw_bits[i] >> 11) & 0xE;
}
}
}
static void unpack_modulations(const PVRTCBlock *p_block, const int p_2bit, int p_modulation[8][16], int p_modulation_modes[8][16], int p_x, int p_y) {
int block_mod_mode = p_block->data[1] & 1;
uint32_t modulation_bits = p_block->data[0];
if (p_2bit && block_mod_mode) {
for (int y = 0; y < BLK_Y_SIZE; y++) {
for (int x = 0; x < BLK_X_2BPP; x++) {
p_modulation_modes[y + p_y][x + p_x] = block_mod_mode;
if (((x ^ y) & 1) == 0) {
p_modulation[y + p_y][x + p_x] = modulation_bits & 3;
modulation_bits >>= 2;
}
}
}
} else if (p_2bit) {
for (int y = 0; y < BLK_Y_SIZE; y++) {
for (int x = 0; x < BLK_X_2BPP; x++) {
p_modulation_modes[y + p_y][x + p_x] = block_mod_mode;
if (modulation_bits & 1) {
p_modulation[y + p_y][x + p_x] = 0x3;
} else {
p_modulation[y + p_y][x + p_x] = 0x0;
}
modulation_bits >>= 1;
}
}
} else {
for (int y = 0; y < BLK_Y_SIZE; y++) {
for (int x = 0; x < BLK_X_4BPP; x++) {
p_modulation_modes[y + p_y][x + p_x] = block_mod_mode;
p_modulation[y + p_y][x + p_x] = modulation_bits & 3;
modulation_bits >>= 2;
}
}
}
ERR_FAIL_COND(modulation_bits != 0);
}
static void interpolate_colors(const int p_colorp[4], const int p_colorq[4], const int p_colorr[4], const int p_colors[4], bool p_2bit, const int x, const int y, int r_result[4]) {
int u, v, uscale;
int k;
int tmp1, tmp2;
int P[4], Q[4], R[4], S[4];
for (k = 0; k < 4; k++) {
P[k] = p_colorp[k];
Q[k] = p_colorq[k];
R[k] = p_colorr[k];
S[k] = p_colors[k];
}
v = (y & 0x3) | ((~y & 0x2) << 1);
if (p_2bit) {
u = (x & 0x7) | ((~x & 0x4) << 1);
} else {
u = (x & 0x3) | ((~x & 0x2) << 1);
}
v = v - BLK_Y_SIZE / 2;
if (p_2bit) {
u = u - BLK_X_2BPP / 2;
uscale = 8;
} else {
u = u - BLK_X_4BPP / 2;
uscale = 4;
}
for (k = 0; k < 4; k++) {
tmp1 = P[k] * uscale + u * (Q[k] - P[k]);
tmp2 = R[k] * uscale + u * (S[k] - R[k]);
tmp1 = tmp1 * 4 + v * (tmp2 - tmp1);
r_result[k] = tmp1;
}
if (p_2bit) {
for (k = 0; k < 3; k++) {
r_result[k] >>= 2;
}
r_result[3] >>= 1;
} else {
for (k = 0; k < 3; k++) {
r_result[k] >>= 1;
}
}
for (k = 0; k < 4; k++) {
ERR_FAIL_COND(r_result[k] >= 256);
}
for (k = 0; k < 3; k++) {
r_result[k] += r_result[k] >> 5;
}
r_result[3] += r_result[3] >> 4;
for (k = 0; k < 4; k++) {
ERR_FAIL_COND(r_result[k] >= 256);
}
}
static void get_modulation_value(int x, int y, const int p_2bit, const int p_modulation[8][16], const int p_modulation_modes[8][16], int *r_mod, int *p_dopt) {
static const int rep_vals0[4] = { 0, 3, 5, 8 };
static const int rep_vals1[4] = { 0, 4, 4, 8 };
int mod_val;
y = (y & 0x3) | ((~y & 0x2) << 1);
if (p_2bit) {
x = (x & 0x7) | ((~x & 0x4) << 1);
} else {
x = (x & 0x3) | ((~x & 0x2) << 1);
}
*p_dopt = 0;
if (p_modulation_modes[y][x] == 0) {
mod_val = rep_vals0[p_modulation[y][x]];
} else if (p_2bit) {
if (((x ^ y) & 1) == 0) {
mod_val = rep_vals0[p_modulation[y][x]];
} else if (p_modulation_modes[y][x] == 1) {
mod_val = (rep_vals0[p_modulation[y - 1][x]] +
rep_vals0[p_modulation[y + 1][x]] +
rep_vals0[p_modulation[y][x - 1]] +
rep_vals0[p_modulation[y][x + 1]] + 2) /
4;
} else if (p_modulation_modes[y][x] == 2) {
mod_val = (rep_vals0[p_modulation[y][x - 1]] +
rep_vals0[p_modulation[y][x + 1]] + 1) /
2;
} else {
mod_val = (rep_vals0[p_modulation[y - 1][x]] +
rep_vals0[p_modulation[y + 1][x]] + 1) /
2;
}
} else {
mod_val = rep_vals1[p_modulation[y][x]];
*p_dopt = p_modulation[y][x] == PT_INDEX;
}
*r_mod = mod_val;
}
static int disable_twiddling = 0;
static uint32_t twiddle_uv(uint32_t p_height, uint32_t p_width, uint32_t p_y, uint32_t p_x) {
uint32_t twiddled;
uint32_t min_dimension;
uint32_t max_value;
uint32_t scr_bit_pos;
uint32_t dst_bit_pos;
int shift_count;
ERR_FAIL_COND_V(p_y >= p_height, 0);
ERR_FAIL_COND_V(p_x >= p_width, 0);
ERR_FAIL_COND_V(!is_po2(p_height), 0);
ERR_FAIL_COND_V(!is_po2(p_width), 0);
if (p_height < p_width) {
min_dimension = p_height;
max_value = p_x;
} else {
min_dimension = p_width;
max_value = p_y;
}
if (disable_twiddling) {
return (p_y * p_width + p_x);
}
scr_bit_pos = 1;
dst_bit_pos = 1;
twiddled = 0;
shift_count = 0;
while (scr_bit_pos < min_dimension) {
if (p_y & scr_bit_pos) {
twiddled |= dst_bit_pos;
}
if (p_x & scr_bit_pos) {
twiddled |= (dst_bit_pos << 1);
}
scr_bit_pos <<= 1;
dst_bit_pos <<= 2;
shift_count += 1;
}
max_value >>= shift_count;
twiddled |= (max_value << (2 * shift_count));
return twiddled;
}
static void decompress_pvrtc(PVRTCBlock *p_comp_img, const int p_2bit, const int p_width, const int p_height, const int p_tiled, unsigned char *p_dst) {
int x, y;
int i, j;
int block_x, blk_y;
int block_xp1, blk_yp1;
int x_block_size;
int block_width, block_height;
int p_x, p_y;
int p_modulation[8][16] = { { 0 } };
int p_modulation_modes[8][16] = { { 0 } };
int Mod, DoPT;
unsigned int u_pos;
// local neighbourhood of blocks
PVRTCBlock *p_blocks[2][2];
PVRTCBlock *prev[2][2] = { { nullptr, nullptr }, { nullptr, nullptr } };
struct
{
int Reps[2][4];
} colors5554[2][2];
int ASig[4], BSig[4];
int r_result[4];
if (p_2bit) {
x_block_size = BLK_X_2BPP;
} else {
x_block_size = BLK_X_4BPP;
}
block_width = MAX(2, p_width / x_block_size);
block_height = MAX(2, p_height / BLK_Y_SIZE);
for (y = 0; y < p_height; y++) {
for (x = 0; x < p_width; x++) {
block_x = (x - x_block_size / 2);
blk_y = (y - BLK_Y_SIZE / 2);
block_x = LIMIT_COORD(block_x, p_width, p_tiled);
blk_y = LIMIT_COORD(blk_y, p_height, p_tiled);
block_x /= x_block_size;
blk_y /= BLK_Y_SIZE;
block_xp1 = LIMIT_COORD(block_x + 1, block_width, p_tiled);
blk_yp1 = LIMIT_COORD(blk_y + 1, block_height, p_tiled);
p_blocks[0][0] = p_comp_img + twiddle_uv(block_height, block_width, blk_y, block_x);
p_blocks[0][1] = p_comp_img + twiddle_uv(block_height, block_width, blk_y, block_xp1);
p_blocks[1][0] = p_comp_img + twiddle_uv(block_height, block_width, blk_yp1, block_x);
p_blocks[1][1] = p_comp_img + twiddle_uv(block_height, block_width, blk_yp1, block_xp1);
if (memcmp(prev, p_blocks, 4 * sizeof(void *)) != 0) {
p_y = 0;
for (i = 0; i < 2; i++) {
p_x = 0;
for (j = 0; j < 2; j++) {
unpack_5554(p_blocks[i][j], colors5554[i][j].Reps);
unpack_modulations(
p_blocks[i][j],
p_2bit,
p_modulation,
p_modulation_modes,
p_x, p_y);
p_x += x_block_size;
}
p_y += BLK_Y_SIZE;
}
memcpy(prev, p_blocks, 4 * sizeof(void *));
}
interpolate_colors(
colors5554[0][0].Reps[0],
colors5554[0][1].Reps[0],
colors5554[1][0].Reps[0],
colors5554[1][1].Reps[0],
p_2bit, x, y,
ASig);
interpolate_colors(
colors5554[0][0].Reps[1],
colors5554[0][1].Reps[1],
colors5554[1][0].Reps[1],
colors5554[1][1].Reps[1],
p_2bit, x, y,
BSig);
get_modulation_value(x, y, p_2bit, (const int(*)[16])p_modulation, (const int(*)[16])p_modulation_modes,
&Mod, &DoPT);
for (i = 0; i < 4; i++) {
r_result[i] = ASig[i] * 8 + Mod * (BSig[i] - ASig[i]);
r_result[i] >>= 3;
}
if (DoPT) {
r_result[3] = 0;
}
u_pos = (x + y * p_width) << 2;
p_dst[u_pos + 0] = (uint8_t)r_result[0];
p_dst[u_pos + 1] = (uint8_t)r_result[1];
p_dst[u_pos + 2] = (uint8_t)r_result[2];
p_dst[u_pos + 3] = (uint8_t)r_result[3];
}
}
}
static void _pvrtc_decompress(Image *p_img) {
ERR_FAIL_COND(p_img->get_format() != Image::FORMAT_PVRTC1_2 && p_img->get_format() != Image::FORMAT_PVRTC1_2A && p_img->get_format() != Image::FORMAT_PVRTC1_4 && p_img->get_format() != Image::FORMAT_PVRTC1_4A);
bool _2bit = (p_img->get_format() == Image::FORMAT_PVRTC1_2 || p_img->get_format() == Image::FORMAT_PVRTC1_2A);
Vector<uint8_t> data = p_img->get_data();
const uint8_t *r = data.ptr();
Vector<uint8_t> newdata;
newdata.resize(p_img->get_width() * p_img->get_height() * 4);
uint8_t *w = newdata.ptrw();
decompress_pvrtc((PVRTCBlock *)r, _2bit, p_img->get_width(), p_img->get_height(), 0, (unsigned char *)w);
bool make_mipmaps = p_img->has_mipmaps();
p_img->create(p_img->get_width(), p_img->get_height(), false, Image::FORMAT_RGBA8, newdata);
if (make_mipmaps) {
p_img->generate_mipmaps();
}
}

View file

@ -1,48 +0,0 @@
/*************************************************************************/
/* texture_loader_pvr.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef TEXTURE_LOADER_PVR_H
#define TEXTURE_LOADER_PVR_H
#include "core/io/resource_loader.h"
#include "scene/resources/texture.h"
class ResourceFormatPVR : public ResourceFormatLoader {
public:
virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
ResourceFormatPVR();
virtual ~ResourceFormatPVR() {}
};
#endif // TEXTURE_LOADER_PVR_H

View file

@ -32,11 +32,8 @@
void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) {
String driver = ProjectSettings::get_singleton()->get("rendering/driver/driver_name");
r_features->push_back("pvrtc");
if (driver == "vulkan") {
// FIXME: Review if this is correct.
r_features->push_back("etc2");
}
// Vulkan and OpenGL ES 3.0 both mandate ETC2 support.
r_features->push_back("etc2");
Vector<String> architectures = _get_preset_architectures(p_preset);
for (int i = 0; i < architectures.size(); ++i) {
@ -1766,7 +1763,7 @@ bool EditorExportPlatformIOS::can_export(const Ref<EditorExportPreset> &p_preset
}
}
String etc_error = test_etc2_or_pvrtc();
const String etc_error = test_etc2();
if (!etc_error.is_empty()) {
valid = false;
err += etc_error;

View file

@ -324,75 +324,6 @@ Ref<Image> RendererStorageRD::_validate_texture_format(const Ref<Image> &p_image
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B;
r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
} break; //unsigned float bc6hu
case Image::FORMAT_PVRTC1_2: {
//this is not properly supported by MoltekVK it seems, so best to use ETC2
if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
r_format.format = RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG;
r_format.format_srgb = RD::DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG;
} else {
//not supported, reconvert
r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
image->decompress();
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_ONE;
} break; //pvrtc
case Image::FORMAT_PVRTC1_2A: {
//this is not properly supported by MoltekVK it seems, so best to use ETC2
if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
r_format.format = RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG;
r_format.format_srgb = RD::DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG;
} else {
//not supported, reconvert
r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
image->decompress();
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;
case Image::FORMAT_PVRTC1_4: {
//this is not properly supported by MoltekVK it seems, so best to use ETC2
if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
r_format.format = RD::DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG;
r_format.format_srgb = RD::DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG;
} else {
//not supported, reconvert
r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
image->decompress();
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_ONE;
} break;
case Image::FORMAT_PVRTC1_4A: {
//this is not properly supported by MoltekVK it seems, so best to use ETC2
if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
r_format.format = RD::DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG;
r_format.format_srgb = RD::DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG;
} else {
//not supported, reconvert
r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
image->decompress();
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;
case Image::FORMAT_ETC2_R11: {
if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) {
r_format.format = RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK;
@ -9284,10 +9215,6 @@ bool RendererStorageRD::has_os_feature(const String &p_feature) const {
return true;
}
if (p_feature == "pvrtc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
return true;
}
return false;
}

View file

@ -729,14 +729,6 @@ void RenderingDevice::_bind_methods() {
BIND_ENUM_CONSTANT(DATA_FORMAT_G16_B16_R16_3PLANE_422_UNORM);
BIND_ENUM_CONSTANT(DATA_FORMAT_G16_B16R16_2PLANE_422_UNORM);
BIND_ENUM_CONSTANT(DATA_FORMAT_G16_B16_R16_3PLANE_444_UNORM);
BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG);
BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG);
BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG);
BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG);
BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG);
BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG);
BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG);
BIND_ENUM_CONSTANT(DATA_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG);
BIND_ENUM_CONSTANT(DATA_FORMAT_MAX);
BIND_ENUM_CONSTANT(TEXTURE_TYPE_1D);

View file

@ -392,14 +392,6 @@ public:
DATA_FORMAT_G16_B16_R16_3PLANE_422_UNORM,
DATA_FORMAT_G16_B16R16_2PLANE_422_UNORM,
DATA_FORMAT_G16_B16_R16_3PLANE_444_UNORM,
DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG,
DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG,
DATA_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG,
DATA_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG,
DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG,
DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG,
DATA_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG,
DATA_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG,
DATA_FORMAT_MAX
};

View file

@ -2822,7 +2822,6 @@ RenderingServer::RenderingServer() {
GLOBAL_DEF_RST("rendering/textures/vram_compression/import_s3tc", true);
GLOBAL_DEF_RST("rendering/textures/vram_compression/import_etc", false);
GLOBAL_DEF_RST("rendering/textures/vram_compression/import_etc2", true);
GLOBAL_DEF_RST("rendering/textures/vram_compression/import_pvrtc", false);
GLOBAL_DEF("rendering/textures/lossless_compression/force_png", false);
GLOBAL_DEF("rendering/textures/lossless_compression/webp_compression_level", 2);

16
thirdparty/README.md vendored
View file

@ -350,7 +350,7 @@ Files extracted from upstream repository:
- `LICENSE.md`.
An [experimental upstream feature](https://github.com/zeux/meshoptimizer/tree/simplify-attr),
has been backported. On top of that, it was modified to report only distance error metrics
has been backported. On top of that, it was modified to report only distance error metrics
instead of a combination of distance and attribute errors. Patches for both changes can be
found in the `patches` directory.
@ -524,19 +524,6 @@ Files extracted from upstream source:
- AUTHORS and LICENCE
## pvrtccompressor
- Upstream: https://bitbucket.org/jthlim/pvrtccompressor (dead link)
Unofficial backup fork: https://github.com/LibreGamesArchive/PVRTCCompressor
- Version: hg (cf7177748ee0dcdccfe89716dc11a47d2dc81af5, 2015)
- License: BSD-3-Clause
Files extracted from upstream source:
- all .cpp and .h files apart from `main.cpp`
- LICENSE.TXT
## recastnavigation
- Upstream: https://github.com/recastnavigation/recastnavigation
@ -737,4 +724,3 @@ Files extracted from upstream source:
- `lib/{common/,compress/,decompress/,zstd.h,zstd_errors.h}`
- `LICENSE`

View file

@ -1,18 +0,0 @@
#pragma once
#include "Bitmap.h"
namespace Javelin {
class AlphaBitmap : public Bitmap {
public:
AlphaBitmap(int w, int h)
: Bitmap(w, h, 1) {
}
const unsigned char *GetData() const { return data; }
unsigned char *GetData() { return data; }
};
}

View file

@ -1,184 +0,0 @@
#include "BitScale.h"
const uint8_t Javelin::Data::BITSCALE_5_TO_8[32] = {
0, 8, 16, 24, 32, 41, 49, 57, 65, 74,
82, 90, 98, 106, 115, 123, 131, 139, 148, 156,
164, 172, 180, 189, 197, 205, 213, 222, 230, 238,
246, 255};
const uint8_t Javelin::Data::BITSCALE_4_TO_8[16] = {
0, 17, 34, 51, 68, 85, 102, 119, 136, 153,
170, 187, 204, 221, 238, 255};
const uint8_t Javelin::Data::BITSCALE_3_TO_8[8] = {
0, 36, 72, 109, 145, 182, 218, 255};
const uint8_t Javelin::Data::BITSCALE_8_TO_5_FLOOR[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
3, 3, 3, 4, 4, 4, 4, 4, 4, 4,
4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 7, 7,
7, 7, 7, 7, 7, 7, 8, 8, 8, 8,
8, 8, 8, 8, 8, 9, 9, 9, 9, 9,
9, 9, 9, 10, 10, 10, 10, 10, 10, 10,
10, 11, 11, 11, 11, 11, 11, 11, 11, 12,
12, 12, 12, 12, 12, 12, 12, 13, 13, 13,
13, 13, 13, 13, 13, 13, 14, 14, 14, 14,
14, 14, 14, 14, 15, 15, 15, 15, 15, 15,
15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
17, 17, 17, 17, 17, 17, 17, 17, 17, 18,
18, 18, 18, 18, 18, 18, 18, 19, 19, 19,
19, 19, 19, 19, 19, 20, 20, 20, 20, 20,
20, 20, 20, 21, 21, 21, 21, 21, 21, 21,
21, 22, 22, 22, 22, 22, 22, 22, 22, 22,
23, 23, 23, 23, 23, 23, 23, 23, 24, 24,
24, 24, 24, 24, 24, 24, 25, 25, 25, 25,
25, 25, 25, 25, 26, 26, 26, 26, 26, 26,
26, 26, 26, 27, 27, 27, 27, 27, 27, 27,
27, 28, 28, 28, 28, 28, 28, 28, 28, 29,
29, 29, 29, 29, 29, 29, 29, 30, 30, 30,
30, 30, 30, 30, 30, 31};
const uint8_t Javelin::Data::BITSCALE_8_TO_4_FLOOR[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 15};
const uint8_t Javelin::Data::BITSCALE_8_TO_3_FLOOR[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 7};
const uint8_t Javelin::Data::BITSCALE_8_TO_5_CEIL[256] = {
0, 1, 1, 1, 1, 1, 1, 1, 1, 2,
2, 2, 2, 2, 2, 2, 2, 3, 3, 3,
3, 3, 3, 3, 3, 4, 4, 4, 4, 4,
4, 4, 4, 5, 5, 5, 5, 5, 5, 5,
5, 5, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 8, 8,
8, 8, 8, 8, 8, 8, 9, 9, 9, 9,
9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
10, 10, 10, 11, 11, 11, 11, 11, 11, 11,
11, 12, 12, 12, 12, 12, 12, 12, 12, 13,
13, 13, 13, 13, 13, 13, 13, 14, 14, 14,
14, 14, 14, 14, 14, 14, 15, 15, 15, 15,
15, 15, 15, 15, 16, 16, 16, 16, 16, 16,
16, 16, 17, 17, 17, 17, 17, 17, 17, 17,
18, 18, 18, 18, 18, 18, 18, 18, 18, 19,
19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
20, 20, 20, 20, 20, 21, 21, 21, 21, 21,
21, 21, 21, 22, 22, 22, 22, 22, 22, 22,
22, 23, 23, 23, 23, 23, 23, 23, 23, 23,
24, 24, 24, 24, 24, 24, 24, 24, 25, 25,
25, 25, 25, 25, 25, 25, 26, 26, 26, 26,
26, 26, 26, 26, 27, 27, 27, 27, 27, 27,
27, 27, 27, 28, 28, 28, 28, 28, 28, 28,
28, 29, 29, 29, 29, 29, 29, 29, 29, 30,
30, 30, 30, 30, 30, 30, 30, 31, 31, 31,
31, 31, 31, 31, 31, 31};
const uint8_t Javelin::Data::BITSCALE_8_TO_4_CEIL[256] = {
0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
10, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 12, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15};
const uint8_t Javelin::Data::BITSCALE_8_TO_3_CEIL[256] = {
0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7};

View file

@ -1,28 +0,0 @@
//============================================================================
#pragma once
#include "core/typedefs.h"
//============================================================================
namespace Javelin
{
namespace Data
{
//============================================================================
extern const uint8_t BITSCALE_5_TO_8[32];
extern const uint8_t BITSCALE_4_TO_8[16];
extern const uint8_t BITSCALE_3_TO_8[8];
extern const uint8_t BITSCALE_8_TO_5_FLOOR[256];
extern const uint8_t BITSCALE_8_TO_4_FLOOR[256];
extern const uint8_t BITSCALE_8_TO_3_FLOOR[256];
extern const uint8_t BITSCALE_8_TO_5_CEIL[256];
extern const uint8_t BITSCALE_8_TO_4_CEIL[256];
extern const uint8_t BITSCALE_8_TO_3_CEIL[256];
//============================================================================
} // namespace Data
} // namespace Javelin
//============================================================================

View file

@ -1,19 +0,0 @@
#pragma once
namespace Javelin {
class BitUtility {
public:
static bool IsPowerOf2(unsigned int x) {
return (x & (x - 1)) == 0;
}
static unsigned int RotateRight(unsigned int value, unsigned int shift) {
if ((shift &= sizeof(value) * 8 - 1) == 0) {
return value;
}
return (value >> shift) | (value << (sizeof(value) * 8 - shift));
}
};
}

View file

@ -1,34 +0,0 @@
#pragma once
#include "Point2.h"
namespace Javelin {
class Bitmap {
public:
int width;
int height;
unsigned char *data;
Bitmap(int w, int h, int bytesPerPixel)
: width(w)
, height(h)
, data(new unsigned char[width * height * bytesPerPixel]) {
}
virtual ~Bitmap() {
delete [] data;
}
Point2<int> GetSize() const { return Point2<int>(width, height); }
int GetArea() const { return width * height; }
int GetBitmapWidth() const { return width; }
int GetBitmapHeight() const { return height; }
const unsigned char *GetRawData() const { return data; }
};
}

View file

@ -1,152 +0,0 @@
#pragma once
namespace Javelin {
template<typename T>
class ColorRgb {
public:
T b;
T g;
T r;
ColorRgb()
: b(0)
, g(0)
, r(0) {
}
ColorRgb(T red, T green, T blue)
: b(blue)
, g(green)
, r(red) {
}
ColorRgb(const ColorRgb<T> &x)
: b(x.b)
, g(x.g)
, r(x.r) {
}
ColorRgb<int> operator *(int x) {
return ColorRgb<int>(r * x, g * x, b * x);
}
ColorRgb<int> operator +(const ColorRgb<T> &x) const {
return ColorRgb<int>(r + (int)x.r, g + (int)x.g, b + (int)x.b);
}
ColorRgb<int> operator -(const ColorRgb<T> &x) const {
return ColorRgb<int>(r - (int)x.r, g - (int)x.g, b - (int)x.b);
}
int operator %(const ColorRgb<T> &x) const {
return r * (int)x.r + g * (int)x.g + b * (int)x.b;
}
bool operator ==(const ColorRgb<T> &x) const {
return r == x.r && g == x.g && b == x.b;
}
bool operator !=(const ColorRgb<T> &x) const {
return r != x.r || g != x.g || b != x.b;
}
void SetMin(const ColorRgb<T> &x) {
if (x.r < r) {
r = x.r;
}
if (x.g < g) {
g = x.g;
}
if (x.b < b) {
b = x.b;
}
}
void SetMax(const ColorRgb<T> &x) {
if (x.r > r) {
r = x.r;
}
if (x.g > g) {
g = x.g;
}
if (x.b > b) {
b = x.b;
}
}
};
template<typename T>
class ColorRgba : public ColorRgb<T> {
public:
T a;
ColorRgba() :
a(0) {
}
ColorRgba(T red, T green, T blue, T alpha)
: ColorRgb<T>(red, green, blue)
, a(alpha) {
}
ColorRgba(const ColorRgba<T> &x)
: ColorRgb<T>(x.r, x.g, x.b)
, a(x.a) {
}
ColorRgba<int> operator *(int x) {
return ColorRgba<T>(ColorRgb<T>::r * x,
ColorRgb<T>::g * x,
ColorRgb<T>::b * x,
a * x);
}
ColorRgba<int> operator +(const ColorRgba<T> &x) {
return ColorRgba<T>(ColorRgb<T>::r + (int)x.r,
ColorRgb<T>::g + (int)x.g,
ColorRgb<T>::b + (int)x.b,
a + (int)x.a);
}
ColorRgba<int> operator -(const ColorRgba<T> &x) {
return ColorRgba<T>(ColorRgb<T>::r - (int)x.r,
ColorRgb<T>::g - (int)x.g,
ColorRgb<T>::b - (int)x.b,
a - (int)x.a);
}
int operator %(const ColorRgba<T> &x) {
return ColorRgb<T>::r * (int)x.r +
ColorRgb<T>::g * (int)x.g +
ColorRgb<T>::b * (int)x.b +
a * (int)x.a;
}
bool operator ==(const ColorRgba<T> &x) {
return ColorRgb<T>::r == x.r && ColorRgb<T>::g == x.g &&
ColorRgb<T>::b == x.b && a == x.a;
}
bool operator !=(const ColorRgba<T> &x) {
return ColorRgb<T>::r != x.r || ColorRgb<T>::g != x.g ||
ColorRgb<T>::b != x.b || a != x.a;
}
void SetMin(const ColorRgba<T> &x) {
ColorRgb<T>::SetMin(x);
if (x.a < a) {
a = x.a;
}
}
void SetMax(const ColorRgba<T> &x) {
ColorRgb<T>::SetMax(x);
if (x.a > a) {
a = x.a;
}
}
};
}

View file

@ -1,21 +0,0 @@
#pragma once
namespace Javelin {
template<typename T>
class Interval {
public:
T min;
T max;
Interval() {
}
Interval<T> &operator|=(const T &x) {
min.SetMin(x);
max.SetMax(x);
return *this;
}
};
}

View file

@ -1,25 +0,0 @@
Copyright © 2014, Jeffrey Lim. All Rights Reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View file

@ -1,43 +0,0 @@
//============================================================================
#include "MortonTable.h"
//============================================================================
const unsigned short Javelin::Data::MORTON_TABLE[256] =
{
0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015,
0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055,
0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115,
0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155,
0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415,
0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455,
0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515,
0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555,
0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015,
0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055,
0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115,
0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155,
0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415,
0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455,
0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515,
0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555,
0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015,
0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055,
0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115,
0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155,
0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415,
0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455,
0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515,
0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555,
0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015,
0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055,
0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115,
0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155,
0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415,
0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455,
0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515,
0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555
};
//============================================================================

View file

@ -1,18 +0,0 @@
//============================================================================
#pragma once
//============================================================================
namespace Javelin
{
namespace Data
{
//============================================================================
extern const unsigned short MORTON_TABLE[256];
//============================================================================
} // namespace Data
} // namespace Javelin
//============================================================================

View file

@ -1,17 +0,0 @@
#pragma once
namespace Javelin {
template<typename T>
class Point2 {
public:
T x;
T y;
Point2(int a, int b)
: x(a)
, y(b) {
}
};
}

View file

@ -1,144 +0,0 @@
//============================================================================
#include "PvrTcDecoder.h"
#include "PvrTcPacket.h"
#include "MortonTable.h"
#include <assert.h>
//============================================================================
using namespace Javelin;
using Data::MORTON_TABLE;
//============================================================================
inline unsigned PvrTcDecoder::GetMortonNumber(int x, int y)
{
return MORTON_TABLE[x >> 8] << 17 | MORTON_TABLE[y >> 8] << 16 | MORTON_TABLE[x & 0xFF] << 1 | MORTON_TABLE[y & 0xFF];
}
//============================================================================
void PvrTcDecoder::DecodeRgb4Bpp(ColorRgb<unsigned char>* result, const Point2<int>& size, const void* data)
{
assert(size.x == size.y);
const int blocks = size.x / 4;
const int blockMask = blocks-1;
const PvrTcPacket* packets = static_cast<const PvrTcPacket*>(data);
for(int y = 0; y < blocks; ++y)
{
for(int x = 0; x < blocks; ++x)
{
const PvrTcPacket* packet = packets + GetMortonNumber(x, y);
unsigned mod = packet->modulationData;
const unsigned char (*weights)[4] = PvrTcPacket::WEIGHTS + 4*packet->usePunchthroughAlpha;
const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS;
for(int py = 0; py < 4; ++py)
{
const int yOffset = (py < 2) ? -1 : 0;
const int y0 = (y + yOffset) & blockMask;
const int y1 = (y0+1) & blockMask;
for(int px = 0; px < 4; ++px)
{
const int xOffset = (px < 2) ? -1 : 0;
const int x0 = (x + xOffset) & blockMask;
const int x1 = (x0+1) & blockMask;
const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0);
const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0);
const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1);
const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1);
ColorRgb<int> ca = p0->GetColorRgbA() * (*factor)[0] +
p1->GetColorRgbA() * (*factor)[1] +
p2->GetColorRgbA() * (*factor)[2] +
p3->GetColorRgbA() * (*factor)[3];
ColorRgb<int> cb = p0->GetColorRgbB() * (*factor)[0] +
p1->GetColorRgbB() * (*factor)[1] +
p2->GetColorRgbB() * (*factor)[2] +
p3->GetColorRgbB() * (*factor)[3];
const unsigned char* w = weights[mod&3];
ColorRgb<unsigned char> c;
c.r = (ca.r * w[0] + cb.r * w[1]) >> 7;
c.g = (ca.g * w[0] + cb.g * w[1]) >> 7;
c.b = (ca.b * w[0] + cb.b * w[1]) >> 7;
result[(py+y*4)*size.x + (px+x*4)] = c;
mod >>= 2;
factor++;
}
}
}
}
}
void PvrTcDecoder::DecodeRgba4Bpp(ColorRgba<unsigned char>* result, const Point2<int>& size, const void* data)
{
assert(size.x == size.y);
const int blocks = size.x / 4;
const int blockMask = blocks-1;
const PvrTcPacket* packets = static_cast<const PvrTcPacket*>(data);
for(int y = 0; y < blocks; ++y)
{
for(int x = 0; x < blocks; ++x)
{
const PvrTcPacket* packet = packets + GetMortonNumber(x, y);
unsigned mod = packet->modulationData;
const unsigned char (*weights)[4] = PvrTcPacket::WEIGHTS + 4*packet->usePunchthroughAlpha;
const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS;
for(int py = 0; py < 4; ++py)
{
const int yOffset = (py < 2) ? -1 : 0;
const int y0 = (y + yOffset) & blockMask;
const int y1 = (y0+1) & blockMask;
for(int px = 0; px < 4; ++px)
{
const int xOffset = (px < 2) ? -1 : 0;
const int x0 = (x + xOffset) & blockMask;
const int x1 = (x0+1) & blockMask;
const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0);
const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0);
const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1);
const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1);
ColorRgba<int> ca = p0->GetColorRgbaA() * (*factor)[0] +
p1->GetColorRgbaA() * (*factor)[1] +
p2->GetColorRgbaA() * (*factor)[2] +
p3->GetColorRgbaA() * (*factor)[3];
ColorRgba<int> cb = p0->GetColorRgbaB() * (*factor)[0] +
p1->GetColorRgbaB() * (*factor)[1] +
p2->GetColorRgbaB() * (*factor)[2] +
p3->GetColorRgbaB() * (*factor)[3];
const unsigned char* w = weights[mod&3];
ColorRgba<unsigned char> c;
c.r = (ca.r * w[0] + cb.r * w[1]) >> 7;
c.g = (ca.g * w[0] + cb.g * w[1]) >> 7;
c.b = (ca.b * w[0] + cb.b * w[1]) >> 7;
c.a = (ca.a * w[2] + cb.a * w[3]) >> 7;
result[(py+y*4)*size.x + (px+x*4)] = c;
mod >>= 2;
factor++;
}
}
}
}
}
//============================================================================

View file

@ -1,25 +0,0 @@
//============================================================================
#pragma once
#include "Point2.h"
#include "ColorRgba.h"
//============================================================================
namespace Javelin
{
//============================================================================
class PvrTcDecoder
{
public:
static void DecodeRgb4Bpp(ColorRgb<unsigned char>* result, const Point2<int>& size, const void* data);
static void DecodeRgba4Bpp(ColorRgba<unsigned char>* result, const Point2<int>& size, const void* data);
private:
static unsigned GetMortonNumber(int x, int y);
};
//============================================================================
}
//============================================================================

View file

@ -1,474 +0,0 @@
//============================================================================
#include "PvrTcEncoder.h"
#include "AlphaBitmap.h"
#include "PvrTcPacket.h"
#include "RgbBitmap.h"
#include "RgbaBitmap.h"
#include "MortonTable.h"
#include "BitUtility.h"
#include "Interval.h"
#include <assert.h>
#include <math.h>
#include <stdint.h>
//============================================================================
using namespace Javelin;
using Data::MORTON_TABLE;
//============================================================================
static const unsigned char MODULATION_LUT[16] =
{
0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3
};
//============================================================================
inline unsigned PvrTcEncoder::GetMortonNumber(int x, int y)
{
return MORTON_TABLE[x >> 8] << 17 | MORTON_TABLE[y >> 8] << 16 | MORTON_TABLE[x & 0xFF] << 1 | MORTON_TABLE[y & 0xFF];
}
//============================================================================
void PvrTcEncoder::EncodeAlpha2Bpp(void* result, const AlphaBitmap& bitmap)
{
int size = bitmap.GetBitmapWidth();
assert(size == bitmap.GetBitmapHeight());
assert(BitUtility::IsPowerOf2(size));
// Blocks in each dimension.
int xBlocks = size/8;
int yBlocks = size/4;
const unsigned char* bitmapData = bitmap.GetRawData();
PvrTcPacket* packets = static_cast<PvrTcPacket*>(result);
for(int y = 0; y < yBlocks; ++y)
{
for(int x = 0; x < xBlocks; ++x)
{
PvrTcPacket* packet = packets + GetMortonNumber(x, y);
packet->usePunchthroughAlpha = 0;
packet->colorAIsOpaque = 0;
packet->colorA = 0x7ff; // White, with 0 alpha
packet->colorBIsOpaque = 1;
packet->colorB = 0x7fff; // White with full alpha
const unsigned char* blockBitmapData = &bitmapData[y*4*size + x*8];
uint32_t modulationData = 0;
for(int py = 0; py < 4; ++py)
{
const unsigned char* rowBitmapData = blockBitmapData;
for(int px = 0; px < 8; ++px)
{
unsigned char pixel = *rowBitmapData++;
modulationData = BitUtility::RotateRight(modulationData | (pixel >> 7), 1);
}
blockBitmapData += size;
}
packet->modulationData = modulationData;
}
}
}
void PvrTcEncoder::EncodeAlpha4Bpp(void* result, const AlphaBitmap& bitmap)
{
int size = bitmap.GetBitmapWidth();
assert(size == bitmap.GetBitmapHeight());
assert(BitUtility::IsPowerOf2(size));
// Blocks in each dimension.
int blocks = size/4;
const unsigned char* bitmapData = bitmap.GetRawData();
PvrTcPacket* packets = static_cast<PvrTcPacket*>(result);
for(int y = 0; y < blocks; ++y)
{
for(int x = 0; x < blocks; ++x)
{
PvrTcPacket* packet = packets + GetMortonNumber(x, y);
packet->usePunchthroughAlpha = 0;
packet->colorAIsOpaque = 0;
packet->colorA = 0x7ff; // White, with 0 alpha
packet->colorBIsOpaque = 1;
packet->colorB = 0x7fff; // White with full alpha
const unsigned char* blockBitmapData = &bitmapData[(y*size + x)*4];
uint32_t modulationData = 0;
for(int py = 0; py < 4; ++py)
{
const unsigned char* rowBitmapData = blockBitmapData;
for(int px = 0; px < 4; ++px)
{
unsigned char pixel = *rowBitmapData++;
modulationData = BitUtility::RotateRight(modulationData | MODULATION_LUT[pixel>>4], 2);
}
blockBitmapData += size;
}
packet->modulationData = modulationData;
}
}
}
//============================================================================
typedef Interval<ColorRgb<unsigned char> > ColorRgbBoundingBox;
static void CalculateBoundingBox(ColorRgbBoundingBox& cbb, const RgbBitmap& bitmap, int blockX, int blockY)
{
int size = bitmap.GetBitmapWidth();
const ColorRgb<unsigned char>* data = bitmap.GetData() + blockY * 4 * size + blockX * 4;
cbb.min = data[0];
cbb.max = data[0];
cbb |= data[1];
cbb |= data[2];
cbb |= data[3];
cbb |= data[size];
cbb |= data[size+1];
cbb |= data[size+2];
cbb |= data[size+3];
cbb |= data[2*size];
cbb |= data[2*size+1];
cbb |= data[2*size+2];
cbb |= data[2*size+3];
cbb |= data[3*size];
cbb |= data[3*size+1];
cbb |= data[3*size+2];
cbb |= data[3*size+3];
}
void PvrTcEncoder::EncodeRgb4Bpp(void* result, const RgbBitmap& bitmap)
{
assert(bitmap.GetBitmapWidth() == bitmap.GetBitmapHeight());
assert(BitUtility::IsPowerOf2(bitmap.GetBitmapWidth()));
const int size = bitmap.GetBitmapWidth();
const int blocks = size / 4;
const int blockMask = blocks-1;
PvrTcPacket* packets = static_cast<PvrTcPacket*>(result);
for(int y = 0; y < blocks; ++y)
{
for(int x = 0; x < blocks; ++x)
{
ColorRgbBoundingBox cbb;
CalculateBoundingBox(cbb, bitmap, x, y);
PvrTcPacket* packet = packets + GetMortonNumber(x, y);
packet->usePunchthroughAlpha = 0;
packet->SetColorA(cbb.min);
packet->SetColorB(cbb.max);
}
}
for(int y = 0; y < blocks; ++y)
{
for(int x = 0; x < blocks; ++x)
{
const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS;
const ColorRgb<unsigned char>* data = bitmap.GetData() + y * 4 * size + x * 4;
uint32_t modulationData = 0;
for(int py = 0; py < 4; ++py)
{
const int yOffset = (py < 2) ? -1 : 0;
const int y0 = (y + yOffset) & blockMask;
const int y1 = (y0+1) & blockMask;
for(int px = 0; px < 4; ++px)
{
const int xOffset = (px < 2) ? -1 : 0;
const int x0 = (x + xOffset) & blockMask;
const int x1 = (x0+1) & blockMask;
const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0);
const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0);
const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1);
const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1);
ColorRgb<int> ca = p0->GetColorRgbA() * (*factor)[0] +
p1->GetColorRgbA() * (*factor)[1] +
p2->GetColorRgbA() * (*factor)[2] +
p3->GetColorRgbA() * (*factor)[3];
ColorRgb<int> cb = p0->GetColorRgbB() * (*factor)[0] +
p1->GetColorRgbB() * (*factor)[1] +
p2->GetColorRgbB() * (*factor)[2] +
p3->GetColorRgbB() * (*factor)[3];
const ColorRgb<unsigned char>& pixel = data[py*size + px];
ColorRgb<int> d = cb - ca;
ColorRgb<int> p;
p.r=pixel.r*16;
p.g=pixel.g*16;
p.b=pixel.b*16;
ColorRgb<int> v = p - ca;
// PVRTC uses weightings of 0, 3/8, 5/8 and 1
// The boundaries for these are 3/16, 1/2 (=8/16), 13/16
int projection = (v % d) * 16;
int lengthSquared = d % d;
if(projection > 3*lengthSquared) modulationData++;
if(projection > 8*lengthSquared) modulationData++;
if(projection > 13*lengthSquared) modulationData++;
modulationData = BitUtility::RotateRight(modulationData, 2);
factor++;
}
}
PvrTcPacket* packet = packets + GetMortonNumber(x, y);
packet->modulationData = modulationData;
}
}
}
//============================================================================
static void CalculateBoundingBox(ColorRgbBoundingBox& cbb, const RgbaBitmap& bitmap, int blockX, int blockY)
{
int size = bitmap.GetBitmapWidth();
const ColorRgba<unsigned char>* data = bitmap.GetData() + blockY * 4 * size + blockX * 4;
cbb.min = data[0];
cbb.max = data[0];
cbb |= data[1];
cbb |= data[2];
cbb |= data[3];
cbb |= data[size];
cbb |= data[size+1];
cbb |= data[size+2];
cbb |= data[size+3];
cbb |= data[2*size];
cbb |= data[2*size+1];
cbb |= data[2*size+2];
cbb |= data[2*size+3];
cbb |= data[3*size];
cbb |= data[3*size+1];
cbb |= data[3*size+2];
cbb |= data[3*size+3];
}
void PvrTcEncoder::EncodeRgb4Bpp(void* result, const RgbaBitmap& bitmap)
{
assert(bitmap.GetBitmapWidth() == bitmap.GetBitmapHeight());
assert(BitUtility::IsPowerOf2(bitmap.GetBitmapWidth()));
const int size = bitmap.GetBitmapWidth();
const int blocks = size / 4;
const int blockMask = blocks-1;
PvrTcPacket* packets = static_cast<PvrTcPacket*>(result);
for(int y = 0; y < blocks; ++y)
{
for(int x = 0; x < blocks; ++x)
{
ColorRgbBoundingBox cbb;
CalculateBoundingBox(cbb, bitmap, x, y);
PvrTcPacket* packet = packets + GetMortonNumber(x, y);
packet->usePunchthroughAlpha = 0;
packet->SetColorA(cbb.min);
packet->SetColorB(cbb.max);
}
}
for(int y = 0; y < blocks; ++y)
{
for(int x = 0; x < blocks; ++x)
{
const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS;
const ColorRgba<unsigned char>* data = bitmap.GetData() + y * 4 * size + x * 4;
uint32_t modulationData = 0;
for(int py = 0; py < 4; ++py)
{
const int yOffset = (py < 2) ? -1 : 0;
const int y0 = (y + yOffset) & blockMask;
const int y1 = (y0+1) & blockMask;
for(int px = 0; px < 4; ++px)
{
const int xOffset = (px < 2) ? -1 : 0;
const int x0 = (x + xOffset) & blockMask;
const int x1 = (x0+1) & blockMask;
const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0);
const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0);
const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1);
const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1);
ColorRgb<int> ca = p0->GetColorRgbA() * (*factor)[0] +
p1->GetColorRgbA() * (*factor)[1] +
p2->GetColorRgbA() * (*factor)[2] +
p3->GetColorRgbA() * (*factor)[3];
ColorRgb<int> cb = p0->GetColorRgbB() * (*factor)[0] +
p1->GetColorRgbB() * (*factor)[1] +
p2->GetColorRgbB() * (*factor)[2] +
p3->GetColorRgbB() * (*factor)[3];
const ColorRgb<unsigned char>& pixel = data[py*size + px];
ColorRgb<int> d = cb - ca;
ColorRgb<int> p;
p.r=pixel.r*16;
p.g=pixel.g*16;
p.b=pixel.b*16;
ColorRgb<int> v = p - ca;
// PVRTC uses weightings of 0, 3/8, 5/8 and 1
// The boundaries for these are 3/16, 1/2 (=8/16), 13/16
int projection = (v % d) * 16;
int lengthSquared = d % d;
if(projection > 3*lengthSquared) modulationData++;
if(projection > 8*lengthSquared) modulationData++;
if(projection > 13*lengthSquared) modulationData++;
modulationData = BitUtility::RotateRight(modulationData, 2);
factor++;
}
}
PvrTcPacket* packet = packets + GetMortonNumber(x, y);
packet->modulationData = modulationData;
}
}
}
//============================================================================
typedef Interval<ColorRgba<unsigned char> > ColorRgbaBoundingBox;
static void CalculateBoundingBox(ColorRgbaBoundingBox& cbb, const RgbaBitmap& bitmap, int blockX, int blockY)
{
int size = bitmap.GetBitmapWidth();
const ColorRgba<unsigned char>* data = bitmap.GetData() + blockY * 4 * size + blockX * 4;
cbb.min = data[0];
cbb.max = data[0];
cbb |= data[1];
cbb |= data[2];
cbb |= data[3];
cbb |= data[size];
cbb |= data[size+1];
cbb |= data[size+2];
cbb |= data[size+3];
cbb |= data[2*size];
cbb |= data[2*size+1];
cbb |= data[2*size+2];
cbb |= data[2*size+3];
cbb |= data[3*size];
cbb |= data[3*size+1];
cbb |= data[3*size+2];
cbb |= data[3*size+3];
}
void PvrTcEncoder::EncodeRgba4Bpp(void* result, const RgbaBitmap& bitmap)
{
assert(bitmap.GetBitmapWidth() == bitmap.GetBitmapHeight());
assert(BitUtility::IsPowerOf2(bitmap.GetBitmapWidth()));
const int size = bitmap.GetBitmapWidth();
const int blocks = size / 4;
const int blockMask = blocks-1;
PvrTcPacket* packets = static_cast<PvrTcPacket*>(result);
for(int y = 0; y < blocks; ++y)
{
for(int x = 0; x < blocks; ++x)
{
ColorRgbaBoundingBox cbb;
CalculateBoundingBox(cbb, bitmap, x, y);
PvrTcPacket* packet = packets + GetMortonNumber(x, y);
packet->usePunchthroughAlpha = 0;
packet->SetColorA(cbb.min);
packet->SetColorB(cbb.max);
}
}
for(int y = 0; y < blocks; ++y)
{
for(int x = 0; x < blocks; ++x)
{
const unsigned char (*factor)[4] = PvrTcPacket::BILINEAR_FACTORS;
const ColorRgba<unsigned char>* data = bitmap.GetData() + y * 4 * size + x * 4;
uint32_t modulationData = 0;
for(int py = 0; py < 4; ++py)
{
const int yOffset = (py < 2) ? -1 : 0;
const int y0 = (y + yOffset) & blockMask;
const int y1 = (y0+1) & blockMask;
for(int px = 0; px < 4; ++px)
{
const int xOffset = (px < 2) ? -1 : 0;
const int x0 = (x + xOffset) & blockMask;
const int x1 = (x0+1) & blockMask;
const PvrTcPacket* p0 = packets + GetMortonNumber(x0, y0);
const PvrTcPacket* p1 = packets + GetMortonNumber(x1, y0);
const PvrTcPacket* p2 = packets + GetMortonNumber(x0, y1);
const PvrTcPacket* p3 = packets + GetMortonNumber(x1, y1);
ColorRgba<int> ca = p0->GetColorRgbaA() * (*factor)[0] +
p1->GetColorRgbaA() * (*factor)[1] +
p2->GetColorRgbaA() * (*factor)[2] +
p3->GetColorRgbaA() * (*factor)[3];
ColorRgba<int> cb = p0->GetColorRgbaB() * (*factor)[0] +
p1->GetColorRgbaB() * (*factor)[1] +
p2->GetColorRgbaB() * (*factor)[2] +
p3->GetColorRgbaB() * (*factor)[3];
const ColorRgba<unsigned char>& pixel = data[py*size + px];
ColorRgba<int> d = cb - ca;
ColorRgba<int> p;
p.r=pixel.r*16;
p.g=pixel.g*16;
p.b=pixel.b*16;
p.a=pixel.a*16;
ColorRgba<int> v = p - ca;
// PVRTC uses weightings of 0, 3/8, 5/8 and 1
// The boundaries for these are 3/16, 1/2 (=8/16), 13/16
int projection = (v % d) * 16;
int lengthSquared = d % d;
if(projection > 3*lengthSquared) modulationData++;
if(projection > 8*lengthSquared) modulationData++;
if(projection > 13*lengthSquared) modulationData++;
modulationData = BitUtility::RotateRight(modulationData, 2);
factor++;
}
}
PvrTcPacket* packet = packets + GetMortonNumber(x, y);
packet->modulationData = modulationData;
}
}
}
//============================================================================

View file

@ -1,40 +0,0 @@
//============================================================================
#pragma once
#include "ColorRgba.h"
//============================================================================
namespace Javelin
{
//============================================================================
class AlphaBitmap;
class RgbBitmap;
class RgbaBitmap;
class PvrTcEncoder
{
public:
// Result must be large enough for bitmap.GetArea()/4 bytes
static void EncodeAlpha2Bpp(void* result, const AlphaBitmap& bitmap);
// Result must be large enough for bitmap.GetArea()/2 bytes
static void EncodeAlpha4Bpp(void* result, const AlphaBitmap& bitmap);
// Result must be large enough for bitmap.GetArea()/2 bytes
static void EncodeRgb4Bpp(void* result, const RgbBitmap& bitmap);
// Result must be large enough for bitmap.GetArea()/2 bytes
static void EncodeRgb4Bpp(void* result, const RgbaBitmap& bitmap);
// Result must be large enough for bitmap.GetArea()/2 bytes
static void EncodeRgba4Bpp(void* result, const RgbaBitmap& bitmap);
private:
static unsigned GetMortonNumber(int x, int y);
};
//============================================================================
}
//============================================================================

View file

@ -1,209 +0,0 @@
//============================================================================
#include "PvrTcPacket.h"
#include "BitScale.h"
//============================================================================
using namespace Javelin;
//============================================================================
const unsigned char PvrTcPacket::BILINEAR_FACTORS[16][4] =
{
{ 4, 4, 4, 4 },
{ 2, 6, 2, 6 },
{ 8, 0, 8, 0 },
{ 6, 2, 6, 2 },
{ 2, 2, 6, 6 },
{ 1, 3, 3, 9 },
{ 4, 0, 12, 0 },
{ 3, 1, 9, 3 },
{ 8, 8, 0, 0 },
{ 4, 12, 0, 0 },
{ 16, 0, 0, 0 },
{ 12, 4, 0, 0 },
{ 6, 6, 2, 2 },
{ 3, 9, 1, 3 },
{ 12, 0, 4, 0 },
{ 9, 3, 3, 1 },
};
// Weights are { colorA, colorB, alphaA, alphaB }
const unsigned char PvrTcPacket::WEIGHTS[8][4] =
{
// Weights for Mode=0
{ 8, 0, 8, 0 },
{ 5, 3, 5, 3 },
{ 3, 5, 3, 5 },
{ 0, 8, 0, 8 },
// Weights for Mode=1
{ 8, 0, 8, 0 },
{ 4, 4, 4, 4 },
{ 4, 4, 0, 0 },
{ 0, 8, 0, 8 },
};
//============================================================================
ColorRgb<int> PvrTcPacket::GetColorRgbA() const
{
if(colorAIsOpaque)
{
unsigned char r = colorA >> 9;
unsigned char g = colorA >> 4 & 0x1f;
unsigned char b = colorA & 0xf;
return ColorRgb<int>(Data::BITSCALE_5_TO_8[r],
Data::BITSCALE_5_TO_8[g],
Data::BITSCALE_4_TO_8[b]);
}
else
{
unsigned char r = (colorA >> 7) & 0xf;
unsigned char g = (colorA >> 3) & 0xf;
unsigned char b = colorA & 7;
return ColorRgb<int>(Data::BITSCALE_4_TO_8[r],
Data::BITSCALE_4_TO_8[g],
Data::BITSCALE_3_TO_8[b]);
}
}
ColorRgb<int> PvrTcPacket::GetColorRgbB() const
{
if(colorBIsOpaque)
{
unsigned char r = colorB >> 10;
unsigned char g = colorB >> 5 & 0x1f;
unsigned char b = colorB & 0x1f;
return ColorRgb<int>(Data::BITSCALE_5_TO_8[r],
Data::BITSCALE_5_TO_8[g],
Data::BITSCALE_5_TO_8[b]);
}
else
{
unsigned char r = colorB >> 8 & 0xf;
unsigned char g = colorB >> 4 & 0xf;
unsigned char b = colorB & 0xf;
return ColorRgb<int>(Data::BITSCALE_4_TO_8[r],
Data::BITSCALE_4_TO_8[g],
Data::BITSCALE_4_TO_8[b]);
}
}
ColorRgba<int> PvrTcPacket::GetColorRgbaA() const
{
if(colorAIsOpaque)
{
unsigned char r = colorA >> 9;
unsigned char g = colorA >> 4 & 0x1f;
unsigned char b = colorA & 0xf;
return ColorRgba<int>(Data::BITSCALE_5_TO_8[r],
Data::BITSCALE_5_TO_8[g],
Data::BITSCALE_4_TO_8[b],
255);
}
else
{
unsigned char a = colorA >> 11 & 7;
unsigned char r = colorA >> 7 & 0xf;
unsigned char g = colorA >> 3 & 0xf;
unsigned char b = colorA & 7;
return ColorRgba<int>(Data::BITSCALE_4_TO_8[r],
Data::BITSCALE_4_TO_8[g],
Data::BITSCALE_3_TO_8[b],
Data::BITSCALE_3_TO_8[a]);
}
}
ColorRgba<int> PvrTcPacket::GetColorRgbaB() const
{
if(colorBIsOpaque)
{
unsigned char r = colorB >> 10;
unsigned char g = colorB >> 5 & 0x1f;
unsigned char b = colorB & 0x1f;
return ColorRgba<int>(Data::BITSCALE_5_TO_8[r],
Data::BITSCALE_5_TO_8[g],
Data::BITSCALE_5_TO_8[b],
255);
}
else
{
unsigned char a = colorB >> 12 & 7;
unsigned char r = colorB >> 8 & 0xf;
unsigned char g = colorB >> 4 & 0xf;
unsigned char b = colorB & 0xf;
return ColorRgba<int>(Data::BITSCALE_4_TO_8[r],
Data::BITSCALE_4_TO_8[g],
Data::BITSCALE_4_TO_8[b],
Data::BITSCALE_3_TO_8[a]);
}
}
//============================================================================
void PvrTcPacket::SetColorA(const ColorRgb<unsigned char>& c)
{
int r = Data::BITSCALE_8_TO_5_FLOOR[c.r];
int g = Data::BITSCALE_8_TO_5_FLOOR[c.g];
int b = Data::BITSCALE_8_TO_4_FLOOR[c.b];
colorA = r<<9 | g<<4 | b;
colorAIsOpaque = true;
}
void PvrTcPacket::SetColorB(const ColorRgb<unsigned char>& c)
{
int r = Data::BITSCALE_8_TO_5_CEIL[c.r];
int g = Data::BITSCALE_8_TO_5_CEIL[c.g];
int b = Data::BITSCALE_8_TO_5_CEIL[c.b];
colorB = r<<10 | g<<5 | b;
colorBIsOpaque = true;
}
void PvrTcPacket::SetColorA(const ColorRgba<unsigned char>& c)
{
int a = Data::BITSCALE_8_TO_3_FLOOR[c.a];
if(a == 7)
{
int r = Data::BITSCALE_8_TO_5_FLOOR[c.r];
int g = Data::BITSCALE_8_TO_5_FLOOR[c.g];
int b = Data::BITSCALE_8_TO_4_FLOOR[c.b];
colorA = r<<9 | g<<4 | b;
colorAIsOpaque = true;
}
else
{
int r = Data::BITSCALE_8_TO_4_FLOOR[c.r];
int g = Data::BITSCALE_8_TO_4_FLOOR[c.g];
int b = Data::BITSCALE_8_TO_3_FLOOR[c.b];
colorA = a<<11 | r<<7 | g<<3 | b;
colorAIsOpaque = false;
}
}
void PvrTcPacket::SetColorB(const ColorRgba<unsigned char>& c)
{
int a = Data::BITSCALE_8_TO_3_CEIL[c.a];
if(a == 7)
{
int r = Data::BITSCALE_8_TO_5_CEIL[c.r];
int g = Data::BITSCALE_8_TO_5_CEIL[c.g];
int b = Data::BITSCALE_8_TO_5_CEIL[c.b];
colorB = r<<10 | g<<5 | b;
colorBIsOpaque = true;
}
else
{
int r = Data::BITSCALE_8_TO_4_CEIL[c.r];
int g = Data::BITSCALE_8_TO_4_CEIL[c.g];
int b = Data::BITSCALE_8_TO_4_CEIL[c.b];
colorB = a<<12 | r<<8 | g<<4 | b;
colorBIsOpaque = false;
}
}
//============================================================================

View file

@ -1,65 +0,0 @@
//============================================================================
//
// Modulation data specifies weightings of colorA to colorB for each pixel
//
// For mode = 0
// 00: 0/8
// 01: 3/8
// 10: 5/8
// 11: 8/8
//
// For mode = 1
// 00: 0/8
// 01: 4/8
// 10: 4/8 with alpha punchthrough
// 11: 8/8
//
// For colorIsOpaque=0
// 3 bits A
// 4 bits R
// 4 bits G
// 3/4 bits B
//
// For colorIsOpaque=1
// 5 bits R
// 5 bits G
// 4/5 bits B
//
//============================================================================
#pragma once
#include "ColorRgba.h"
//============================================================================
namespace Javelin
{
//============================================================================
struct PvrTcPacket
{
unsigned int modulationData;
unsigned usePunchthroughAlpha : 1;
unsigned colorA : 14;
unsigned colorAIsOpaque : 1;
unsigned colorB : 15;
unsigned colorBIsOpaque : 1;
ColorRgb<int> GetColorRgbA() const;
ColorRgb<int> GetColorRgbB() const;
ColorRgba<int> GetColorRgbaA() const;
ColorRgba<int> GetColorRgbaB() const;
void SetColorA(const ColorRgb<unsigned char>& c);
void SetColorB(const ColorRgb<unsigned char>& c);
void SetColorA(const ColorRgba<unsigned char>& c);
void SetColorB(const ColorRgba<unsigned char>& c);
static const unsigned char BILINEAR_FACTORS[16][4];
static const unsigned char WEIGHTS[8][4];
};
//============================================================================
} // namespace Javelin
//============================================================================

View file

@ -1,23 +0,0 @@
#pragma once
#include "Bitmap.h"
#include "ColorRgba.h"
namespace Javelin {
class RgbBitmap : public Bitmap {
public:
RgbBitmap(int w, int h)
: Bitmap(w, h, 3) {
}
const ColorRgb<unsigned char> *GetData() const {
return reinterpret_cast<ColorRgb<unsigned char> *>(data);
}
ColorRgb<unsigned char> *GetData() {
return reinterpret_cast<ColorRgb<unsigned char> *>(data);
}
};
}

View file

@ -1,23 +0,0 @@
#pragma once
#include "ColorRgba.h"
#include "Bitmap.h"
namespace Javelin {
class RgbaBitmap : public Bitmap {
public:
RgbaBitmap(int w, int h)
: Bitmap(w, h, 4) {
}
const ColorRgba<unsigned char> *GetData() const {
return reinterpret_cast<ColorRgba<unsigned char> *>(data);
}
ColorRgba<unsigned char> *GetData() {
return reinterpret_cast<ColorRgba<unsigned char> *>(data);
}
};
}