summaryrefslogtreecommitdiffstats
path: root/thirdparty/basis_universal/transcoder/basisu_global_selector_palette.h
diff options
context:
space:
mode:
authorRémi Verschelde <rverschelde@gmail.com>2020-02-11 16:01:55 +0100
committerGitHub <noreply@github.com>2020-02-11 16:01:55 +0100
commit1eb424ec9549bdd086dfb54c847d107519be73d9 (patch)
treed9a3ec0c72f3a4eda02e16ed883f560e02cf1ccf /thirdparty/basis_universal/transcoder/basisu_global_selector_palette.h
parent3e3f8a47616327d7faeb17f558bb81a943385e82 (diff)
parentdb81928e08cb58d5f67908c6dfcf9433e572ffe8 (diff)
downloadredot-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.h673
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