diff options
author | Rémi Verschelde <rverschelde@gmail.com> | 2020-02-11 16:01:55 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-11 16:01:55 +0100 |
commit | 1eb424ec9549bdd086dfb54c847d107519be73d9 (patch) | |
tree | d9a3ec0c72f3a4eda02e16ed883f560e02cf1ccf /thirdparty/basis_universal/transcoder/basisu_global_selector_palette.h | |
parent | 3e3f8a47616327d7faeb17f558bb81a943385e82 (diff) | |
parent | db81928e08cb58d5f67908c6dfcf9433e572ffe8 (diff) | |
download | redot-engine-1eb424ec9549bdd086dfb54c847d107519be73d9.tar.gz |
Merge pull request #36098 from godotengine/vulkan
Add initial Vulkan support, master branch goes UNSTABLE
Diffstat (limited to 'thirdparty/basis_universal/transcoder/basisu_global_selector_palette.h')
-rw-r--r-- | thirdparty/basis_universal/transcoder/basisu_global_selector_palette.h | 673 |
1 files changed, 673 insertions, 0 deletions
diff --git a/thirdparty/basis_universal/transcoder/basisu_global_selector_palette.h b/thirdparty/basis_universal/transcoder/basisu_global_selector_palette.h new file mode 100644 index 0000000000..b0260541c3 --- /dev/null +++ b/thirdparty/basis_universal/transcoder/basisu_global_selector_palette.h @@ -0,0 +1,673 @@ +// basisu_global_selector_palette.h +// Copyright (C) 2019 Binomial LLC. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once +#include "basisu_transcoder_internal.h" +#include <algorithm> + +namespace basist +{ + class etc1_global_palette_entry_modifier + { + public: + enum { cTotalBits = 15, cTotalValues = 1 << cTotalBits }; + + etc1_global_palette_entry_modifier(uint32_t index = 0) + { +#ifdef _DEBUG + static bool s_tested; + if (!s_tested) + { + s_tested = true; + for (uint32_t i = 0; i < cTotalValues; i++) + { + etc1_global_palette_entry_modifier m(i); + etc1_global_palette_entry_modifier n = m; + + assert(n.get_index() == i); + } + } +#endif + + set_index(index); + } + + void set_index(uint32_t index) + { + assert(index < cTotalValues); + m_rot = index & 3; + m_flip = (index >> 2) & 1; + m_inv = (index >> 3) & 1; + m_contrast = (index >> 4) & 3; + m_shift = (index >> 6) & 1; + m_median = (index >> 7) & 1; + m_div = (index >> 8) & 1; + m_rand = (index >> 9) & 1; + m_dilate = (index >> 10) & 1; + m_shift_x = (index >> 11) & 1; + m_shift_y = (index >> 12) & 1; + m_erode = (index >> 13) & 1; + m_high_pass = (index >> 14) & 1; + } + + uint32_t get_index() const + { + return m_rot | (m_flip << 2) | (m_inv << 3) | (m_contrast << 4) | (m_shift << 6) | (m_median << 7) | (m_div << 8) | (m_rand << 9) | (m_dilate << 10) | (m_shift_x << 11) | (m_shift_y << 12) | (m_erode << 13) | (m_high_pass << 14); + } + + void clear() + { + basisu::clear_obj(*this); + } + + uint8_t m_contrast; + bool m_rand; + bool m_median; + bool m_div; + bool m_shift; + bool m_inv; + bool m_flip; + bool m_dilate; + bool m_shift_x; + bool m_shift_y; + bool m_erode; + bool m_high_pass; + uint8_t m_rot; + }; + + enum modifier_types + { + cModifierContrast, + cModifierRand, + cModifierMedian, + cModifierDiv, + cModifierShift, + cModifierInv, + cModifierFlippedAndRotated, + cModifierDilate, + cModifierShiftX, + cModifierShiftY, + cModifierErode, + cModifierHighPass, + cTotalModifiers + }; + +#define ETC1_GLOBAL_SELECTOR_CODEBOOK_MAX_MOD_BITS (etc1_global_palette_entry_modifier::cTotalBits) + + struct etc1_selector_palette_entry + { + etc1_selector_palette_entry() + { + clear(); + } + + void clear() + { + basisu::clear_obj(*this); + } + + uint8_t operator[] (uint32_t i) const { assert(i < 16); return m_selectors[i]; } + uint8_t&operator[] (uint32_t i) { assert(i < 16); return m_selectors[i]; } + + void set_uint32(uint32_t v) + { + for (uint32_t byte_index = 0; byte_index < 4; byte_index++) + { + uint32_t b = (v >> (byte_index * 8)) & 0xFF; + + m_selectors[byte_index * 4 + 0] = b & 3; + m_selectors[byte_index * 4 + 1] = (b >> 2) & 3; + m_selectors[byte_index * 4 + 2] = (b >> 4) & 3; + m_selectors[byte_index * 4 + 3] = (b >> 6) & 3; + } + } + + uint32_t get_uint32() const + { + return get_byte(0) | (get_byte(1) << 8) | (get_byte(2) << 16) | (get_byte(3) << 24); + } + + uint32_t get_byte(uint32_t byte_index) const + { + assert(byte_index < 4); + + return m_selectors[byte_index * 4 + 0] | + (m_selectors[byte_index * 4 + 1] << 2) | + (m_selectors[byte_index * 4 + 2] << 4) | + (m_selectors[byte_index * 4 + 3] << 6); + } + + uint8_t operator()(uint32_t x, uint32_t y) const { assert((x < 4) && (y < 4)); return m_selectors[x + y * 4]; } + uint8_t&operator()(uint32_t x, uint32_t y) { assert((x < 4) && (y < 4)); return m_selectors[x + y * 4]; } + + uint32_t calc_distance(const etc1_selector_palette_entry &other) const + { + uint32_t dist = 0; + for (uint32_t i = 0; i < 8; i++) + { + int delta = static_cast<int>(m_selectors[i]) - static_cast<int>(other.m_selectors[i]); + dist += delta * delta; + } + return dist; + } + +#if 0 + uint32_t calc_hamming_dist(const etc1_selector_palette_entry &other) const + { + uint32_t dist = 0; + for (uint32_t i = 0; i < 4; i++) + dist += g_hamming_dist[get_byte(i) ^ other.get_byte(i)]; + return dist; + } +#endif + + etc1_selector_palette_entry get_inverted() const + { + etc1_selector_palette_entry result; + + for (uint32_t i = 0; i < 16; i++) + result.m_selectors[i] = 3 - m_selectors[i]; + + return result; + } + + etc1_selector_palette_entry get_divided() const + { + etc1_selector_palette_entry result; + + const uint8_t div_selector[4] = { 2, 0, 3, 1 }; + + for (uint32_t i = 0; i < 16; i++) + result.m_selectors[i] = div_selector[m_selectors[i]]; + + return result; + } + + etc1_selector_palette_entry get_shifted(int delta) const + { + etc1_selector_palette_entry result; + + for (uint32_t i = 0; i < 16; i++) + result.m_selectors[i] = static_cast<uint8_t>(basisu::clamp<int>(m_selectors[i] + delta, 0, 3)); + + return result; + } + + etc1_selector_palette_entry get_randomized() const + { + uint32_t seed = get_uint32(); + + etc1_selector_palette_entry result; + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + int s = (*this)(x, y); + + // between 0 and 10 + uint32_t i = basisd_urand(seed, 6) + basisd_urand(seed, 6); + if (i == 0) + s -= 2; + else if (i == 10) + s += 2; + else if (i < 3) + s -= 1; + else if (i > 7) + s += 1; + + result(x, y) = static_cast<uint8_t>(basisu::clamp<int>(s, 0, 3)); + } + } + + return result; + } + + etc1_selector_palette_entry get_contrast(int table_index) const + { + assert(table_index < 4); + + etc1_selector_palette_entry result; + + static const uint8_t s_contrast_tables[4][4] = + { + { 0, 1, 2, 3 }, // not used + { 0, 0, 3, 3 }, + { 1, 1, 2, 2 }, + { 1, 1, 3, 3 } + }; + + for (uint32_t i = 0; i < 16; i++) + { + result[i] = s_contrast_tables[table_index][(*this)[i]]; + } + + return result; + } + + etc1_selector_palette_entry get_dilated() const + { + etc1_selector_palette_entry result; + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + uint32_t max_selector = 0; + + for (int yd = -1; yd <= 1; yd++) + { + int fy = y + yd; + if ((fy < 0) || (fy > 3)) + continue; + + for (int xd = -1; xd <= 1; xd++) + { + int fx = x + xd; + if ((fx < 0) || (fx > 3)) + continue; + + max_selector = basisu::maximum<uint32_t>(max_selector, (*this)(fx, fy)); + } + } + + result(x, y) = static_cast<uint8_t>(max_selector); + } + } + + return result; + } + + etc1_selector_palette_entry get_eroded() const + { + etc1_selector_palette_entry result; + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + uint32_t min_selector = 99; + + for (int yd = -1; yd <= 1; yd++) + { + int fy = y + yd; + if ((fy < 0) || (fy > 3)) + continue; + + for (int xd = -1; xd <= 1; xd++) + { + int fx = x + xd; + if ((fx < 0) || (fx > 3)) + continue; + + min_selector = basisu::minimum<uint32_t>(min_selector, (*this)(fx, fy)); + } + } + + result(x, y) = static_cast<uint8_t>(min_selector); + } + } + + return result; + } + + etc1_selector_palette_entry get_shift_x() const + { + etc1_selector_palette_entry result; + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + int sx = x - 1; + if (sx < 0) + sx = 0; + + result(x, y) = (*this)(sx, y); + } + } + + return result; + } + + etc1_selector_palette_entry get_shift_y() const + { + etc1_selector_palette_entry result; + + for (uint32_t y = 0; y < 4; y++) + { + int sy = y - 1; + if (sy < 0) + sy = 3; + + for (uint32_t x = 0; x < 4; x++) + result(x, y) = (*this)(x, sy); + } + + return result; + } + + etc1_selector_palette_entry get_median() const + { + etc1_selector_palette_entry result; + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + // ABC + // D F + // GHI + + uint8_t selectors[8]; + uint32_t n = 0; + + for (int yd = -1; yd <= 1; yd++) + { + int fy = y + yd; + if ((fy < 0) || (fy > 3)) + continue; + + for (int xd = -1; xd <= 1; xd++) + { + if ((xd | yd) == 0) + continue; + + int fx = x + xd; + if ((fx < 0) || (fx > 3)) + continue; + + selectors[n++] = (*this)(fx, fy); + } + } + + std::sort(selectors, selectors + n); + + result(x, y) = selectors[n / 2]; + } + } + + return result; + } + + etc1_selector_palette_entry get_high_pass() const + { + etc1_selector_palette_entry result; + + static const int kernel[3][3] = + { + { 0, -1, 0 }, + { -1, 8, -1 }, + { 0, -1, 0 } + }; + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + // ABC + // D F + // GHI + + int sum = 0; + + for (int yd = -1; yd <= 1; yd++) + { + int fy = y + yd; + fy = basisu::clamp<int>(fy, 0, 3); + + for (int xd = -1; xd <= 1; xd++) + { + int fx = x + xd; + fx = basisu::clamp<int>(fx, 0, 3); + + int k = (*this)(fx, fy); + sum += k * kernel[yd + 1][xd + 1]; + } + } + + sum = sum / 4; + + result(x, y) = static_cast<uint8_t>(basisu::clamp<int>(sum, 0, 3)); + } + } + + return result; + } + + etc1_selector_palette_entry get_flipped_and_rotated(bool flip, uint32_t rotation_index) const + { + etc1_selector_palette_entry temp; + + if (flip) + { + for (uint32_t y = 0; y < 4; y++) + for (uint32_t x = 0; x < 4; x++) + temp(x, y) = (*this)(x, 3 - y); + } + else + { + temp = *this; + } + + etc1_selector_palette_entry result; + + switch (rotation_index) + { + case 0: + result = temp; + break; + case 1: + for (uint32_t y = 0; y < 4; y++) + for (uint32_t x = 0; x < 4; x++) + result(x, y) = temp(y, 3 - x); + break; + case 2: + for (uint32_t y = 0; y < 4; y++) + for (uint32_t x = 0; x < 4; x++) + result(x, y) = temp(3 - x, 3 - y); + break; + case 3: + for (uint32_t y = 0; y < 4; y++) + for (uint32_t x = 0; x < 4; x++) + result(x, y) = temp(3 - y, x); + break; + default: + assert(0); + break; + } + + return result; + } + + etc1_selector_palette_entry get_modified(const etc1_global_palette_entry_modifier &modifier) const + { + etc1_selector_palette_entry r(*this); + + if (modifier.m_shift_x) + r = r.get_shift_x(); + + if (modifier.m_shift_y) + r = r.get_shift_y(); + + r = r.get_flipped_and_rotated(modifier.m_flip != 0, modifier.m_rot); + + if (modifier.m_dilate) + r = r.get_dilated(); + + if (modifier.m_erode) + r = r.get_eroded(); + + if (modifier.m_high_pass) + r = r.get_high_pass(); + + if (modifier.m_rand) + r = r.get_randomized(); + + if (modifier.m_div) + r = r.get_divided(); + + if (modifier.m_shift) + r = r.get_shifted(1); + + if (modifier.m_contrast) + r = r.get_contrast(modifier.m_contrast); + + if (modifier.m_inv) + r = r.get_inverted(); + + if (modifier.m_median) + r = r.get_median(); + + return r; + } + + etc1_selector_palette_entry apply_modifier(modifier_types mod_type, const etc1_global_palette_entry_modifier &modifier) const + { + switch (mod_type) + { + case cModifierContrast: + return get_contrast(modifier.m_contrast); + case cModifierRand: + return get_randomized(); + case cModifierMedian: + return get_median(); + case cModifierDiv: + return get_divided(); + case cModifierShift: + return get_shifted(1); + case cModifierInv: + return get_inverted(); + case cModifierFlippedAndRotated: + return get_flipped_and_rotated(modifier.m_flip != 0, modifier.m_rot); + case cModifierDilate: + return get_dilated(); + case cModifierShiftX: + return get_shift_x(); + case cModifierShiftY: + return get_shift_y(); + case cModifierErode: + return get_eroded(); + case cModifierHighPass: + return get_high_pass(); + default: + assert(0); + break; + } + + return *this; + } + + etc1_selector_palette_entry get_modified(const etc1_global_palette_entry_modifier &modifier, uint32_t num_order, const modifier_types *pOrder) const + { + etc1_selector_palette_entry r(*this); + + for (uint32_t i = 0; i < num_order; i++) + { + r = r.apply_modifier(pOrder[i], modifier); + } + + return r; + } + + bool operator< (const etc1_selector_palette_entry &other) const + { + for (uint32_t i = 0; i < 16; i++) + { + if (m_selectors[i] < other.m_selectors[i]) + return true; + else if (m_selectors[i] != other.m_selectors[i]) + return false; + } + + return false; + } + + bool operator== (const etc1_selector_palette_entry &other) const + { + for (uint32_t i = 0; i < 16; i++) + { + if (m_selectors[i] != other.m_selectors[i]) + return false; + } + + return true; + } + + private: + uint8_t m_selectors[16]; + }; + + typedef std::vector<etc1_selector_palette_entry> etc1_selector_palette_entry_vec; + + extern const uint32_t g_global_selector_cb[]; + extern const uint32_t g_global_selector_cb_size; + +#define ETC1_GLOBAL_SELECTOR_CODEBOOK_MAX_PAL_BITS (12) + + struct etc1_global_selector_codebook_entry_id + { + uint32_t m_palette_index; + etc1_global_palette_entry_modifier m_modifier; + + etc1_global_selector_codebook_entry_id(uint32_t palette_index, const etc1_global_palette_entry_modifier &modifier) : m_palette_index(palette_index), m_modifier(modifier) { } + + etc1_global_selector_codebook_entry_id() { } + + void set(uint32_t palette_index, const etc1_global_palette_entry_modifier &modifier) { m_palette_index = palette_index; m_modifier = modifier; } + }; + + typedef std::vector<etc1_global_selector_codebook_entry_id> etc1_global_selector_codebook_entry_id_vec; + + class etc1_global_selector_codebook + { + public: + etc1_global_selector_codebook() { } + etc1_global_selector_codebook(uint32_t N, const uint32_t *pEntries) { init(N, pEntries); } + + void init(uint32_t N, const uint32_t* pEntries); + + void print_code(FILE *pFile); + + void clear() + { + m_palette.clear(); + } + + uint32_t size() const { return (uint32_t)m_palette.size(); } + + const etc1_selector_palette_entry_vec &get_palette() const + { + return m_palette; + } + + etc1_selector_palette_entry get_entry(uint32_t palette_index) const + { + return m_palette[palette_index]; + } + + etc1_selector_palette_entry get_entry(uint32_t palette_index, const etc1_global_palette_entry_modifier &modifier) const + { + return m_palette[palette_index].get_modified(modifier); + } + + etc1_selector_palette_entry get_entry(const etc1_global_selector_codebook_entry_id &id) const + { + return m_palette[id.m_palette_index].get_modified(id.m_modifier); + } + + etc1_selector_palette_entry_vec m_palette; + }; + +} // namespace basist |