From 1a312748550a7d4c5e436a3d2331be165d8abe07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Thu, 10 Dec 2020 15:44:05 +0100 Subject: PVRTC: Move compress func to `modules/pvr`, drop obsolete PVRTexTool code The code we had for PVRTexTool doesn't work as it's not compatible with current PVRTexTool CLI options, and likely hasn't been for years. Instead, we have our own vendored pvrtccompressor thirdparty library which all users have thus de-facto been using. This commit moves the compress code to `modules/pvr` where it belongs. There's no proper compress function for PVRTC 2-bit format, that's a bug that will need to be fixed (currently it's compressed as 4-bit format even if you use Image::FORMAT_PVRTC2). Fixes #28669. --- editor/editor_node.cpp | 8 +- editor/editor_settings.cpp | 9 -- editor/pvrtc_compress.cpp | 141 ---------------------- editor/pvrtc_compress.h | 38 ------ modules/etc/image_compress_etc.cpp | 226 +++++++++++++++++++++++++++++++++++ modules/etc/image_compress_etc.h | 36 ++++++ modules/etc/image_etc.cpp | 224 ---------------------------------- modules/etc/image_etc.h | 36 ------ modules/etc/register_types.cpp | 2 +- modules/pvr/image_compress_pvrtc.cpp | 86 +++++++++++++ modules/pvr/image_compress_pvrtc.h | 36 ++++++ modules/pvr/register_types.cpp | 3 + modules/pvr/texture_loader_pvr.cpp | 50 +------- 13 files changed, 392 insertions(+), 503 deletions(-) delete mode 100644 editor/pvrtc_compress.cpp delete mode 100644 editor/pvrtc_compress.h create mode 100644 modules/etc/image_compress_etc.cpp create mode 100644 modules/etc/image_compress_etc.h delete mode 100644 modules/etc/image_etc.cpp delete mode 100644 modules/etc/image_etc.h create mode 100644 modules/pvr/image_compress_pvrtc.cpp create mode 100644 modules/pvr/image_compress_pvrtc.h diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index f3086d416b..66c54c4267 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -58,7 +58,9 @@ #include "scene/gui/tab_container.h" #include "scene/gui/tabs.h" #include "scene/gui/texture_progress.h" +#include "scene/main/window.h" #include "scene/resources/packed_scene.h" +#include "servers/display_server.h" #include "servers/navigation_server_2d.h" #include "servers/navigation_server_3d.h" #include "servers/physics_server_2d.h" @@ -172,12 +174,10 @@ #include "editor/progress_dialog.h" #include "editor/project_export.h" #include "editor/project_settings_editor.h" -#include "editor/pvrtc_compress.h" #include "editor/quick_open.h" #include "editor/register_exporters.h" #include "editor/settings_config_dialog.h" -#include "scene/main/window.h" -#include "servers/display_server.h" + #include #include @@ -5726,8 +5726,6 @@ EditorNode::EditorNode() { EditorInspector::add_inspector_plugin(smp); } - _pvrtc_register_compressors(); - editor_selection = memnew(EditorSelection); EditorFileSystem *efs = memnew(EditorFileSystem); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index cc04ea5a58..44df3926fc 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -407,15 +407,6 @@ void EditorSettings::_load_defaults(Ref p_extra_config) { _initial_set("filesystem/file_dialog/thumbnail_size", 64); hints["filesystem/file_dialog/thumbnail_size"] = PropertyInfo(Variant::INT, "filesystem/file_dialog/thumbnail_size", PROPERTY_HINT_RANGE, "32,128,16"); - // Import - _initial_set("filesystem/import/pvrtc_texture_tool", ""); -#ifdef WINDOWS_ENABLED - hints["filesystem/import/pvrtc_texture_tool"] = PropertyInfo(Variant::STRING, "filesystem/import/pvrtc_texture_tool", PROPERTY_HINT_GLOBAL_FILE, "*.exe"); -#else - hints["filesystem/import/pvrtc_texture_tool"] = PropertyInfo(Variant::STRING, "filesystem/import/pvrtc_texture_tool", PROPERTY_HINT_GLOBAL_FILE, ""); -#endif - _initial_set("filesystem/import/pvrtc_fast_conversion", false); - /* Docks */ // SceneTree diff --git a/editor/pvrtc_compress.cpp b/editor/pvrtc_compress.cpp deleted file mode 100644 index 23bcf9540e..0000000000 --- a/editor/pvrtc_compress.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/*************************************************************************/ -/* pvrtc_compress.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 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 "pvrtc_compress.h" - -#include "core/io/resource_loader.h" -#include "core/io/resource_saver.h" -#include "core/os/dir_access.h" -#include "core/os/file_access.h" -#include "core/os/os.h" -#include "editor_settings.h" -#include "scene/resources/texture.h" - -static void (*_base_image_compress_pvrtc2_func)(Image *) = nullptr; -static void (*_base_image_compress_pvrtc4_func)(Image *) = nullptr; - -static void _compress_image(Image::CompressMode p_mode, Image *p_image) { - String ttpath = EditorSettings::get_singleton()->get("filesystem/import/pvrtc_texture_tool"); - - if (ttpath.strip_edges() == "" || !FileAccess::exists(ttpath)) { - switch (p_mode) { - case Image::COMPRESS_PVRTC2: - if (_base_image_compress_pvrtc2_func) { - _base_image_compress_pvrtc2_func(p_image); - } else if (_base_image_compress_pvrtc4_func) { - _base_image_compress_pvrtc4_func(p_image); - } - break; - case Image::COMPRESS_PVRTC4: - if (_base_image_compress_pvrtc4_func) { - _base_image_compress_pvrtc4_func(p_image); - } - break; - default: - ERR_FAIL_MSG("Unsupported Image compress mode used in PVRTC module."); - } - return; - } - - String tmppath = EditorSettings::get_singleton()->get_cache_dir(); - String src_img = tmppath.plus_file("_tmp_src_img.png"); - String dst_img = tmppath.plus_file("_tmp_dst_img.pvr"); - - List args; - args.push_back("-i"); - args.push_back(src_img); - args.push_back("-o"); - args.push_back(dst_img); - args.push_back("-f"); - - switch (p_mode) { - case Image::COMPRESS_PVRTC2: - args.push_back("PVRTC2"); - break; - case Image::COMPRESS_PVRTC4: - args.push_back("PVRTC4"); - break; - case Image::COMPRESS_ETC: - args.push_back("ETC"); - break; - default: - ERR_FAIL_MSG("Unsupported Image compress mode used in PVRTC module."); - } - - if (EditorSettings::get_singleton()->get("filesystem/import/pvrtc_fast_conversion").operator bool()) { - args.push_back("-pvrtcfast"); - } - if (p_image->has_mipmaps()) { - args.push_back("-m"); - } - - // Save source PNG. - Ref t = memnew(ImageTexture); - t->create_from_image(Ref(p_image)); - ResourceSaver::save(src_img, t); - - Error err = OS::get_singleton()->execute(ttpath, args, true); - if (err != OK) { - // Clean up generated files. - DirAccess::remove_file_or_error(src_img); - DirAccess::remove_file_or_error(dst_img); - ERR_FAIL_MSG("Could not execute PVRTC tool: " + ttpath); - } - - t = ResourceLoader::load(dst_img, "Texture2D"); - if (t.is_null()) { - // Clean up generated files. - DirAccess::remove_file_or_error(src_img); - DirAccess::remove_file_or_error(dst_img); - ERR_FAIL_MSG("Can't load back converted image using PVRTC tool."); - } - - p_image->copy_internals_from(t->get_data()); - - // Clean up generated files. - DirAccess::remove_file_or_error(src_img); - DirAccess::remove_file_or_error(dst_img); -} - -static void _compress_pvrtc2(Image *p_image) { - _compress_image(Image::COMPRESS_PVRTC2, p_image); -} - -static void _compress_pvrtc4(Image *p_image) { - _compress_image(Image::COMPRESS_PVRTC4, p_image); -} - -void _pvrtc_register_compressors() { - _base_image_compress_pvrtc2_func = Image::_image_compress_pvrtc2_func; - _base_image_compress_pvrtc4_func = Image::_image_compress_pvrtc4_func; - - Image::_image_compress_pvrtc2_func = _compress_pvrtc2; - Image::_image_compress_pvrtc4_func = _compress_pvrtc4; -} diff --git a/editor/pvrtc_compress.h b/editor/pvrtc_compress.h deleted file mode 100644 index 7b6c17d3c4..0000000000 --- a/editor/pvrtc_compress.h +++ /dev/null @@ -1,38 +0,0 @@ -/*************************************************************************/ -/* pvrtc_compress.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 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 PVRTC_COMPRESS_H -#define PVRTC_COMPRESS_H - -#include "core/io/image.h" - -void _pvrtc_register_compressors(); - -#endif // PVRTC_COMPRESS_H diff --git a/modules/etc/image_compress_etc.cpp b/modules/etc/image_compress_etc.cpp new file mode 100644 index 0000000000..bcdea41b43 --- /dev/null +++ b/modules/etc/image_compress_etc.cpp @@ -0,0 +1,226 @@ +/*************************************************************************/ +/* image_compress_etc.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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_etc.h" + +#include "core/io/image.h" +#include "core/os/copymem.h" +#include "core/os/os.h" +#include "core/string/print_string.h" + +#include +#include + +static Image::Format _get_etc2_mode(Image::UsedChannels format) { + switch (format) { + case Image::USED_CHANNELS_R: + return Image::FORMAT_ETC2_R11; + + case Image::USED_CHANNELS_RG: + return Image::FORMAT_ETC2_RG11; + + case Image::USED_CHANNELS_RGB: + return Image::FORMAT_ETC2_RGB8; + + case Image::USED_CHANNELS_RGBA: + return Image::FORMAT_ETC2_RGBA8; + + // TODO: would be nice if we could use FORMAT_ETC2_RGB8A1 for FORMAT_RGBA5551 + default: + // TODO: Kept for compatibility, but should be investigated whether it's correct or if it should error out + return Image::FORMAT_ETC2_RGBA8; + } +} + +static Etc::Image::Format _image_format_to_etc2comp_format(Image::Format format) { + switch (format) { + case Image::FORMAT_ETC: + return Etc::Image::Format::ETC1; + + case Image::FORMAT_ETC2_R11: + return Etc::Image::Format::R11; + + case Image::FORMAT_ETC2_R11S: + return Etc::Image::Format::SIGNED_R11; + + case Image::FORMAT_ETC2_RG11: + return Etc::Image::Format::RG11; + + case Image::FORMAT_ETC2_RG11S: + return Etc::Image::Format::SIGNED_RG11; + + case Image::FORMAT_ETC2_RGB8: + return Etc::Image::Format::RGB8; + + case Image::FORMAT_ETC2_RGBA8: + return Etc::Image::Format::RGBA8; + + case Image::FORMAT_ETC2_RGB8A1: + return Etc::Image::Format::RGB8A1; + + default: + ERR_FAIL_V(Etc::Image::Format::UNKNOWN); + } +} + +static void _compress_etc(Image *p_img, float p_lossy_quality, bool force_etc1_format, Image::UsedChannels p_channels) { + Image::Format img_format = p_img->get_format(); + + if (img_format >= Image::FORMAT_DXT1) { + return; //do not compress, already compressed + } + + if (img_format > Image::FORMAT_RGBA8) { + // TODO: we should be able to handle FORMAT_RGBA4444 and FORMAT_RGBA5551 eventually + return; + } + + // FIXME: Commented out during Vulkan rebase. + /* + if (force_etc1_format) { + // If VRAM compression is using ETC, but image has alpha, convert to RGBA4444 or LA8 + // This saves space while maintaining the alpha channel + if (detected_channels == Image::USED_CHANNELS_RGBA) { + if (p_img->has_mipmaps()) { + // Image doesn't support mipmaps with RGBA4444 textures + p_img->clear_mipmaps(); + } + p_img->convert(Image::FORMAT_RGBA4444); + return; + } else if (detected_channels == Image::USE_CHANNELS_LA) { + p_img->convert(Image::FORMAT_LA8); + return; + } + } + */ + + uint32_t imgw = p_img->get_width(), imgh = p_img->get_height(); + + Image::Format etc_format = force_etc1_format ? Image::FORMAT_ETC : _get_etc2_mode(p_channels); + + Ref img = p_img->duplicate(); + + if (img->get_format() != Image::FORMAT_RGBA8) { + img->convert(Image::FORMAT_RGBA8); //still uses RGBA to convert + } + + if (img->has_mipmaps()) { + if (next_power_of_2(imgw) != imgw || next_power_of_2(imgh) != imgh) { + img->resize_to_po2(); + imgw = img->get_width(); + imgh = img->get_height(); + } + } else { + if (imgw % 4 != 0 || imgh % 4 != 0) { + if (imgw % 4) { + imgw += 4 - imgw % 4; + } + if (imgh % 4) { + imgh += 4 - imgh % 4; + } + + img->resize(imgw, imgh); + } + } + + const uint8_t *r = img->get_data().ptr(); + ERR_FAIL_COND(!r); + + unsigned int target_size = Image::get_image_data_size(imgw, imgh, etc_format, p_img->has_mipmaps()); + int mmc = 1 + (p_img->has_mipmaps() ? Image::get_image_required_mipmaps(imgw, imgh, etc_format) : 0); + + Vector dst_data; + dst_data.resize(target_size); + + uint8_t *w = dst_data.ptrw(); + + // prepare parameters to be passed to etc2comp + int num_cpus = OS::get_singleton()->get_processor_count(); + int encoding_time = 0; + float effort = 0.0; //default, reasonable time + + if (p_lossy_quality > 0.75) { + effort = 0.4; + } else if (p_lossy_quality > 0.85) { + effort = 0.6; + } else if (p_lossy_quality > 0.95) { + effort = 0.8; + } + + Etc::ErrorMetric error_metric = Etc::ErrorMetric::RGBX; // NOTE: we can experiment with other error metrics + Etc::Image::Format etc2comp_etc_format = _image_format_to_etc2comp_format(etc_format); + + int wofs = 0; + + print_verbose("ETC: Begin encoding, format: " + Image::get_format_name(etc_format)); + uint64_t t = OS::get_singleton()->get_ticks_msec(); + for (int i = 0; i < mmc; i++) { + // convert source image to internal etc2comp format (which is equivalent to Image::FORMAT_RGBAF) + // NOTE: We can alternatively add a case to Image::convert to handle Image::FORMAT_RGBAF conversion. + int mipmap_ofs = 0, mipmap_size = 0, mipmap_w = 0, mipmap_h = 0; + img->get_mipmap_offset_size_and_dimensions(i, mipmap_ofs, mipmap_size, mipmap_w, mipmap_h); + const uint8_t *src = &r[mipmap_ofs]; + + Etc::ColorFloatRGBA *src_rgba_f = new Etc::ColorFloatRGBA[mipmap_w * mipmap_h]; + for (int j = 0; j < mipmap_w * mipmap_h; j++) { + int si = j * 4; // RGBA8 + src_rgba_f[j] = Etc::ColorFloatRGBA::ConvertFromRGBA8(src[si], src[si + 1], src[si + 2], src[si + 3]); + } + + unsigned char *etc_data = nullptr; + unsigned int etc_data_len = 0; + unsigned int extended_width = 0, extended_height = 0; + Etc::Encode((float *)src_rgba_f, mipmap_w, mipmap_h, etc2comp_etc_format, error_metric, effort, num_cpus, num_cpus, &etc_data, &etc_data_len, &extended_width, &extended_height, &encoding_time); + + CRASH_COND(wofs + etc_data_len > target_size); + memcpy(&w[wofs], etc_data, etc_data_len); + wofs += etc_data_len; + + delete[] etc_data; + delete[] src_rgba_f; + } + + print_verbose("ETC: Time encoding: " + rtos(OS::get_singleton()->get_ticks_msec() - t)); + + p_img->create(imgw, imgh, p_img->has_mipmaps(), etc_format, dst_data); +} + +static void _compress_etc1(Image *p_img, float p_lossy_quality) { + _compress_etc(p_img, p_lossy_quality, true, Image::USED_CHANNELS_RGB); +} + +static void _compress_etc2(Image *p_img, float p_lossy_quality, Image::UsedChannels p_channels) { + _compress_etc(p_img, p_lossy_quality, false, p_channels); +} + +void _register_etc_compress_func() { + Image::_image_compress_etc1_func = _compress_etc1; + Image::_image_compress_etc2_func = _compress_etc2; +} diff --git a/modules/etc/image_compress_etc.h b/modules/etc/image_compress_etc.h new file mode 100644 index 0000000000..016e64e4fc --- /dev/null +++ b/modules/etc/image_compress_etc.h @@ -0,0 +1,36 @@ +/*************************************************************************/ +/* image_compress_etc.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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_ETC_H +#define IMAGE_COMPRESS_ETC_H + +void _register_etc_compress_func(); + +#endif // IMAGE_COMPRESS_ETC_H diff --git a/modules/etc/image_etc.cpp b/modules/etc/image_etc.cpp deleted file mode 100644 index 4e9e64c6a7..0000000000 --- a/modules/etc/image_etc.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/*************************************************************************/ -/* image_etc.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 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_etc.h" -#include "Etc.h" -#include "EtcFilter.h" -#include "core/io/image.h" -#include "core/os/copymem.h" -#include "core/os/os.h" -#include "core/string/print_string.h" - -static Image::Format _get_etc2_mode(Image::UsedChannels format) { - switch (format) { - case Image::USED_CHANNELS_R: - return Image::FORMAT_ETC2_R11; - - case Image::USED_CHANNELS_RG: - return Image::FORMAT_ETC2_RG11; - - case Image::USED_CHANNELS_RGB: - return Image::FORMAT_ETC2_RGB8; - - case Image::USED_CHANNELS_RGBA: - return Image::FORMAT_ETC2_RGBA8; - - // TODO: would be nice if we could use FORMAT_ETC2_RGB8A1 for FORMAT_RGBA5551 - default: - // TODO: Kept for compatibility, but should be investigated whether it's correct or if it should error out - return Image::FORMAT_ETC2_RGBA8; - } -} - -static Etc::Image::Format _image_format_to_etc2comp_format(Image::Format format) { - switch (format) { - case Image::FORMAT_ETC: - return Etc::Image::Format::ETC1; - - case Image::FORMAT_ETC2_R11: - return Etc::Image::Format::R11; - - case Image::FORMAT_ETC2_R11S: - return Etc::Image::Format::SIGNED_R11; - - case Image::FORMAT_ETC2_RG11: - return Etc::Image::Format::RG11; - - case Image::FORMAT_ETC2_RG11S: - return Etc::Image::Format::SIGNED_RG11; - - case Image::FORMAT_ETC2_RGB8: - return Etc::Image::Format::RGB8; - - case Image::FORMAT_ETC2_RGBA8: - return Etc::Image::Format::RGBA8; - - case Image::FORMAT_ETC2_RGB8A1: - return Etc::Image::Format::RGB8A1; - - default: - ERR_FAIL_V(Etc::Image::Format::UNKNOWN); - } -} - -static void _compress_etc(Image *p_img, float p_lossy_quality, bool force_etc1_format, Image::UsedChannels p_channels) { - Image::Format img_format = p_img->get_format(); - - if (img_format >= Image::FORMAT_DXT1) { - return; //do not compress, already compressed - } - - if (img_format > Image::FORMAT_RGBA8) { - // TODO: we should be able to handle FORMAT_RGBA4444 and FORMAT_RGBA5551 eventually - return; - } - - // FIXME: Commented out during Vulkan rebase. - /* - if (force_etc1_format) { - // If VRAM compression is using ETC, but image has alpha, convert to RGBA4444 or LA8 - // This saves space while maintaining the alpha channel - if (detected_channels == Image::USED_CHANNELS_RGBA) { - if (p_img->has_mipmaps()) { - // Image doesn't support mipmaps with RGBA4444 textures - p_img->clear_mipmaps(); - } - p_img->convert(Image::FORMAT_RGBA4444); - return; - } else if (detected_channels == Image::USE_CHANNELS_LA) { - p_img->convert(Image::FORMAT_LA8); - return; - } - } - */ - - uint32_t imgw = p_img->get_width(), imgh = p_img->get_height(); - - Image::Format etc_format = force_etc1_format ? Image::FORMAT_ETC : _get_etc2_mode(p_channels); - - Ref img = p_img->duplicate(); - - if (img->get_format() != Image::FORMAT_RGBA8) { - img->convert(Image::FORMAT_RGBA8); //still uses RGBA to convert - } - - if (img->has_mipmaps()) { - if (next_power_of_2(imgw) != imgw || next_power_of_2(imgh) != imgh) { - img->resize_to_po2(); - imgw = img->get_width(); - imgh = img->get_height(); - } - } else { - if (imgw % 4 != 0 || imgh % 4 != 0) { - if (imgw % 4) { - imgw += 4 - imgw % 4; - } - if (imgh % 4) { - imgh += 4 - imgh % 4; - } - - img->resize(imgw, imgh); - } - } - - const uint8_t *r = img->get_data().ptr(); - ERR_FAIL_COND(!r); - - unsigned int target_size = Image::get_image_data_size(imgw, imgh, etc_format, p_img->has_mipmaps()); - int mmc = 1 + (p_img->has_mipmaps() ? Image::get_image_required_mipmaps(imgw, imgh, etc_format) : 0); - - Vector dst_data; - dst_data.resize(target_size); - - uint8_t *w = dst_data.ptrw(); - - // prepare parameters to be passed to etc2comp - int num_cpus = OS::get_singleton()->get_processor_count(); - int encoding_time = 0; - float effort = 0.0; //default, reasonable time - - if (p_lossy_quality > 0.75) { - effort = 0.4; - } else if (p_lossy_quality > 0.85) { - effort = 0.6; - } else if (p_lossy_quality > 0.95) { - effort = 0.8; - } - - Etc::ErrorMetric error_metric = Etc::ErrorMetric::RGBX; // NOTE: we can experiment with other error metrics - Etc::Image::Format etc2comp_etc_format = _image_format_to_etc2comp_format(etc_format); - - int wofs = 0; - - print_verbose("ETC: Begin encoding, format: " + Image::get_format_name(etc_format)); - uint64_t t = OS::get_singleton()->get_ticks_msec(); - for (int i = 0; i < mmc; i++) { - // convert source image to internal etc2comp format (which is equivalent to Image::FORMAT_RGBAF) - // NOTE: We can alternatively add a case to Image::convert to handle Image::FORMAT_RGBAF conversion. - int mipmap_ofs = 0, mipmap_size = 0, mipmap_w = 0, mipmap_h = 0; - img->get_mipmap_offset_size_and_dimensions(i, mipmap_ofs, mipmap_size, mipmap_w, mipmap_h); - const uint8_t *src = &r[mipmap_ofs]; - - Etc::ColorFloatRGBA *src_rgba_f = new Etc::ColorFloatRGBA[mipmap_w * mipmap_h]; - for (int j = 0; j < mipmap_w * mipmap_h; j++) { - int si = j * 4; // RGBA8 - src_rgba_f[j] = Etc::ColorFloatRGBA::ConvertFromRGBA8(src[si], src[si + 1], src[si + 2], src[si + 3]); - } - - unsigned char *etc_data = nullptr; - unsigned int etc_data_len = 0; - unsigned int extended_width = 0, extended_height = 0; - Etc::Encode((float *)src_rgba_f, mipmap_w, mipmap_h, etc2comp_etc_format, error_metric, effort, num_cpus, num_cpus, &etc_data, &etc_data_len, &extended_width, &extended_height, &encoding_time); - - CRASH_COND(wofs + etc_data_len > target_size); - memcpy(&w[wofs], etc_data, etc_data_len); - wofs += etc_data_len; - - delete[] etc_data; - delete[] src_rgba_f; - } - - print_verbose("ETC: Time encoding: " + rtos(OS::get_singleton()->get_ticks_msec() - t)); - - p_img->create(imgw, imgh, p_img->has_mipmaps(), etc_format, dst_data); -} - -static void _compress_etc1(Image *p_img, float p_lossy_quality) { - _compress_etc(p_img, p_lossy_quality, true, Image::USED_CHANNELS_RGB); -} - -static void _compress_etc2(Image *p_img, float p_lossy_quality, Image::UsedChannels p_channels) { - _compress_etc(p_img, p_lossy_quality, false, p_channels); -} - -void _register_etc_compress_func() { - Image::_image_compress_etc1_func = _compress_etc1; - Image::_image_compress_etc2_func = _compress_etc2; -} diff --git a/modules/etc/image_etc.h b/modules/etc/image_etc.h deleted file mode 100644 index 7b4f26e127..0000000000 --- a/modules/etc/image_etc.h +++ /dev/null @@ -1,36 +0,0 @@ -/*************************************************************************/ -/* image_etc.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 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_ETC1_H -#define IMAGE_ETC1_H - -void _register_etc_compress_func(); - -#endif // IMAGE_ETC_H diff --git a/modules/etc/register_types.cpp b/modules/etc/register_types.cpp index 0972857808..225ba6b954 100644 --- a/modules/etc/register_types.cpp +++ b/modules/etc/register_types.cpp @@ -30,7 +30,7 @@ #include "register_types.h" -#include "image_etc.h" +#include "image_compress_etc.h" #include "texture_loader_pkm.h" static Ref resource_loader_pkm; diff --git a/modules/pvr/image_compress_pvrtc.cpp b/modules/pvr/image_compress_pvrtc.cpp new file mode 100644 index 0000000000..4cb0083556 --- /dev/null +++ b/modules/pvr/image_compress_pvrtc.cpp @@ -0,0 +1,86 @@ +/*************************************************************************/ +/* image_compress_pvrtc.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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/reference.h" + +#include +#include + +static void _compress_pvrtc4(Image *p_img) { + Ref 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); + } + img->convert(Image::FORMAT_RGBA8); + if (!img->has_mipmaps() && make_mipmaps) { + img->generate_mipmaps(); + } + + bool use_alpha = img->detect_alpha(); + + Ref new_img; + new_img.instance(); + new_img->create(img->get_width(), img->get_height(), img->has_mipmaps(), use_alpha ? Image::FORMAT_PVRTC4A : Image::FORMAT_PVRTC4); + + Vector 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(); + copymem(dst, &r[ofs], size); + Javelin::ColorRgba *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() { + // FIXME: We claim to support PVRTC2 but use the same method as for PVRTC4. + Image::_image_compress_pvrtc2_func = _compress_pvrtc4; + Image::_image_compress_pvrtc4_func = _compress_pvrtc4; +} diff --git a/modules/pvr/image_compress_pvrtc.h b/modules/pvr/image_compress_pvrtc.h new file mode 100644 index 0000000000..fde65f4bbe --- /dev/null +++ b/modules/pvr/image_compress_pvrtc.h @@ -0,0 +1,36 @@ +/*************************************************************************/ +/* image_compress_pvrtc.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 diff --git a/modules/pvr/register_types.cpp b/modules/pvr/register_types.cpp index 1eb697bba3..9bfc334d76 100644 --- a/modules/pvr/register_types.cpp +++ b/modules/pvr/register_types.cpp @@ -30,6 +30,7 @@ #include "register_types.h" +#include "image_compress_pvrtc.h" #include "texture_loader_pvr.h" static Ref resource_loader_pvr; @@ -37,6 +38,8 @@ static Ref resource_loader_pvr; void register_pvr_types() { resource_loader_pvr.instance(); ResourceLoader::add_resource_format_loader(resource_loader_pvr); + + _register_pvrtc_compress_func(); } void unregister_pvr_types() { diff --git a/modules/pvr/texture_loader_pvr.cpp b/modules/pvr/texture_loader_pvr.cpp index 0923714387..46101262c8 100644 --- a/modules/pvr/texture_loader_pvr.cpp +++ b/modules/pvr/texture_loader_pvr.cpp @@ -29,11 +29,8 @@ /*************************************************************************/ #include "texture_loader_pvr.h" -#include "PvrTcEncoder.h" -#include "RgbaBitmap.h" + #include "core/os/file_access.h" -#include -#include static void _pvrtc_decompress(Image *p_img); @@ -183,53 +180,8 @@ String ResourceFormatPVR::get_resource_type(const String &p_path) const { return ""; } -static void _compress_pvrtc4(Image *p_img) { - Ref 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); - } - img->convert(Image::FORMAT_RGBA8); - if (!img->has_mipmaps() && make_mipmaps) { - img->generate_mipmaps(); - } - - bool use_alpha = img->detect_alpha(); - - Ref new_img; - new_img.instance(); - new_img->create(img->get_width(), img->get_height(), img->has_mipmaps(), use_alpha ? Image::FORMAT_PVRTC4A : Image::FORMAT_PVRTC4); - - Vector 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(); - copymem(dst, &r[ofs], size); - Javelin::ColorRgba *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); -} - ResourceFormatPVR::ResourceFormatPVR() { Image::_image_decompress_pvrtc = _pvrtc_decompress; - Image::_image_compress_pvrtc4_func = _compress_pvrtc4; - Image::_image_compress_pvrtc2_func = _compress_pvrtc4; } ///////////////////////////////////////////////////////// -- cgit v1.2.3 From 9263f8eb4bacd771c47dab35aaa31c7569ece035 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Thu, 10 Dec 2020 23:01:00 +0100 Subject: Image: Rename PVRTC{2,4} to PVRTC1_{2,4}, drop COMPRESS_PVRTC2 We haven't had a proper implementation for COMPRESS_PVRTC2 (which is PVRTC1 2-bpp) in years, so let's drop it instead of keeping a compress type which doesn't work. The other enum values were renamed to clarify that our PVRTC2 and PVRTC4 are respectively PVRTC1 2-bpp and PVRTC1 4-bpp. PVRTC2 2-bpp and 4-bpp are not implemented yet. --- core/io/image.cpp | 71 ++++++++++------------ core/io/image.h | 16 +++-- doc/classes/Image.xml | 29 ++++----- editor/import/resource_importer_texture.cpp | 2 +- modules/pvr/image_compress_pvrtc.cpp | 8 +-- modules/pvr/texture_loader_pvr.cpp | 8 +-- .../rendering/renderer_rd/renderer_storage_rd.cpp | 8 +-- 7 files changed, 67 insertions(+), 75 deletions(-) diff --git a/core/io/image.cpp b/core/io/image.cpp index 6dde25af32..7c32c02701 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -66,10 +66,10 @@ const char *Image::format_names[Image::FORMAT_MAX] = { "BPTC_RGBA", "BPTC_RGBF", "BPTC_RGBFU", - "PVRTC2", //pvrtc - "PVRTC2A", - "PVRTC4", - "PVRTC4A", + "PVRTC1_2", //pvrtc + "PVRTC1_2A", + "PVRTC1_4", + "PVRTC1_4A", "ETC", //etc1 "ETC2_R11", //etc2 "ETC2_R11S", //signed", NOT srgb. @@ -155,13 +155,13 @@ int Image::get_format_pixel_size(Format p_format) { return 1; //float / case FORMAT_BPTC_RGBFU: return 1; //unsigned float - case FORMAT_PVRTC2: + case FORMAT_PVRTC1_2: return 1; //pvrtc - case FORMAT_PVRTC2A: + case FORMAT_PVRTC1_2A: return 1; - case FORMAT_PVRTC4: + case FORMAT_PVRTC1_4: return 1; - case FORMAT_PVRTC4A: + case FORMAT_PVRTC1_4A: return 1; case FORMAT_ETC: return 1; //etc1 @@ -200,13 +200,13 @@ 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_PVRTC2: - case FORMAT_PVRTC2A: { + case FORMAT_PVRTC1_2: + case FORMAT_PVRTC1_2A: { r_w = 16; r_h = 8; } break; - case FORMAT_PVRTC4A: - case FORMAT_PVRTC4: { + case FORMAT_PVRTC1_4A: + case FORMAT_PVRTC1_4: { r_w = 8; r_h = 8; } break; @@ -242,9 +242,9 @@ 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_PVRTC4 || p_format == FORMAT_PVRTC4A || 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_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) { return 1; - } else if (p_format == FORMAT_PVRTC2 || p_format == FORMAT_PVRTC2A) { + } else if (p_format == FORMAT_PVRTC1_2 || p_format == FORMAT_PVRTC1_2A) { return 2; } else { return 0; @@ -261,12 +261,12 @@ int Image::get_format_block_size(Format p_format) { return 4; } - case FORMAT_PVRTC2: - case FORMAT_PVRTC2A: { + case FORMAT_PVRTC1_2: + case FORMAT_PVRTC1_2A: { return 4; } - case FORMAT_PVRTC4A: - case FORMAT_PVRTC4: { + case FORMAT_PVRTC1_4A: + case FORMAT_PVRTC1_4: { return 4; } case FORMAT_ETC: { @@ -2216,8 +2216,8 @@ bool Image::is_invisible() const { } break; - case FORMAT_PVRTC2A: - case FORMAT_PVRTC4A: + case FORMAT_PVRTC1_2A: + case FORMAT_PVRTC1_4A: case FORMAT_DXT3: case FORMAT_DXT5: { detected = true; @@ -2258,8 +2258,8 @@ Image::AlphaMode Image::detect_alpha() const { } } break; - case FORMAT_PVRTC2A: - case FORMAT_PVRTC4A: + case FORMAT_PVRTC1_2A: + case FORMAT_PVRTC1_4A: case FORMAT_DXT3: case FORMAT_DXT5: { detected = true; @@ -2355,7 +2355,7 @@ 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_PVRTC2 && format <= FORMAT_PVRTC4A && _image_decompress_pvrtc) { + } 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); @@ -2377,13 +2377,9 @@ 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_PVRTC2: { - ERR_FAIL_COND_V(!_image_compress_pvrtc2_func, ERR_UNAVAILABLE); - _image_compress_pvrtc2_func(this); - } break; - case COMPRESS_PVRTC4: { - ERR_FAIL_COND_V(!_image_compress_pvrtc4_func, ERR_UNAVAILABLE); - _image_compress_pvrtc4_func(this); + 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); @@ -2714,8 +2710,7 @@ 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_pvrtc2_func)(Image *) = nullptr; -void (*Image::_image_compress_pvrtc4_func)(Image *) = 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; @@ -3173,10 +3168,10 @@ 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_PVRTC2); //pvrtc - BIND_ENUM_CONSTANT(FORMAT_PVRTC2A); - BIND_ENUM_CONSTANT(FORMAT_PVRTC4); - BIND_ENUM_CONSTANT(FORMAT_PVRTC4A); + 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. @@ -3200,10 +3195,10 @@ void Image::_bind_methods() { BIND_ENUM_CONSTANT(ALPHA_BLEND); BIND_ENUM_CONSTANT(COMPRESS_S3TC); - BIND_ENUM_CONSTANT(COMPRESS_PVRTC2); - BIND_ENUM_CONSTANT(COMPRESS_PVRTC4); + BIND_ENUM_CONSTANT(COMPRESS_PVRTC1_4); BIND_ENUM_CONSTANT(COMPRESS_ETC); BIND_ENUM_CONSTANT(COMPRESS_ETC2); + BIND_ENUM_CONSTANT(COMPRESS_BPTC); BIND_ENUM_CONSTANT(USED_CHANNELS_L); BIND_ENUM_CONSTANT(USED_CHANNELS_LA); diff --git a/core/io/image.h b/core/io/image.h index c4c84589e5..0151df0cf9 100644 --- a/core/io/image.h +++ b/core/io/image.h @@ -91,10 +91,10 @@ public: FORMAT_BPTC_RGBA, //btpc bc7 FORMAT_BPTC_RGBF, //float bc6h FORMAT_BPTC_RGBFU, //unsigned float bc6hu - FORMAT_PVRTC2, //pvrtc - FORMAT_PVRTC2A, - FORMAT_PVRTC4, - FORMAT_PVRTC4A, + 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. @@ -138,8 +138,7 @@ 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_pvrtc2_func)(Image *); - static void (*_image_compress_pvrtc4_func)(Image *); + 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); @@ -332,11 +331,10 @@ public: enum CompressMode { COMPRESS_S3TC, - COMPRESS_PVRTC2, - COMPRESS_PVRTC4, + COMPRESS_PVRTC1_4, COMPRESS_ETC, COMPRESS_ETC2, - COMPRESS_BPTC + COMPRESS_BPTC, }; enum CompressSource { COMPRESS_SOURCE_GENERIC, diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml index b4325e822c..71db1e5106 100644 --- a/doc/classes/Image.xml +++ b/doc/classes/Image.xml @@ -636,18 +636,19 @@ Texture format that uses [url=https://www.khronos.org/opengl/wiki/BPTC_Texture_Compression]BPTC[/url] compression with unsigned floating-point RGB components. - + 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. - - Same as [url=https://en.wikipedia.org/wiki/PVRTC]PVRTC2[/url], but with an alpha component. + + Same as [constant FORMAT_PVRTC1_2], but with an alpha component. - - Similar to [url=https://en.wikipedia.org/wiki/PVRTC]PVRTC2[/url], but with 4-bit color depth and no alpha. + + 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. - - Same as [url=https://en.wikipedia.org/wiki/PVRTC]PVRTC4[/url], but with an alpha component. + + Same as [constant FORMAT_PVRTC1_4], but with an alpha component. [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. @@ -714,18 +715,18 @@ Use S3TC compression. - - Use PVRTC2 compression. - - - Use PVRTC4 compression. + + Use PVRTC1 4-bpp compression. - + Use ETC compression. - + Use ETC2 compression. + + Use BPTC compression. + diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index ac2485fe31..c8dae53722 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -537,7 +537,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String } if (ProjectSettings::get_singleton()->get("rendering/vram_compression/import_pvrtc")) { - _save_stex(image, p_save_path + ".pvrtc.stex", compress_mode, lossy, Image::COMPRESS_PVRTC4, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel); + _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"); } diff --git a/modules/pvr/image_compress_pvrtc.cpp b/modules/pvr/image_compress_pvrtc.cpp index 4cb0083556..6695a539d0 100644 --- a/modules/pvr/image_compress_pvrtc.cpp +++ b/modules/pvr/image_compress_pvrtc.cpp @@ -36,7 +36,7 @@ #include #include -static void _compress_pvrtc4(Image *p_img) { +static void _compress_pvrtc1_4bpp(Image *p_img) { Ref img = p_img->duplicate(); bool make_mipmaps = false; @@ -53,7 +53,7 @@ static void _compress_pvrtc4(Image *p_img) { Ref new_img; new_img.instance(); - new_img->create(img->get_width(), img->get_height(), img->has_mipmaps(), use_alpha ? Image::FORMAT_PVRTC4A : Image::FORMAT_PVRTC4); + new_img->create(img->get_width(), img->get_height(), img->has_mipmaps(), use_alpha ? Image::FORMAT_PVRTC1_4A : Image::FORMAT_PVRTC1_4); Vector data = new_img->get_data(); { @@ -80,7 +80,5 @@ static void _compress_pvrtc4(Image *p_img) { } void _register_pvrtc_compress_func() { - // FIXME: We claim to support PVRTC2 but use the same method as for PVRTC4. - Image::_image_compress_pvrtc2_func = _compress_pvrtc4; - Image::_image_compress_pvrtc4_func = _compress_pvrtc4; + Image::_image_compress_pvrtc1_4bpp_func = _compress_pvrtc1_4bpp; } diff --git a/modules/pvr/texture_loader_pvr.cpp b/modules/pvr/texture_loader_pvr.cpp index 46101262c8..c9cbb1935a 100644 --- a/modules/pvr/texture_loader_pvr.cpp +++ b/modules/pvr/texture_loader_pvr.cpp @@ -108,11 +108,11 @@ RES ResourceFormatPVR::load(const String &p_path, const String &p_original_path, switch (flags & 0xFF) { case 0x18: case 0xC: - format = (flags & PVR_HAS_ALPHA) ? Image::FORMAT_PVRTC2A : Image::FORMAT_PVRTC2; + 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_PVRTC4A : Image::FORMAT_PVRTC4; + format = (flags & PVR_HAS_ALPHA) ? Image::FORMAT_PVRTC1_4A : Image::FORMAT_PVRTC1_4; break; case 0x16: format = Image::FORMAT_L8; @@ -587,9 +587,9 @@ static void decompress_pvrtc(PVRTCBlock *p_comp_img, const int p_2bit, const int } static void _pvrtc_decompress(Image *p_img) { - ERR_FAIL_COND(p_img->get_format() != Image::FORMAT_PVRTC2 && p_img->get_format() != Image::FORMAT_PVRTC2A && p_img->get_format() != Image::FORMAT_PVRTC4 && p_img->get_format() != Image::FORMAT_PVRTC4A); + 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_PVRTC2 || p_img->get_format() == Image::FORMAT_PVRTC2A); + bool _2bit = (p_img->get_format() == Image::FORMAT_PVRTC1_2 || p_img->get_format() == Image::FORMAT_PVRTC1_2A); Vector data = p_img->get_data(); const uint8_t *r = data.ptr(); diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index 96f6d5ea32..564d61f9fb 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -318,7 +318,7 @@ Ref RendererStorageRD::_validate_texture_format(const Ref &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_PVRTC2: { + 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; @@ -336,7 +336,7 @@ Ref RendererStorageRD::_validate_texture_format(const Ref &p_image r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; } break; //pvrtc - case Image::FORMAT_PVRTC2A: { + 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; @@ -353,7 +353,7 @@ Ref RendererStorageRD::_validate_texture_format(const Ref &p_image r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; } break; - case Image::FORMAT_PVRTC4: { + 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; @@ -370,7 +370,7 @@ Ref RendererStorageRD::_validate_texture_format(const Ref &p_image r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; } break; - case Image::FORMAT_PVRTC4A: { + 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; -- cgit v1.2.3