Просмотр исходного кода

Merge pull request #75 from RazielXYZ/master

Drop astc-codec and use astc-encoder for decoding too
Бранимир Караџић 3 лет назад
Родитель
Сommit
1955d8f99a
37 измененных файлов с 58 добавлено и 7502 удалено
  1. 0 202
      3rdparty/astc-codec/LICENSE
  2. 0 75
      3rdparty/astc-codec/include/astc-codec/astc-codec.h
  3. 0 77
      3rdparty/astc-codec/src/base/bit_stream.h
  4. 0 78
      3rdparty/astc-codec/src/base/bottom_n.h
  5. 0 80
      3rdparty/astc-codec/src/base/math_utils.h
  6. 0 520
      3rdparty/astc-codec/src/base/optional.h
  7. 0 69
      3rdparty/astc-codec/src/base/string_utils.h
  8. 0 172
      3rdparty/astc-codec/src/base/type_traits.h
  9. 0 175
      3rdparty/astc-codec/src/base/uint128.h
  10. 0 35
      3rdparty/astc-codec/src/base/utils.h
  11. 0 185
      3rdparty/astc-codec/src/decoder/astc_file.cc
  12. 0 97
      3rdparty/astc-codec/src/decoder/astc_file.h
  13. 0 132
      3rdparty/astc-codec/src/decoder/codec.cc
  14. 0 41
      3rdparty/astc-codec/src/decoder/codec.h
  15. 0 963
      3rdparty/astc-codec/src/decoder/endpoint_codec.cc
  16. 0 90
      3rdparty/astc-codec/src/decoder/endpoint_codec.h
  17. 0 162
      3rdparty/astc-codec/src/decoder/footprint.cc
  18. 0 106
      3rdparty/astc-codec/src/decoder/footprint.h
  19. 0 574
      3rdparty/astc-codec/src/decoder/integer_sequence_codec.cc
  20. 0 169
      3rdparty/astc-codec/src/decoder/integer_sequence_codec.h
  21. 0 591
      3rdparty/astc-codec/src/decoder/intermediate_astc_block.cc
  22. 0 128
      3rdparty/astc-codec/src/decoder/intermediate_astc_block.h
  23. 0 262
      3rdparty/astc-codec/src/decoder/logical_astc_block.cc
  24. 0 127
      3rdparty/astc-codec/src/decoder/logical_astc_block.h
  25. 0 601
      3rdparty/astc-codec/src/decoder/partition.cc
  26. 0 97
      3rdparty/astc-codec/src/decoder/partition.h
  27. 0 761
      3rdparty/astc-codec/src/decoder/physical_astc_block.cc
  28. 0 128
      3rdparty/astc-codec/src/decoder/physical_astc_block.h
  29. 0 462
      3rdparty/astc-codec/src/decoder/quantization.cc
  30. 0 65
      3rdparty/astc-codec/src/decoder/quantization.h
  31. 0 74
      3rdparty/astc-codec/src/decoder/types.h
  32. 0 122
      3rdparty/astc-codec/src/decoder/weight_infill.cc
  33. 0 38
      3rdparty/astc-codec/src/decoder/weight_infill.h
  34. 3 15
      scripts/bimg.lua
  35. 0 2
      scripts/bimg_encode.lua
  36. 47 27
      src/image.cpp
  37. 8 0
      src/image_encode.cpp

+ 0 - 202
3rdparty/astc-codec/LICENSE

@@ -1,202 +0,0 @@
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   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.

+ 0 - 75
3rdparty/astc-codec/include/astc-codec/astc-codec.h

@@ -1,75 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#ifndef ASTC_CODEC_ASTC_CODEC_H_
-#define ASTC_CODEC_ASTC_CODEC_H_
-
-#include <cstddef>
-#include <cstdint>
-
-namespace astc_codec {
-
-// These are the valid ASTC footprints according to the specification in
-// Section C.2.7.
-enum class FootprintType {
-  k4x4,
-  k5x4,
-  k5x5,
-  k6x5,
-  k6x6,
-  k8x5,
-  k8x6,
-  k10x5,
-  k10x6,
-  k8x8,
-  k10x8,
-  k10x10,
-  k12x10,
-  k12x12,
-
-  kCount
-};
-
-// Decompresses ASTC LDR image data to a RGBA32 buffer.
-//
-// Supports formats defined in the KHR_texture_compression_astc_ldr spec and
-// returns UNORM8 values.  sRGB is not supported, and should be implemented
-// by the caller.
-//
-// |astc_data| - Compressed ASTC image buffer, must be at least |astc_data_size|
-//               bytes long.
-// |astc_data_size| - The size of |astc_data|, in bytes.
-// |width| - Image width, in pixels.
-// |height| - Image height, in pixels.
-// |footprint| - The ASTC footprint (block size) of the compressed image buffer.
-// |out_buffer| - Pointer to a buffer where the decompressed image will be
-//                stored, must be at least |out_buffer_size| bytes long.
-// |out_buffer_size| - The size of |out_buffer|, in bytes, at least
-//                     height*out_buffer_stride. If this is too small, this
-//                     function will return false and no data will be
-//                     decompressed.
-// |out_buffer_stride| - The stride that should be used to store rows of the
-//                       decoded image, must be at least 4*width bytes.
-//
-// Returns true if the decompression succeeded, or false if decompression
-// failed, or if the astc_data_size was too small for the given width, height,
-// and footprint, or if out_buffer_size is too small.
-bool ASTCDecompressToRGBA(const uint8_t* astc_data, size_t astc_data_size,
-                          size_t width, size_t height, FootprintType footprint,
-                          uint8_t* out_buffer, size_t out_buffer_size,
-                          size_t out_buffer_stride);
-
-}  // namespace astc_codec
-
-#endif  // ASTC_CODEC_ASTC_CODEC_H_

+ 0 - 77
3rdparty/astc-codec/src/base/bit_stream.h

@@ -1,77 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#ifndef ASTC_CODEC_BASE_BIT_STREAM_H_
-#define ASTC_CODEC_BASE_BIT_STREAM_H_
-
-#include <cassert>
-#include <cstdint>
-
-namespace astc_codec {
-namespace base {
-
-// Represents a stream of bits that can be read or written in arbitrary-sized
-// chunks.
-template<typename IntType = uint64_t>
-class BitStream {
- public:
-  // Creates an empty BitStream.
-  BitStream() = default;
-  BitStream(IntType data, uint32_t data_size)
-      : data_(data), data_size_(data_size) {
-    assert(data_size_ <= sizeof(data_) * 8);
-  }
-
-  // Return the number of bits in the stream.
-  uint32_t Bits() const { return data_size_; }
-
-  // Put |size| bits into the stream.
-  // Fails if there is not enough space in the buffer to store the bits.
-  template<typename ResultType>
-  void PutBits(ResultType x, uint32_t size) {
-    assert(data_size_ + size <= sizeof(data_) * 8);
-
-    data_ |= (IntType(x) & MaskFor(size)) << data_size_;
-    data_size_ += size;
-  }
-
-  // Get |count| bits from the stream.
-  // Returns true if |count| bits were successfully retrieved.
-  template<typename ResultType>
-  bool GetBits(uint32_t count, ResultType* result) {
-    if (count <= data_size_) {
-      *result = static_cast<ResultType>(data_ & MaskFor(count));
-      data_ = data_ >> count;
-      data_size_ -= count;
-      return true;
-    } else {
-      *result = ResultType();
-      return false;
-    }
-  }
-
- private:
-  IntType MaskFor(uint32_t bits) const {
-    return (bits == sizeof(IntType) * 8) ? ~IntType(0)
-                                         : (IntType(1) << bits) - 1;
-  }
-
-  IntType data_ = IntType();
-  uint32_t data_size_ = 0;
-};
-
-}  // namespace base
-}  // namespace astc_codec
-
-#endif  // ASTC_CODEC_BASE_BIT_STREAM_H_

+ 0 - 78
3rdparty/astc-codec/src/base/bottom_n.h

@@ -1,78 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#ifndef ASTC_CODEC_BASE_BOTTOM_N_H_
-#define ASTC_CODEC_BASE_BOTTOM_N_H_
-
-#include <algorithm>
-#include <functional>
-#include <vector>
-
-namespace astc_codec {
-namespace base {
-
-// Used to aggregate the lowest N values of data supplied.
-template<typename T, typename CompareFn = std::less<T>>
-class BottomN {
- public:
-  typedef std::vector<T> ContainerType;
-
-  // Creates an empty BottomN with limit |max_size|.
-  BottomN(size_t max_size) : max_size_(max_size) { }
-
-  bool Empty() const { return data_.empty(); }
-  size_t Size() const { return data_.size(); }
-
-  const T& Top() const { return data_.front(); }
-
-  void Push(const T& value) {
-    if (data_.size() < max_size_ || compare_(value, Top())) {
-      data_.push_back(value);
-      std::push_heap(data_.begin(), data_.end(), compare_);
-
-      if (Size() > max_size_) {
-        PopTop();
-      }
-    }
-  }
-
-  std::vector<T> Pop() {
-    const size_t len = Size();
-    std::vector<T> result(len);
-
-    for (size_t i = 0; i < len; ++i) {
-      result[len - i - 1] = PopTop();
-    }
-
-    return result;
-  }
-
- private:
-  T PopTop() {
-    std::pop_heap(data_.begin(), data_.end(), compare_);
-    T result = data_.back();
-    data_.pop_back();
-    return result;
-  }
-
-  ContainerType data_;
-  CompareFn compare_;
-
-  const size_t max_size_;
-};
-
-}  // namespace base
-}  // namespace astc_codec
-
-#endif  // ASTC_CODEC_BASE_BOTTOM_N_H_

+ 0 - 80
3rdparty/astc-codec/src/base/math_utils.h

@@ -1,80 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#ifndef ASTC_CODEC_BASE_MATH_UTILS_H_
-#define ASTC_CODEC_BASE_MATH_UTILS_H_
-
-#include "src/base/uint128.h"
-
-#include <cassert>
-#include <cstdint>
-#include <type_traits>
-
-namespace astc_codec {
-namespace base {
-
-inline int Log2Floor(uint32_t n) {
-  if (n == 0) {
-    return -1;
-  }
-
-  int log = 0;
-  uint32_t value = n;
-  for (int i = 4; i >= 0; --i) {
-    int shift = (1 << i);
-    uint32_t x = value >> shift;
-    if (x != 0) {
-      value = x;
-      log += shift;
-    }
-  }
-  assert(value == 1);
-  return log;
-}
-
-inline int CountOnes(uint32_t n) {
-  n -= ((n >> 1) & 0x55555555);
-  n = ((n >> 2) & 0x33333333) + (n & 0x33333333);
-  return static_cast<int>((((n + (n >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24);
-}
-
-template<typename T>
-inline T ReverseBits(T value) {
-  uint32_t s = sizeof(value) * 8;
-  T mask = ~T(0);
-  while ((s >>= 1) > 0) {
-    mask ^= (mask << s);
-    value = ((value >> s) & mask) | ((value << s) & ~mask);
-  }
-
-  return value;
-}
-
-template<typename T>
-inline T GetBits(T source, uint32_t offset, uint32_t count) {
-  static_assert(std::is_same<T, UInt128>::value || std::is_unsigned<T>::value,
-                "T must be unsigned.");
-
-  const uint32_t total_bits = sizeof(T) * 8;
-  assert(count > 0);
-  assert(offset + count <= total_bits);
-
-  const T mask = count == total_bits ? ~T(0) : ~T(0) >> (total_bits - count);
-  return (source >> offset) & mask;
-}
-
-}  // namespace base
-}  // namespace astc_codec
-
-#endif  // ASTC_CODEC_BASE_MATH_UTILS_H_

+ 0 - 520
3rdparty/astc-codec/src/base/optional.h

@@ -1,520 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#ifndef ASTC_CODEC_BASE_OPTIONAL_H_
-#define ASTC_CODEC_BASE_OPTIONAL_H_
-
-#include "src/base/type_traits.h"
-
-#include <cassert>
-#include <initializer_list>
-#include <type_traits>
-#include <utility>
-
-#include <cstddef>
-
-// Optional<T> - a template class to store an optional value of type T.
-//
-// Usage examples:
-//
-// Initialization and construction:
-//   Optional<Foo> foo;            // |foo| doesn't contain a value.
-//   Optional<Foo> foo(Foo(10));   // |foo| contains a copy-constructed value.
-//   Optional<Foo> foo2(foo);      // |foo2| contains a copy of |foo|'s value.
-//   Optional<Foo> foo3(std::move(foo2));  // Guess what?
-//
-// Assignment:
-//   Foo foo_value(0);
-//   Optional<Foo> foo;   // |foo| is empty.
-//   Optional<Foo> foo2;  // |foo2| is empty.
-//   foo2 = foo;          // |foo2| is still empty.
-//   foo = foo_value;     // set value of |foo| to a copy of |foo_value|
-//   foo = std::move(foo_value);  // move |foo_value| into |foo|.
-//   foo2 = foo;          // now |foo2| has a copy of |foo|'s value.
-//   foo = kNullopt;      // unset |foo|, it has no value.
-//
-// Checking and accessing value:
-//   if (foo) {
-//      // |foo| has a value.
-//      doStuff(*foo);      // |*foo| is the value inside |foo|.
-//      foo->callMethod();  // Same as (*foo).callMethod().
-//   } else {
-//      // |foo| is empty.
-//   }
-//
-//   foo.value()              // Same as *foo
-//   foo.valueOr(<default>)   // Return <default> is |foo| has no value.
-//
-// In-place construction:
-//
-//   Optional<Foo> foo;   // |foo| is empty.
-//   foo.emplace(20);     // |foo| now contains a value constructed as Foo(20)
-//
-//   Optional<Foo> foo(kInplace, 20);  // |foo| is initialized with a value
-//                                     // that is constructed in-place as
-//                                     // Foo(20).
-//
-//   return makeOptional<Foo>(20);     // Takes Foo constructor arguments
-//                                     // directly.
-//
-// Returning values:
-//
-//  Optional<Foo> myFunc(...) {
-//      if (someCondition) {
-//          return Foo(10);      // call Optional<Foo>(Foo&) constructor.
-//      } else {
-//          return {};           // call Optional<Foo>() constructor, which
-//                               // builds an empty value.
-//      }
-//  }
-//
-// Memory layout:
-//   Optional<Foo> is equivalent to:
-//
-//       struct {
-//           bool flag;
-//           Foo value;
-//       };
-//
-//  in terms of memory layout. This means it *doubles* the size of integral
-//  types. Also:
-//
-//  - Optional<Foo> can be constructed from anything that constructs a Foo.
-//
-//  - Same with Optional<Foo>(kInplace, Args...) where Args... matches any
-//    arguments that can be passed to a Foo constructor.
-//
-//  - Comparison operators are provided. Beware: an empty Optional<Foo>
-//    is always smaller than any Foo value.
-
-namespace astc_codec {
-namespace base {
-
-namespace details {
-
-// Base classes to reduce the number of instantiations of the Optional's
-// internal members.
-class OptionalFlagBase {
- public:
-  void setConstructed(bool constructed) { mConstructed = constructed; }
-  constexpr bool constructed() const { return mConstructed; }
-  constexpr operator bool() const { return constructed(); }
-  bool hasValue() const { return constructed(); }
-
-  constexpr OptionalFlagBase(bool constructed = false)
-      : mConstructed(constructed) { }
-
- private:
-  bool mConstructed = false;
-};
-
-template<size_t Size, size_t Align>
-class OptionalStorageBase {
- protected:
-  using StoreT = typename std::aligned_storage<Size, Align>::type;
-  StoreT mStorage = {};
-};
-
-}  // namespace details
-
-// A tag type for empty optional construction
-struct NulloptT {
-  constexpr explicit NulloptT(int) { }
-};
-
-// A tag type for inplace value construction
-struct InplaceT {
-  constexpr explicit InplaceT(int) { }
-};
-
-// Tag values for null optional and inplace construction
-constexpr NulloptT kNullopt{1};
-constexpr InplaceT kInplace{1};
-
-// Forward declaration for an early use
-template<class T>
-class Optional;
-
-// A type trait for checking if a type is an optional instantiation
-// Note: if you want to refer to the template name inside the template,
-//  you need to declare this alias outside of it - because the
-//  class name inside of the template stands for an instantiated template
-//  E.g, for template <T> class Foo if you say 'Foo' inside the class, it
-//  actually means Foo<T>;
-template<class U>
-using is_any_optional =
-    is_template_instantiation_of<typename std::decay<U>::type, Optional>;
-
-template<class T>
-class Optional
-    : private details::OptionalFlagBase,
-      private details::OptionalStorageBase<sizeof(T),
-                                           std::alignment_of<T>::value> {
-  // make sure all optionals are buddies - this is needed to implement
-  // conversion from optionals of other types
-  template<class U>
-  friend class Optional;
-
-  template<class U>
-  using self = Optional<U>;
-
-  using base_flag = details::OptionalFlagBase;
-  using base_storage =
-      details::OptionalStorageBase<sizeof(T), std::alignment_of<T>::value>;
-
- public:
-  // std::optional will have this, so let's provide it
-  using value_type = T;
-
-  // make sure we forbid some Optional instantiations where things may get
-  // really messy
-  static_assert(!std::is_same<typename std::decay<T>::type, NulloptT>::value,
-                "Optional of NulloptT is not allowed");
-  static_assert(!std::is_same<typename std::decay<T>::type, InplaceT>::value,
-                "Optional of InplaceT is not allowed");
-  static_assert(!std::is_reference<T>::value,
-                "Optional references are not allowed: use a pointer instead");
-
-  // constructors
-  constexpr Optional() { }
-  constexpr Optional(NulloptT) { }
-
-  Optional(const Optional& other) : base_flag(other.constructed()) {
-    if (this->constructed()) {
-      new (&get()) T(other.get());
-    }
-  }
-  Optional(Optional&& other) : base_flag(other.constructed()) {
-    if (this->constructed()) {
-      new (&get()) T(std::move(other.get()));
-    }
-  }
-
-  // Conversion constructor from optional of similar type
-  template<class U, class = enable_if_c<!is_any_optional<U>::value &&
-                                        std::is_constructible<T, U>::value>>
-  Optional(const Optional<U>& other) : base_flag(other.constructed()) {
-    if (this->constructed()) {
-      new (&get()) T(other.get());
-    }
-  }
-
-  // Move-conversion constructor
-  template<class U, class = enable_if_c<!is_any_optional<U>::value &&
-                                        std::is_constructible<T, U>::value>>
-  Optional(Optional<U>&& other) : base_flag(other.constructed()) {
-    if (this->constructed()) {
-      new (&get()) T(std::move(other.get()));
-    }
-  }
-
-  // Construction from a raw value
-  Optional(const T& value) : base_flag(true) { new (&get()) T(value); }
-  // Move construction from a raw value
-  Optional(T&& value) : base_flag(true) { new (&get()) T(std::move(value)); }
-
-  // Inplace construction from a list of |T|'s ctor arguments
-  template<class... Args>
-  Optional(InplaceT, Args&&... args) : base_flag(true) {
-    new (&get()) T(std::forward<Args>(args)...);
-  }
-
-  // Inplace construction from an initializer list passed into |T|'s ctor
-  template<class U, class = enable_if<
-                        std::is_constructible<T, std::initializer_list<U>>>>
-  Optional(InplaceT, std::initializer_list<U> il) : base_flag(true) {
-    new (&get()) T(il);
-  }
-
-  // direct assignment
-  Optional& operator=(const Optional& other) {
-    if (&other == this) {
-      return *this;
-    }
-
-    if (this->constructed()) {
-      if (other.constructed()) {
-        get() = other.get();
-      } else {
-        destruct();
-        this->setConstructed(false);
-      }
-    } else {
-      if (other.constructed()) {
-        new (&get()) T(other.get());
-        this->setConstructed(true);
-      } else {
-        ;  // we're good
-      }
-    }
-    return *this;
-  }
-
-  // move assignment
-  Optional& operator=(Optional&& other) {
-    if (this->constructed()) {
-      if (other.constructed()) {
-        get() = std::move(other.get());
-      } else {
-        destruct();
-        this->setConstructed(false);
-      }
-    } else {
-      if (other.constructed()) {
-        new (&get()) T(std::move(other.get()));
-        this->setConstructed(true);
-      } else {
-        ;  // we're good
-      }
-    }
-    return *this;
-  }
-
-  // conversion assignment
-  template<class U,
-           class = enable_if_convertible<typename std::decay<U>::type, T>>
-  Optional& operator=(const Optional<U>& other) {
-    if (this->constructed()) {
-      if (other.constructed()) {
-        get() = other.get();
-      } else {
-        destruct();
-        this->setConstructed(false);
-      }
-    } else {
-      if (other.constructed()) {
-        new (&get()) T(other.get());
-        this->setConstructed(true);
-      } else {
-        ;  // we're good
-      }
-    }
-    return *this;
-  }
-
-  // conversion move assignment
-  template<class U,
-           class = enable_if_convertible<typename std::decay<U>::type, T>>
-  Optional& operator=(Optional<U>&& other) {
-    if (this->constructed()) {
-      if (other.constructed()) {
-        get() = std::move(other.get());
-      } else {
-        destruct();
-        this->setConstructed(false);
-      }
-    } else {
-      if (other.constructed()) {
-        new (&get()) T(std::move(other.get()));
-        this->setConstructed(true);
-      } else {
-        ;  // we're good
-      }
-    }
-    return *this;
-  }
-
-  // the most complicated one: forwarding constructor for anything convertible
-  // to |T|, excluding the stuff implemented above explicitly
-  template<class U,
-           class = enable_if_c<
-               !is_any_optional<typename std::decay<U>::type>::value &&
-               std::is_convertible<typename std::decay<U>::type, T>::value>>
-  Optional& operator=(U&& other) {
-    if (this->constructed()) {
-      get() = std::forward<U>(other);
-    } else {
-      new (&get()) T(std::forward<U>(other));
-      this->setConstructed(true);
-    }
-    return *this;
-  }
-
-  // Adopt value checkers from the parent
-  using base_flag::operator bool;
-  using base_flag::hasValue;
-
-  T& value() {
-    assert(this->constructed());
-    return get();
-  }
-  constexpr const T& value() const {
-    assert(this->constructed());
-    return get();
-  }
-
-  T* ptr() { return this->constructed() ? &get() : nullptr; }
-  constexpr const T* ptr() const {
-    return this->constructed() ? &get() : nullptr;
-  }
-
-  // Value getter with fallback
-  template<class U = T,
-           class = enable_if_convertible<typename std::decay<U>::type, T>>
-  constexpr T valueOr(U&& defaultValue) const {
-    return this->constructed() ? get() : std::move(defaultValue);
-  }
-
-  // Pointer-like operators
-  T& operator*() {
-    assert(this->constructed());
-    return get();
-  }
-  constexpr const T& operator*() const {
-    assert(this->constructed());
-    return get();
-  }
-
-  T* operator->() {
-    assert(this->constructed());
-    return &get();
-  }
-  constexpr const T* operator->() const {
-    assert(this->constructed());
-    return &get();
-  }
-
-  ~Optional() {
-    if (this->constructed()) {
-      destruct();
-    }
-  }
-
-  void clear() {
-    if (this->constructed()) {
-      destruct();
-      this->setConstructed(false);
-    }
-  }
-
-  template<class U,
-           class = enable_if_convertible<typename std::decay<U>::type, T>>
-  void reset(U&& u) {
-    *this = std::forward<U>(u);
-  }
-
-  // In-place construction with possible destruction of the old value
-  template<class... Args>
-  void emplace(Args&&... args) {
-    if (this->constructed()) {
-      destruct();
-    }
-    new (&get()) T(std::forward<Args>(args)...);
-    this->setConstructed(true);
-  }
-
-  // In-place construction with possible destruction of the old value
-  // initializer-list version
-  template<class U, class = enable_if<
-                        std::is_constructible<T, std::initializer_list<U>>>>
-  void emplace(std::initializer_list<U> il) {
-    if (this->constructed()) {
-      destruct();
-    }
-    new (&get()) T(il);
-    this->setConstructed(true);
-  }
-
- private:
-  // A helper function to convert the internal raw storage to T&
-  constexpr const T& get() const {
-    return *reinterpret_cast<const T*>(
-        reinterpret_cast<const char*>(&this->mStorage));
-  }
-
-  // Same thing, mutable
-  T& get() { return const_cast<T&>(const_cast<const Optional*>(this)->get()); }
-
-  // Shortcut for a destructor call for the stored object
-  void destruct() { get().T::~T(); }
-};
-
-template<class T>
-Optional<typename std::decay<T>::type> makeOptional(T&& t) {
-  return Optional<typename std::decay<T>::type>(std::forward<T>(t));
-}
-
-template<class T, class... Args>
-Optional<typename std::decay<T>::type> makeOptional(Args&&... args) {
-  return Optional<typename std::decay<T>::type>(kInplace,
-                                                std::forward<Args>(args)...);
-}
-
-template<class T>
-bool operator==(const Optional<T>& l, const Optional<T>& r) {
-  return l.hasValue() ? r.hasValue() && *l == *r : !r.hasValue();
-}
-template<class T>
-bool operator==(const Optional<T>& l, NulloptT) {
-  return !l;
-}
-template<class T>
-bool operator==(NulloptT, const Optional<T>& r) {
-  return !r;
-}
-template<class T>
-bool operator==(const Optional<T>& l, const T& r) {
-  return bool(l) && *l == r;
-}
-template<class T>
-bool operator==(const T& l, const Optional<T>& r) {
-  return bool(r) && l == *r;
-}
-
-template<class T>
-bool operator!=(const Optional<T>& l, const Optional<T>& r) {
-  return !(l == r);
-}
-template<class T>
-bool operator!=(const Optional<T>& l, NulloptT) {
-  return bool(l);
-}
-template<class T>
-bool operator!=(NulloptT, const Optional<T>& r) {
-  return bool(r);
-}
-template<class T>
-bool operator!=(const Optional<T>& l, const T& r) {
-  return !l || !(*l == r);
-}
-template<class T>
-bool operator!=(const T& l, const Optional<T>& r) {
-  return !r || !(l == *r);
-}
-
-template<class T>
-bool operator<(const Optional<T>& l, const Optional<T>& r) {
-  return !r ? false : (!l ? true : *l < *r);
-}
-template<class T>
-bool operator<(const Optional<T>&, NulloptT) {
-  return false;
-}
-template<class T>
-bool operator<(NulloptT, const Optional<T>& r) {
-  return bool(r);
-}
-template<class T>
-bool operator<(const Optional<T>& l, const T& r) {
-  return !l || *l < r;
-}
-template<class T>
-bool operator<(const T& l, const Optional<T>& r) {
-  return bool(r) && l < *r;
-}
-
-}  // namespace base
-}  // namespace astc_codec
-
-#endif  // ASTC_CODEC_BASE_OPTIONAL_H_

+ 0 - 69
3rdparty/astc-codec/src/base/string_utils.h

@@ -1,69 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#ifndef ASTC_CODEC_BASE_STRING_UTILS_H_
-#define ASTC_CODEC_BASE_STRING_UTILS_H_
-
-#include <limits>
-#include <string>
-#include <stdlib.h>
-
-namespace astc_codec {
-namespace base {
-
-// Iterates over a string's parts using |splitBy| as a delimiter.
-// |splitBy| must be a nonempty string well, or it's a no-op.
-// Otherwise, |func| is called on each of the splits, excluding the
-// characters that are part of |splitBy|.  If two |splitBy|'s occur in a row,
-// |func| will be called on a StringView("") in between. See
-// StringUtils_unittest.cpp for the full story.
-template<class Func>
-void Split(const std::string& str, const std::string& splitBy, Func func) {
-  if (splitBy.empty()) {
-    return;
-  }
-
-  size_t splitSize = splitBy.size();
-  size_t begin = 0;
-  size_t end = str.find(splitBy);
-
-  while (true) {
-    func(str.substr(begin, end - begin));
-    if (end == std::string::npos) {
-      return;
-    }
-
-    begin = end + splitSize;
-    end = str.find(splitBy, begin);
-  }
-}
-
-static int32_t ParseInt32(const char* str, int32_t deflt) {
-  using std::numeric_limits;
-
-  char* error = nullptr;
-  int64_t value = strtol(str, &error, 0);
-  // Limit long values to int32 min/max.  Needed for lp64; no-op on 32 bits.
-  if (value > std::numeric_limits<int32_t>::max()) {
-    value = std::numeric_limits<int32_t>::max();
-  } else if (value < std::numeric_limits<int32_t>::min()) {
-    value = std::numeric_limits<int32_t>::min();
-  }
-  return (error == str) ? deflt : static_cast<int32_t>(value);
-}
-
-}  // namespace base
-}  // namespace astc_codec
-
-#endif  // ASTC_CODEC_BASE_STRING_UTILS_H_

+ 0 - 172
3rdparty/astc-codec/src/base/type_traits.h

@@ -1,172 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#ifndef ASTC_CODEC_BASE_TYPE_TRAITS_H_
-#define ASTC_CODEC_BASE_TYPE_TRAITS_H_
-
-#include <iterator>
-#include <type_traits>
-
-namespace astc_codec {
-namespace base {
-
-namespace details {
-
-// a simple helper class for SFINAE below.
-template<class X = void>
-struct dummy {
-  using type = X;
-};
-
-}  // namespace details
-
-// add some convenience shortcuts for an overly complex std::enable_if syntax
-
-// Use 'enable_if<Predicate,Type>' instead of
-// 'typename std::enable_if<Predicate::value,Type>::type'
-template<class Predicate, class Type = void*>
-using enable_if = typename std::enable_if<Predicate::value, Type>::type;
-
-// Use 'enable_if_c<BooleanFlag,Type>' instead of
-// 'typename std::enable_if<BooleanFlag,Type>::type'
-template<bool predicate, class Type = void*>
-using enable_if_c = typename std::enable_if<predicate, Type>::type;
-
-// Use 'enable_if_convertible<From,To,Type>' instead of
-// 'typename std::enable_if<std::is_convertible<From,To>::value, Type>::type'
-template<class From, class To, class Type = void*>
-using enable_if_convertible = enable_if<std::is_convertible<From, To>>;
-
-// -----------------------------------------------------------------------------
-// A predicate for checking if some object is callable with a specific
-// signature. Examples:
-//
-//     is_callable_as<int, void()>::value == false.
-//     is_callable_as<strcmp, void()>::value == false.
-//     is_callable_as<strcmp, int(const char*, const char*)>::value == true
-//
-template<class F, class Signature, class X = void>
-struct is_callable_as : std::false_type {};
-
-// This specialization is SFINAE-d out if template arguments can't be combined
-// into a call expression F(), or if the result of that call is not |R|
-template<class F, class R, class... Args>
-struct is_callable_as<F, R(Args...),
-                      typename std::enable_if<std::is_same<
-                          typename details::dummy<decltype(std::declval<F>()(
-                              std::declval<Args>()...))>::type,
-                          R>::value>::type> : std::true_type {};
-
-//
-// A similar predicate to only check arguments of the function call and ignore
-// the specified return type
-//
-//  is_callable_as<strcmp, int(const char*, const char*)>::value == true
-//  is_callable_as<strcmp, void(const char*, const char*)>::value == false
-//  is_callable_with_args<strcmp, void(const char*, const char*)>::value == true
-//
-template<class F, class Signature, class X = void>
-struct is_callable_with_args : std::false_type {};
-
-template<class F, class R, class... Args>
-struct is_callable_with_args<
-    F, R(Args...),
-    typename std::enable_if<
-        !std::is_same<typename details::dummy<decltype(
-                          std::declval<F>()(std::declval<Args>()...))>::type,
-                      F>::value>::type> : std::true_type {};
-
-// -----------------------------------------------------------------------------
-// Check if a type |T| is any instantiation of a template |U|. Examples:
-//
-//    is_template_instantiation_of<int, std::vector>::value == false
-//    is_template_instantiation_of<
-//         std::list<std::vector<int>>, std::vector>::value == false
-//    is_template_instantiation_of<std::vector<int>, std::vector>::value == true
-//    is_template_instantiation_of<
-//         std::vector<std::vector<int>>, std::vector>::value == true
-//
-template<class T, template<class...> class U>
-struct is_template_instantiation_of : std::false_type {};
-
-template<template<class...> class U, class... Args>
-struct is_template_instantiation_of<U<Args...>, U> : std::true_type {};
-// -----------------------------------------------------------------------------
-
-//
-// is_range<T> - check if type |T| is a range-like type.
-//
-// It makes sure that expressions std::begin(t) and std::end(t) are well-formed
-// and those return the same type.
-//
-// Note: with expression SFINAE from C++14 is_range_helper<> could be renamed to
-//   is_range<> with no extra code. C++11 needs an extra level of enable_if<>
-//   to make it work when the type isn't a range.
-//
-
-namespace details {
-
-template<class T>
-using is_range_helper = std::is_same<
-    decltype(std::begin(
-        std::declval<typename std::add_lvalue_reference<T>::type>())),
-    decltype(
-        std::end(std::declval<typename std::add_lvalue_reference<T>::type>()))>;
-
-}  // namespace details
-
-template<class T, class = void>
-struct is_range : std::false_type {};
-
-template<class T>
-struct is_range<
-    T, typename std::enable_if<details::is_range_helper<T>::value>::type>
-    : std::true_type {};
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// A class to incapsulate integer sequence 0, 1, ..., <num_args>
-//      Seq<int...>
-// Useful to pass function parameters in an array/tuple to call it later.
-//
-
-template<int...>
-struct Seq {};
-
-// A 'maker' class to construct Seq<int...> given only <num_args>
-//    value.
-//      MakeSeq<N, S...> works this way, e.g.
-//
-//      MakeSeq<2> inherits MakeSeq<2 - 1, 2 - 1> == MakeSeq<1, 1>
-//          MakeSeq<1, 1> : MakeSeq<1 - 1, 1 - 1, 1> == MakeSeq<0, 0, 1>
-//          MakeSeq<0, 0, 1> == MakeSeq<0, S...> and defines |type| = Seq<0, 1>
-
-template<int N, int... S>
-struct MakeSeq : MakeSeq<N - 1, N - 1, S...> {};
-
-template<int... S>
-struct MakeSeq<0, S...> {
-  using type = Seq<S...>;
-};
-
-//
-// MakeSeqT alias to quickly create Seq<...>:
-//      MakeSeqT<3> == Seq<0, 1, 2>
-template<int... S>
-using MakeSeqT = typename MakeSeq<S...>::type;
-
-}  // namespace base
-}  // namespace astc_codec
-
-#endif  // ASTC_CODEC_BASE_TYPE_TRAITS_H_

+ 0 - 175
3rdparty/astc-codec/src/base/uint128.h

@@ -1,175 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#ifndef ASTC_CODEC_BASE_UINT128_H_
-#define ASTC_CODEC_BASE_UINT128_H_
-
-#include <cassert>
-#include <cstdint>
-
-namespace astc_codec {
-namespace base {
-
-class UInt128 {
- public:
-  UInt128() = default;
-  UInt128(uint64_t low) : low_(low) { }
-  UInt128(uint64_t high, uint64_t low) : low_(low), high_(high) { }
-  UInt128(const UInt128& other) : low_(other.low_), high_(other.high_) { }
-
-  uint64_t LowBits() const { return low_; }
-  uint64_t HighBits() const { return high_; }
-
-  // Allow explicit casts to uint64_t.
-  explicit operator uint64_t() const { return low_; }
-
-  // Copy operators.
-  UInt128& operator=(const UInt128& other) {
-    high_ = other.high_;
-    low_ = other.low_;
-    return *this;
-  }
-
-  // Equality operators.
-  bool operator==(const UInt128& other) const {
-    return high_ == other.high_ && low_ == other.low_;
-  }
-
-  bool operator!=(const UInt128& other) const {
-    return high_ != other.high_ || low_ != other.low_;
-  }
-
-  // Shifting.
-  UInt128& operator<<=(int shift) {
-    high_ = shift >= 64 ? (shift >= 128 ? 0 : low_ << (shift - 64))
-                        : high_ << shift;
-
-    if (shift > 0 && shift < 64) {
-      const uint64_t overlappingBits = low_ >> (64 - shift);
-      high_ |= overlappingBits;
-    }
-
-    low_ = shift >= 64 ? 0 : low_ << shift;
-    return *this;
-  }
-
-  UInt128 operator<<(int shift) const {
-    UInt128 result = *this;
-    result <<= shift;
-    return result;
-  }
-
-  UInt128& operator>>=(int shift) {
-    low_ = shift >= 64 ? (shift >= 128 ? 0 : high_ >> (shift - 64))
-                       : low_ >> shift;
-
-    if (shift > 0 && shift < 64) {
-      const uint64_t overlappingBits = high_ << (64 - shift);
-      low_ |= overlappingBits;
-    }
-
-    high_ = shift >= 64 ? 0 : high_ >> shift;
-
-    return *this;
-  }
-
-  UInt128 operator>>(int shift) const {
-    UInt128 result = *this;
-    result >>= shift;
-    return result;
-  }
-
-  // Binary operations.
-  UInt128& operator|=(const UInt128& other) {
-    high_ |= other.high_;
-    low_ |= other.low_;
-    return *this;
-  }
-
-  UInt128 operator|(const UInt128& other) const {
-    UInt128 result = *this;
-    result |= other;
-    return result;
-  }
-
-  UInt128& operator&=(const UInt128& other) {
-    high_ &= other.high_;
-    low_ &= other.low_;
-    return *this;
-  }
-
-  UInt128 operator&(const UInt128& other) const {
-    UInt128 result = *this;
-    result &= other;
-    return result;
-  }
-
-  UInt128& operator^=(const UInt128& other) {
-    high_ ^= other.high_;
-    low_ ^= other.low_;
-    return *this;
-  }
-
-  UInt128 operator^(const UInt128& other) const {
-    UInt128 result = *this;
-    result ^= other;
-    return result;
-  }
-
-  UInt128 operator~() const {
-    UInt128 result = *this;
-    result.high_ = ~high_;
-    result.low_ = ~low_;
-    return result;
-  }
-
-  // Addition/subtraction.
-  UInt128& operator+=(const UInt128& other) {
-    const uint64_t carry =
-        (((low_ & other.low_) & 1) + (low_ >> 1) + (other.low_ >> 1)) >> 63;
-    high_ += other.high_ + carry;
-    low_ += other.low_;
-    return *this;
-  }
-
-  UInt128 operator+(const UInt128& other) const {
-    UInt128 result = *this;
-    result += other;
-    return result;
-  }
-
-  UInt128& operator-=(const UInt128& other) {
-    low_ -= other.low_;
-    const uint64_t carry =
-        (((low_ & other.low_) & 1) + (low_ >> 1) + (other.low_ >> 1)) >> 63;
-    high_ -= other.high_ + carry;
-    return *this;
-  }
-
-  UInt128 operator-(const UInt128& other) const {
-    UInt128 result = *this;
-    result -= other;
-    return result;
-  }
-
- private:
-  // TODO(google): Different order for little endian.
-  uint64_t low_ = 0;
-  uint64_t high_ = 0;
-};
-
-}  // namespace base
-}  // namespace astc_codec
-
-#endif  // ASTC_CODEC_BASE_UINT128_H_

+ 0 - 35
3rdparty/astc-codec/src/base/utils.h

@@ -1,35 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#ifndef ASTC_CODEC_BASE_UTILS_H_
-#define ASTC_CODEC_BASE_UTILS_H_
-
-#include <cassert>
-#include <cstdio>
-#include <cstdlib>
-
-#ifdef NDEBUG
-#define UTILS_RELEASE_ASSERT(x)                                        \
-  do {                                                                 \
-    const bool result = (x);                                           \
-    if (!result) {                                                     \
-      fprintf(stderr, "Error: UTILS_RELEASE_ASSERT failed: %s\n", #x); \
-      abort();                                                         \
-    }                                                                  \
-  } while (false)
-#else
-#define UTILS_RELEASE_ASSERT(x) assert(x)
-#endif
-
-#endif  // ASTC_CODEC_BASE_UTILS_H_

+ 0 - 185
3rdparty/astc-codec/src/decoder/astc_file.cc

@@ -1,185 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#include "src/decoder/astc_file.h"
-
-#include <cstring>
-#include <fstream>
-#include <memory>
-#include <sstream>
-
-namespace astc_codec {
-
-namespace {
-static constexpr size_t kASTCHeaderSize = 16;
-
-// Reads a value of size T from the buffer at the current offset, then
-// increments the offset.
-template<typename T>
-inline T ReadVal(const char* file_data, size_t& offset) {
-  T x;
-  memcpy(&x, &file_data[offset], sizeof(T));
-  offset += sizeof(T);
-  return x;
-}
-}  // namespace
-
-ASTCFile::ASTCFile(Header&& header, std::string&& blocks)
-    : header_(std::move(header)), blocks_(std::move(blocks)) {}
-
-std::unique_ptr<ASTCFile> ASTCFile::LoadFromMemory(const char* data,
-                                                   size_t length,
-                                                   std::string* error) {
-  if (length < kASTCHeaderSize) {
-    *error = "Incomplete header.";
-    return nullptr;
-  }
-
-  base::Optional<Header> header_opt = ParseHeader(data);
-  if (!header_opt) {
-    *error = "Invalid ASTC header.";
-    return nullptr;
-  }
-
-  Header header = header_opt.value();
-
-  if (header.block_width_ == 0 || header.block_height_ == 0) {
-    *error = "Invalid block size.";
-    return nullptr;
-  }
-
-  std::string blocks(data + kASTCHeaderSize, data + length);
-
-  // Check that this file has the expected number of blocks.
-  const size_t expected_block_count =
-      ((header.width_ + header.block_width_ - 1) / header.block_width_) *
-      ((header.height_ + header.block_height_ - 1) / header.block_height_);
-
-  if (blocks.size() % PhysicalASTCBlock::kSizeInBytes != 0 ||
-      blocks.size() / PhysicalASTCBlock::kSizeInBytes != expected_block_count) {
-    std::stringstream ss;
-    ss << "Unexpected file length " << blocks.size() << " expected "
-       << kASTCHeaderSize +
-              expected_block_count * PhysicalASTCBlock::kSizeInBytes
-       << " bytes.";
-    *error = ss.str();
-    return nullptr;
-  }
-
-  return std::unique_ptr<ASTCFile>(
-      new ASTCFile(std::move(header), std::move(blocks)));
-}
-
-std::unique_ptr<ASTCFile> ASTCFile::LoadFile(const std::string& path,
-                                             std::string* error) {
-  std::ifstream is(path, std::ios::binary);
-  if (!is) {
-    *error = "File not found: " + path;
-    return nullptr;
-  }
-
-  char header_data[kASTCHeaderSize] = {};
-  if (!is.read(header_data, kASTCHeaderSize)) {
-    *error = "Failed to load ASTC header.";
-    return nullptr;
-  }
-
-  base::Optional<Header> header_opt = ParseHeader(header_data);
-  if (!header_opt) {
-    *error = "Invalid ASTC header.";
-    return nullptr;
-  }
-
-  Header header = header_opt.value();
-
-  std::string blocks;
-  {
-    std::ostringstream ss;
-    ss << is.rdbuf();
-    blocks = ss.str();
-  }
-
-  // Check that this file has the expected number of blocks.
-  const size_t expected_block_count =
-      ((header.width_ + header.block_width_ - 1) / header.block_width_) *
-      ((header.height_ + header.block_height_ - 1) / header.block_height_);
-
-  if (blocks.size() % PhysicalASTCBlock::kSizeInBytes != 0 ||
-      blocks.size() / PhysicalASTCBlock::kSizeInBytes != expected_block_count) {
-    std::stringstream ss;
-    ss << "Unexpected file length " << blocks.size() << " expected "
-       << kASTCHeaderSize +
-              expected_block_count * PhysicalASTCBlock::kSizeInBytes
-       << " bytes.";
-    *error = ss.str();
-    return nullptr;
-  }
-
-  return std::unique_ptr<ASTCFile>(
-      new ASTCFile(std::move(header), std::move(blocks)));
-}
-
-base::Optional<Footprint> ASTCFile::GetFootprint() const {
-  return Footprint::FromDimensions(int(header_.block_width_), int(header_.block_height_));
-}
-
-std::string ASTCFile::GetFootprintString() const {
-  std::stringstream footprint;
-  footprint << header_.block_width_ << "x" << header_.block_height_;
-  return footprint.str();
-}
-
-const std::string& ASTCFile::GetRawBlockData() const {
-  return blocks_;
-}
-
-PhysicalASTCBlock ASTCFile::GetBlock(size_t block_idx) const {
-  const size_t sz = PhysicalASTCBlock::kSizeInBytes;
-  const size_t offset = PhysicalASTCBlock::kSizeInBytes * block_idx;
-  assert(offset <= blocks_.size() - sz);
-  return PhysicalASTCBlock(blocks_.substr(offset, sz));
-}
-
-base::Optional<ASTCFile::Header> ASTCFile::ParseHeader(const char* header) {
-  size_t offset = 0;
-  // TODO(google): Handle endianness.
-  const uint32_t magic = ReadVal<uint32_t>(header, offset);
-  if (magic != 0x5CA1AB13) {
-    return {};
-  }
-
-  const uint32_t block_width = ReadVal<uint8_t>(header, offset);
-  const uint32_t block_height = ReadVal<uint8_t>(header, offset);
-  const uint32_t block_depth = ReadVal<uint8_t>(header, offset);
-
-  uint32_t width = 0;
-  width |= ReadVal<uint8_t>(header, offset);
-  width |= ReadVal<uint8_t>(header, offset) << 8;
-  width |= ReadVal<uint8_t>(header, offset) << 16;
-
-  uint32_t height = 0;
-  height |= ReadVal<uint8_t>(header, offset);
-  height |= ReadVal<uint8_t>(header, offset) << 8;
-  height |= ReadVal<uint8_t>(header, offset) << 16;
-
-  uint32_t depth = 0;
-  depth |= ReadVal<uint8_t>(header, offset);
-  depth |= ReadVal<uint8_t>(header, offset) << 8;
-  depth |= ReadVal<uint8_t>(header, offset) << 16;
-  assert(offset == kASTCHeaderSize);
-
-  return Header(width, height, depth, block_width, block_height, block_depth);
-}
-
-}  // namespace astc_codec

+ 0 - 97
3rdparty/astc-codec/src/decoder/astc_file.h

@@ -1,97 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#ifndef ASTC_CODEC_DECODER_ASTC_FILE_H_
-#define ASTC_CODEC_DECODER_ASTC_FILE_H_
-
-#include "src/base/optional.h"
-#include "src/decoder/footprint.h"
-#include "src/decoder/physical_astc_block.h"
-
-#include <memory>
-#include <string>
-
-namespace astc_codec {
-
-// A thin wrapper around a .astc file on disk. This class simply reads the ASTC
-// header, and stores the block data in memory.
-class ASTCFile {
- private:
-  struct Header {
-    Header(size_t width, size_t height, size_t depth, size_t block_width,
-           size_t block_height, size_t block_depth)
-        : width_(width),
-          height_(height),
-          depth_(depth),
-          block_width_(block_width),
-          block_height_(block_height),
-          block_depth_(block_depth) {}
-
-    size_t width_;
-    size_t height_;
-    size_t depth_;
-
-    size_t block_width_;
-    size_t block_height_;
-    size_t block_depth_;
-  };
-
-  ASTCFile(ASTCFile::Header&& header, std::string&& blocks);
-
- public:
-  // Load an ASTC file from memory.
-  // If loading failed, nullptr is returned and an error string is populated
-  // in the error parameter.
-  static std::unique_ptr<ASTCFile> LoadFromMemory(const char* data,
-                                                  size_t length,
-                                                  std::string* error);
-
-  // Load an ASTC file from file.
-  // If loading failed, nullptr is returned and an error string is populated
-  // in the error parameter.
-  static std::unique_ptr<ASTCFile> LoadFile(const std::string& path,
-                                            std::string* error);
-
-  // Returns the footprint for the file, if it is considered to be a valid
-  // footprint.
-  base::Optional<Footprint> GetFootprint() const;
-
-  // Returns the string of the form "NxM" where N and M are the width and height
-  // of the block footprint, respectively.
-  std::string GetFootprintString() const;
-
-  // Get the raw block data for the astc file.
-  const std::string& GetRawBlockData() const;
-
-  // Returns the physical block at the associated block index.
-  PhysicalASTCBlock GetBlock(size_t block_idx) const;
-
-  size_t GetWidth() const { return header_.width_; }
-  size_t GetHeight() const { return header_.height_; }
-  size_t GetDepth() const { return header_.depth_; }
-
-  size_t NumBlocks() const {
-    return blocks_.size() / PhysicalASTCBlock::kSizeInBytes;
-  }
-
- private:
-  static base::Optional<ASTCFile::Header> ParseHeader(const char* header);
-
-  const Header header_;
-  const std::string blocks_;
-};
-
-}  // namespace astc_codec
-
-#endif  // ASTC_CODEC_DECODER_ASTC_FILE_H_

+ 0 - 132
3rdparty/astc-codec/src/decoder/codec.cc

@@ -1,132 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#include "src/decoder/codec.h"
-#include "src/base/uint128.h"
-#include "src/decoder/logical_astc_block.h"
-#include "src/decoder/physical_astc_block.h"
-
-#include <cstring>
-
-namespace astc_codec {
-
-namespace {
-static constexpr size_t kBytesPerPixelUNORM8 = 4;
-}
-
-bool DecompressToImage(const uint8_t* astc_data, size_t astc_data_size,
-                       size_t width, size_t height, Footprint footprint,
-                       uint8_t* out_buffer, size_t out_buffer_size,
-                       size_t out_buffer_stride) {
-  const size_t block_width = footprint.Width();
-  const size_t block_height = footprint.Height();
-  assert(block_width != 0);
-  assert(block_height != 0);
-
-  if (width == 0 || height == 0) {
-    return false;
-  }
-
-  const size_t blocks_wide = (width + block_width - 1) / block_width;
-  assert(blocks_wide != 0);
-
-  // Check that this buffer has the expected number of blocks.
-  const size_t expected_block_count =
-      ((width + block_width - 1) / block_width) *
-      ((height + block_height - 1) / block_height);
-
-  if (astc_data_size % PhysicalASTCBlock::kSizeInBytes != 0 ||
-      astc_data_size / PhysicalASTCBlock::kSizeInBytes !=
-          expected_block_count) {
-    // TODO(google): Expose error?
-    return false;
-  }
-
-  if (kBytesPerPixelUNORM8 * width > out_buffer_stride ||
-      out_buffer_stride * height < out_buffer_size) {
-    // Output buffer too small.
-    return false;
-  }
-
-  base::UInt128 block;
-  static_assert(sizeof(block) == PhysicalASTCBlock::kSizeInBytes,
-                "Block size mismatch");
-
-  for (size_t i0 = 0; i0 < astc_data_size; i0 += PhysicalASTCBlock::kSizeInBytes) {
-    const size_t block_index = i0 / PhysicalASTCBlock::kSizeInBytes;
-    const size_t block_x = block_index % blocks_wide;
-    const size_t block_y = block_index / blocks_wide;
-    block = *(base::UInt128*)(astc_data + i0);
-
-    PhysicalASTCBlock physical_block(block);
-    auto lb = UnpackLogicalBlock(footprint, physical_block);
-    if (!lb) {
-      return false;
-    }
-
-    LogicalASTCBlock logical_block = lb.value();
-
-    for (size_t y = 0; y < block_height; ++y) {
-      const size_t py = block_height * block_y + y;
-      uint8_t* out_row = out_buffer + py * out_buffer_stride;
-
-      for (size_t x = 0; x < block_width; ++x) {
-        const size_t px = block_width * block_x + x;
-
-        // Skip out of bounds.
-        if (px >= width || py >= height) {
-          continue;
-        }
-
-        uint8_t* pixel = out_row + px * kBytesPerPixelUNORM8;
-        const RgbaColor decoded_color = logical_block.ColorAt(int(x), int(y));
-        for (size_t i = 0; i < kBytesPerPixelUNORM8; ++i) {
-          pixel[i] = static_cast<uint8_t>(decoded_color[i]);
-        }
-      }
-    }
-  }
-
-  return true;
-}
-
-bool DecompressToImage(const ASTCFile& file, uint8_t* out_buffer,
-                       size_t out_buffer_size, size_t out_buffer_stride) {
-  base::Optional<Footprint> footprint = file.GetFootprint();
-  if (!footprint) {
-    return false;
-  }
-
-  return DecompressToImage(
-      reinterpret_cast<const uint8_t*>(file.GetRawBlockData().c_str()),
-      file.GetRawBlockData().size(), file.GetWidth(), file.GetHeight(),
-      footprint.value(), out_buffer, out_buffer_size, out_buffer_stride);
-}
-
-bool ASTCDecompressToRGBA(const uint8_t* astc_data, size_t astc_data_size,
-                          size_t width, size_t height, FootprintType footprint,
-                          uint8_t* out_buffer, size_t out_buffer_size,
-                          size_t out_buffer_stride) {
-  base::Optional<Footprint> footprint_opt =
-      Footprint::FromFootprintType(footprint);
-  if (!footprint_opt) {
-    return false;
-  }
-
-  return DecompressToImage(astc_data, astc_data_size, width, height,
-                           footprint_opt.value(), out_buffer, out_buffer_size,
-                           out_buffer_stride);
-}
-
-}  // namespace astc_codec

+ 0 - 41
3rdparty/astc-codec/src/decoder/codec.h

@@ -1,41 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#ifndef ASTC_CODEC_DECODER_CODEC_H_
-#define ASTC_CODEC_DECODER_CODEC_H_
-
-#include "src/decoder/astc_file.h"
-#include "src/decoder/footprint.h"
-
-#include <string>
-
-namespace astc_codec {
-
-// Decompresses ASTC blocks to an image buffer.
-// Returns true if the decompression succeeded and the out buffer has been
-// filled.
-bool DecompressToImage(const uint8_t* astc_data, size_t astc_data_size,
-                       size_t width, size_t height, Footprint footprint,
-                       uint8_t* out_buffer, size_t out_buffer_size,
-                       size_t out_buffer_stride);
-
-// Decompresses an ASTC file to an image buffer.
-// Returns true if the decompression succeeded and the out buffer has been
-// filled.
-bool DecompressToImage(const ASTCFile& file, uint8_t* out_buffer,
-                       size_t out_buffer_size, size_t out_buffer_stride);
-
-}  // namespace astc_codec
-
-#endif  // ASTC_CODEC_DECODER_CODEC_H_

+ 0 - 963
3rdparty/astc-codec/src/decoder/endpoint_codec.cc

@@ -1,963 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#include "src/decoder/endpoint_codec.h"
-#include "src/decoder/quantization.h"
-
-#include <algorithm>
-#include <array>
-#include <numeric>
-#include <utility>
-
-namespace astc_codec {
-
-namespace {
-
-template<typename T>
-T Clamp(T value, T min, T max) {
-  return value < min ? min : (value > max ? max : value);
-}
-
-// This is the 'blue_contract' function defined in Section C.2.14 of the ASTC
-// specification.
-template<typename ArrayType>
-void BlueContract(ArrayType* const cptr) {
-  ArrayType& c = *cptr;
-  c[0] = (c[0] + c[2]) >> 1;
-  c[1] = (c[1] + c[2]) >> 1;
-}
-
-// Returns the inverse of values in BlueContract, subjected to the constraint
-// that the new values are stored in the range [0, 255].
-template<typename ArrayType>
-ArrayType InvertBlueContract(const ArrayType& c) {
-  ArrayType result = c;
-  result[0] = Clamp(2 * c[0] - c[2], 0, 255);
-  result[1] = Clamp(2 * c[1] - c[2], 0, 255);
-  return result;
-}
-
-// This is the 'bit_transfer_signed' function defined in Section C.2.14 of the
-// ASTC specification.
-void BitTransferSigned(int* const a, int* const b) {
-  *b >>= 1;
-  *b |= *a & 0x80;
-  *a >>= 1;
-  *a &= 0x3F;
-  if ((*a & 0x20) != 0) {
-    *a -= 0x40;
-  }
-}
-
-// Takes two values, |a| in the range [-32, 31], and |b| in the range [0, 255],
-// and returns the two values in [0, 255] that will reconstruct |a| and |b| when
-// passed to the BitTransferSigned function.
-void InvertBitTransferSigned(int* const a, int* const b) {
-  assert(*a >= -32); assert(*a < 32);
-  assert(*b >= 0);   assert(*b < 256);
-
-  if (*a < 0) {
-    *a += 0x40;
-  }
-  *a <<= 1;
-  *a |= (*b & 0x80);
-  *b <<= 1;
-  *b &= 0xff;
-}
-
-template<typename ContainerType>
-void Quantize(ContainerType* const c, size_t max_value) {
-  for (auto& x : *c) {
-    x = QuantizeCEValueToRange(x, int(max_value));
-  }
-}
-
-template<typename ArrayType>
-ArrayType QuantizeColor(const ArrayType& c, size_t max_value) {
-  ArrayType result = c;
-  Quantize(&result, max_value);
-  return result;
-}
-
-template<typename ContainerType>
-void Unquantize(ContainerType* const c, size_t max_value) {
-  for (auto& x : *c) {
-    x = UnquantizeCEValueFromRange(x, int(max_value));
-  }
-}
-
-template<typename ArrayType>
-ArrayType UnquantizeColor(const ArrayType& c, size_t max_value) {
-  ArrayType result = c;
-  Unquantize(&result, max_value);
-  return result;
-}
-
-// Returns the average of the three RGB channels.
-template<typename ContainerType>
-int AverageRGB(const ContainerType& c) {
-  // Each channel can be in the range [0, 255], and we need to divide by three.
-  // However, we want to round the error properly. Both (x + 1) / 3 and
-  // (x + 2) / 3 are relatively imprecise when it comes to rounding, so instead
-  // we increase the precision by multiplying our numerator by some arbitrary
-  // number. Here, we choose 256 to get 8 additional bits and maintain
-  // performance since it turns into a shift rather than a multiply. Our
-  // denominator then becomes  3 * 256 = 768.
-  return (std::accumulate(c.begin(), c.begin() + 3, 0) * 256 + 384) / 768;
-}
-
-// Returns the sum of squared differences between each element of |a| and |b|,
-// which are assumed to contain the same number of elements.
-template<typename ContainerType>
-const typename ContainerType::value_type SquaredError(
-    const ContainerType& a, const ContainerType& b,
-    size_t num_channels = std::tuple_size<ContainerType>::value) {
-  using ValueTy = typename ContainerType::value_type;
-  static_assert(std::is_signed<ValueTy>::value,
-                "Value type assumed to be signed to avoid branch below.");
-  ValueTy result = ValueTy(0);
-  for (size_t i = 0; i < num_channels; ++i) {
-    ValueTy error = a[i] - b[i];
-    result += error * error;
-  }
-  return result;
-}
-
-constexpr int MaxValuesForModes(ColorEndpointMode mode_a,
-                                ColorEndpointMode mode_b) {
-  return (NumColorValuesForEndpointMode(mode_a) >
-          NumColorValuesForEndpointMode(mode_b))
-      ? NumColorValuesForEndpointMode(mode_a)
-      : NumColorValuesForEndpointMode(mode_b);
-}
-
-// This function takes the two colors in |endpoint_low| and |endpoint_high| and
-// encodes them into |vals| according to the ASTC spec in section C.2.14. It
-// assumes that the two colors are close enough to grayscale that the encoding
-// should use the ColorEndpointMode kLDRLumaBaseOffset or kLDRLumaDirect. Which
-// one is chosen depends on which produces smaller error for the given
-// quantization value stored in |max_value|
-bool EncodeColorsLuma(const RgbaColor& endpoint_low,
-                      const RgbaColor& endpoint_high,
-                      int max_value, ColorEndpointMode* const astc_mode,
-                      std::vector<int>* const vals) {
-  assert(vals->size() ==
-         size_t(NumValuesForEncodingMode(EndpointEncodingMode::kDirectLuma)));
-  int avg1 = AverageRGB(endpoint_low);
-  int avg2 = AverageRGB(endpoint_high);
-
-  // For the offset mode, L1 is strictly greater than L2, so if we are using
-  // it to encode the color values, we need to swap the weights and
-  // endpoints so that the larger of the two is the second endpoint.
-  bool needs_weight_swap = false;
-  if (avg1 > avg2) {
-    needs_weight_swap = true;
-    std::swap(avg1, avg2);
-  }
-  assert(avg1 <= avg2);
-
-  // Now, the first endpoint is based on the low-order six bits of the first
-  // value, and the high order two bits of the second value. The low order
-  // six bits of the second value are used as the (strictly positive) offset
-  // from the first value.
-  const int offset = std::min(avg2 - avg1, 0x3F);
-  const int quant_off_low =
-      QuantizeCEValueToRange((avg1 & 0x3F) << 2, max_value);
-  const int quant_off_high =
-      QuantizeCEValueToRange((avg1 & 0xC0) | offset, max_value);
-
-  const int quant_low = QuantizeCEValueToRange(avg1, max_value);
-  const int quant_high = QuantizeCEValueToRange(avg2, max_value);
-
-  RgbaColor unquant_off_low, unquant_off_high;
-  RgbaColor unquant_low, unquant_high;
-
-  (*vals)[0] = quant_off_low;
-  (*vals)[1] = quant_off_high;
-  DecodeColorsForMode(
-      *vals, max_value, ColorEndpointMode::kLDRLumaBaseOffset,
-      &unquant_off_low, &unquant_off_high);
-
-  (*vals)[0] = quant_low;
-  (*vals)[1] = quant_high;
-  DecodeColorsForMode(*vals, max_value, ColorEndpointMode::kLDRLumaDirect,
-                      &unquant_low, &unquant_high);
-
-  const auto calculate_error =
-      [needs_weight_swap, &endpoint_low, &endpoint_high]
-      (const RgbaColor& low, const RgbaColor& high) {
-    int error = 0;
-    if (needs_weight_swap) {
-      error += SquaredError(low, endpoint_high);
-      error += SquaredError(high, endpoint_low);
-    } else {
-      error += SquaredError(low, endpoint_low);
-      error += SquaredError(high, endpoint_high);
-    }
-    return error;
-  };
-
-  const int direct_error = calculate_error(unquant_low, unquant_high);
-  const int off_error = calculate_error(unquant_off_low, unquant_off_high);
-
-  if (direct_error <= off_error) {
-    (*vals)[0] = quant_low;
-    (*vals)[1] = quant_high;
-    *astc_mode = ColorEndpointMode::kLDRLumaDirect;
-  } else {
-    (*vals)[0] = quant_off_low;
-    (*vals)[1] = quant_off_high;
-    *astc_mode = ColorEndpointMode::kLDRLumaBaseOffset;
-  }
-
-  return needs_weight_swap;
-}
-
-class QuantizedEndpointPair {
- public:
-  QuantizedEndpointPair(const RgbaColor& c_low, const RgbaColor& c_high,
-                        int max_value)
-      : orig_low_(c_low),
-        orig_high_(c_high),
-        quant_low_(QuantizeColor(c_low, max_value)),
-        quant_high_(QuantizeColor(c_high, max_value)),
-        unquant_low_(UnquantizeColor(quant_low_, max_value)),
-        unquant_high_(UnquantizeColor(quant_high_, max_value)) { }
-
-  const RgbaColor& QuantizedLow() const { return quant_low_; }
-  const RgbaColor& QuantizedHigh() const { return quant_high_; }
-
-  const RgbaColor& UnquantizedLow() const { return unquant_low_; }
-  const RgbaColor& UnquantizedHigh() const { return unquant_high_; }
-
-  const RgbaColor& OriginalLow() const { return orig_low_; }
-  const RgbaColor& OriginalHigh() const { return orig_high_; }
-
- private:
-  RgbaColor orig_low_;
-  RgbaColor orig_high_;
-
-  RgbaColor quant_low_;
-  RgbaColor quant_high_;
-
-  RgbaColor unquant_low_;
-  RgbaColor unquant_high_;
-};
-
-class CEEncodingOption {
- public:
-  CEEncodingOption() { }
-  CEEncodingOption(
-      int squared_error, const QuantizedEndpointPair* quantized_endpoints,
-      bool swap_endpoints, bool blue_contract, bool use_offset_mode)
-      : squared_error_(squared_error),
-        quantized_endpoints_(quantized_endpoints),
-        swap_endpoints_(swap_endpoints),
-        blue_contract_(blue_contract),
-        use_offset_mode_(use_offset_mode) { }
-
-  // Returns true if able to generate valid |astc_mode| and |vals|. In some
-  // instances, such as if the endpoints reprsent a base/offset pair, we may not
-  // be able to guarantee blue-contract encoding due to how the base/offset pair
-  // are represented and the specifics of the decoding procedure. Similarly,
-  // some direct RGBA encodings also may not be able to emit blue-contract modes
-  // due to an unlucky combination of channels. In these instances, this
-  // function will return false, and all pointers will remain unmodified.
-  bool Pack(bool with_alpha, ColorEndpointMode* const astc_mode,
-            std::vector<int>* const vals, bool* const needs_weight_swap) const {
-    auto unquantized_low = quantized_endpoints_->UnquantizedLow();
-    auto unquantized_high = quantized_endpoints_->UnquantizedHigh();
-
-    // In offset mode, we do BitTransferSigned before analyzing the values
-    // of the endpoints in order to determine whether or not we're going to
-    // be using blue-contract mode.
-    if (use_offset_mode_) {
-      for (size_t i = 0; i < std::tuple_size<RgbaColor>::value; ++i) {
-        BitTransferSigned(&unquantized_high[i], &unquantized_low[i]);
-      }
-    }
-
-    // Define variables as outlined in the ASTC spec C.2.14 for the RGB[A]
-    // direct and base-offset modes
-    int s0 = 0, s1 = 0;
-    for (int i = 0; i < 3; ++i) {
-      s0 += unquantized_low[i];
-      s1 += unquantized_high[i];
-    }
-
-    // Can we guarantee a blue-contract mode if we want it? In other words,
-    // if we swap which endpoint is high and which endpoint is low, can we
-    // guarantee that we will hit the corresponding decode path?
-    bool swap_vals = false;
-    if (use_offset_mode_) {
-      if (blue_contract_) {
-        swap_vals = s1 >= 0;
-      } else {
-        swap_vals = s1 < 0;
-      }
-
-      // In offset mode, we have two different measurements that swap the
-      // endpoints prior to encoding, so we don't need to swap them here.
-      // If we need to swap them to guarantee a blue-contract mode, then
-      // abort and wait until we get the other error measurement.
-      if (swap_vals) {
-        return false;
-      }
-    } else {
-      if (blue_contract_) {
-        // If we want a blue_contract path, but s1 == s0, then swapping the
-        // values will have no effect.
-        if (s1 == s0) {
-          return false;
-        }
-
-        swap_vals = s1 > s0;
-        // If we're encoding blue contract mode directly, then we implicitly
-        // swap the endpoints during decode, meaning that we need to take
-        // note of that here.
-        *needs_weight_swap = !(*needs_weight_swap);
-      } else {
-        swap_vals = s1 < s0;
-      }
-    }
-
-    const auto* quantized_low = &(quantized_endpoints_->QuantizedLow());
-    const auto* quantized_high = &(quantized_endpoints_->QuantizedHigh());
-
-    if (swap_vals) {
-      assert(!use_offset_mode_);
-      std::swap(quantized_low, quantized_high);
-      *needs_weight_swap = !(*needs_weight_swap);
-    }
-
-    (*vals)[0] = quantized_low->at(0);
-    (*vals)[1] = quantized_high->at(0);
-    (*vals)[2] = quantized_low->at(1);
-    (*vals)[3] = quantized_high->at(1);
-    (*vals)[4] = quantized_low->at(2);
-    (*vals)[5] = quantized_high->at(2);
-
-    if (use_offset_mode_) {
-      *astc_mode = ColorEndpointMode::kLDRRGBBaseOffset;
-    } else {
-      *astc_mode = ColorEndpointMode::kLDRRGBDirect;
-    }
-
-    if (with_alpha) {
-      (*vals)[6] = quantized_low->at(3);
-      (*vals)[7] = quantized_high->at(3);
-
-      if (use_offset_mode_) {
-        *astc_mode = ColorEndpointMode::kLDRRGBABaseOffset;
-      } else {
-        *astc_mode = ColorEndpointMode::kLDRRGBADirect;
-      }
-    }
-
-    // If we swapped them to measure, then they need to be swapped after
-    // decoding
-    if (swap_endpoints_) {
-      *needs_weight_swap = !(*needs_weight_swap);
-    }
-
-    return true;
-  }
-
-  bool BlueContract() const { return blue_contract_; }
-  int Error() const { return squared_error_; }
-
- private:
-  int squared_error_;
-  const QuantizedEndpointPair* quantized_endpoints_;
-  bool swap_endpoints_;
-  bool blue_contract_;
-  bool use_offset_mode_;
-};
-
-bool EncodeColorsRGBA(const RgbaColor& endpoint_low_rgba,
-                      const RgbaColor& endpoint_high_rgba,
-                      int max_value, bool with_alpha,
-                      ColorEndpointMode* const astc_mode,
-                      std::vector<int>* const vals) {
-  const size_t num_channels = with_alpha ? std::tuple_size<RgbaColor>::value : 3;
-  // The difficulty of encoding into this mode is determining whether or
-  // not we'd like to use the 'blue contract' function to reconstruct
-  // the endpoints and whether or not we'll be more accurate by using the
-  // base/offset color modes instead of quantizing the color channels
-  // directly. With that in mind, we:
-  // 1. Generate the inverted values for blue-contract and offset modes.
-  // 2. Quantize all of the different endpoints.
-  // 3. Unquantize each sets and decide which one gives least error
-  // 4. Encode the values correspondingly.
-
-  // 1. Generate the inverted values for blue-contract and offset modes.
-  const auto inv_bc_low = InvertBlueContract(endpoint_low_rgba);
-  const auto inv_bc_high = InvertBlueContract(endpoint_high_rgba);
-
-  RgbaColor direct_base, direct_offset;
-  for (size_t i = 0; i < std::tuple_size<RgbaColor>::value; ++i) {
-    direct_base[i] = endpoint_low_rgba[i];
-    direct_offset[i] =
-        Clamp(endpoint_high_rgba[i] - endpoint_low_rgba[i], -32, 31);
-    InvertBitTransferSigned(&direct_offset[i], &direct_base[i]);
-  }
-
-  RgbaColor inv_bc_base, inv_bc_offset;
-  for (size_t i = 0; i < std::tuple_size<RgbaColor>::value; ++i) {
-    // Remember, for blue-contract'd offset modes, the base is compared
-    // against the second endpoint and not the first.
-    inv_bc_base[i] = inv_bc_high[i];
-    inv_bc_offset[i] = Clamp(inv_bc_low[i] - inv_bc_high[i], -32, 31);
-    InvertBitTransferSigned(&inv_bc_offset[i], &inv_bc_base[i]);
-  }
-
-  // The order of the endpoints for offset modes may determine how well they
-  // approximate the given endpoints. It may be that the quantization value
-  // produces more accurate values for the base than the offset or
-  // vice/versa. For this reason, we need to generate quantized versions of
-  // the endpoints as if they were swapped to see if we get better error
-  // out of it.
-
-  RgbaColor direct_base_swapped, direct_offset_swapped;
-  for (size_t i = 0; i < std::tuple_size<RgbaColor>::value; ++i) {
-    direct_base_swapped[i] = endpoint_high_rgba[i];
-    direct_offset_swapped[i] =
-        Clamp(endpoint_low_rgba[i] - endpoint_high_rgba[i], -32, 31);
-    InvertBitTransferSigned(&direct_offset_swapped[i], &direct_base_swapped[i]);
-  }
-
-  RgbaColor inv_bc_base_swapped, inv_bc_offset_swapped;
-  for (size_t i = 0; i < std::tuple_size<RgbaColor>::value; ++i) {
-    // Remember, for blue-contract'd offset modes, the base is compared
-    // against the second endpoint and not the first. Hence, the swapped
-    // version will compare the base against the first endpoint.
-    inv_bc_base_swapped[i] = inv_bc_low[i];
-    inv_bc_offset_swapped[i] = Clamp(inv_bc_high[i] - inv_bc_low[i], -32, 31);
-    InvertBitTransferSigned(&inv_bc_offset_swapped[i], &inv_bc_base_swapped[i]);
-  }
-
-  // 2. Quantize the endpoints directly.
-  const QuantizedEndpointPair direct_quantized(
-      endpoint_low_rgba, endpoint_high_rgba, max_value);
-  const QuantizedEndpointPair bc_quantized(
-      inv_bc_low, inv_bc_high, max_value);
-
-  const QuantizedEndpointPair offset_quantized(
-      direct_base, direct_offset, max_value);
-  const QuantizedEndpointPair bc_offset_quantized(
-      inv_bc_base, inv_bc_offset, max_value);
-
-  const QuantizedEndpointPair offset_swapped_quantized(
-      direct_base_swapped, direct_offset_swapped, max_value);
-  const QuantizedEndpointPair bc_offset_swapped_quantized(
-      inv_bc_base_swapped, inv_bc_offset_swapped, max_value);
-
-  // 3. Unquantize each set and decide which one gives least error.
-  std::array<CEEncodingOption, 6> errors;
-  auto errors_itr = errors.begin();
-
-  // 3.1 regular unquantized error
-  {
-    const auto rgba_low = direct_quantized.UnquantizedLow();
-    const auto rgba_high = direct_quantized.UnquantizedHigh();
-
-    const int sq_rgb_error =
-        SquaredError(rgba_low, endpoint_low_rgba, num_channels) +
-        SquaredError(rgba_high, endpoint_high_rgba, num_channels);
-
-    const bool swap_endpoints = false;
-    const bool blue_contract = false;
-    const bool offset_mode = false;
-    *(errors_itr++) = CEEncodingOption(
-        sq_rgb_error, &direct_quantized,
-        swap_endpoints, blue_contract, offset_mode);
-  }
-
-  // 3.2 Compute blue-contract'd error.
-  {
-    auto bc_low = bc_quantized.UnquantizedLow();
-    auto bc_high = bc_quantized.UnquantizedHigh();
-    BlueContract(&bc_low);
-    BlueContract(&bc_high);
-
-    const int sq_bc_error =
-        SquaredError(bc_low, endpoint_low_rgba, num_channels) +
-        SquaredError(bc_high, endpoint_high_rgba, num_channels);
-
-    const bool swap_endpoints = false;
-    const bool blue_contract = true;
-    const bool offset_mode = false;
-    *(errors_itr++) = CEEncodingOption(
-        sq_bc_error, &bc_quantized,
-        swap_endpoints, blue_contract, offset_mode);
-  }
-
-  // 3.3 Compute base/offset unquantized error.
-  const auto compute_base_offset_error =
-      [num_channels, &errors_itr, &endpoint_low_rgba, &endpoint_high_rgba]
-      (const QuantizedEndpointPair& pair, bool swapped) {
-    auto base = pair.UnquantizedLow();
-    auto offset = pair.UnquantizedHigh();
-
-    for (size_t i = 0; i < num_channels; ++i) {
-      BitTransferSigned(&offset[i], &base[i]);
-      offset[i] = Clamp(base[i] + offset[i], 0, 255);
-    }
-
-    int base_offset_error = 0;
-    // If we swapped the endpoints going in, then without blue contract
-    // we should be comparing the base against the high endpoint.
-    if (swapped) {
-      base_offset_error =
-          SquaredError(base, endpoint_high_rgba, num_channels) +
-          SquaredError(offset, endpoint_low_rgba, num_channels);
-    } else {
-      base_offset_error =
-          SquaredError(base, endpoint_low_rgba, num_channels) +
-          SquaredError(offset, endpoint_high_rgba, num_channels);
-    }
-
-    const bool blue_contract = false;
-    const bool offset_mode = true;
-    *(errors_itr++) = CEEncodingOption(
-        base_offset_error, &pair, swapped, blue_contract, offset_mode);
-  };
-
-  compute_base_offset_error(offset_quantized, false);
-
-  // 3.4 Compute base/offset blue-contract error.
-  const auto compute_base_offset_blue_contract_error =
-      [num_channels, &errors_itr, &endpoint_low_rgba, &endpoint_high_rgba]
-      (const QuantizedEndpointPair& pair, bool swapped) {
-    auto base = pair.UnquantizedLow();
-    auto offset = pair.UnquantizedHigh();
-
-    for (size_t i = 0; i < num_channels; ++i) {
-      BitTransferSigned(&offset[i], &base[i]);
-      offset[i] = Clamp(base[i] + offset[i], 0, 255);
-    }
-
-    BlueContract(&base);
-    BlueContract(&offset);
-
-    int sq_bc_error = 0;
-    // Remember, for blue-contract'd offset modes, the base is compared
-    // against the second endpoint and not the first. So, we compare
-    // against the first if we swapped the endpoints going in.
-    if (swapped) {
-      sq_bc_error =
-          SquaredError(base, endpoint_low_rgba, num_channels) +
-          SquaredError(offset, endpoint_high_rgba, num_channels);
-    } else {
-      sq_bc_error =
-          SquaredError(base, endpoint_high_rgba, num_channels) +
-          SquaredError(offset, endpoint_low_rgba, num_channels);
-    }
-
-    const bool blue_contract = true;
-    const bool offset_mode = true;
-    *(errors_itr++) = CEEncodingOption(sq_bc_error, &pair,
-                                       swapped, blue_contract, offset_mode);
-  };
-
-  compute_base_offset_blue_contract_error(bc_offset_quantized, false);
-
-  // 3.5 Compute swapped base/offset error.
-  compute_base_offset_error(offset_swapped_quantized, true);
-
-  // 3.6 Compute swapped base/offset blue-contract error.
-  compute_base_offset_blue_contract_error(
-      bc_offset_swapped_quantized, true);
-
-  std::sort(errors.begin(), errors.end(),
-            [](const CEEncodingOption& a, const CEEncodingOption& b) {
-              return a.Error() < b.Error();
-            });
-
-  // 4. Encode the values correspondingly.
-  // For this part, we go through each measurement in order of increasing
-  // error. Based on the properties of each measurement, we decide how to
-  // best encode the quantized endpoints that produced that error value. If
-  // for some reason we cannot encode that metric, then we skip it and move
-  // to the next one.
-  for (const auto& measurement : errors) {
-    bool needs_weight_swap = false;
-    if (measurement.Pack(with_alpha, astc_mode, vals, &needs_weight_swap)) {
-      // Make sure that if we ask for a blue-contract mode that we get it *and*
-      // if we don't ask for it then we don't get it.
-      assert(!(measurement.BlueContract() ^
-               UsesBlueContract(max_value, *astc_mode, *vals)));
-
-      // We encoded what we got.
-      return needs_weight_swap;
-    }
-  }
-
-  assert(false && "Shouldn't have reached this point -- some combination of "
-                  "endpoints should be possible to encode!");
-  return false;
-}
-
-}  // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-
-bool UsesBlueContract(int max_value, ColorEndpointMode mode,
-                      const std::vector<int>& vals) {
-  assert(vals.size() >= size_t(NumColorValuesForEndpointMode(mode)));
-
-  switch (mode) {
-    case ColorEndpointMode::kLDRRGBDirect:
-    case ColorEndpointMode::kLDRRGBADirect: {
-      constexpr int kNumVals = MaxValuesForModes(
-          ColorEndpointMode::kLDRRGBDirect, ColorEndpointMode::kLDRRGBADirect);
-      std::array<int, kNumVals> v {};
-      std::copy(vals.begin(), vals.end(), v.begin());
-      Unquantize(&v, max_value);
-
-      const int s0 = v[0] + v[2] + v[4];
-      const int s1 = v[1] + v[3] + v[5];
-
-      return s0 > s1;
-    }
-
-    case ColorEndpointMode::kLDRRGBBaseOffset:
-    case ColorEndpointMode::kLDRRGBABaseOffset: {
-      constexpr int kNumVals = MaxValuesForModes(
-          ColorEndpointMode::kLDRRGBBaseOffset,
-          ColorEndpointMode::kLDRRGBABaseOffset);
-      std::array<int, kNumVals> v {};
-      std::copy(vals.begin(), vals.end(), v.begin());
-      Unquantize(&v, max_value);
-
-      BitTransferSigned(&v[1], &v[0]);
-      BitTransferSigned(&v[3], &v[2]);
-      BitTransferSigned(&v[5], &v[4]);
-
-      return v[1] + v[3] + v[5] < 0;
-    }
-
-    default:
-      return false;
-  }
-}
-
-bool EncodeColorsForMode(
-    const RgbaColor& endpoint_low_rgba, const RgbaColor& endpoint_high_rgba,
-    int max_value, EndpointEncodingMode encoding_mode,
-    ColorEndpointMode* const astc_mode, std::vector<int>* const vals) {
-  bool needs_weight_swap = false;
-  vals->resize(NumValuesForEncodingMode(encoding_mode));
-
-  switch (encoding_mode) {
-    case EndpointEncodingMode::kDirectLuma:
-      return EncodeColorsLuma(
-          endpoint_low_rgba, endpoint_high_rgba, max_value, astc_mode, vals);
-
-    case EndpointEncodingMode::kDirectLumaAlpha: {
-      // TODO(google): See if luma-alpha base-offset is better
-      const int avg1 = AverageRGB(endpoint_low_rgba);
-      const int avg2 = AverageRGB(endpoint_high_rgba);
-
-      (*vals)[0] = QuantizeCEValueToRange(avg1, max_value);
-      (*vals)[1] = QuantizeCEValueToRange(avg2, max_value);
-      (*vals)[2] = QuantizeCEValueToRange(endpoint_low_rgba[3], max_value);
-      (*vals)[3] = QuantizeCEValueToRange(endpoint_high_rgba[3], max_value);
-      *astc_mode = ColorEndpointMode::kLDRLumaAlphaDirect;
-    }
-    break;
-
-    case EndpointEncodingMode::kBaseScaleRGB:
-    case EndpointEncodingMode::kBaseScaleRGBA: {
-      RgbaColor base = endpoint_high_rgba;
-      RgbaColor scaled = endpoint_low_rgba;
-
-      // Similar to luma base-offset, the scaled value is strictly less than
-      // the base value here according to the decode procedure. In this case,
-      // if the base is larger than the scale then we need to swap.
-      int num_channels_ge = 0;
-      for (int i = 0; i < 3; ++i) {
-        num_channels_ge +=
-            static_cast<int>(endpoint_high_rgba[i] >= endpoint_low_rgba[i]);
-      }
-
-      if (num_channels_ge < 2) {
-        needs_weight_swap = true;
-        std::swap(base, scaled);
-      }
-
-      // Since the second endpoint is just a direct copy of the RGB values, we
-      // can start by quantizing them.
-      const auto q_base = QuantizeColor(base, max_value);
-      const auto uq_base = UnquantizeColor(q_base, max_value);
-
-      // The first endpoint (scaled) is defined by piecewise multiplying the
-      // second endpoint (base) by the scale factor and then dividing by 256.
-      // This means that the inverse operation is to first piecewise multiply
-      // the first endpoint by 256 and then divide by the unquantized second
-      // endpoint. We take the average of each of each of these scale values as
-      // our final scale value.
-      // TODO(google): Is this the best way to determine the scale factor?
-      int num_samples = 0;
-      int scale_sum = 0;
-      for (int i = 0; i < 3; ++i) {
-        int x = uq_base[i];
-        if (x != 0) {
-          ++num_samples;
-          scale_sum += (scaled[i] * 256) / x;
-        }
-      }
-
-      (*vals)[0] = q_base[0];
-      (*vals)[1] = q_base[1];
-      (*vals)[2] = q_base[2];
-      if (num_samples > 0) {
-        const int avg_scale = Clamp(scale_sum / num_samples, 0, 255);
-        (*vals)[3] = QuantizeCEValueToRange(avg_scale, max_value);
-      } else {
-        // In this case, all of the base values are zero, so we can use whatever
-        // we want as the scale -- it won't affect the outcome.
-        (*vals)[3] = max_value;
-      }
-      *astc_mode = ColorEndpointMode::kLDRRGBBaseScale;
-
-      if (encoding_mode == EndpointEncodingMode::kBaseScaleRGBA) {
-        (*vals)[4] = QuantizeCEValueToRange(scaled[3], max_value);
-        (*vals)[5] = QuantizeCEValueToRange(base[3], max_value);
-        *astc_mode = ColorEndpointMode::kLDRRGBBaseScaleTwoA;
-      }
-    }
-    break;
-
-    case EndpointEncodingMode::kDirectRGB:
-    case EndpointEncodingMode::kDirectRGBA:
-      return EncodeColorsRGBA(
-          endpoint_low_rgba, endpoint_high_rgba, max_value,
-          encoding_mode == EndpointEncodingMode::kDirectRGBA, astc_mode, vals);
-
-    default:
-      assert(false && "Unimplemented color encoding.");
-  }
-
-  return needs_weight_swap;
-}
-
-// These decoding procedures follow the code outlined in Section C.2.14 of
-// the ASTC specification.
-void DecodeColorsForMode(const std::vector<int>& vals,
-                         int max_value, ColorEndpointMode mode,
-                         RgbaColor* const endpoint_low_rgba,
-                         RgbaColor* const endpoint_high_rgba) {
-  assert(vals.size() >= size_t(NumColorValuesForEndpointMode(mode)));
-  switch (mode) {
-    case ColorEndpointMode::kLDRLumaDirect: {
-      const int l0 = UnquantizeCEValueFromRange(vals[0], max_value);
-      const int l1 = UnquantizeCEValueFromRange(vals[1], max_value);
-
-      *endpoint_low_rgba = {{ l0, l0, l0, 255 }};
-      *endpoint_high_rgba = {{ l1, l1, l1, 255 }};
-    }
-    break;
-
-    case ColorEndpointMode::kLDRLumaBaseOffset: {
-      const int v0 = UnquantizeCEValueFromRange(vals[0], max_value);
-      const int v1 = UnquantizeCEValueFromRange(vals[1], max_value);
-
-      const int l0 = (v0 >> 2) | (v1 & 0xC0);
-      const int l1 = std::min(l0 + (v1 & 0x3F), 0xFF);
-
-      *endpoint_low_rgba = {{ l0, l0, l0, 255 }};
-      *endpoint_high_rgba = {{ l1, l1, l1, 255 }};
-    }
-    break;
-
-    case ColorEndpointMode::kLDRLumaAlphaDirect: {
-      constexpr int kNumVals =
-          NumColorValuesForEndpointMode(ColorEndpointMode::kLDRLumaAlphaDirect);
-
-      std::array<int, kNumVals> v;
-      std::copy(vals.begin(), vals.end(), v.begin());
-      Unquantize(&v, max_value);
-
-      *endpoint_low_rgba = {{ v[0], v[0], v[0], v[2] }};
-      *endpoint_high_rgba = {{ v[1], v[1], v[1], v[3] }};
-    }
-    break;
-
-    case ColorEndpointMode::kLDRLumaAlphaBaseOffset: {
-      constexpr int kNumVals = NumColorValuesForEndpointMode(
-          ColorEndpointMode::kLDRLumaAlphaBaseOffset);
-
-      std::array<int, kNumVals> v;
-      std::copy(vals.begin(), vals.end(), v.begin());
-      Unquantize(&v, max_value);
-
-      BitTransferSigned(&v[1], &v[0]);
-      BitTransferSigned(&v[3], &v[2]);
-
-      *endpoint_low_rgba = {{ v[0], v[0], v[0], v[2] }};
-      const int high_luma = v[0] + v[1];
-      *endpoint_high_rgba = {{ high_luma, high_luma, high_luma, v[2] + v[3] }};
-
-      for (auto& c : *endpoint_low_rgba) { c = Clamp(c, 0, 255); }
-      for (auto& c : *endpoint_high_rgba) { c = Clamp(c, 0, 255); }
-    }
-    break;
-
-    case ColorEndpointMode::kLDRRGBBaseScale: {
-      constexpr int kNumVals =
-          NumColorValuesForEndpointMode(ColorEndpointMode::kLDRRGBBaseScale);
-
-      std::array<int, kNumVals> v;
-      std::copy(vals.begin(), vals.end(), v.begin());
-      Unquantize(&v, max_value);
-
-      *endpoint_high_rgba = {{ v[0], v[1], v[2], 255 }};
-      for (int i = 0; i < 3; ++i) {
-        const int x = endpoint_high_rgba->at(i);
-        endpoint_low_rgba->at(i) = (x * v[3]) >> 8;
-      }
-      endpoint_low_rgba->at(3) = 255;
-    }
-    break;
-
-    case ColorEndpointMode::kLDRRGBDirect: {
-      constexpr int kNumVals =
-          NumColorValuesForEndpointMode(ColorEndpointMode::kLDRRGBDirect);
-
-      std::array<int, kNumVals> v;
-      std::copy(vals.begin(), vals.end(), v.begin());
-      Unquantize(&v, max_value);
-
-      const int s0 = v[0] + v[2] + v[4];
-      const int s1 = v[1] + v[3] + v[5];
-
-      *endpoint_low_rgba = {{ v[0], v[2], v[4], 255 }};
-      *endpoint_high_rgba = {{ v[1], v[3], v[5], 255 }};
-
-      if (s1 < s0) {
-        std::swap(*endpoint_low_rgba, *endpoint_high_rgba);
-        BlueContract(endpoint_low_rgba);
-        BlueContract(endpoint_high_rgba);
-      }
-    }
-    break;
-
-    case ColorEndpointMode::kLDRRGBBaseOffset: {
-      constexpr int kNumVals =
-          NumColorValuesForEndpointMode(ColorEndpointMode::kLDRRGBBaseOffset);
-
-      std::array<int, kNumVals> v;
-      std::copy(vals.begin(), vals.end(), v.begin());
-      Unquantize(&v, max_value);
-
-      BitTransferSigned(&v[1], &v[0]);
-      BitTransferSigned(&v[3], &v[2]);
-      BitTransferSigned(&v[5], &v[4]);
-
-      *endpoint_low_rgba = {{ v[0], v[2], v[4], 255 }};
-      *endpoint_high_rgba = {{ v[0] + v[1], v[2] + v[3], v[4] + v[5], 255 }};
-
-      if (v[1] + v[3] + v[5] < 0) {
-        std::swap(*endpoint_low_rgba, *endpoint_high_rgba);
-        BlueContract(endpoint_low_rgba);
-        BlueContract(endpoint_high_rgba);
-      }
-
-      for (auto& c : *endpoint_low_rgba) { c = Clamp(c, 0, 255); }
-      for (auto& c : *endpoint_high_rgba) { c = Clamp(c, 0, 255); }
-    }
-    break;
-
-    case ColorEndpointMode::kLDRRGBBaseScaleTwoA: {
-      constexpr int kNumVals = NumColorValuesForEndpointMode(
-          ColorEndpointMode::kLDRRGBBaseScaleTwoA);
-
-      std::array<int, kNumVals> v;
-      std::copy(vals.begin(), vals.end(), v.begin());
-      Unquantize(&v, max_value);
-
-      // Base
-      *endpoint_low_rgba = *endpoint_high_rgba = {{ v[0], v[1], v[2], 255 }};
-
-      // Scale
-      for (int i = 0; i < 3; ++i) {
-        auto& x = endpoint_low_rgba->at(i);
-        x = (x * v[3]) >> 8;
-      }
-
-      // Two A
-      endpoint_low_rgba->at(3) = v[4];
-      endpoint_high_rgba->at(3) = v[5];
-    }
-    break;
-
-    case ColorEndpointMode::kLDRRGBADirect: {
-      constexpr int kNumVals =
-          NumColorValuesForEndpointMode(ColorEndpointMode::kLDRRGBADirect);
-
-      std::array<int, kNumVals> v;
-      std::copy(vals.begin(), vals.end(), v.begin());
-      Unquantize(&v, max_value);
-
-      const int s0 = v[0] + v[2] + v[4];
-      const int s1 = v[1] + v[3] + v[5];
-
-      *endpoint_low_rgba = {{ v[0], v[2], v[4], v[6] }};
-      *endpoint_high_rgba = {{ v[1], v[3], v[5], v[7] }};
-
-      if (s1 < s0) {
-        std::swap(*endpoint_low_rgba, *endpoint_high_rgba);
-        BlueContract(endpoint_low_rgba);
-        BlueContract(endpoint_high_rgba);
-      }
-    }
-    break;
-
-    case ColorEndpointMode::kLDRRGBABaseOffset: {
-      constexpr int kNumVals =
-          NumColorValuesForEndpointMode(ColorEndpointMode::kLDRRGBABaseOffset);
-
-      std::array<int, kNumVals> v;
-      std::copy(vals.begin(), vals.end(), v.begin());
-      Unquantize(&v, max_value);
-
-      BitTransferSigned(&v[1], &v[0]);
-      BitTransferSigned(&v[3], &v[2]);
-      BitTransferSigned(&v[5], &v[4]);
-      BitTransferSigned(&v[7], &v[6]);
-
-      *endpoint_low_rgba = {{ v[0], v[2], v[4], v[6] }};
-      *endpoint_high_rgba = {{
-          v[0] + v[1], v[2] + v[3], v[4] + v[5], v[6] + v[7] }};
-
-      if (v[1] + v[3] + v[5] < 0) {
-        std::swap(*endpoint_low_rgba, *endpoint_high_rgba);
-        BlueContract(endpoint_low_rgba);
-        BlueContract(endpoint_high_rgba);
-      }
-
-      for (auto& c : *endpoint_low_rgba) { c = Clamp(c, 0, 255); }
-      for (auto& c : *endpoint_high_rgba) { c = Clamp(c, 0, 255); }
-    }
-    break;
-
-    default:
-      // Unimplemented color encoding.
-      // TODO(google): Is this the correct error handling?
-      *endpoint_high_rgba = *endpoint_low_rgba = {{ 0, 0, 0, 0 }};
-  }
-}
-
-}  // namespace astc_codec

+ 0 - 90
3rdparty/astc-codec/src/decoder/endpoint_codec.h

@@ -1,90 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#ifndef ASTC_CODEC_DECODER_ENDPOINT_CODEC_H_
-#define ASTC_CODEC_DECODER_ENDPOINT_CODEC_H_
-
-#include "src/decoder/physical_astc_block.h"
-#include "src/decoder/types.h"
-
-#include <array>
-#include <vector>
-
-namespace astc_codec {
-
-// We use a special distinction for encode modes used to pass to the
-// EncodeColorsForMode function below. The reason is that some of the color
-// modes have sub-modes (like blue-contract) that change whether or not it is
-// useful to encode an endpoint pair using one mode versus another. To avoid
-// this problem, we approach the problem of encoding by specifying some
-// high-level encoding modes. These eventually choose one of the low level
-// ColorEndpointModes from Section C.2.14 when used in EncodeColorsForMode.
-enum class EndpointEncodingMode {
-  kDirectLuma,
-  kDirectLumaAlpha,
-  kBaseScaleRGB,
-  kBaseScaleRGBA,
-  kDirectRGB,
-  kDirectRGBA
-};
-
-// Returns the number of values in the encoded endpoint pair after encoding
-// to a specific high-level encoding mode.
-constexpr int NumValuesForEncodingMode(EndpointEncodingMode mode) {
-  return
-      mode == EndpointEncodingMode::kDirectLuma ? 2 :
-      mode == EndpointEncodingMode::kDirectLumaAlpha ? 4 :
-      mode == EndpointEncodingMode::kBaseScaleRGB ? 4 :
-      mode == EndpointEncodingMode::kBaseScaleRGBA ? 6 :
-      mode == EndpointEncodingMode::kDirectRGB ? 6 : 8;
-}
-
-// Fills |vals| with the quantized endpoint colors values defined in the ASTC
-// specification. The values are quantized to the range [0, max_value]. These
-// quantization limits can be obtained by querying the associated functions in
-// integer_sequence_codec. The returned |astc_mode| will be the ASTC mode used
-// to encode the resulting sequence.
-//
-// The |encoding_mode| is used to determine the way that we encode the values.
-// Each encoding mode is used to determine which ASTC mode best corresponds
-// to the pair of endpoints. It is a necessary hint to the encoding function
-// in order to process the endpoints. Each encoding mode gurantees a certain
-// number of values generated per endpoints.
-//
-// The return value will be true if the endpoints have been switched in order to
-// reap the most benefit from the way the hardware decodes the given mode. In
-// this case, the associated weights that interpolate this color must also be
-// switched. In other words, for each w, it should change to 64 - w.
-bool EncodeColorsForMode(
-    const RgbaColor& endpoint_low_rgba, const RgbaColor& endpoint_high_rgba,
-    int max_value, EndpointEncodingMode encoding_mode,
-    ColorEndpointMode* astc_mode, std::vector<int>* vals);
-
-// Decodes the color values quantized to the range [0, max_value] into RGBA
-// endpoints for the given mode. This function is the inverse of
-// EncodeColorsForMode -- see that function for details. This function should
-// work on all LDR endpoint modes, but no HDR modes.
-void DecodeColorsForMode(const std::vector<int>& vals,
-                         int max_value, ColorEndpointMode mode,
-                         RgbaColor* endpoint_low_rgba,
-                         RgbaColor* endpoint_high_rgba);
-
-// Returns true if the quantized |vals| in the range [0, max_value] use the
-// 'blue_contract' modification during decoding for the given |mode|.
-bool UsesBlueContract(int max_value, ColorEndpointMode mode,
-                      const std::vector<int>& vals);
-
-}  // namespace astc_codec
-
-#endif  // ASTC_CODEC_DECODER_ENDPOINT_CODEC_H_

+ 0 - 162
3rdparty/astc-codec/src/decoder/footprint.cc

@@ -1,162 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#include "src/decoder/footprint.h"
-#include "src/base/string_utils.h"
-
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-namespace astc_codec {
-
-namespace {
-
-// Encodes the width and height into an integer so that we can use a switch
-// statement instead of a costly lookup map.
-constexpr int EncodeDims(int width, int height) {
-  return (width << 16) | height;
-}
-
-}  // namespace
-
-base::Optional<FootprintType>
-Footprint::GetValidFootprintForDimensions(int width, int height) {
-  switch (EncodeDims(width, height)) {
-    case EncodeDims(4, 4): return FootprintType::k4x4;
-    case EncodeDims(5, 4): return FootprintType::k5x4;
-    case EncodeDims(5, 5): return FootprintType::k5x5;
-    case EncodeDims(6, 5): return FootprintType::k6x5;
-    case EncodeDims(6, 6): return FootprintType::k6x6;
-    case EncodeDims(8, 5): return FootprintType::k8x5;
-    case EncodeDims(8, 6): return FootprintType::k8x6;
-    case EncodeDims(8, 8): return FootprintType::k8x8;
-    case EncodeDims(10, 5): return FootprintType::k10x5;
-    case EncodeDims(10, 6): return FootprintType::k10x6;
-    case EncodeDims(10, 8): return FootprintType::k10x8;
-    case EncodeDims(10, 10): return FootprintType::k10x10;
-    case EncodeDims(12, 10): return FootprintType::k12x10;
-    case EncodeDims(12, 12): return FootprintType::k12x12;
-    default:                 return {};
-  }
-}
-
-int Footprint::GetWidthForFootprint(FootprintType footprint) {
-  switch (footprint) {
-    case FootprintType::k4x4: return 4;
-    case FootprintType::k5x4: return 5;
-    case FootprintType::k5x5: return 5;
-    case FootprintType::k6x5: return 6;
-    case FootprintType::k6x6: return 6;
-    case FootprintType::k8x5: return 8;
-    case FootprintType::k8x6: return 8;
-    case FootprintType::k10x5: return 10;
-    case FootprintType::k10x6: return 10;
-    case FootprintType::k8x8: return 8;
-    case FootprintType::k10x8: return 10;
-    case FootprintType::k10x10: return 10;
-    case FootprintType::k12x10: return 12;
-    case FootprintType::k12x12: return 12;
-    default:
-      assert(false);
-      return -1;
-  }
-}
-
-int Footprint::GetHeightForFootprint(FootprintType footprint) {
-  switch (footprint) {
-    case FootprintType::k4x4: return 4;
-    case FootprintType::k5x4: return 4;
-    case FootprintType::k5x5: return 5;
-    case FootprintType::k6x5: return 5;
-    case FootprintType::k6x6: return 6;
-    case FootprintType::k8x5: return 5;
-    case FootprintType::k8x6: return 6;
-    case FootprintType::k10x5: return 5;
-    case FootprintType::k10x6: return 6;
-    case FootprintType::k8x8: return 8;
-    case FootprintType::k10x8: return 8;
-    case FootprintType::k10x10: return 10;
-    case FootprintType::k12x10: return 10;
-    case FootprintType::k12x12: return 12;
-    default:
-      assert(false);
-      return -1;
-  }
-}
-
-Footprint::Footprint(FootprintType footprint)
-    : footprint_(footprint), width_(GetWidthForFootprint(footprint)),
-      height_(GetHeightForFootprint(footprint)) { }
-
-////////////////////////////////////////////////////////////////////////////////
-
-base::Optional<Footprint> Footprint::Parse(const char* footprint_string) {
-  assert(footprint_string && footprint_string[0] != '\0');
-
-  std::vector<std::string> dimension_strings;
-  base::Split(footprint_string, "x", [&dimension_strings](std::string&& s) {
-    dimension_strings.push_back(std::move(s));
-  });
-
-  if (dimension_strings.size() != 2) {
-    assert(false && "Invalid format for footprint");
-    return {};
-  }
-
-  const int width = base::ParseInt32(dimension_strings[0].c_str(), 0);
-  const int height = base::ParseInt32(dimension_strings[1].c_str(), 0);
-
-  assert(width > 0 && height > 0 && "Invalid width or height.");
-
-  return FromDimensions(width, height);
-}
-
-base::Optional<Footprint> Footprint::FromDimensions(int width, int height) {
-  base::Optional<FootprintType> valid_footprint =
-      GetValidFootprintForDimensions(width, height);
-  if (valid_footprint) {
-    return Footprint(valid_footprint.value());
-  } else {
-    return {};
-  }
-}
-
-// Returns a Footprint for the given FootprintType.
-base::Optional<Footprint> Footprint::FromFootprintType(FootprintType type) {
-  if (type >= FootprintType::k4x4 && type < FootprintType::kCount) {
-    return Footprint(type);
-  } else {
-    return {};
-  }
-}
-
-size_t Footprint::StorageRequirements(int width, int height) const {
-  const int blocks_wide = (width + width_ - 1) / width_;
-  const int blocks_high = (height + height_ - 1) / height_;
-
-  constexpr size_t kASTCBlockSizeInBytes = 16;
-  return blocks_wide * blocks_high * kASTCBlockSizeInBytes;
-}
-
-// Returns bits/pixel for a given footprint.
-float Footprint::Bitrate() const {
-  const int kASTCBlockBitCount = 128;
-  const int footprint_pixel_count = width_ * height_;
-  return static_cast<float>(kASTCBlockBitCount) /
-         static_cast<float>(footprint_pixel_count);
-}
-
-}  // namespace astc_codec

+ 0 - 106
3rdparty/astc-codec/src/decoder/footprint.h

@@ -1,106 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#ifndef ASTC_CODEC_DECODER_FOOTPRINT_H_
-#define ASTC_CODEC_DECODER_FOOTPRINT_H_
-
-#include "include/astc-codec/astc-codec.h"
-#include "src/base/optional.h"
-
-#include <cstddef>
-
-namespace astc_codec {
-
-// An ASTC texture can be encoded with varying choices in block size. A set of
-// predefined block sizes are specified in the ASTC specification. These are
-// referred to in the literature as "footprints" available to an encoder when
-// constructing an ASTC bitstream. This class provides various utility functions
-// for interacting with these footprints.
-class Footprint {
- public:
-  Footprint() = delete;
-  Footprint(const Footprint& footprint) = default;
-
-  // Return the footprint type.
-  FootprintType Type() const { return footprint_; }
-
-  // Return logical descriptions of the dimensions.
-  int Width() const { return width_; }
-  int Height() const { return height_; }
-
-  // Returns the number of pixels for a block with this footprint.
-  int NumPixels() const { return width_ * height_; }
-
-  // Returns the number of bytes needed to store an ASTC encoded image with the
-  // given width and height.
-  size_t StorageRequirements(int width, int height) const;
-
-  // Returns the number of bits used per pixel.
-  float Bitrate() const;
-
-  static constexpr int NumValidFootprints() {
-    return static_cast<int>(FootprintType::kCount);
-  }
-
-  bool operator==(const Footprint& other) const {
-    return footprint_ == other.footprint_;
-  }
-
-  // These are the valid and available ASTC footprints.
-  static Footprint Get4x4() { return Footprint(FootprintType::k4x4); }
-  static Footprint Get5x4() { return Footprint(FootprintType::k5x4); }
-  static Footprint Get5x5() { return Footprint(FootprintType::k5x5); }
-  static Footprint Get6x5() { return Footprint(FootprintType::k6x5); }
-  static Footprint Get6x6() { return Footprint(FootprintType::k6x6); }
-  static Footprint Get8x5() { return Footprint(FootprintType::k8x5); }
-  static Footprint Get8x6() { return Footprint(FootprintType::k8x6); }
-  static Footprint Get8x8() { return Footprint(FootprintType::k8x8); }
-  static Footprint Get10x5() { return Footprint(FootprintType::k10x5); }
-  static Footprint Get10x6() { return Footprint(FootprintType::k10x6); }
-  static Footprint Get10x8() { return Footprint(FootprintType::k10x8); }
-  static Footprint Get10x10() { return Footprint(FootprintType::k10x10); }
-  static Footprint Get12x10() { return Footprint(FootprintType::k12x10); }
-  static Footprint Get12x12() { return Footprint(FootprintType::k12x12); }
-
-  // Constructs a footprint from a string of the form "NxM", or no value if
-  // width and height are not a valid footprint.
-  static base::Optional<Footprint> Parse(const char* footprint_string);
-
-  // Returns a footprint corresponding to a block of the given width and height,
-  // or no value if it does not.
-  static base::Optional<Footprint> FromDimensions(int width, int height);
-
-  // Returns a Footprint for the given FootprintType.
-  static base::Optional<Footprint> FromFootprintType(FootprintType type);
-
- private:
-  // The only constructor.
-  explicit Footprint(FootprintType footprint);
-
-  // Returns the valid footprint for the width and height if possible.
-  static base::Optional<FootprintType> GetValidFootprintForDimensions(
-      int width, int height);
-
-  // Returns the associated dimension for the given valid footprint.
-  static int GetWidthForFootprint(FootprintType footprint);
-  static int GetHeightForFootprint(FootprintType footprint);
-
-  FootprintType footprint_;
-  int width_;
-  int height_;
-};
-
-}  // namespace astc_codec
-
-#endif  // ASTC_CODEC_DECODER_FOOTPRINT_H_

+ 0 - 574
3rdparty/astc-codec/src/decoder/integer_sequence_codec.cc

@@ -1,574 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#include "src/decoder/integer_sequence_codec.h"
-#include "src/base/math_utils.h"
-#include "src/base/utils.h"
-
-#include <algorithm>
-#include <iostream>
-
-namespace astc_codec {
-
-namespace {
-
-// Tables of trit and quint encodings generated by the implementation in
-// http://cs/aosp-master/external/skia/src/utils/SkTextureCompressor_ASTC.cpp
-//
-// These tables are used to decode the blocks of values encoded using the ASTC
-// integer sequence encoding. The theory is that five trits (values that can
-// take any number in the range [0, 2]) can take on a total of 3^5 = 243 total
-// values, which can be stored in eight bits. These eight bits are used to
-// decode the five trits based on the ASTC specification in Section C.2.12.
-// For simplicity, we have stored a look-up table here so that we don't need
-// to implement the decoding logic. Similarly, seven bits are used to decode
-// three quints (since 5^3 = 125 < 128).
-static const std::array<int, 5> kTritEncodings[256] = {
-  {{ 0, 0, 0, 0, 0 }}, {{ 1, 0, 0, 0, 0 }}, {{ 2, 0, 0, 0, 0 }},
-  {{ 0, 0, 2, 0, 0 }}, {{ 0, 1, 0, 0, 0 }}, {{ 1, 1, 0, 0, 0 }},
-  {{ 2, 1, 0, 0, 0 }}, {{ 1, 0, 2, 0, 0 }}, {{ 0, 2, 0, 0, 0 }},
-  {{ 1, 2, 0, 0, 0 }}, {{ 2, 2, 0, 0, 0 }}, {{ 2, 0, 2, 0, 0 }},
-  {{ 0, 2, 2, 0, 0 }}, {{ 1, 2, 2, 0, 0 }}, {{ 2, 2, 2, 0, 0 }},
-  {{ 2, 0, 2, 0, 0 }}, {{ 0, 0, 1, 0, 0 }}, {{ 1, 0, 1, 0, 0 }},
-  {{ 2, 0, 1, 0, 0 }}, {{ 0, 1, 2, 0, 0 }}, {{ 0, 1, 1, 0, 0 }},
-  {{ 1, 1, 1, 0, 0 }}, {{ 2, 1, 1, 0, 0 }}, {{ 1, 1, 2, 0, 0 }},
-  {{ 0, 2, 1, 0, 0 }}, {{ 1, 2, 1, 0, 0 }}, {{ 2, 2, 1, 0, 0 }},
-  {{ 2, 1, 2, 0, 0 }}, {{ 0, 0, 0, 2, 2 }}, {{ 1, 0, 0, 2, 2 }},
-  {{ 2, 0, 0, 2, 2 }}, {{ 0, 0, 2, 2, 2 }}, {{ 0, 0, 0, 1, 0 }},
-  {{ 1, 0, 0, 1, 0 }}, {{ 2, 0, 0, 1, 0 }}, {{ 0, 0, 2, 1, 0 }},
-  {{ 0, 1, 0, 1, 0 }}, {{ 1, 1, 0, 1, 0 }}, {{ 2, 1, 0, 1, 0 }},
-  {{ 1, 0, 2, 1, 0 }}, {{ 0, 2, 0, 1, 0 }}, {{ 1, 2, 0, 1, 0 }},
-  {{ 2, 2, 0, 1, 0 }}, {{ 2, 0, 2, 1, 0 }}, {{ 0, 2, 2, 1, 0 }},
-  {{ 1, 2, 2, 1, 0 }}, {{ 2, 2, 2, 1, 0 }}, {{ 2, 0, 2, 1, 0 }},
-  {{ 0, 0, 1, 1, 0 }}, {{ 1, 0, 1, 1, 0 }}, {{ 2, 0, 1, 1, 0 }},
-  {{ 0, 1, 2, 1, 0 }}, {{ 0, 1, 1, 1, 0 }}, {{ 1, 1, 1, 1, 0 }},
-  {{ 2, 1, 1, 1, 0 }}, {{ 1, 1, 2, 1, 0 }}, {{ 0, 2, 1, 1, 0 }},
-  {{ 1, 2, 1, 1, 0 }}, {{ 2, 2, 1, 1, 0 }}, {{ 2, 1, 2, 1, 0 }},
-  {{ 0, 1, 0, 2, 2 }}, {{ 1, 1, 0, 2, 2 }}, {{ 2, 1, 0, 2, 2 }},
-  {{ 1, 0, 2, 2, 2 }}, {{ 0, 0, 0, 2, 0 }}, {{ 1, 0, 0, 2, 0 }},
-  {{ 2, 0, 0, 2, 0 }}, {{ 0, 0, 2, 2, 0 }}, {{ 0, 1, 0, 2, 0 }},
-  {{ 1, 1, 0, 2, 0 }}, {{ 2, 1, 0, 2, 0 }}, {{ 1, 0, 2, 2, 0 }},
-  {{ 0, 2, 0, 2, 0 }}, {{ 1, 2, 0, 2, 0 }}, {{ 2, 2, 0, 2, 0 }},
-  {{ 2, 0, 2, 2, 0 }}, {{ 0, 2, 2, 2, 0 }}, {{ 1, 2, 2, 2, 0 }},
-  {{ 2, 2, 2, 2, 0 }}, {{ 2, 0, 2, 2, 0 }}, {{ 0, 0, 1, 2, 0 }},
-  {{ 1, 0, 1, 2, 0 }}, {{ 2, 0, 1, 2, 0 }}, {{ 0, 1, 2, 2, 0 }},
-  {{ 0, 1, 1, 2, 0 }}, {{ 1, 1, 1, 2, 0 }}, {{ 2, 1, 1, 2, 0 }},
-  {{ 1, 1, 2, 2, 0 }}, {{ 0, 2, 1, 2, 0 }}, {{ 1, 2, 1, 2, 0 }},
-  {{ 2, 2, 1, 2, 0 }}, {{ 2, 1, 2, 2, 0 }}, {{ 0, 2, 0, 2, 2 }},
-  {{ 1, 2, 0, 2, 2 }}, {{ 2, 2, 0, 2, 2 }}, {{ 2, 0, 2, 2, 2 }},
-  {{ 0, 0, 0, 0, 2 }}, {{ 1, 0, 0, 0, 2 }}, {{ 2, 0, 0, 0, 2 }},
-  {{ 0, 0, 2, 0, 2 }}, {{ 0, 1, 0, 0, 2 }}, {{ 1, 1, 0, 0, 2 }},
-  {{ 2, 1, 0, 0, 2 }}, {{ 1, 0, 2, 0, 2 }}, {{ 0, 2, 0, 0, 2 }},
-  {{ 1, 2, 0, 0, 2 }}, {{ 2, 2, 0, 0, 2 }}, {{ 2, 0, 2, 0, 2 }},
-  {{ 0, 2, 2, 0, 2 }}, {{ 1, 2, 2, 0, 2 }}, {{ 2, 2, 2, 0, 2 }},
-  {{ 2, 0, 2, 0, 2 }}, {{ 0, 0, 1, 0, 2 }}, {{ 1, 0, 1, 0, 2 }},
-  {{ 2, 0, 1, 0, 2 }}, {{ 0, 1, 2, 0, 2 }}, {{ 0, 1, 1, 0, 2 }},
-  {{ 1, 1, 1, 0, 2 }}, {{ 2, 1, 1, 0, 2 }}, {{ 1, 1, 2, 0, 2 }},
-  {{ 0, 2, 1, 0, 2 }}, {{ 1, 2, 1, 0, 2 }}, {{ 2, 2, 1, 0, 2 }},
-  {{ 2, 1, 2, 0, 2 }}, {{ 0, 2, 2, 2, 2 }}, {{ 1, 2, 2, 2, 2 }},
-  {{ 2, 2, 2, 2, 2 }}, {{ 2, 0, 2, 2, 2 }}, {{ 0, 0, 0, 0, 1 }},
-  {{ 1, 0, 0, 0, 1 }}, {{ 2, 0, 0, 0, 1 }}, {{ 0, 0, 2, 0, 1 }},
-  {{ 0, 1, 0, 0, 1 }}, {{ 1, 1, 0, 0, 1 }}, {{ 2, 1, 0, 0, 1 }},
-  {{ 1, 0, 2, 0, 1 }}, {{ 0, 2, 0, 0, 1 }}, {{ 1, 2, 0, 0, 1 }},
-  {{ 2, 2, 0, 0, 1 }}, {{ 2, 0, 2, 0, 1 }}, {{ 0, 2, 2, 0, 1 }},
-  {{ 1, 2, 2, 0, 1 }}, {{ 2, 2, 2, 0, 1 }}, {{ 2, 0, 2, 0, 1 }},
-  {{ 0, 0, 1, 0, 1 }}, {{ 1, 0, 1, 0, 1 }}, {{ 2, 0, 1, 0, 1 }},
-  {{ 0, 1, 2, 0, 1 }}, {{ 0, 1, 1, 0, 1 }}, {{ 1, 1, 1, 0, 1 }},
-  {{ 2, 1, 1, 0, 1 }}, {{ 1, 1, 2, 0, 1 }}, {{ 0, 2, 1, 0, 1 }},
-  {{ 1, 2, 1, 0, 1 }}, {{ 2, 2, 1, 0, 1 }}, {{ 2, 1, 2, 0, 1 }},
-  {{ 0, 0, 1, 2, 2 }}, {{ 1, 0, 1, 2, 2 }}, {{ 2, 0, 1, 2, 2 }},
-  {{ 0, 1, 2, 2, 2 }}, {{ 0, 0, 0, 1, 1 }}, {{ 1, 0, 0, 1, 1 }},
-  {{ 2, 0, 0, 1, 1 }}, {{ 0, 0, 2, 1, 1 }}, {{ 0, 1, 0, 1, 1 }},
-  {{ 1, 1, 0, 1, 1 }}, {{ 2, 1, 0, 1, 1 }}, {{ 1, 0, 2, 1, 1 }},
-  {{ 0, 2, 0, 1, 1 }}, {{ 1, 2, 0, 1, 1 }}, {{ 2, 2, 0, 1, 1 }},
-  {{ 2, 0, 2, 1, 1 }}, {{ 0, 2, 2, 1, 1 }}, {{ 1, 2, 2, 1, 1 }},
-  {{ 2, 2, 2, 1, 1 }}, {{ 2, 0, 2, 1, 1 }}, {{ 0, 0, 1, 1, 1 }},
-  {{ 1, 0, 1, 1, 1 }}, {{ 2, 0, 1, 1, 1 }}, {{ 0, 1, 2, 1, 1 }},
-  {{ 0, 1, 1, 1, 1 }}, {{ 1, 1, 1, 1, 1 }}, {{ 2, 1, 1, 1, 1 }},
-  {{ 1, 1, 2, 1, 1 }}, {{ 0, 2, 1, 1, 1 }}, {{ 1, 2, 1, 1, 1 }},
-  {{ 2, 2, 1, 1, 1 }}, {{ 2, 1, 2, 1, 1 }}, {{ 0, 1, 1, 2, 2 }},
-  {{ 1, 1, 1, 2, 2 }}, {{ 2, 1, 1, 2, 2 }}, {{ 1, 1, 2, 2, 2 }},
-  {{ 0, 0, 0, 2, 1 }}, {{ 1, 0, 0, 2, 1 }}, {{ 2, 0, 0, 2, 1 }},
-  {{ 0, 0, 2, 2, 1 }}, {{ 0, 1, 0, 2, 1 }}, {{ 1, 1, 0, 2, 1 }},
-  {{ 2, 1, 0, 2, 1 }}, {{ 1, 0, 2, 2, 1 }}, {{ 0, 2, 0, 2, 1 }},
-  {{ 1, 2, 0, 2, 1 }}, {{ 2, 2, 0, 2, 1 }}, {{ 2, 0, 2, 2, 1 }},
-  {{ 0, 2, 2, 2, 1 }}, {{ 1, 2, 2, 2, 1 }}, {{ 2, 2, 2, 2, 1 }},
-  {{ 2, 0, 2, 2, 1 }}, {{ 0, 0, 1, 2, 1 }}, {{ 1, 0, 1, 2, 1 }},
-  {{ 2, 0, 1, 2, 1 }}, {{ 0, 1, 2, 2, 1 }}, {{ 0, 1, 1, 2, 1 }},
-  {{ 1, 1, 1, 2, 1 }}, {{ 2, 1, 1, 2, 1 }}, {{ 1, 1, 2, 2, 1 }},
-  {{ 0, 2, 1, 2, 1 }}, {{ 1, 2, 1, 2, 1 }}, {{ 2, 2, 1, 2, 1 }},
-  {{ 2, 1, 2, 2, 1 }}, {{ 0, 2, 1, 2, 2 }}, {{ 1, 2, 1, 2, 2 }},
-  {{ 2, 2, 1, 2, 2 }}, {{ 2, 1, 2, 2, 2 }}, {{ 0, 0, 0, 1, 2 }},
-  {{ 1, 0, 0, 1, 2 }}, {{ 2, 0, 0, 1, 2 }}, {{ 0, 0, 2, 1, 2 }},
-  {{ 0, 1, 0, 1, 2 }}, {{ 1, 1, 0, 1, 2 }}, {{ 2, 1, 0, 1, 2 }},
-  {{ 1, 0, 2, 1, 2 }}, {{ 0, 2, 0, 1, 2 }}, {{ 1, 2, 0, 1, 2 }},
-  {{ 2, 2, 0, 1, 2 }}, {{ 2, 0, 2, 1, 2 }}, {{ 0, 2, 2, 1, 2 }},
-  {{ 1, 2, 2, 1, 2 }}, {{ 2, 2, 2, 1, 2 }}, {{ 2, 0, 2, 1, 2 }},
-  {{ 0, 0, 1, 1, 2 }}, {{ 1, 0, 1, 1, 2 }}, {{ 2, 0, 1, 1, 2 }},
-  {{ 0, 1, 2, 1, 2 }}, {{ 0, 1, 1, 1, 2 }}, {{ 1, 1, 1, 1, 2 }},
-  {{ 2, 1, 1, 1, 2 }}, {{ 1, 1, 2, 1, 2 }}, {{ 0, 2, 1, 1, 2 }},
-  {{ 1, 2, 1, 1, 2 }}, {{ 2, 2, 1, 1, 2 }}, {{ 2, 1, 2, 1, 2 }},
-  {{ 0, 2, 2, 2, 2 }}, {{ 1, 2, 2, 2, 2 }}, {{ 2, 2, 2, 2, 2 }},
-  {{ 2, 1, 2, 2, 2 }}
-};
-
-static const std::array<int, 3> kQuintEncodings[128] = {
-  {{ 0, 0, 0 }}, {{ 1, 0, 0 }}, {{ 2, 0, 0 }}, {{ 3, 0, 0 }}, {{ 4, 0, 0 }},
-  {{ 0, 4, 0 }}, {{ 4, 4, 0 }}, {{ 4, 4, 4 }}, {{ 0, 1, 0 }}, {{ 1, 1, 0 }},
-  {{ 2, 1, 0 }}, {{ 3, 1, 0 }}, {{ 4, 1, 0 }}, {{ 1, 4, 0 }}, {{ 4, 4, 1 }},
-  {{ 4, 4, 4 }}, {{ 0, 2, 0 }}, {{ 1, 2, 0 }}, {{ 2, 2, 0 }}, {{ 3, 2, 0 }},
-  {{ 4, 2, 0 }}, {{ 2, 4, 0 }}, {{ 4, 4, 2 }}, {{ 4, 4, 4 }}, {{ 0, 3, 0 }},
-  {{ 1, 3, 0 }}, {{ 2, 3, 0 }}, {{ 3, 3, 0 }}, {{ 4, 3, 0 }}, {{ 3, 4, 0 }},
-  {{ 4, 4, 3 }}, {{ 4, 4, 4 }}, {{ 0, 0, 1 }}, {{ 1, 0, 1 }}, {{ 2, 0, 1 }},
-  {{ 3, 0, 1 }}, {{ 4, 0, 1 }}, {{ 0, 4, 1 }}, {{ 4, 0, 4 }}, {{ 0, 4, 4 }},
-  {{ 0, 1, 1 }}, {{ 1, 1, 1 }}, {{ 2, 1, 1 }}, {{ 3, 1, 1 }}, {{ 4, 1, 1 }},
-  {{ 1, 4, 1 }}, {{ 4, 1, 4 }}, {{ 1, 4, 4 }}, {{ 0, 2, 1 }}, {{ 1, 2, 1 }},
-  {{ 2, 2, 1 }}, {{ 3, 2, 1 }}, {{ 4, 2, 1 }}, {{ 2, 4, 1 }}, {{ 4, 2, 4 }},
-  {{ 2, 4, 4 }}, {{ 0, 3, 1 }}, {{ 1, 3, 1 }}, {{ 2, 3, 1 }}, {{ 3, 3, 1 }},
-  {{ 4, 3, 1 }}, {{ 3, 4, 1 }}, {{ 4, 3, 4 }}, {{ 3, 4, 4 }}, {{ 0, 0, 2 }},
-  {{ 1, 0, 2 }}, {{ 2, 0, 2 }}, {{ 3, 0, 2 }}, {{ 4, 0, 2 }}, {{ 0, 4, 2 }},
-  {{ 2, 0, 4 }}, {{ 3, 0, 4 }}, {{ 0, 1, 2 }}, {{ 1, 1, 2 }}, {{ 2, 1, 2 }},
-  {{ 3, 1, 2 }}, {{ 4, 1, 2 }}, {{ 1, 4, 2 }}, {{ 2, 1, 4 }}, {{ 3, 1, 4 }},
-  {{ 0, 2, 2 }}, {{ 1, 2, 2 }}, {{ 2, 2, 2 }}, {{ 3, 2, 2 }}, {{ 4, 2, 2 }},
-  {{ 2, 4, 2 }}, {{ 2, 2, 4 }}, {{ 3, 2, 4 }}, {{ 0, 3, 2 }}, {{ 1, 3, 2 }},
-  {{ 2, 3, 2 }}, {{ 3, 3, 2 }}, {{ 4, 3, 2 }}, {{ 3, 4, 2 }}, {{ 2, 3, 4 }},
-  {{ 3, 3, 4 }}, {{ 0, 0, 3 }}, {{ 1, 0, 3 }}, {{ 2, 0, 3 }}, {{ 3, 0, 3 }},
-  {{ 4, 0, 3 }}, {{ 0, 4, 3 }}, {{ 0, 0, 4 }}, {{ 1, 0, 4 }}, {{ 0, 1, 3 }},
-  {{ 1, 1, 3 }}, {{ 2, 1, 3 }}, {{ 3, 1, 3 }}, {{ 4, 1, 3 }}, {{ 1, 4, 3 }},
-  {{ 0, 1, 4 }}, {{ 1, 1, 4 }}, {{ 0, 2, 3 }}, {{ 1, 2, 3 }}, {{ 2, 2, 3 }},
-  {{ 3, 2, 3 }}, {{ 4, 2, 3 }}, {{ 2, 4, 3 }}, {{ 0, 2, 4 }}, {{ 1, 2, 4 }},
-  {{ 0, 3, 3 }}, {{ 1, 3, 3 }}, {{ 2, 3, 3 }}, {{ 3, 3, 3 }}, {{ 4, 3, 3 }},
-  {{ 3, 4, 3 }}, {{ 0, 3, 4 }}, {{ 1, 3, 4 }}
-};
-
-// A cached table containing the max ranges for values encoded using ASTC's
-// Bounded Integer Sequence Encoding. These are the numbers between 1 and 255
-// that can be represented exactly as a number in the ranges
-// [0, 2^k), [0, 3 * 2^k), and [0, 5 * 2^k).
-static const std::array<int, kNumPossibleRanges> kMaxRanges = []() {
-  std::array<int, kNumPossibleRanges> ranges;
-
-  // Initialize the table that we need for determining value encodings.
-  auto next_max_range = ranges.begin();
-  auto add_val = [&next_max_range](int val) {
-    if (val <= 0 || (1 << kLog2MaxRangeForBits) <= val) {
-      return;
-    }
-
-    *(next_max_range++) = val;
-  };
-
-  for (int i = 0; i <= kLog2MaxRangeForBits; ++i) {
-    add_val(3 * (1 << i) - 1);
-    add_val(5 * (1 << i) - 1);
-    add_val((1 << i) - 1);
-  }
-
-  assert(std::distance(next_max_range, ranges.end()) == 0);
-  std::sort(ranges.begin(), ranges.end());
-  return ranges;
-}();
-
-// Returns true if x == 0 or if x is a power of two. This function is only used
-// in the GetCountsForRange function, where we need to have it return true
-// on zero since we can have single trit/quint ISE encodings according to
-// Table C.2.7.
-template<typename T,
-         typename std::enable_if<std::is_integral<T>::value, T>::type = 0>
-inline constexpr bool IsPow2(T x) { return (x & (x - 1)) == 0; }
-
-// For the ISE block encoding, these arrays determine how many bits are
-// used after each value to store the interleaved quint/trit block.
-const int kInterleavedQuintBits[3] = { 3, 2, 2 };
-const int kInterleavedTritBits[5] = { 2, 2, 1, 2, 1 };
-
-// Some template meta programming to get around the fact that MSVC
-// will not allow  (ValRange == 5) ? 3 : 5 as a template parameter
-template<int ValRange>
-struct DecodeBlockSize {
-  enum { value =  (ValRange == 5 ? 3 : 5) };
-};
-
-// Decodes either a trit or quint block using the BISE (Bounded Integer Sequence
-// Encoding) defined in Section C.2.12 of the ASTC specification. ValRange is
-// expected to be either 3 or 5 depending on whether or not we're encoding trits
-// or quints respectively. In other words, it is the remaining factor in whether
-// the passed blocks contain encoded values of the form 3*2^k or 5*2^k.
-template<int ValRange>
-std::array<int, /* kNumVals = */ DecodeBlockSize<ValRange>::value> DecodeISEBlock(
-    uint64_t block_bits, int num_bits) {
-  static_assert(ValRange == 3 || ValRange == 5,
-                "We only know about trits and quints");
-
-  // We either have three quints or five trits
-  constexpr const int kNumVals = (ValRange == 5) ? 3 : 5;
-
-  // Depending on whether or not we're using quints or trits will determine
-  // the positions of the interleaved bits in the encoded block.
-  constexpr const int* const kInterleavedBits =
-      (ValRange == 5) ? kInterleavedQuintBits : kInterleavedTritBits;
-
-  // Set up the bits for reading
-  base::BitStream<base::UInt128> block_bit_src(block_bits, sizeof(block_bits) * 8);
-
-  // Decode the block
-  std::array<int, kNumVals> m;
-  uint64_t encoded = 0;
-  uint32_t encoded_bits_read = 0;
-  for (int i = 0; i < kNumVals; ++i) {
-    {
-      uint64_t bits = 0;
-      const bool result = block_bit_src.GetBits(num_bits, &bits);
-      assert(result);
-      (void)result;
-
-      m[i] = static_cast<int>(bits);
-    }
-
-    uint64_t encoded_bits;
-    {
-      const bool result = block_bit_src.GetBits(kInterleavedBits[i], &encoded_bits);
-      assert(result);
-      (void)result;
-    }
-    encoded |= encoded_bits << encoded_bits_read;
-    encoded_bits_read += kInterleavedBits[i];
-  }
-
-  // Make sure that our encoded trit/quint doesn't exceed its bounds
-  assert(ValRange != 3 || encoded < 256);
-  assert(ValRange != 5 || encoded < 128);
-
-  const int* const kEncodings = (ValRange == 5) ?
-      kQuintEncodings[encoded].data() : kTritEncodings[encoded].data();
-
-  std::array<int, kNumVals> result;
-  for (int i = 0; i < kNumVals; ++i) {
-    assert(m[i] < 1 << num_bits);
-    result[i] = kEncodings[i] << num_bits | m[i];
-  }
-  return result;
-}
-
-// Encode a single trit or quint block using the BISE (Bounded Integer Sequence
-// Encoding) defined in Section C.2.12 of the ASTC specification. ValRange is
-// expected to be either 3 or 5 depending on whether or not we're encoding trits
-// or quints respectively. In other words, it is the remaining factor in whether
-// the passed blocks contain encoded values of the form 3*2^k or 5*2^k.
-template <int ValRange>
-void EncodeISEBlock(const std::vector<int>& vals, int bits_per_val,
-                    base::BitStream<base::UInt128>* bit_sink) {
-  static_assert(ValRange == 3 || ValRange == 5,
-                "We only know about trits and quints");
-
-  // We either have three quints or five trits
-  constexpr const int kNumVals = (ValRange == 5) ? 3 : 5;
-
-  // Three quints in seven bits or five trits in eight bits
-  constexpr const int kNumEncodedBitsPerBlock = (ValRange == 5) ? 7 : 8;
-
-  // Depending on whether or not we're using quints or trits will determine
-  // the positions of the interleaved bits in the encoding
-  constexpr const int* const kInterleavedBits =
-      (ValRange == 5) ? kInterleavedQuintBits : kInterleavedTritBits;
-
-  // ISE blocks can only have up to a specific number of values...
-  assert(vals.size() <= kNumVals);
-
-  // Split up into bits and non bits. Non bits are used to find the quint/trit
-  // encoding that we need.
-  std::array<int, kNumVals> non_bits = {{ 0 }};
-  std::array<int, kNumVals> bits = {{ 0 }};
-  for (size_t i = 0; i < vals.size(); ++i) {
-    bits[i] = vals[i] & ((1 << bits_per_val) - 1);
-    non_bits[i] = vals[i] >> bits_per_val;
-    assert(non_bits[i] < ValRange);
-  }
-
-  // We only need to add as many bits as necessary, so let's limit it based
-  // on the computation described in Section C.2.22 of the ASTC specification
-  const int total_num_bits =
-      int(((vals.size() * kNumEncodedBitsPerBlock + kNumVals - 1) / kNumVals)
-      + vals.size() * bits_per_val);
-  int bits_added = 0;
-
-  // The number of bits used for the quint/trit encoding is necessary to know
-  // in order to properly select the encoding we need to represent.
-  int num_encoded_bits = 0;
-  for (int i = 0; i < kNumVals; ++i) {
-    bits_added += bits_per_val;
-    if (bits_added >= total_num_bits) {
-      break;
-    }
-
-    num_encoded_bits += kInterleavedBits[i];
-    bits_added += kInterleavedBits[i];
-    if (bits_added >= total_num_bits) {
-      break;
-    }
-  }
-  bits_added = 0;
-  assert(num_encoded_bits <= kNumEncodedBitsPerBlock);
-
-  // TODO(google): The faster way to do this would be to construct trees out
-  // of the quint/trit encoding patterns, or just invert the decoding logic.
-  // Here we go from the end backwards because it makes our tests are more
-  // deterministic.
-  int non_bit_encoding = -1;
-  for (int j = (1 << num_encoded_bits) - 1; j >= 0; --j) {
-    bool matches = true;
-
-    // We don't need to match all trits here, just the ones that correspond
-    // to the values that we passed in
-    for (size_t i = 0; i < kNumVals; ++i) {
-      if ((ValRange == 5 && kQuintEncodings[j][i] != non_bits[i]) ||
-          (ValRange == 3 && kTritEncodings[j][i] != non_bits[i])) {
-        matches = false;
-        break;
-      }
-    }
-
-    if (matches) {
-      non_bit_encoding = j;
-      break;
-    }
-  }
-
-  assert(non_bit_encoding >= 0);
-
-  // Now pack the bits into the block
-  for (size_t i = 0; i < vals.size(); ++i) {
-    // First add the base bits for this value
-    if (bits_added + bits_per_val <= total_num_bits) {
-      bit_sink->PutBits(bits[i], bits_per_val);
-      bits_added += bits_per_val;
-    }
-
-    // Now add the interleaved bits from the quint/trit
-    int num_int_bits = kInterleavedBits[i];
-    int int_bits = non_bit_encoding & ((1 << num_int_bits) - 1);
-    if (bits_added + num_int_bits <= total_num_bits) {
-      bit_sink->PutBits(int_bits, num_int_bits);
-      bits_added += num_int_bits;
-      non_bit_encoding >>= num_int_bits;
-    }
-  }
-}
-
-inline void CHECK_COUNTS(int trits, int quints) {
-  assert(trits == 0 || quints == 0);   // Either trits or quints
-  assert(trits == 0 || trits == 1);    // At most one trit
-  assert(quints == 0 || quints == 1);  // At most one quint
-  (void)trits; (void)quints;
-}
-
-}  // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-
-std::array<int, kNumPossibleRanges>::const_iterator ISERangeBegin() {
-  return kMaxRanges.cbegin();
-}
-
-std::array<int, kNumPossibleRanges>::const_iterator ISERangeEnd() {
-  return kMaxRanges.cend();
-}
-
-void IntegerSequenceCodec::GetCountsForRange(
-    int range, int* const trits, int* const quints, int* const bits) {
-  // Make sure the passed pointers are valid
-  assert(trits != nullptr);
-  assert(quints != nullptr);
-  assert(bits != nullptr);
-
-  // These are generally errors -- there should never be any ASTC values
-  // outside of this range
-  UTILS_RELEASE_ASSERT(range > 0);
-  UTILS_RELEASE_ASSERT(range < 1 << kLog2MaxRangeForBits);
-
-  *bits = 0;
-  *trits = 0;
-  *quints = 0;
-
-  // Search through the numbers of the form 2^n, 3 * 2^n and 5 * 2^n
-  const int max_vals_for_range =
-      *std::lower_bound(kMaxRanges.begin(), kMaxRanges.end(), range) + 1;
-
-  // Make sure we found something
-  assert(max_vals_for_range > 1);
-
-  // Find out what kind of range it is
-  if ((max_vals_for_range % 3 == 0) && IsPow2(max_vals_for_range / 3)) {
-    *bits = base::Log2Floor(max_vals_for_range / 3);
-    *trits = 1;
-    *quints = 0;
-  } else if ((max_vals_for_range % 5 == 0) && IsPow2(max_vals_for_range / 5)) {
-    *bits = base::Log2Floor(max_vals_for_range / 5);
-    *trits = 0;
-    *quints = 1;
-  } else if (IsPow2(max_vals_for_range)) {
-    *bits = base::Log2Floor(max_vals_for_range);
-    *trits = 0;
-    *quints = 0;
-  }
-
-  // If we set any of these values then we're done.
-  if ((*bits | *trits | *quints) != 0) {
-    CHECK_COUNTS(*trits, *quints);
-  }
-}
-
-// Returns the overall bit count for a range of val_count values encoded
-// using the specified number of trits, quints and straight bits (respectively)
-int IntegerSequenceCodec::GetBitCount(int num_vals,
-                                      int trits, int quints, int bits) {
-  CHECK_COUNTS(trits, quints);
-
-  // See section C.2.22 for the formula used here.
-  const int trit_bit_count = ((num_vals * 8 * trits) + 4) / 5;
-  const int quint_bit_count = ((num_vals * 7 * quints) + 2) / 3;
-  const int base_bit_count = num_vals * bits;
-  return trit_bit_count + quint_bit_count + base_bit_count;
-}
-
-IntegerSequenceCodec::IntegerSequenceCodec(int range) {
-  int trits, quints, bits;
-  GetCountsForRange(range, &trits, &quints, &bits);
-  InitializeWithCounts(trits, quints, bits);
-}
-
-IntegerSequenceCodec::IntegerSequenceCodec(
-    int trits, int quints, int bits) {
-  InitializeWithCounts(trits, quints, bits);
-}
-
-void IntegerSequenceCodec::InitializeWithCounts(
-    int trits, int quints, int bits) {
-  CHECK_COUNTS(trits, quints);
-
-  if (trits > 0) {
-    encoding_ = EncodingMode::kTritEncoding;
-  } else if (quints > 0) {
-    encoding_ = EncodingMode::kQuintEncoding;
-  } else {
-    encoding_ = EncodingMode::kBitEncoding;
-  }
-
-  bits_ = bits;
-}
-
-int IntegerSequenceCodec::NumValsPerBlock() const {
-  const std::array<int, 3> kNumValsByEncoding = {{ 5, 3, 1 }};
-  return kNumValsByEncoding[static_cast<int>(encoding_)];
-}
-
-int IntegerSequenceCodec::EncodedBlockSize() const {
-  const std::array<int, 3> kExtraBlockSizeByEncoding = {{ 8, 7, 0 }};
-  const int num_vals = NumValsPerBlock();
-  return kExtraBlockSizeByEncoding[static_cast<int>(encoding_)]
-      + num_vals * bits_;
-}
-
-std::vector<int> IntegerSequenceDecoder::Decode(
-    int num_vals, base::BitStream<base::UInt128> *bit_src) const {
-  int trits = (encoding_ == kTritEncoding)? 1 : 0;
-  int quints = (encoding_ == kQuintEncoding)? 1 : 0;
-  const int total_num_bits = GetBitCount(num_vals, trits, quints, bits_);
-  const int bits_per_block = EncodedBlockSize();
-  assert(bits_per_block < 64);
-
-  int bits_left = total_num_bits;
-  std::vector<int> result;
-  while (bits_left > 0) {
-    uint64_t block_bits;
-    {
-      const bool result0 = bit_src->GetBits(std::min(bits_left, bits_per_block), &block_bits);
-      assert(result0);
-      (void)result0;
-    }
-
-    switch (encoding_) {
-      case kTritEncoding: {
-        auto trit_vals = DecodeISEBlock<3>(block_bits, bits_);
-        result.insert(result.end(), trit_vals.begin(), trit_vals.end());
-      }
-      break;
-
-      case kQuintEncoding: {
-        auto quint_vals = DecodeISEBlock<5>(block_bits, bits_);
-        result.insert(result.end(), quint_vals.begin(), quint_vals.end());
-      }
-      break;
-
-      case kBitEncoding:
-        result.push_back(static_cast<int>(block_bits));
-        break;
-    }
-
-    bits_left -= bits_per_block;
-  }
-
-  // Resize result to only contain as many values as requested
-  assert(result.size() >= static_cast<size_t>(num_vals));
-  result.resize(num_vals);
-
-  // Encoded all the values
-  return result;
-}
-
-void IntegerSequenceEncoder::Encode(base::BitStream<base::UInt128>* bit_sink) const {
-  // Go through all of the values and chop them up into blocks. The properties
-  // of the trit and quint encodings mean that if we need to encode fewer values
-  // in a block than the number of values encoded in the block then we need to
-  // consider the last few values to be zero.
-
-  auto next_val = vals_.begin();
-  while (next_val != vals_.end()) {
-    switch (encoding_) {
-      case kTritEncoding: {
-        std::vector<int> trit_vals;
-        for (int i = 0; i < 5; ++i) {
-          if (next_val != vals_.end()) {
-            trit_vals.push_back(*next_val);
-            ++next_val;
-          }
-        }
-
-        EncodeISEBlock<3>(trit_vals, bits_, bit_sink);
-      }
-      break;
-
-      case kQuintEncoding: {
-        std::vector<int> quint_vals;
-        for (int i = 0; i < 3; ++i) {
-          if (next_val != vals_.end()) {
-            quint_vals.push_back(*next_val);
-            ++next_val;
-          }
-        }
-
-        EncodeISEBlock<5>(quint_vals, bits_, bit_sink);
-      }
-      break;
-
-      case kBitEncoding: {
-        bit_sink->PutBits(*next_val, EncodedBlockSize());
-        ++next_val;
-      }
-      break;
-    }
-  }
-}
-
-}  // namespace astc_codec

+ 0 - 169
3rdparty/astc-codec/src/decoder/integer_sequence_codec.h

@@ -1,169 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#ifndef ASTC_CODEC_DECODER_INTEGER_SEQUENCE_CODEC_H_
-#define ASTC_CODEC_DECODER_INTEGER_SEQUENCE_CODEC_H_
-
-#include "src/base/bit_stream.h"
-#include "src/base/uint128.h"
-
-#include <array>
-#include <string>
-#include <vector>
-
-namespace astc_codec {
-
-// The maximum number of bits that we would need to encode an ISE value. The
-// ASTC specification does not give a maximum number, however unquantized color
-// values have a maximum range of 255, meaning that we can't feasibly have more
-// than eight bits per value.
-constexpr int kLog2MaxRangeForBits = 8;
-
-// Ranges can take any of the the forms 2^k, 3*2^k, or 5*2^k for k up to
-// kLog2MaxRangeForBits. Hence we have three types of ranges. Since the
-// maximum encoded value is 255, k won't go larger than 8. We don't have quints
-// that accompany [6, 8]-bits, as (5 * 2^6 = 320 > 255) and we don't have trits
-// that accompany [7, 8]-bits, as (3 * 2^7 = 384 > 255). But we do have trits
-// and quints that accompany no bits. Hence we have a total of
-// 3 * kLog2MaxRangeForBits - 3 - 2 + 2 total ranges.
-constexpr int kNumPossibleRanges = 3 * kLog2MaxRangeForBits - 3;
-
-// Returns an iterator through the available ASTC ranges.
-std::array<int, kNumPossibleRanges>::const_iterator ISERangeBegin();
-std::array<int, kNumPossibleRanges>::const_iterator ISERangeEnd();
-
-// Base class for ASTC integer sequence encoders and decoders. These codecs
-// operate on sequences of integers and produce bit patterns that pack the
-// integers based on the encoding scheme specified in the ASTC specification
-// Section C.2.12. The resulting bit pattern is a sequence of encoded blocks.
-// All blocks in a sequence are one of the following encodings:
-//
-//   (1 -- bit encoding) one encoded value of the form 2^k
-//   (2 -- trit encoding) five encoded values of the form 3*2^k
-//   (3 -- quint encoding) three encoded values of the form 5*2^k
-//
-// The layouts of each block are designed such that the blocks can be truncated
-// during encoding in order to support variable length input sequences (i.e. a
-// sequence of values that are encoded using trit encoded blocks does not
-// need to have a multiple-of-five length).
-class IntegerSequenceCodec {
- public:
-  // Returns the number of trits, quints, and bits needed to encode values in
-  // [0, range]. This is used to determine the layout of ISE encoded bit
-  // streams. The returned array holds the number of trits, quints, and bits
-  // respectively. range is expected to be within the interval [1, 5242879]
-  static void GetCountsForRange(int range, int* trits, int* quints, int* bits);
-
-  // Returns the number of bits needed to encode the given number of values with
-  // respect to the number of trits, quints, and bits specified in ise_counts
-  // (in that order). It is expected that either trits or quints can be
-  // nonzero, but not both, and neither can be larger than one. Anything else is
-  // undefined.
-  static int GetBitCount(int num_vals, int trits, int quints, int bits);
-
-  // Convenience function that returns the number of bits needed to encoded
-  // num_vals within the range [0, range] (inclusive).
-  static inline int GetBitCountForRange(int num_vals, int range) {
-    int trits, quints, bits;
-    GetCountsForRange(range, &trits, &quints, &bits);
-    return GetBitCount(num_vals, trits, quints, bits);
-  }
-
- protected:
-  explicit IntegerSequenceCodec(int range);
-  IntegerSequenceCodec(int trits, int quints, int bits);
-
-  // The encoding mode -- since having trits and quints are mutually exclusive,
-  // we can store the encoding we decide on in this enum.
-  enum EncodingMode {
-    kTritEncoding = 0,
-    kQuintEncoding,
-    kBitEncoding,
-  };
-
-  EncodingMode encoding_;
-  int bits_;
-
-  // Returns the number of values stored in a single ISE block. Since quints and
-  // trits are packed three/five to a bit pattern (respectively), each sequence
-  // is chunked into blocks in order to encode it. For only bit-encodings, the
-  // block size is one.
-  int NumValsPerBlock() const;
-
-  // Returns the size of a single ISE block in bits (see NumValsPerBlock).
-  int EncodedBlockSize() const;
-
- private:
-  // Determines the encoding mode.
-  void InitializeWithCounts(int trits, int quints, int bits);
-};
-
-// The integer sequence decoder. The decoder only remembers the given encoding
-// but each invocation of Decode operates independently on the input bits.
-class IntegerSequenceDecoder : public IntegerSequenceCodec {
- public:
-  // Creates a decoder that decodes values within [0, range] (inclusive).
-  explicit IntegerSequenceDecoder(int range)
-      : IntegerSequenceCodec(range) { }
-
-  // Creates a decoder based on the number of trits, quints, and bits expected
-  // in the bit stream passed to Decode.
-  IntegerSequenceDecoder(int trits, int quints, int bits)
-      : IntegerSequenceCodec(trits, quints, bits) { }
-
-  // Decodes num_vals from the bit_src. The number of bits read is dependent
-  // on the number of bits required to encode num_vals based on the calculation
-  // provided in Section C.2.22 of the ASTC specification. The return value
-  // always contains exactly num_vals.
-  std::vector<int> Decode(int num_vals,
-                          base::BitStream<base::UInt128>* bit_src) const;
-};
-
-// The integer sequence encoder. The encoder accepts values one by one and
-// places them into a temporary array that it holds. When needed the user
-// may call Encode to produce an encoded bit stream of the associated values.
-class IntegerSequenceEncoder : public IntegerSequenceCodec {
- public:
-  // Creates an encoder that encodes values within [0, range] (inclusive).
-  explicit IntegerSequenceEncoder(int range)
-      : IntegerSequenceCodec(range) { }
-
-  // Creates an encoder based on the number of trits, quints, and bits for
-  // the bit stream produced by Encode.
-  IntegerSequenceEncoder(int trits, int quints, int bits)
-      : IntegerSequenceCodec(trits, quints, bits) { }
-
-  // Adds a value to the encoding sequence.
-  void AddValue(int val) {
-    // Make sure it's within bounds
-    assert(encoding_ != EncodingMode::kTritEncoding || val < 3 * (1 << bits_));
-    assert(encoding_ != EncodingMode::kQuintEncoding || val < 5 * (1 << bits_));
-    assert(encoding_ != EncodingMode::kBitEncoding || val < (1 << bits_));
-    vals_.push_back(val);
-  }
-
-  // Writes the encoding for vals_ to the bit_sink. Multiple calls to Encode
-  // will produce the same result.
-  void Encode(base::BitStream<base::UInt128>* bit_sink) const;
-
-  // Removes all of the previously added values to the encoder.
-  void Reset() { vals_.clear(); }
-
- private:
-  std::vector<int> vals_;
-};
-
-}  // namespace astc_codec
-
-#endif  // ASTC_CODEC_DECODER_INTEGER_SEQUENCE_CODEC_H_

+ 0 - 591
3rdparty/astc-codec/src/decoder/intermediate_astc_block.cc

@@ -1,591 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#include "src/decoder/intermediate_astc_block.h"
-#include "src/decoder/integer_sequence_codec.h"
-#include "src/base/bit_stream.h"
-#include "src/base/math_utils.h"
-#include "src/base/optional.h"
-#include "src/base/uint128.h"
-
-#include <algorithm>
-#include <numeric>
-#include <sstream>
-
-namespace astc_codec {
-
-namespace {
-
-constexpr int kEndpointRange_ReturnInvalidWeightDims = -1;
-constexpr int kEndpointRange_ReturnNotEnoughColorBits = -2;
-
-base::UInt128 PackVoidExtentBlock(uint16_t r, uint16_t g, uint16_t b,
-                                  uint16_t a, std::array<uint16_t, 4> coords) {
-  base::BitStream<base::UInt128> bit_sink;
-
-  // Put void extent mode...
-  bit_sink.PutBits(0xDFC, 12);
-
-  // Each of the coordinates goes in 13 bits at a time.
-  for (auto coord : coords) {
-    assert(coord < 1 << 13);
-    bit_sink.PutBits(coord, 13);
-  }
-  assert(bit_sink.Bits() == 64);
-
-  // Then we add R, G, B, and A in order
-  bit_sink.PutBits(r, 16);
-  bit_sink.PutBits(g, 16);
-  bit_sink.PutBits(b, 16);
-  bit_sink.PutBits(a, 16);
-
-  assert(bit_sink.Bits() == 128);
-
-  base::UInt128 result;
-  bit_sink.GetBits(128, &result);
-  return result;
-}
-
-base::Optional<std::string> GetEncodedWeightRange(int range,
-                                                  std::array<int, 3>* const r) {
-  const std::array<std::array<int, 3>, 12> kValidRangeEncodings =
-      {{ {{ 0, 1, 0 }}, {{ 1, 1, 0 }}, {{ 0, 0, 1 }},
-         {{ 1, 0, 1 }}, {{ 0, 1, 1 }}, {{ 1, 1, 1 }},
-         {{ 0, 1, 0 }}, {{ 1, 1, 0 }}, {{ 0, 0, 1 }},
-         {{ 1, 0, 1 }}, {{ 0, 1, 1 }}, {{ 1, 1, 1 }} }};
-
-  // If our range is larger than all available ranges, this is an error.
-  const int smallest_range = kValidWeightRanges.front();
-  const int largest_range = kValidWeightRanges.back();
-  if (range < smallest_range || largest_range < range) {
-    std::stringstream strm;
-    strm << "Could not find block mode. Invalid weight range: "
-         << range << " not in [" << smallest_range << ", "
-         << largest_range << std::endl;
-    return strm.str();
-  }
-
-  // Find the upper bound on the range, otherwise.
-  const auto range_iter = std::lower_bound(
-      kValidWeightRanges.cbegin(), kValidWeightRanges.cend(), range);
-  auto enc_iter = kValidRangeEncodings.cbegin();
-  enc_iter += std::distance(kValidWeightRanges.cbegin(), range_iter);
-  *r = *enc_iter;
-  return {};
-}
-
-struct BlockModeInfo {
-  int min_weight_grid_dim_x;
-  int max_weight_grid_dim_x;
-  int min_weight_grid_dim_y;
-  int max_weight_grid_dim_y;
-  int r0_bit_pos;
-  int r1_bit_pos;
-  int r2_bit_pos;
-  int weight_grid_x_offset_bit_pos;
-  int weight_grid_y_offset_bit_pos;
-  bool require_single_plane_low_prec;
-};
-
-constexpr int kNumBlockModes = 10;
-const std::array<BlockModeInfo, kNumBlockModes> kBlockModeInfo {{
-  { 4, 7, 2, 5, 4, 0, 1, 7, 5, false },      // B+4 A+2
-  { 8, 11, 2, 5, 4, 0, 1, 7, 5, false },     // B+8 A+2
-  { 2, 5, 8, 11, 4, 0, 1, 5, 7, false },     // A+2 B+8
-  { 2, 5, 6, 7, 4, 0, 1, 5, 7, false },      // A+2 B+6
-  { 2, 3, 2, 5, 4, 0, 1, 7, 5, false },      // B+2 A+2
-  { 12, 12, 2, 5, 4, 2, 3, -1, 5, false },   // 12  A+2
-  { 2, 5, 12, 12, 4, 2, 3, 5, -1, false },   // A+2 12
-  { 6, 6, 10, 10, 4, 2, 3, -1, -1, false },  // 6   10
-  { 10, 10, 6, 6, 4, 2, 3, -1, -1, false },  // 10  6
-  { 6, 9, 6, 9, 4, 2, 3, 5, 9, true }        // A+6 B+6
-}};
-
-// These are the bits that must be set for ASTC to recognize a given
-// block mode. They are the 1's set in table C.2.8 of the spec.
-const std::array<int, kNumBlockModes> kBlockModeMask = {{
-  0x0, 0x4, 0x8, 0xC, 0x10C, 0x0, 0x80, 0x180, 0x1A0, 0x100
-}};
-
-static base::Optional<std::string> PackBlockMode(int dim_x, int dim_y, int range,
-                                          bool dual_plane,
-                                          base::BitStream<base::UInt128>* const bit_sink) {
-  // We need to set the high precision bit if our range is too high...
-  bool high_prec = range > 7;
-
-  std::array<int, 3> r = {};
-  const auto result = GetEncodedWeightRange(range, &r);
-  if (result) {
-    return result;
-  }
-
-  // The high two bits of R must not be zero. If this happens then it's
-  // an illegal encoding according to Table C.2.7 that should have gotten
-  // caught in GetEncodedWeightRange
-  assert((r[1] | r[2]) > 0);
-
-  // Just go through the table and see if any of the modes can handle
-  // the given dimensions.
-  for (int mode = 0; mode < kNumBlockModes; ++mode) {
-    const BlockModeInfo& block_mode = kBlockModeInfo[mode];
-
-    bool is_valid_mode = true;
-    is_valid_mode &= block_mode.min_weight_grid_dim_x <= dim_x;
-    is_valid_mode &= dim_x <= block_mode.max_weight_grid_dim_x;
-    is_valid_mode &= block_mode.min_weight_grid_dim_y <= dim_y;
-    is_valid_mode &= dim_y <= block_mode.max_weight_grid_dim_y;
-    is_valid_mode &= !(block_mode.require_single_plane_low_prec && dual_plane);
-    is_valid_mode &= !(block_mode.require_single_plane_low_prec && high_prec);
-
-    if (!is_valid_mode) {
-      continue;
-    }
-
-    // Initialize to the bits we must set.
-    uint32_t encoded_mode = kBlockModeMask[mode];
-    auto setBit = [&encoded_mode](const uint32_t value, const uint32_t offset) {
-      encoded_mode = (encoded_mode & ~(1 << offset)) | ((value & 1) << offset);
-    };
-
-    // Set all the bits we need to set
-    setBit(r[0], block_mode.r0_bit_pos);
-    setBit(r[1], block_mode.r1_bit_pos);
-    setBit(r[2], block_mode.r2_bit_pos);
-
-    // Find our width and height offset from the base width and height weight
-    // grid dimension for the given block mode. These are the 1-2 bits that
-    // get encoded in the block mode used to calculate the final weight grid
-    // width and height.
-    const int offset_x = dim_x - block_mode.min_weight_grid_dim_x;
-    const int offset_y = dim_y - block_mode.min_weight_grid_dim_y;
-
-    // If we don't have an offset position then our offset better be zero.
-    // If this isn't the case, then this isn't a viable block mode and we
-    // should have caught this sooner.
-    assert(block_mode.weight_grid_x_offset_bit_pos >= 0 || offset_x == 0);
-    assert(block_mode.weight_grid_y_offset_bit_pos >= 0 || offset_y == 0);
-
-    encoded_mode |= offset_x << block_mode.weight_grid_x_offset_bit_pos;
-    encoded_mode |= offset_y << block_mode.weight_grid_y_offset_bit_pos;
-
-    if (!block_mode.require_single_plane_low_prec) {
-      setBit(high_prec, 9);
-      setBit(dual_plane, 10);
-    }
-
-    // Make sure that the mode is the first thing the bit sink is writing to
-    assert(bit_sink->Bits() == 0);
-    bit_sink->PutBits(encoded_mode, 11);
-
-    return {};
-  }
-
-  return std::string("Could not find viable block mode");
-}
-
-// Returns true if all endpoint modes are equal.
-bool SharedEndpointModes(const IntermediateBlockData& data) {
-  return std::accumulate(
-      data.endpoints.begin(), data.endpoints.end(), true,
-      [&data](const bool& a, const IntermediateEndpointData& b) {
-        return a && b.mode == data.endpoints[0].mode;
-      });
-}
-
-// Returns the starting bit (between 0 and 128) where the extra CEM and
-// dual plane info is stored in the ASTC block.
-int ExtraConfigBitPosition(const IntermediateBlockData& data) {
-  const bool has_dual_channel = data.dual_plane_channel.hasValue();
-  const int num_weights = data.weight_grid_dim_x * data.weight_grid_dim_y *
-      (has_dual_channel ? 2 : 1);
-  const int num_weight_bits =
-      IntegerSequenceCodec::GetBitCountForRange(num_weights, data.weight_range);
-
-  int extra_config_bits = 0;
-  if (!SharedEndpointModes(data)) {
-    const int num_encoded_cem_bits = 2 + int(data.endpoints.size()) * 3;
-    extra_config_bits = num_encoded_cem_bits - 6;
-  }
-
-  if (has_dual_channel) {
-    extra_config_bits += 2;
-  }
-
-  return 128 - num_weight_bits - extra_config_bits;
-}
-
-}  // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-
-base::Optional<IntermediateBlockData> UnpackIntermediateBlock(
-    const PhysicalASTCBlock& pb) {
-  if (pb.IsIllegalEncoding()) {
-    return {};
-  }
-
-  if (pb.IsVoidExtent()) {
-    return {};
-  }
-
-  // Non void extent? Then let's try to decode everything else.
-  IntermediateBlockData data;
-
-  // All blocks have color values...
-  const base::UInt128 color_bits_mask =
-      (base::UInt128(1) << pb.NumColorBits().value()) - 1;
-  const base::UInt128 color_bits =
-      (pb.GetBlockBits() >> pb.ColorStartBit().value()) & color_bits_mask;
-  base::BitStream<base::UInt128> bit_src(color_bits, 128);
-
-  IntegerSequenceDecoder color_decoder(pb.ColorValuesRange().value());
-  const int num_colors_in_block = pb.NumColorValues().value();
-  std::vector<int> colors = color_decoder.Decode(num_colors_in_block, &bit_src);
-
-  // Decode simple info
-  const auto weight_dims = pb.WeightGridDims();
-  data.weight_grid_dim_x = weight_dims->at(0);
-  data.weight_grid_dim_y = weight_dims->at(1);
-  data.weight_range = pb.WeightRange().value();
-
-  data.partition_id = pb.PartitionID();
-  data.dual_plane_channel = pb.DualPlaneChannel();
-
-  auto colors_iter = colors.begin();
-  for (int i = 0; i < pb.NumPartitions().value(); ++i) {
-    IntermediateEndpointData ep_data;
-    ep_data.mode = pb.GetEndpointMode(i).value();
-
-    const int num_colors = NumColorValuesForEndpointMode(ep_data.mode);
-    ep_data.colors.insert(ep_data.colors.end(), colors_iter,
-                          colors_iter + num_colors);
-    colors_iter += num_colors;
-
-    data.endpoints.push_back(ep_data);
-  }
-  assert(colors_iter == colors.end());
-  data.endpoint_range = pb.ColorValuesRange().value();
-
-  // Finally decode the weights
-  const base::UInt128 weight_bits_mask =
-      (base::UInt128(1) << pb.NumWeightBits().value()) - 1;
-  const base::UInt128 weight_bits =
-      base::ReverseBits(pb.GetBlockBits()) & weight_bits_mask;
-  bit_src = base::BitStream<base::UInt128>(weight_bits, 128);
-
-  IntegerSequenceDecoder weight_decoder(data.weight_range);
-  int num_weights = data.weight_grid_dim_x * data.weight_grid_dim_y;
-  num_weights *= pb.IsDualPlane() ? 2 : 1;
-  data.weights = weight_decoder.Decode(num_weights, &bit_src);
-
-  return data;
-}
-
-int EndpointRangeForBlock(const IntermediateBlockData& data) {
-  // First check to see if we exceed the number of bits allotted for weights, as
-  // specified in C.2.24. If so, then the endpoint range is meaningless, but not
-  // because we had an overzealous color endpoint mode, so return a different
-  // error code.
-  if (IntegerSequenceCodec::GetBitCountForRange(
-          data.weight_grid_dim_x * data.weight_grid_dim_y *
-          (data.dual_plane_channel.hasValue() ? 2 : 1),
-          data.weight_range) > 96) {
-    return kEndpointRange_ReturnInvalidWeightDims;
-  }
-
-  const int num_partitions = int(data.endpoints.size());
-
-  // Calculate the number of bits that we would write prior to getting to the
-  // color endpoint data
-  const int bits_written =
-      11   // Block mode
-      + 2  // Num partitions
-      + ((num_partitions > 1) ? 10 : 0)  // Partition ID
-      + ((num_partitions == 1) ? 4 : 6);  // Shared CEM bits
-
-  // We can determine the range based on how many bits we have between the start
-  // of the color endpoint data and the next section, which is the extra config
-  // bit position
-  const int color_bits_available = ExtraConfigBitPosition(data) - bits_written;
-
-  int num_color_values = 0;
-  for (const auto& ep_data : data.endpoints) {
-    num_color_values += NumColorValuesForEndpointMode(ep_data.mode);
-  }
-
-  // There's no way any valid ASTC encoding has no room left for any color
-  // values. If we hit this then something is wrong in the caller -- abort.
-  // According to section C.2.24, the smallest number of bits available is
-  // ceil(13*C/5), where C is the number of color endpoint integers needed.
-  const int bits_needed = (13 * num_color_values + 4) / 5;
-  if (color_bits_available < bits_needed) {
-    return kEndpointRange_ReturnNotEnoughColorBits;
-  }
-
-  int color_value_range = 255;
-  for (; color_value_range > 1; --color_value_range) {
-    const int bits_for_range = IntegerSequenceCodec::GetBitCountForRange(
-        num_color_values, color_value_range);
-    if (bits_for_range <= color_bits_available) {
-      break;
-    }
-  }
-
-  return color_value_range;
-}
-
-base::Optional<VoidExtentData> UnpackVoidExtent(const PhysicalASTCBlock& pb) {
-  if (pb.IsIllegalEncoding()) {
-    return {};
-  }
-
-  if (!pb.IsVoidExtent()) {
-    return {};
-  }
-
-  // All blocks have color values...
-  const base::UInt128 color_bits_mask =
-      (base::UInt128(1) << pb.NumColorBits().value()) - 1;
-  const uint64_t color_bits = (
-      (pb.GetBlockBits() >> pb.ColorStartBit().value()) & color_bits_mask).LowBits();
-
-  assert(pb.NumColorValues().value() == 4);
-  VoidExtentData data;
-  data.r = static_cast<uint16_t>((color_bits >>  0) & 0xFFFF);
-  data.g = static_cast<uint16_t>((color_bits >> 16) & 0xFFFF);
-  data.b = static_cast<uint16_t>((color_bits >> 32) & 0xFFFF);
-  data.a = static_cast<uint16_t>((color_bits >> 48) & 0xFFFF);
-
-  const auto void_extent_coords = pb.VoidExtentCoords();
-  if (void_extent_coords) {
-    data.coords[0] = uint16_t(void_extent_coords->at(0));
-    data.coords[1] = uint16_t(void_extent_coords->at(1));
-    data.coords[2] = uint16_t(void_extent_coords->at(2));
-    data.coords[3] = uint16_t(void_extent_coords->at(3));
-  } else {
-    uint16_t all_ones = (1 << 13) - 1;
-    for (auto& coord : data.coords) {
-      coord = all_ones;
-    }
-  }
-
-  return data;
-}
-
-// Packs the given intermediate block into a physical block. Returns false if
-// the provided values in the intermediate block emit an illegal ASTC
-// encoding.
-base::Optional<std::string> Pack(const IntermediateBlockData& data,
-                                 base::UInt128* pb) {
-  if (data.weights.size() !=
-      size_t(data.weight_grid_dim_x * data.weight_grid_dim_y *
-      (data.dual_plane_channel.hasValue() ? 2 : 1))) {
-    return std::string("Incorrect number of weights!");
-  }
-
-  // If it's not a void extent block, then it gets a bit more tricky...
-  base::BitStream<base::UInt128> bit_sink;
-
-  // First we need to encode the block mode.
-  const auto error_string = PackBlockMode(
-      data.weight_grid_dim_x, data.weight_grid_dim_y, data.weight_range,
-      data.dual_plane_channel.hasValue(), &bit_sink);
-  if (error_string) {
-    return error_string;
-  }
-
-  // Next, we place the number of partitions minus one.
-  const int num_partitions = int(data.endpoints.size());
-  bit_sink.PutBits(num_partitions - 1, 2);
-
-  // If we have more than one partition, then we also have a partition ID.
-  if (num_partitions > 1) {
-    const int id = data.partition_id.value();
-    assert(id >= 0);
-    bit_sink.PutBits(id, 10);
-  }
-
-  // Take a detour, let's encode the weights so that we know how many bits they
-  // consume.
-  base::BitStream<base::UInt128> weight_sink;
-
-  IntegerSequenceEncoder weight_enc(data.weight_range);
-  for (auto weight : data.weights) {
-    weight_enc.AddValue(weight);
-  }
-  weight_enc.Encode(&weight_sink);
-
-  const int num_weight_bits = weight_sink.Bits();
-  assert(num_weight_bits ==
-           IntegerSequenceCodec::GetBitCountForRange(
-               int(data.weights.size()), data.weight_range));
-
-  // Let's continue... how much after the color data do we need to write?
-  int extra_config = 0;
-
-  // Determine if all endpoint pairs share the same endpoint mode
-  assert(data.endpoints.size() > 0);
-  bool shared_endpoint_mode = SharedEndpointModes(data);
-
-  // The first part of the endpoint mode (CEM) comes directly after the
-  // partition info, if it exists. If there is no partition info, the CEM comes
-  // right after the block mode. In the single-partition case, we just write out
-  // the entire singular CEM, but in the multi-partition case, if all CEMs are
-  // the same then their shared CEM is specified directly here, too. In both
-  // cases, shared_endpoint_mode is true (in the singular case,
-  // shared_endpoint_mode is trivially true).
-  if (shared_endpoint_mode) {
-    if (num_partitions > 1) {
-      bit_sink.PutBits(0, 2);
-    }
-    bit_sink.PutBits(static_cast<int>(data.endpoints[0].mode), 4);
-  } else {
-    // Here, the CEM is not shared across all endpoint pairs, and we need to
-    // figure out what to place here, and what to place in the extra config
-    // bits before the weight data...
-
-    // Non-shared config modes must all be within the same class (out of four)
-    // See Section C.2.11
-    int min_class = 2;  // We start with 2 here instead of three because it's
-                        // the highest that can be encoded -- even if all modes
-                        // are class 3.
-    int max_class = 0;
-    for (const auto& ep_data : data.endpoints) {
-      const int ep_mode_class = static_cast<int>(ep_data.mode) >> 2;
-      min_class = std::min(min_class, ep_mode_class);
-      max_class = std::max(max_class, ep_mode_class);
-    }
-
-    assert(max_class >= min_class);
-
-    if (max_class - min_class > 1) {
-      return std::string("Endpoint modes are invalid");
-    }
-
-    // Construct the CEM mode -- six of its bits will fit here, but otherwise
-    // the rest will go in the extra configuration bits.
-    base::BitStream<uint32_t> cem_encoder;
-
-    // First encode the base class
-    assert(min_class >= 0);
-    assert(min_class < 3);
-    cem_encoder.PutBits(min_class + 1, 2);
-
-    // Next, encode the class selector bits -- this is simply the offset
-    // from the base class
-    for (const auto& ep_data : data.endpoints) {
-      const int ep_mode_class = static_cast<int>(ep_data.mode) >> 2;
-      const int class_selector_bit = ep_mode_class - min_class;
-      assert(class_selector_bit == 0 || class_selector_bit == 1);
-      cem_encoder.PutBits(class_selector_bit, 1);
-    }
-
-    // Finally, we need to choose from each class which actual mode
-    // we belong to and encode those.
-    for (const auto& ep_data : data.endpoints) {
-      const int ep_mode = static_cast<int>(ep_data.mode) & 3;
-      assert(ep_mode < 4);
-      cem_encoder.PutBits(ep_mode, 2);
-    }
-    assert(cem_encoder.Bits() == uint32_t(2 + num_partitions * 3));
-
-    uint32_t encoded_cem;
-    cem_encoder.GetBits(2 + num_partitions * 3, &encoded_cem);
-
-    // Since only six bits fit here before the color endpoint data, the rest
-    // need to go in the extra config data.
-    extra_config = encoded_cem >> 6;
-
-    // Write out the six bits we had
-    bit_sink.PutBits(encoded_cem, 6);
-  }
-
-  // If we have a dual-plane channel, we can tack that onto our extra config
-  // data
-  if (data.dual_plane_channel.hasValue()) {
-    const int channel = data.dual_plane_channel.value();
-    assert(channel < 4);
-    extra_config <<= 2;
-    extra_config |= channel;
-  }
-
-  // Get the range of endpoint values. It can't be -1 because we should have
-  // checked for that much earlier.
-  const int color_value_range = data.endpoint_range
-      ? data.endpoint_range.value()
-      : EndpointRangeForBlock(data);
-
-  assert(color_value_range != kEndpointRange_ReturnInvalidWeightDims);
-  if (color_value_range == kEndpointRange_ReturnNotEnoughColorBits) {
-    return { "Intermediate block emits illegal color range" };
-  }
-
-  IntegerSequenceEncoder color_enc(color_value_range);
-  for (const auto& ep_data : data.endpoints) {
-    for (int color : ep_data.colors) {
-      if (color > color_value_range) {
-        return { "Color outside available color range!" };
-      }
-
-      color_enc.AddValue(color);
-    }
-  }
-  color_enc.Encode(&bit_sink);
-
-  // Now we need to skip some bits to get to the extra configuration bits. The
-  // number of bits we need to skip depends on where we are in the stream and
-  // where we need to get to.
-  const int extra_config_bit_position = ExtraConfigBitPosition(data);
-  const int extra_config_bits =
-      128 - num_weight_bits - extra_config_bit_position;
-  assert(extra_config_bits >= 0);
-  assert(extra_config < 1 << extra_config_bits);
-
-  // Make sure the color encoder didn't write more than we thought it would.
-  int bits_to_skip = extra_config_bit_position - bit_sink.Bits();
-  assert(bits_to_skip >= 0);
-
-  while (bits_to_skip > 0) {
-    const int skipping = std::min(32, bits_to_skip);
-    bit_sink.PutBits(0, skipping);
-    bits_to_skip -= skipping;
-  }
-
-  // Finally, write out the rest of the config bits.
-  bit_sink.PutBits(extra_config, extra_config_bits);
-
-  // We should be right up to the weight bits...
-  assert(bit_sink.Bits() == uint32_t(128 - num_weight_bits));
-
-  // Flush out our bit writer and write out the weight bits
-  base::UInt128 astc_bits;
-  bit_sink.GetBits(128 - num_weight_bits, &astc_bits);
-
-  base::UInt128 rev_weight_bits;
-  weight_sink.GetBits(weight_sink.Bits(), &rev_weight_bits);
-
-  astc_bits |= base::ReverseBits(rev_weight_bits);
-
-  // And we're done! Whew!
-  *pb = astc_bits;
-  return PhysicalASTCBlock(*pb).IsIllegalEncoding();
-}
-
-base::Optional<std::string> Pack(const VoidExtentData& data,
-                                 base::UInt128* pb) {
-  *pb = PackVoidExtentBlock(data.r, data.g, data.b, data.a, data.coords);
-  return PhysicalASTCBlock(*pb).IsIllegalEncoding();
-}
-
-}  // namespace astc_codec

+ 0 - 128
3rdparty/astc-codec/src/decoder/intermediate_astc_block.h

@@ -1,128 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#ifndef ASTC_CODEC_DECODER_INTERMEDIATE_ASTC_BLOCK_H_
-#define ASTC_CODEC_DECODER_INTERMEDIATE_ASTC_BLOCK_H_
-
-#include "src/base/optional.h"
-#include "src/base/uint128.h"
-#include "src/decoder/physical_astc_block.h"
-
-#include <array>
-#include <vector>
-
-namespace astc_codec {
-
-// From Table C.2.7 -- These are the only valid ranges that weight
-// values can take.
-constexpr std::array<int, 12> kValidWeightRanges =
-{{ 1, 2, 3, 4, 5, 7, 9, 11, 15, 19, 23, 31 }};
-
-// Void extent data are all the ASTC blocks that are labeled for having a
-// constant color. In the ASTC spec, some of these blocks may optionally
-// have "void extent coordinates" that describe how far in texture space
-// the constant color should span. If these coordinates are not valid,
-// then the coordinates are all set to a fully saturated bit mask
-// ((1 << 13) - 1) and the block is treated as a singular constant color.
-// We call both types of these blocks "void extent" to remove confusion
-// in our code.
-struct VoidExtentData {
-  uint16_t r;
-  uint16_t g;
-  uint16_t b;
-  uint16_t a;
-  std::array<uint16_t, 4> coords;
-};
-
-// Intermediate endpoint data. Really this is just an endpoint mode
-// and a couple of values that represent the data used to decode the
-// RGB values from the color endpoint mode.
-struct IntermediateEndpointData {
-  ColorEndpointMode mode;
-  std::vector<int> colors;
-};
-
-// This is an unpacked physical ASTC block, but it does not have enough
-// information to be worked with logically. It is simply a container of
-// all of the unpacked ASTC information. It is used as a staging area
-// for the information that is later Pack()'d into a PhysicalASTCBlock.
-struct IntermediateBlockData {
-  int weight_grid_dim_x;
-  int weight_grid_dim_y;
-  int weight_range;
-
-  // Quantized, non-interpolated weights
-  std::vector<int> weights;
-
-  // The 10-bit partition ID if we need one
-  base::Optional<int> partition_id;
-
-  // The dual-plane channel in [0, 3] if it exists.
-  base::Optional<int> dual_plane_channel;
-
-  // The quantized/encoded endpoint values for this block. The range of each
-  // endpoint value is specified by |endpoint_range|, if it exists. If not, the
-  // range can be queried by calling EndpointRangeForBlock
-  std::vector<IntermediateEndpointData> endpoints;
-
-  // The range [0, endpoint_range] that any one endpoint value can take. Users
-  // should not write to this value themselves. If it is empty at the time
-  // someone calls Pack(), it will be automatically inferred. Otherwise, it is
-  // set by Unpack() based on what the underlying encoding specified.
-  base::Optional<int> endpoint_range;
-};
-
-// Returns the maximum value that a given endpoint value can take according to
-// the other settings in the block. Ignores the |endpoint_range| member
-// variable. Returns negative values on error:
-//  -1 : Too many bits required to store weight grid
-//  -2 : There are too few bits allocated for color endpoint data according to
-//       C.2.24 in the ASTC spec
-int EndpointRangeForBlock(const IntermediateBlockData& data);
-inline int EndpointRangeForBlock(const VoidExtentData& data);
-
-// Unpacks the physical ASTC block into the intermediate block. Returns false
-// if the physical block is an error encoded block, or if the physical block
-// is a void extent block. On error the contents of ib are undefined.
-base::Optional<IntermediateBlockData> UnpackIntermediateBlock(
-    const PhysicalASTCBlock& pb);
-
-// Unpacks the physical ASTC block into a void extent block. Returns false
-// if the physical block is an error encoded block, or if the physical block
-// is an intermediate block. On error the contents of ib are undefined.
-base::Optional<VoidExtentData> UnpackVoidExtent(const PhysicalASTCBlock& pb);
-
-// Packs the given intermediate block into a physical block. Returns an error
-// string if the provided values in the intermediate block emit an illegal ASTC
-// encoding. In this case the results in the physical block are undefined.
-base::Optional<std::string> Pack(const IntermediateBlockData& data,
-                                 base::UInt128* pb);
-
-// Packs the given void extent block into a physical block. Returns an error
-// string if the provided values in the void extent block emit an illegal ASTC
-// encoding. In this case the results in the physical block are undefined.
-base::Optional<std::string> Pack(const VoidExtentData& data, base::UInt128* pb);
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// Impl
-
-inline int EndpointRangeForBlock(const VoidExtentData&) {
-  // Void extent blocks use 16-bit ARGB definitions
-  return (1 << 16) - 1;
-}
-
-}  // namespace astc_codec
-
-#endif  // ASTC_CODEC_DECODER_INTERMEDIATE_ASTC_BLOCK_H_

+ 0 - 262
3rdparty/astc-codec/src/decoder/logical_astc_block.cc

@@ -1,262 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#include "src/decoder/logical_astc_block.h"
-#include "src/decoder/endpoint_codec.h"
-#include "src/decoder/footprint.h"
-#include "src/decoder/integer_sequence_codec.h"
-#include "src/decoder/quantization.h"
-#include "src/decoder/weight_infill.h"
-
-namespace astc_codec {
-
-namespace {
-
-Partition GenerateSinglePartition(Footprint footprint) {
-  return Partition { footprint, /* num_parts = */ 1, /* partition_id = */ 0,
-        std::vector<int>(footprint.NumPixels(), 0) };
-}
-
-static std::vector<EndpointPair> DecodeEndpoints(const IntermediateBlockData& block) {
-  const int endpoint_range = block.endpoint_range
-      ? block.endpoint_range.value()
-      : EndpointRangeForBlock(block);
-  assert(endpoint_range > 0);
-
-  std::vector<EndpointPair> endpoints;
-  for (const auto& eps : block.endpoints) {
-    RgbaColor decmp_one_rgba, decmp_two_rgba;
-    DecodeColorsForMode(eps.colors, endpoint_range, eps.mode,
-                        &decmp_one_rgba, &decmp_two_rgba);
-    endpoints.emplace_back(decmp_one_rgba, decmp_two_rgba);
-  }
-  return endpoints;
-}
-
-static std::vector<EndpointPair> DecodeEndpoints(const VoidExtentData& block) {
-  EndpointPair eps;
-  eps.first[0] = eps.second[0] = (block.r * 255) / 65535;
-  eps.first[1] = eps.second[1] = (block.g * 255) / 65535;
-  eps.first[2] = eps.second[2] = (block.b * 255) / 65535;
-  eps.first[3] = eps.second[3] = (block.a * 255) / 65535;
-
-  std::vector<EndpointPair> endpoints;
-  endpoints.emplace_back(eps);
-  return endpoints;
-}
-
-Partition ComputePartition(const Footprint& footprint,
-                           const IntermediateBlockData& block) {
-  if (block.partition_id) {
-    const int part_id = block.partition_id.value();
-    const int num_parts = int(block.endpoints.size());
-    return GetASTCPartition(footprint, num_parts, part_id);
-  } else {
-    return GenerateSinglePartition(footprint);
-  }
-}
-
-Partition ComputePartition(const Footprint& footprint, const VoidExtentData&) {
-  return GenerateSinglePartition(footprint);
-}
-
-}  // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-
-LogicalASTCBlock::LogicalASTCBlock(const Footprint& footprint)
-    : endpoints_(1),
-      weights_(footprint.NumPixels(), 0),
-      partition_(GenerateSinglePartition(footprint)) { }
-
-LogicalASTCBlock::LogicalASTCBlock(const Footprint& footprint,
-                                   const IntermediateBlockData& block)
-    : endpoints_(DecodeEndpoints(block)),
-      partition_(ComputePartition(footprint, block)) {
-  CalculateWeights(footprint, block);
-}
-
-LogicalASTCBlock::LogicalASTCBlock(const Footprint& footprint,
-                                   const VoidExtentData& block)
-    : endpoints_(DecodeEndpoints(block)),
-      partition_(ComputePartition(footprint, block)) {
-  CalculateWeights(footprint, block);
-}
-
-void LogicalASTCBlock::CalculateWeights(const Footprint& footprint,
-                                        const IntermediateBlockData& block) {
-  const int grid_size_x = block.weight_grid_dim_x;
-  const int grid_size_y = block.weight_grid_dim_y;
-  const int weight_grid_size = grid_size_x * grid_size_y;
-
-  // Either we have a dual plane and we have twice as many weights as
-  // specified or we don't
-  assert(block.dual_plane_channel
-        ? block.weights.size() == size_t(weight_grid_size * 2)
-        : block.weights.size() == size_t(weight_grid_size));
-
-  std::vector<int> unquantized;
-  unquantized.reserve(weight_grid_size);
-
-  // According to C.2.16, if we have dual-plane weights, then we have two
-  // weights per texel -- one adjacent to the other. Hence, we have to skip
-  // some when we decode the separate weight values.
-  const int weight_frequency = (block.dual_plane_channel) ? 2 : 1;
-  const int weight_range = block.weight_range;
-
-  for (int i = 0; i < weight_grid_size; ++i) {
-    const int weight = block.weights[i * weight_frequency];
-    unquantized.push_back(UnquantizeWeightFromRange(weight, weight_range));
-  }
-  weights_ = InfillWeights(unquantized, footprint, grid_size_x, grid_size_y);
-
-  if (block.dual_plane_channel) {
-    SetDualPlaneChannel(block.dual_plane_channel.value());
-    for (int i = 0; i < weight_grid_size; ++i) {
-      const int weight = block.weights[i * weight_frequency + 1];
-      unquantized[i] = UnquantizeWeightFromRange(weight, weight_range);
-    }
-    dual_plane_->weights =
-        InfillWeights(unquantized, footprint, grid_size_x, grid_size_y);
-  }
-}
-
-void LogicalASTCBlock::CalculateWeights(const Footprint& footprint,
-                                        const VoidExtentData&) {
-  weights_ = std::vector<int>(footprint.NumPixels(), 0);
-}
-
-void LogicalASTCBlock::SetWeightAt(int x, int y, int weight) {
-  assert(weight >= 0);
-  assert(weight <= 64);
-  weights_.at(y * GetFootprint().Width() + x) = weight;
-}
-
-int LogicalASTCBlock::WeightAt(int x, int y) const {
-  return weights_.at(y * GetFootprint().Width() + x);
-}
-
-void LogicalASTCBlock::SetDualPlaneWeightAt(int channel, int x, int y,
-                                            int weight) {
-  assert(weight >= 0);
-  assert(weight <= 64);
-
-  // If it's not a dual plane, then this has no logical meaning
-  assert(IsDualPlane());
-
-  // If it is a dual plane and the passed channel matches the query, then we
-  // return the specialized weights
-  if (dual_plane_->channel == channel) {
-    dual_plane_->weights.at(y * GetFootprint().Width() + x) = weight;
-  } else {
-    // If the channel is not the special channel, then return the general weight
-    SetWeightAt(x, y, weight);
-  }
-}
-
-int LogicalASTCBlock::DualPlaneWeightAt(int channel, int x, int y) const {
-  // If it's not a dual plane, then we just return the weight for all channels
-  if (!IsDualPlane()) {
-    // TODO(google): Log warning, Requesting dual-plane channel for a non
-    // dual-plane block!
-    return WeightAt(x, y);
-  }
-
-  // If it is a dual plane and the passed channel matches the query, then we
-  // return the specialized weights
-  if (dual_plane_->channel == channel) {
-    return dual_plane_->weights.at(y * GetFootprint().Width() + x);
-  }
-
-  // If the channel is not the special channel, then return the general weight
-  return WeightAt(x, y);
-}
-
-void LogicalASTCBlock::SetDualPlaneChannel(int channel) {
-  if (channel < 0) {
-    dual_plane_.clear();
-  } else if (dual_plane_) {
-    dual_plane_->channel = channel;
-  } else {
-    dual_plane_ = DualPlaneData {channel, weights_};
-  }
-}
-
-RgbaColor LogicalASTCBlock::ColorAt(int x, int y) const {
-  const auto footprint = GetFootprint();
-  assert(x >= 0);  assert(x < footprint.Width());
-  assert(y >= 0);  assert(y < footprint.Height());
-
-  const int texel_idx = y * footprint.Width() + x;
-  const int part = partition_.assignment[texel_idx];
-  const auto& endpoints = endpoints_[part];
-
-  RgbaColor result;
-  for (int channel = 0; channel < 4; ++channel) {
-    const int weight = (dual_plane_ && dual_plane_->channel == channel)
-        ? dual_plane_->weights[texel_idx]
-        : weights_[texel_idx];
-    const int p0 = endpoints.first[channel];
-    const int p1 = endpoints.second[channel];
-
-    assert(p0 >= 0); assert(p0 < 256);
-    assert(p1 >= 0); assert(p1 < 256);
-
-    // According to C.2.19
-    const int c0 = (p0 << 8) | p0;
-    const int c1 = (p1 << 8) | p1;
-    const int c = (c0 * (64 - weight) + c1 * weight + 32) / 64;
-    // TODO(google): Handle conversion to sRGB or FP16 per C.2.19.
-    const int quantized = ((c * 255) + 32767) / 65536;
-    assert(quantized < 256);
-    result[channel] = quantized;
-  }
-
-  return result;
-}
-
-void LogicalASTCBlock::SetPartition(const Partition& p) {
-  assert(p.footprint == partition_.footprint &&
-         "New partitions may not be for a different footprint");
-  partition_ = p;
-  endpoints_.resize(p.num_parts);
-}
-
-void LogicalASTCBlock::SetEndpoints(const EndpointPair& eps, int subset) {
-  assert(subset < partition_.num_parts);
-  assert(size_t(subset) < endpoints_.size());
-
-  endpoints_[subset] = eps;
-}
-
-base::Optional<LogicalASTCBlock> UnpackLogicalBlock(
-    const Footprint& footprint, const PhysicalASTCBlock& pb) {
-  if (pb.IsVoidExtent()) {
-    base::Optional<VoidExtentData> ve = UnpackVoidExtent(pb);
-    if (!ve) {
-      return {};
-    }
-
-    return LogicalASTCBlock(footprint, ve.value());
-  } else {
-    base::Optional<IntermediateBlockData> ib = UnpackIntermediateBlock(pb);
-    if (!ib) {
-      return {};
-    }
-
-    return LogicalASTCBlock(footprint, ib.value());
-  }
-}
-
-}  // namespace astc_codec

+ 0 - 127
3rdparty/astc-codec/src/decoder/logical_astc_block.h

@@ -1,127 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#ifndef ASTC_CODEC_DECODER_LOGICAL_ASTC_BLOCK_H_
-#define ASTC_CODEC_DECODER_LOGICAL_ASTC_BLOCK_H_
-
-#include "src/base/optional.h"
-#include "src/decoder/footprint.h"
-#include "src/decoder/intermediate_astc_block.h"
-#include "src/decoder/partition.h"
-#include "src/decoder/physical_astc_block.h"
-
-#include <array>
-#include <utility>
-#include <vector>
-
-namespace astc_codec {
-
-// A logical ASTC block holds the endpoints, indices, and partition information
-// of a compressed block. These values generally do not adhere to any
-// quality-for-bitrate-imposed limits and are solely logical entities for
-// determining the best representation of a given block.
-class LogicalASTCBlock {
- public:
-  LogicalASTCBlock(const LogicalASTCBlock&) = default;
-  LogicalASTCBlock(LogicalASTCBlock&&) = default;
-
-  // Unpack an intermediate block into a logical one.
-  LogicalASTCBlock(const Footprint& footprint,
-                   const IntermediateBlockData& block);
-
-  // Unpack a void extent intermediate block into a logical one.
-  LogicalASTCBlock(const Footprint& footprint, const VoidExtentData& block);
-
-  // Create a new, empty ASTC block
-  explicit LogicalASTCBlock(const Footprint& footprint);
-
-  // Returns the footprint associated with this block. The footprint is defined
-  // via the partition, because the partition definition is dependent on the
-  // footprint.
-  const Footprint& GetFootprint() const { return partition_.footprint; }
-
-  // Returns the unquantized and infilled weight in the range [0, 64] for the
-  // given texel location. Assumes that the block is a single-plane block,
-  // meaning that weights are used equally across all channels.
-  void SetWeightAt(int x, int y, int weight);
-  int WeightAt(int x, int y) const;
-
-  // Returns the unquantized and infilled weight in the range [0, 64] for the
-  // given channel at the given texel location. If the block does not have a
-  // dual-plane channel then the reference-returning version will fail, as it
-  // cannot return a reference to a value that (potentially) doesn't exist.
-  void SetDualPlaneWeightAt(int channel, int x, int y, int weight);
-  int DualPlaneWeightAt(int channel, int x, int y) const;
-
-  // Returns the color as it would be in the given pixel coordinates of the
-  // block. Fails if the coordinates are outside of the range of the block
-  // footprint
-  RgbaColor ColorAt(int x, int y) const;
-
-  // Sets the current partition for the block. |p|'s footprint must match the
-  // return value of GetFootprint() or else this call will fail.
-  void SetPartition(const Partition& p);
-
-  // Sets the endpoints for the given subset.
-  void SetEndpoints(const EndpointPair& eps, int subset);
-  void SetEndpoints(const Endpoint& ep1, const Endpoint& ep2, int subset) {
-    SetEndpoints(std::make_pair(ep1, ep2), subset);
-  }
-
-  // Sets the dual plane channel for the block. Value must be within the range
-  // [0, 3]. If a negative value is passed, then the dual-plane data for the
-  // block is removed, and the block is treated as a single-plane block.
-  void SetDualPlaneChannel(int channel);
-  bool IsDualPlane() const { return dual_plane_.hasValue(); }
-
- private:
-  // A block may have up to four endpoint pairs.
-  std::vector<EndpointPair> endpoints_;
-
-  // Weights are stored as values in the interval [0, 64].
-  std::vector<int> weights_;
-
-  // The partition information for this block. This determines the
-  // appropriate subsets that each pixel should belong to.
-  Partition partition_;
-
-  // Dual plane data holds both the channel and the weights that describe
-  // the dual plane data for the given block. If a block has a dual plane, then
-  // we need to know both the channel and the weights associated with it.
-  struct DualPlaneData {
-    int channel;
-    std::vector<int> weights;
-  };
-
-  // The dual-plane data is optional from a logical representation of the block.
-  base::Optional<DualPlaneData> dual_plane_;
-
-  // Calculates the unquantized and interpolated weights from the encoded weight
-  // values and possibly dual-plane weights specified in the passed ASTC block.
-  void CalculateWeights(const Footprint& footprint,
-                        const IntermediateBlockData& block);
-
-  // Calculates the weights for a VoidExtentBlock.
-  void CalculateWeights(const Footprint& footprint,
-                        const VoidExtentData& block);
-};
-
-// Unpacks the physical ASTC block into a logical block. Returns false if the
-// physical block is an error encoded block.
-base::Optional<LogicalASTCBlock> UnpackLogicalBlock(
-    const Footprint& footprint, const PhysicalASTCBlock& pb);
-
-}  // namespace astc_codec
-
-#endif  // ASTC_CODEC_DECODER_LOGICAL_ASTC_BLOCK_H_

+ 0 - 601
3rdparty/astc-codec/src/decoder/partition.cc

@@ -1,601 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#include "src/decoder/partition.h"
-#include "src/base/bottom_n.h"
-#include "src/base/utils.h"
-#include "src/decoder/footprint.h"
-
-#include <algorithm>
-#include <array>
-#include <limits>
-#include <memory>
-#include <numeric>
-#include <queue>
-#include <set>
-#include <unordered_set>
-#include <utility>
-
-namespace astc_codec {
-
-namespace {
-
-// The maximum number of partitions supported by ASTC is four.
-constexpr int kMaxNumSubsets = 4;
-
-// Partition selection function based on the ASTC specification.
-// See section C.2.21
-int SelectASTCPartition(int seed, int x, int y, int z, int partitioncount,
-                        int num_pixels) {
-  if (partitioncount <= 1) {
-    return 0;
-  }
-
-  if (num_pixels < 31) {
-    x <<= 1;
-    y <<= 1;
-    z <<= 1;
-  }
-
-  seed += (partitioncount - 1) * 1024;
-
-  uint32_t rnum = seed;
-  rnum ^= rnum >> 15;
-  rnum -= rnum << 17;
-  rnum += rnum << 7;
-  rnum += rnum << 4;
-  rnum ^= rnum >> 5;
-  rnum += rnum << 16;
-  rnum ^= rnum >> 7;
-  rnum ^= rnum >> 3;
-  rnum ^= rnum << 6;
-  rnum ^= rnum >> 17;
-
-  uint8_t seed1 = rnum & 0xF;
-  uint8_t seed2 = (rnum >> 4) & 0xF;
-  uint8_t seed3 = (rnum >> 8) & 0xF;
-  uint8_t seed4 = (rnum >> 12) & 0xF;
-  uint8_t seed5 = (rnum >> 16) & 0xF;
-  uint8_t seed6 = (rnum >> 20) & 0xF;
-  uint8_t seed7 = (rnum >> 24) & 0xF;
-  uint8_t seed8 = (rnum >> 28) & 0xF;
-  uint8_t seed9 = (rnum >> 18) & 0xF;
-  uint8_t seed10 = (rnum >> 22) & 0xF;
-  uint8_t seed11 = (rnum >> 26) & 0xF;
-  uint8_t seed12 = ((rnum >> 30) | (rnum << 2)) & 0xF;
-
-  seed1 *= seed1;
-  seed2 *= seed2;
-  seed3 *= seed3;
-  seed4 *= seed4;
-  seed5 *= seed5;
-  seed6 *= seed6;
-  seed7 *= seed7;
-  seed8 *= seed8;
-  seed9 *= seed9;
-  seed10 *= seed10;
-  seed11 *= seed11;
-  seed12 *= seed12;
-
-  int sh1, sh2, sh3;
-  if (seed & 1) {
-    sh1 = (seed & 2 ? 4 : 5);
-    sh2 = (partitioncount == 3 ? 6 : 5);
-  } else {
-    sh1 = (partitioncount == 3 ? 6 : 5);
-    sh2 = (seed & 2 ? 4 : 5);
-  }
-  sh3 = (seed & 0x10) ? sh1 : sh2;
-
-  seed1 >>= sh1;
-  seed2 >>= sh2;
-  seed3 >>= sh1;
-  seed4 >>= sh2;
-  seed5 >>= sh1;
-  seed6 >>= sh2;
-  seed7 >>= sh1;
-  seed8 >>= sh2;
-
-  seed9 >>= sh3;
-  seed10 >>= sh3;
-  seed11 >>= sh3;
-  seed12 >>= sh3;
-
-  int a = seed1 * x + seed2 * y + seed11 * z + (rnum >> 14);
-  int b = seed3 * x + seed4 * y + seed12 * z + (rnum >> 10);
-  int c = seed5 * x + seed6 * y + seed9  * z + (rnum >> 06);
-  int d = seed7 * x + seed8 * y + seed10 * z + (rnum >> 02);
-
-  a &= 0x3F;
-  b &= 0x3F;
-  c &= 0x3F;
-  d &= 0x3F;
-
-  if (partitioncount <= 3) {
-    d = 0;
-  }
-  if (partitioncount <= 2) {
-    c = 0;
-  }
-
-  if (a >= b && a >= c && a >= d) {
-    return 0;
-  } else if (b >= c && b >= d) {
-    return 1;
-  } else if (c >= d) {
-    return 2;
-  } else {
-    return 3;
-  }
-}
-
-// A partition hash that we can pass to containers like std::unordered_set
-struct PartitionHasher {
-  size_t operator()(const Partition& part) const {
-    // The issue here is that if we have two different partitions, A and B, then
-    // their hash should be equal if A and B are equal. We define the distance
-    // between A and B using PartitionMetric, but internally that finds a 1-1
-    // mapping from labels in A to labels in B.
-    //
-    // With that in mind, when we define a hash for partitions, we need to find
-    // a 1-1 mapping to a 'universal' labeling scheme. Here we define that as
-    // the heuristic: the first encountered label will be 0, the second will be
-    // 1, etc. This creates a unique 1-1 mapping scheme from any partition.
-    //
-    // Note, we can't use this heuristic for the PartitionMetric, as it will
-    // generate very large discrepancies between similar labellings (for example
-    // 000...001 vs 011...111). We are just looking for a boolean distinction
-    // whether or not two partitions are different and don't care how different
-    // they are.
-    std::array<int, kMaxNumSubsets> mapping {{ -1, -1, -1, -1 }};
-    int next_subset = 0;
-    for (int subset : part.assignment) {
-      if (mapping[subset] < 0) {
-        mapping[subset] = next_subset++;
-      }
-    }
-    assert(next_subset <= kMaxNumSubsets);
-
-    // The return value will be the hash of the assignment according to this
-    // mapping
-    const size_t seed0 = 0;
-    return std::accumulate(part.assignment.begin(), part.assignment.end(), seed0,
-                           [&mapping](size_t seed, const int& subset) {
-                             std::hash<size_t> hasher;
-                             const int s = mapping[subset];
-                             return hasher(seed) ^ hasher(static_cast<size_t>(s));
-                           });
-  }
-};
-
-// Construct a VP-Tree of partitions. Since our PartitionMetric satisfies
-// the triangle inequality, we can use this general higher-dimensional space
-// partitioning tree to organize our partitions.
-//
-// TODO(google): !SPEED! Right now this tree stores an actual linked
-// structure of pointers which is likely very slow during construction and
-// very not cache-coherent during traversal, so it'd probably be good to
-// switch to a flattened binary tree structure if performance becomes an
-// issue.
-class PartitionTree {
- public:
-  // Unclear what it means to have an uninitialized tree, so delete default
-  // constructors, but allow the tree to be moved
-  PartitionTree() = delete;
-  PartitionTree(const PartitionTree&) = delete;
-  PartitionTree(PartitionTree&& t) = default;
-
-  // Generate a PartitionTree from iterators over |Partition|s
-  template<typename Itr>
-  PartitionTree(Itr begin, Itr end) : parts_(begin, end) {
-    std::vector<int> part_indices(parts_.size());
-    std::iota(part_indices.begin(), part_indices.end(), 0);
-    root_ = std::unique_ptr<PartitionTreeNode>(
-        new PartitionTreeNode(parts_, part_indices));
-  }
-
-  // Search for the k-nearest partitions that are closest to part based on
-  // the result of PartitionMetric
-  void Search(const Partition& part, int k,
-              std::vector<const Partition*>* const results,
-              std::vector<int>* const distances) const {
-    ResultHeap heap(k);
-    SearchNode(root_, part, &heap);
-
-    results->clear();
-    if (nullptr != distances) {
-      distances->clear();
-    }
-
-    std::vector<ResultNode> search_results = heap.Pop();
-    for (const auto& result : search_results) {
-      results->push_back(&parts_[result.part_idx]);
-      if (nullptr != distances) {
-        distances->push_back(result.distance);
-      }
-    }
-
-    assert(results->size() == size_t(k));
-  }
-
- private:
-  // Heap elements to be stored while searching the tree. The two relevant
-  // pieces of information are the partition index and it's distance from the
-  // queried partition.
-  struct ResultNode {
-    int part_idx;
-    int distance;
-
-    // Heap based on distance from query point.
-    bool operator<(const ResultNode& other) const {
-      return distance < other.distance;
-    }
-  };
-
-  using ResultHeap = base::BottomN<ResultNode>;
-
-  struct PartitionTreeNode {
-    int part_idx;
-    int split_dist;
-
-    std::unique_ptr<PartitionTreeNode> left;
-    std::unique_ptr<PartitionTreeNode> right;
-
-    PartitionTreeNode(const std::vector<Partition> &parts,
-                      const std::vector<int> &part_indices)
-        : split_dist(-1) {
-      assert(part_indices.size() > 0);
-
-      right.reset(nullptr);
-      left.reset(nullptr);
-
-      // Store the first node as our vantage point
-      part_idx = part_indices[0];
-      const Partition& vantage_point = parts[part_indices[0]];
-
-      // Calculate the distances of the remaining nodes against the vantage
-      // point.
-      std::vector<std::pair<int, int>> part_dists;
-      for (size_t i = 1; i < part_indices.size(); ++i) {
-        const int idx = part_indices[i];
-        const int dist = PartitionMetric(vantage_point, parts[idx]);
-        if (dist > 0) {
-          part_dists.push_back(std::make_pair(idx, dist));
-        }
-      }
-
-      // If there are no more different parts, then this is a leaf node
-      if (part_dists.empty()) {
-        return;
-      }
-
-      struct OrderBySecond {
-        typedef std::pair<int, int> PairType;
-          bool operator()(const PairType& lhs, const PairType& rhs) {
-            return lhs.second < rhs.second;
-          }
-      };
-
-      // We want to partition the set such that the points are ordered
-      // based on their distances from the vantage point. We can do this
-      // using the partial sort of nth element.
-      std::nth_element(
-          part_dists.begin(), part_dists.begin() + part_dists.size() / 2,
-          part_dists.end(), OrderBySecond());
-
-      // Once that's done, our split position is in the middle
-      const auto split_iter = part_dists.begin() + part_dists.size() / 2;
-      split_dist = split_iter->second;
-
-      // Recurse down the right and left sub-trees with the indices of the
-      // parts that are farther and closer respectively
-      std::vector<int> right_indices;
-      for (auto itr = split_iter; itr != part_dists.end(); ++itr) {
-        right_indices.push_back(itr->first);
-      }
-
-      if (!right_indices.empty()) {
-        right.reset(new PartitionTreeNode(parts, right_indices));
-      }
-
-      std::vector<int> left_indices;
-      for (auto itr = part_dists.begin(); itr != split_iter; ++itr) {
-        left_indices.push_back(itr->first);
-      }
-
-      if (!left_indices.empty()) {
-        left.reset(new PartitionTreeNode(parts, left_indices));
-      }
-    }
-  };
-
-  void SearchNode(const std::unique_ptr<PartitionTreeNode>& node,
-                  const Partition& p, ResultHeap* const heap) const {
-    if (nullptr == node) {
-      return;
-    }
-
-    // Calculate distance against current node
-    const int dist = PartitionMetric(parts_[node->part_idx], p);
-
-    // Push it onto the heap and remove the top-most nodes to maintain
-    // closest k indices.
-    ResultNode result;
-    result.part_idx = node->part_idx;
-    result.distance = dist;
-    heap->Push(result);
-
-    // If the split distance is uninitialized, it means we have no children.
-    if (node->split_dist < 0) {
-      assert(nullptr == node->left);
-      assert(nullptr == node->right);
-      return;
-    }
-
-    // Next we need to check the left and right trees if their distance
-    // is closer/farther than the farthest element on the heap
-    const int tau = heap->Top().distance;
-    if (dist + tau < node->split_dist || dist - tau < node->split_dist) {
-      SearchNode(node->left, p, heap);
-    }
-
-    if (dist + tau > node->split_dist || dist - tau > node->split_dist) {
-      SearchNode(node->right, p, heap);
-    }
-  }
-
-  std::vector<Partition> parts_;
-  std::unique_ptr<PartitionTreeNode> root_;
-};
-
-// A helper function that generates all of the partitions for each number of
-// subsets in ASTC blocks and stores them in a PartitionTree for fast retrieval.
-const int kNumASTCPartitionIDBits = 10;
-PartitionTree GenerateASTCPartitionTree(Footprint footprint) {
-  std::unordered_set<Partition, PartitionHasher> parts;
-  for (int num_parts = 2; num_parts <= kMaxNumSubsets; ++num_parts) {
-    for (int id = 0; id < (1 << kNumASTCPartitionIDBits); ++id) {
-      Partition part = GetASTCPartition(footprint, num_parts, id);
-
-      // Make sure we're not using a degenerate partition assignment that wastes
-      // an endpoint pair...
-      bool valid_part = true;
-      for (int i = 0; i < num_parts; ++i) {
-        if (std::find(part.assignment.begin(), part.assignment.end(), i) ==
-            part.assignment.end()) {
-          valid_part = false;
-          break;
-        }
-      }
-
-      if (valid_part) {
-        parts.insert(std::move(part));
-      }
-    }
-  }
-
-  return PartitionTree(parts.begin(), parts.end());
-}
-
-// To avoid needing any fancy boilerplate for mapping from a width, height
-// tuple, we can define a simple encoding for the block mode:
-constexpr int EncodeDims(int width, int height) {
-  return (width << 16) | height;
-}
-
-}  // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-
-int PartitionMetric(const Partition& a, const Partition& b) {
-  // Make sure that one partition is at least a subset of the other...
-  UTILS_RELEASE_ASSERT(a.footprint == b.footprint);
-
-  // Make sure that the number of parts is within our limits. ASTC has a maximum
-  // of four subsets per block according to the specification.
-  UTILS_RELEASE_ASSERT(a.num_parts <= kMaxNumSubsets);
-  UTILS_RELEASE_ASSERT(b.num_parts <= kMaxNumSubsets);
-
-  const int w = a.footprint.Width();
-  const int h = b.footprint.Height();
-
-  struct PairCount {
-    int a;
-    int b;
-    int count;
-
-    // Comparison needed for sort below.
-    bool operator>(const PairCount& other) const {
-      return count > other.count;
-    }
-  };
-
-  // Since we need to find the smallest mapping from labels in A to labels in B,
-  // we need to store each label pair in a structure that can later be sorted.
-  // The maximum number of subsets in an ASTC block is four, meaning that
-  // between the two partitions, we can have up to sixteen different pairs.
-  std::array<PairCount, 16> pair_counts;
-  for (int y = 0; y < 4; ++y) {
-    for (int x = 0; x < 4; ++x) {
-      const int idx = y * 4 + x;
-      pair_counts[idx].a = x;
-      pair_counts[idx].b = y;
-      pair_counts[idx].count = 0;
-    }
-  }
-
-  // Count how many times we see each pair of assigned values (order matters!)
-  for (int y = 0; y < h; ++y) {
-    for (int x = 0; x < w; ++x) {
-      const int idx = y * w + x;
-
-      const int a_val = a.assignment[idx];
-      const int b_val = b.assignment[idx];
-
-      assert(a_val >= 0);
-      assert(b_val >= 0);
-
-      assert(a_val < 4);
-      assert(b_val < 4);
-
-      ++(pair_counts[b_val * 4 + a_val].count);
-    }
-  }
-
-  // Sort the pairs in descending order based on their count
-  std::sort(pair_counts.begin(), pair_counts.end(), std::greater<PairCount>());
-
-  // Now assign pairs one by one until we have no more pairs to assign. Once
-  // a value from A is assigned to a value in B, it can no longer be reassigned,
-  // so we can keep track of this in a matrix. Similarly, to keep the assignment
-  // one-to-one, once a value in B has been assigned to, it cannot be assigned
-  // to again.
-  std::array<std::array<bool, kMaxNumSubsets>, kMaxNumSubsets> assigned { };
-
-  int pixels_matched = 0;
-  for (const auto& pair_count : pair_counts) {
-    bool is_assigned = false;
-    for (int i = 0; i < kMaxNumSubsets; ++i) {
-      is_assigned |= assigned.at(pair_count.a).at(i);
-      is_assigned |= assigned.at(i).at(pair_count.b);
-    }
-
-    if (!is_assigned) {
-      assigned.at(pair_count.a).at(pair_count.b) = true;
-      pixels_matched += pair_count.count;
-    }
-  }
-
-  // The difference is the number of pixels that had an assignment versus the
-  // total number of pixels.
-  return w * h - pixels_matched;
-}
-
-// Generates the partition assignment for the given block attributes.
-Partition GetASTCPartition(const Footprint& footprint, int num_parts,
-                           int partition_id) {
-  // Partitions must have at least one subset but may have at most four
-  assert(num_parts >= 0);
-  assert(num_parts <= kMaxNumSubsets);
-
-  // Partition ID can be no more than 10 bits.
-  assert(partition_id >= 0);
-  assert(partition_id < 1 << 10);
-
-  Partition part = {footprint, num_parts, partition_id, /* assignment = */ {}};
-  part.assignment.reserve(footprint.NumPixels());
-
-  // Maintain column-major order so that we match all of the image processing
-  // algorithms that depend on this class.
-  for (int y = 0; y < footprint.Height(); ++y) {
-    for (int x = 0; x < footprint.Width(); ++x) {
-      const int p = SelectASTCPartition(partition_id, x, y, 0, num_parts,
-                                        footprint.NumPixels());
-      part.assignment.push_back(p);
-    }
-  }
-
-  return part;
-}
-
-const std::vector<const Partition*> FindKClosestASTCPartitions(
-    const Partition& candidate, int k) {
-  const int encoded_dims = EncodeDims(candidate.footprint.Width(),
-                                      candidate.footprint.Height());
-
-  int index = 0;
-  switch (encoded_dims) {
-    case EncodeDims(4, 4): index = 0; break;
-    case EncodeDims(5, 4): index = 1; break;
-    case EncodeDims(5, 5): index = 2; break;
-    case EncodeDims(6, 5): index = 3; break;
-    case EncodeDims(6, 6): index = 4; break;
-    case EncodeDims(8, 5): index = 5; break;
-    case EncodeDims(8, 6): index = 6; break;
-    case EncodeDims(8, 8): index = 7; break;
-    case EncodeDims(10, 5): index = 8; break;
-    case EncodeDims(10, 6): index = 9; break;
-    case EncodeDims(10, 8): index = 10; break;
-    case EncodeDims(10, 10): index = 11; break;
-    case EncodeDims(12, 10): index = 12; break;
-    case EncodeDims(12, 12): index = 13; break;
-    default:
-      assert(false && "Unknown footprint dimensions. This should have been caught sooner.");
-      break;
-  }
-
-  static const auto* const kASTCPartitionTrees =
-      new std::array<PartitionTree, Footprint::NumValidFootprints()> {{
-      GenerateASTCPartitionTree(Footprint::Get4x4()),
-      GenerateASTCPartitionTree(Footprint::Get5x4()),
-      GenerateASTCPartitionTree(Footprint::Get5x5()),
-      GenerateASTCPartitionTree(Footprint::Get6x5()),
-      GenerateASTCPartitionTree(Footprint::Get6x6()),
-      GenerateASTCPartitionTree(Footprint::Get8x5()),
-      GenerateASTCPartitionTree(Footprint::Get8x6()),
-      GenerateASTCPartitionTree(Footprint::Get8x8()),
-      GenerateASTCPartitionTree(Footprint::Get10x5()),
-      GenerateASTCPartitionTree(Footprint::Get10x6()),
-      GenerateASTCPartitionTree(Footprint::Get10x8()),
-      GenerateASTCPartitionTree(Footprint::Get10x10()),
-      GenerateASTCPartitionTree(Footprint::Get12x10()),
-      GenerateASTCPartitionTree(Footprint::Get12x12()),
-    }};
-
-  const PartitionTree& parts_vptree = kASTCPartitionTrees->at(index);
-  std::vector<const Partition*> results;
-  parts_vptree.Search(candidate, k, &results, nullptr);
-  return results;
-}
-
-// Returns the valid ASTC partition that is closest to the candidate based on
-// the PartitionMetric defined above.
-const Partition& FindClosestASTCPartition(const Partition& candidate) {
-  // Given a candidate, the closest valid partition will likely not be an exact
-  // match. Consider all of the texels for which this valid partition differs
-  // with the candidate.
-  //
-  // If the valid partition has more subsets than the candidate, then all of the
-  // highest subset will be included in the mismatched texels. Since the number
-  // of possible partitions with increasing subsets grows exponentially, the
-  // chance that a valid partition with fewer subsets appears within the first
-  // few closest partitions is relatively high. Empirically, we can usually find
-  // a partition with at most |candidate.num_parts| number of subsets within the
-  // first four closest partitions.
-  constexpr int kSearchItems = 4;
-
-  const std::vector<const Partition*> results =
-      FindKClosestASTCPartitions(candidate, kSearchItems);
-
-  // Optimistically, look for result with the same number of subsets.
-  for (const auto& result : results) {
-    if (result->num_parts == candidate.num_parts) {
-      return *result;
-    }
-  }
-
-  // If all else fails, then at least find the result with fewer subsets than
-  // we asked for.
-  for (const auto& result : results) {
-    if (result->num_parts < candidate.num_parts) {
-      return *result;
-    }
-  }
-
-  assert(false &&
-         "Could not find partition with acceptable number of subsets!");
-  return *(results[0]);
-}
-
-}  // namespace astc_codec

+ 0 - 97
3rdparty/astc-codec/src/decoder/partition.h

@@ -1,97 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#ifndef ASTC_CODEC_DECODER_PARTITION_H_
-#define ASTC_CODEC_DECODER_PARTITION_H_
-
-#include "src/base/optional.h"
-#include "src/decoder/footprint.h"
-
-#include <vector>
-
-namespace astc_codec {
-
-struct Partition;
-
-// Determines the "difference" between any two partitions of the same size.
-// This metric attempts to find the best one to one mapping from the labels in
-// partition a against the labels in partition b. Once that mapping is found, it
-// returns the number of pixels that are mismatched between the two. Each
-// partition is expected to start in the upper left corner of the block and
-// proceed in raster-scan order. Two partitions are equal if the mapping is
-// bijective. This metric is a metric in the mathematical sense. In other words
-// it has the following properties:
-//
-// 1) PartitionMetric(a, b) >= 0
-// 2) PartitionMetric(a, b) == PartitionMetric(b, a)
-// 3) PartitionMetric(a, b) == 0 iff a == b
-// 4) PartitionMetric(a, b) + PartitionMetric(b, c) >= PartitionMetric(a, c)
-//
-// Throws an error if one partition's footprint is not equal to the other.
-int PartitionMetric(const Partition& a, const Partition& b);
-
-// A partition is a way to divide up an ASTC block into disjoint subsets such
-// that each subset uses a different set of endpoints. This is used to increase
-// the compression quality of blocks. One way to store such a partition is to
-// assign an ID to use with a predetermined decoding method. Here we store the
-// logical representation of partitions by keeping a per-pixel label. All pixels
-// that share a label belong to the same subset.
-struct Partition {
-  // The footprint width and height of this partition. This determines the size
-  // of the assignment array.
-  Footprint footprint;
-
-  // The number of subsets in this partition. The values in the partition
-  // assignment fall within the range [0, num_parts). The maximum number of
-  // parts supported is four.
-  int num_parts;
-
-  // The 10-bit partition ID as stored in bits 13-22 of multi-part ASTC blocks.
-  // (See Section C.2.9) If there is no guarantee that this partition is a valid
-  // ASTC partition, this should be set to absl::nullopt.
-  base::Optional<int> partition_id;
-
-  // A value in the range [0, num_parts) corresponding to the label for
-  // the given texel (x, y) in [0, footprint_width) x [0, footprint_height)
-  // using a raster-order layout.
-  std::vector<int> assignment;
-
-  // Returns true only if their "distance" is zero, i.e. if they have compatible
-  // subset assignments.
-  bool operator==(const Partition& other) const {
-    return PartitionMetric(*this, other) == 0;
-  }
-};
-
-// Generates the ASTC partition assignment for the given block attributes.
-Partition GetASTCPartition(const Footprint& footprint, int num_parts,
-                           int partition_id);
-
-// Returns the |k| valid ASTC partitions that are closest to the candidate based
-// on the PartitionMetric defined above.
-const std::vector<const Partition*> FindKClosestASTCPartitions(
-    const Partition& candidate, int k);
-
-// Returns the valid ASTC partition closest to the candidate with at most as
-// many subsets as the |candidate|. Note: this is not a deterministic function,
-// as the underlying valid partitions are sorted using a hash map and a distance
-// function whose range is the natural numbers. The chances that two or more
-// partitions are equally 'closest' is possible, in which case this function
-// makes no guarantees about which one it will return. For more control, use
-// FindKClosestASTCPartitions above.
-const Partition& FindClosestASTCPartition(const Partition& candidate);
-
-}  // namespace astc_codec
-
-#endif  // ASTC_CODEC_DECODER_PARTITION_H_

+ 0 - 761
3rdparty/astc-codec/src/decoder/physical_astc_block.cc

@@ -1,761 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#include "src/decoder/physical_astc_block.h"
-#include "src/base/math_utils.h"
-#include "src/base/optional.h"
-#include "src/base/uint128.h"
-#include "src/decoder/integer_sequence_codec.h"
-
-#include <array>
-#include <cmath>
-
-namespace astc_codec {
-
-namespace {
-
-static_assert(static_cast<int>(ColorEndpointMode::kNumColorEndpointModes) == 16,
-              "There are only sixteen color endpoint modes defined in the "
-              "ASTC specification. If this is false, then the enum may be "
-              "incorrect.");
-
-constexpr int kASTCBlockSizeBits = 128;
-//constexpr int kASTCBlockSizeBytes = kASTCBlockSizeBits / 8;
-constexpr uint32_t kVoidExtentMaskBits = 9;
-constexpr uint32_t kVoidExtentMask = 0x1FC;
-constexpr int kWeightGridMinBitLength = 24;
-constexpr int kWeightGridMaxBitLength = 96;
-constexpr int kMaxNumPartitions = 4;
-constexpr int kMaxNumWeights = 64;
-
-// These are the overall block modes defined in table C.2.8.  There are 10
-// weight grid encoding schemes + void extent.
-enum class BlockMode {
-  kB4_A2,
-  kB8_A2,
-  kA2_B8,
-  kA2_B6,
-  kB2_A2,
-  k12_A2,
-  kA2_12,
-  k6_10,
-  k10_6,
-  kA6_B6,
-  kVoidExtent,
-};
-
-struct WeightGridProperties {
-  int width;
-  int height;
-  int range;
-};
-
-// Local function prototypes
-base::Optional<BlockMode> DecodeBlockMode(const base::UInt128 astc_bits);
-base::Optional<WeightGridProperties> DecodeWeightProps(
-    const base::UInt128 astc_bits, std::string* error);
-std::array<int, 4> DecodeVoidExtentCoords(const base::UInt128 astc_bits);
-bool DecodeDualPlaneBit(const base::UInt128 astc_bits);
-int DecodeNumPartitions(const base::UInt128 astc_bits);
-int DecodeNumWeightBits(const base::UInt128 astc_bits);
-int DecodeDualPlaneBitStartPos(const base::UInt128 astc_bits);
-ColorEndpointMode DecodeEndpointMode(const base::UInt128 astc_bits,
-                                     int partition);
-int DecodeNumColorValues(const base::UInt128 astc_bits);
-
-// Returns the block mode, if it's valid.
-base::Optional<BlockMode> DecodeBlockMode(const base::UInt128 astc_bits) {
-  using Result = base::Optional<BlockMode>;
-  const uint64_t low_bits = astc_bits.LowBits();
-  if (base::GetBits(low_bits, 0, kVoidExtentMaskBits) == kVoidExtentMask) {
-    return Result(BlockMode::kVoidExtent);
-  }
-
-  if (base::GetBits(low_bits, 0, 2) != 0) {
-    const uint64_t mode_bits = base::GetBits(low_bits, 2, 2);
-    switch (mode_bits) {
-      case 0: return Result(BlockMode::kB4_A2);
-      case 1: return Result(BlockMode::kB8_A2);
-      case 2: return Result(BlockMode::kA2_B8);
-      case 3: return base::GetBits(low_bits, 8, 1) ?
-          Result(BlockMode::kB2_A2) : Result(BlockMode::kA2_B6);
-    }
-  } else {
-    const uint64_t mode_bits = base::GetBits(low_bits, 5, 4);
-    if ((mode_bits & 0xC) == 0x0) {
-      if (base::GetBits(low_bits, 0, 4) == 0) {
-        // Reserved.
-        return Result();
-      } else {
-        return Result(BlockMode::k12_A2);
-      }
-    } else if ((mode_bits & 0xC) == 0x4) {
-      return Result(BlockMode::kA2_12);
-    } else if (mode_bits == 0xC) {
-      return Result(BlockMode::k6_10);
-    } else if (mode_bits == 0xD) {
-      return Result(BlockMode::k10_6);
-    } else if ((mode_bits & 0xC) == 0x8) {
-      return Result(BlockMode::kA6_B6);
-    }
-  }
-
-  return Result();
-}
-
-base::Optional<WeightGridProperties> DecodeWeightProps(
-    const base::UInt128 astc_bits, std::string* error) {
-  auto block_mode = DecodeBlockMode(astc_bits);
-  if (!block_mode) {
-    *error = "Reserved block mode";
-    return {};
-  }
-
-  // The dimensions of the weight grid and their range
-  WeightGridProperties props;
-
-  // Determine the weight extents based on the block mode
-  const uint32_t low_bits =
-      static_cast<uint32_t>(astc_bits.LowBits() & 0xFFFFFFFF);
-  switch (block_mode.value()) {
-    case BlockMode::kB4_A2: {
-      int a = base::GetBits(low_bits, 5, 2);
-      int b = base::GetBits(low_bits, 7, 2);
-      props.width = b + 4;
-      props.height = a + 2;
-    }
-    break;
-
-    case BlockMode::kB8_A2: {
-      int a = base::GetBits(low_bits, 5, 2);
-      int b = base::GetBits(low_bits, 7, 2);
-      props.width = b + 8;
-      props.height = a + 2;
-    }
-    break;
-
-    case BlockMode::kA2_B8: {
-      int a = base::GetBits(low_bits, 5, 2);
-      int b = base::GetBits(low_bits, 7, 2);
-      props.width = a + 2;
-      props.height = b + 8;
-    }
-    break;
-
-    case BlockMode::kA2_B6: {
-      int a = base::GetBits(low_bits, 5, 2);
-      int b = base::GetBits(low_bits, 7, 1);
-      props.width = a + 2;
-      props.height = b + 6;
-    }
-    break;
-
-    case BlockMode::kB2_A2: {
-      int a = base::GetBits(low_bits, 5, 2);
-      int b = base::GetBits(low_bits, 7, 1);
-      props.width = b + 2;
-      props.height = a + 2;
-    }
-    break;
-
-    case BlockMode::k12_A2: {
-      int a = base::GetBits(low_bits, 5, 2);
-      props.width = 12;
-      props.height = a + 2;
-    }
-    break;
-
-    case BlockMode::kA2_12: {
-      int a = base::GetBits(low_bits, 5, 2);
-      props.width = a + 2;
-      props.height = 12;
-    }
-    break;
-
-    case BlockMode::k6_10: {
-      props.width = 6;
-      props.height = 10;
-    }
-    break;
-
-    case BlockMode::k10_6: {
-      props.width = 10;
-      props.height = 6;
-    }
-    break;
-
-    case BlockMode::kA6_B6: {
-      int a = base::GetBits(low_bits, 5, 2);
-      int b = base::GetBits(low_bits, 9, 2);
-      props.width = a + 6;
-      props.height = b + 6;
-    }
-    break;
-
-    // Void extent blocks have no weight grid.
-    case BlockMode::kVoidExtent:
-      *error = "Void extent block has no weight grid";
-      return {};
-
-    // We have a valid block mode which isn't a void extent? We
-    // should be able to decode the weight grid dimensions.
-    default:
-      assert(false && "Error decoding weight grid");
-      *error = "Internal error";
-      return {};
-  }
-
-  // Determine the weight range based on the block mode
-  uint32_t r = base::GetBits(low_bits, 4, 1);
-  switch (block_mode.value()) {
-    case BlockMode::kB4_A2:
-    case BlockMode::kB8_A2:
-    case BlockMode::kA2_B8:
-    case BlockMode::kA2_B6:
-    case BlockMode::kB2_A2: {
-      r |= base::GetBits(low_bits, 0, 2) << 1;
-    }
-    break;
-
-    case BlockMode::k12_A2:
-    case BlockMode::kA2_12:
-    case BlockMode::k6_10:
-    case BlockMode::k10_6:
-    case BlockMode::kA6_B6:  {
-      r |= base::GetBits(low_bits, 2, 2) << 1;
-    }
-    break;
-
-    // We have a valid block mode which doesn't have weights? We
-    // should have caught this earlier.
-    case BlockMode::kVoidExtent:
-    default:
-      assert(false && "Error decoding weight grid");
-      *error = "Internal error";
-      return {};
-  }
-
-  // Decode the range...
-  // High bit is in bit 9 unless we're using a particular block mode
-  uint32_t h = base::GetBits(low_bits, 9, 1);
-  if (block_mode == BlockMode::kA6_B6) {
-    h = 0;
-  }
-
-  // Figure out the range of the weights (Table C.2.7)
-  constexpr std::array<int, 16> kWeightRanges = {{
-      -1, -1, 1, 2, 3, 4, 5, 7, -1, -1, 9, 11, 15, 19, 23, 31
-    }};
-
-  assert(((h << 3) | r) < kWeightRanges.size());
-
-  props.range = kWeightRanges.at((h << 3) | r);
-  if (props.range < 0) {
-    *error = "Reserved range for weight bits";
-    return {};
-  }
-
-  // Error checking -- do we have too many weights?
-  int num_weights = props.width * props.height;
-  if (DecodeDualPlaneBit(astc_bits)) {
-    num_weights *= 2;
-  }
-
-  if (kMaxNumWeights < num_weights) {
-    *error = "Too many weights specified";
-    return {};
-  }
-
-  // Do we have too many weight bits?
-  const int bit_count =
-      IntegerSequenceCodec::GetBitCountForRange(num_weights, props.range);
-
-  if (bit_count < kWeightGridMinBitLength) {
-    *error = "Too few bits required for weight grid";
-    return {};
-  }
-
-  if (kWeightGridMaxBitLength < bit_count) {
-    *error = "Too many bits required for weight grid";
-    return {};
-  }
-
-  return props;
-}
-
-// Returns the four 13-bit integers that define the range of texture
-// coordinates present in a void extent block as defined in Section
-// C.2.23 of the specification. The coordinates returned are of
-// the form (min_s, max_s, min_t, max_t)
-std::array<int, 4> DecodeVoidExtentCoords(const base::UInt128 astc_bits) {
-  const uint64_t low_bits = astc_bits.LowBits();
-
-  std::array<int, 4> coords;
-  for (int i = 0; i < 4; ++i) {
-    coords[i] = static_cast<int>(base::GetBits(low_bits, 12 + 13 * i, 13));
-  }
-
-  return coords;
-}
-
-bool DecodeDualPlaneBit(const base::UInt128 astc_bits) {
-  base::Optional<BlockMode> block_mode = DecodeBlockMode(astc_bits);
-
-  // Void extent blocks certainly aren't dual-plane.
-  if (block_mode == BlockMode::kVoidExtent) {
-    return false;
-  }
-
-  // One special block mode doesn't have any dual plane bit
-  if (block_mode == BlockMode::kA6_B6) {
-    return false;
-  }
-
-  // Otherwise, dual plane is determined by the 10th bit.
-  constexpr int kDualPlaneBitPosition = 10;
-  return base::GetBits(astc_bits, kDualPlaneBitPosition, 1) != 0;
-}
-
-int DecodeNumPartitions(const base::UInt128 astc_bits) {
-  constexpr int kNumPartitionsBitPosition = 11;
-  constexpr int kNumPartitionsBitLength = 2;
-
-  // Non-void extent blocks
-  const uint64_t low_bits = astc_bits.LowBits();
-  const int num_partitions = 1 + static_cast<int>(
-      base::GetBits(low_bits,
-                    kNumPartitionsBitPosition,
-                    kNumPartitionsBitLength));
-  assert(num_partitions > 0);
-  assert(num_partitions <= kMaxNumPartitions);
-
-  return num_partitions;
-}
-
-int DecodeNumWeightBits(const base::UInt128 astc_bits) {
-  std::string error;
-  auto maybe_weight_props = DecodeWeightProps(astc_bits, &error);
-  if (!maybe_weight_props.hasValue()) {
-    return 0;  // No weights? No weight bits...
-  }
-
-  const auto weight_props = maybe_weight_props.value();
-
-  // Figure out the number of weights
-  int num_weights = weight_props.width * weight_props.height;
-  if (DecodeDualPlaneBit(astc_bits)) {
-    num_weights *= 2;
-  }
-
-  // The number of bits is determined by the number of values
-  // that are going to be encoded using the given ise_counts.
-  return IntegerSequenceCodec::GetBitCountForRange(
-      num_weights, weight_props.range);
-}
-
-// Returns the number of bits after the weight data used to
-// store additional CEM bits.
-int DecodeNumExtraCEMBits(const base::UInt128 astc_bits) {
-  const int num_partitions = DecodeNumPartitions(astc_bits);
-
-  // Do we only have one partition?
-  if (num_partitions == 1) {
-    return 0;
-  }
-
-  // Do we have a shared CEM?
-  constexpr int kSharedCEMBitPosition = 23;
-  constexpr int kSharedCEMBitLength = 2;
-  const base::UInt128 shared_cem =
-      base::GetBits(astc_bits, kSharedCEMBitPosition, kSharedCEMBitLength);
-  if (shared_cem == 0) {
-    return 0;
-  }
-
-  const std::array<int, 4> extra_cem_bits_for_partition = {{ 0, 2, 5, 8 }};
-  return extra_cem_bits_for_partition[num_partitions - 1];
-}
-
-// Returns the starting position of the dual plane channel. This comes
-// before the weight data and extra CEM bits.
-int DecodeDualPlaneBitStartPos(const base::UInt128 astc_bits) {
-  const int start_pos = kASTCBlockSizeBits
-      - DecodeNumWeightBits(astc_bits)
-      - DecodeNumExtraCEMBits(astc_bits);
-
-  if (DecodeDualPlaneBit(astc_bits)) {
-    return start_pos - 2;
-  } else {
-    return start_pos;
-  }
-}
-
-// Decodes a CEM mode based on the partition number.
-ColorEndpointMode DecodeEndpointMode(const base::UInt128 astc_bits,
-                                     int partition) {
-  int num_partitions = DecodeNumPartitions(astc_bits);
-  assert(partition >= 0);
-  assert(partition < num_partitions);
-
-  // Do we only have one partition?
-  uint64_t low_bits = astc_bits.LowBits();
-  if (num_partitions == 1) {
-    uint64_t cem = base::GetBits(low_bits, 13, 4);
-    return static_cast<ColorEndpointMode>(cem);
-  }
-
-  // More than one partition ... do we have a shared CEM?
-  if (DecodeNumExtraCEMBits(astc_bits) == 0) {
-    const uint64_t shared_cem = base::GetBits(low_bits, 25, 4);
-    return static_cast<ColorEndpointMode>(shared_cem);
-  }
-
-  // More than one partition and no shared CEM...
-  uint64_t cem = base::GetBits(low_bits, 23, 6);
-  const int base_cem = static_cast<int>(((cem & 0x3) - 1) * 4);
-  cem >>= 2;  // Skip the base CEM bits
-
-  // The number of extra CEM bits at the end of the weight grid is
-  // determined by the number of partitions and what the base cem mode is...
-  const int num_extra_cem_bits = DecodeNumExtraCEMBits(astc_bits);
-  const int extra_cem_start_pos = kASTCBlockSizeBits
-      - num_extra_cem_bits
-      - DecodeNumWeightBits(astc_bits);
-
-  base::UInt128 extra_cem =
-      base::GetBits(astc_bits, extra_cem_start_pos, num_extra_cem_bits);
-  cem |= extra_cem.LowBits() << 4;
-
-  // Decode C and M per Figure C.4
-  int c = -1, m = -1;
-  for (int i = 0; i < num_partitions; ++i) {
-    if (i == partition) {
-      c = cem & 0x1;
-    }
-    cem >>= 1;
-  }
-
-  for (int i = 0; i < num_partitions; ++i) {
-    if (i == partition) {
-      m = cem & 0x3;
-    }
-    cem >>= 2;
-  }
-
-  assert(c >= 0);
-  assert(m >= 0);
-
-  // Compute the mode based on C and M
-  const int mode = base_cem + 4 * c + m;
-  assert(mode < static_cast<int>(ColorEndpointMode::kNumColorEndpointModes));
-  return static_cast<ColorEndpointMode>(mode);
-}
-
-int DecodeNumColorValues(const base::UInt128 astc_bits) {
-  int num_color_values = 0;
-  auto num_partitions = DecodeNumPartitions(astc_bits);
-  for (int i = 0; i < num_partitions; ++i) {
-    ColorEndpointMode endpoint_mode = DecodeEndpointMode(astc_bits, i);
-    num_color_values += NumColorValuesForEndpointMode(endpoint_mode);
-  }
-
-  return num_color_values;
-}
-
-}  // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-
-static_assert(sizeof(PhysicalASTCBlock) == PhysicalASTCBlock::kSizeInBytes,
-              "The size of the struct should be the size of the block so that"
-              "we can effectively use them contiguously in memory.");
-
-PhysicalASTCBlock::PhysicalASTCBlock(const base::UInt128 astc_block)
-    : astc_bits_(astc_block) {}
-
-PhysicalASTCBlock::PhysicalASTCBlock(const std::string& encoded_block)
-    : astc_bits_([&encoded_block]() {
-        assert(encoded_block.size() == PhysicalASTCBlock::kSizeInBytes);
-        base::UInt128 astc_bits = 0;
-        int shift = 0;
-        for (const unsigned char c : encoded_block) {
-          astc_bits |= base::UInt128(static_cast<uint64_t>(c)) << shift;
-          shift += 8;
-        }
-        return astc_bits;
-      }())
-{ }
-
-base::Optional<std::string> PhysicalASTCBlock::IsIllegalEncoding() const {
-  // If the block is not a void extent block, then it must have
-  // weights specified. DecodeWeightProps will return the weight specifications
-  // if they exist and are legal according to C.2.24, and will otherwise be
-  // empty.
-  base::Optional<BlockMode> block_mode = DecodeBlockMode(astc_bits_);
-  if (block_mode != BlockMode::kVoidExtent) {
-    std::string error;
-    auto maybe_weight_props = DecodeWeightProps(astc_bits_, &error);
-    if (!maybe_weight_props.hasValue()) {
-      return error;
-    }
-  }
-
-  // Check void extent blocks...
-  if (block_mode == BlockMode::kVoidExtent) {
-    // ... for reserved bits incorrectly set
-    if (base::GetBits(astc_bits_, 10, 2) != 0x3) {
-      return std::string("Reserved bits set for void extent block");
-    }
-
-    // ... for incorrectly defined texture coordinates
-    std::array<int, 4> coords = DecodeVoidExtentCoords(astc_bits_);
-
-    bool coords_all_1s = true;
-    for (const auto coord : coords) {
-      coords_all_1s &= coord == ((1 << 13) - 1);
-    }
-
-    if (!coords_all_1s && (coords[0] >= coords[1] || coords[2] >= coords[3])) {
-      return std::string("Void extent texture coordinates are invalid");
-    }
-  }
-
-  // If the number of color values exceeds a threshold and it isn't a void
-  // extent block then we've run into an error
-  if (block_mode != BlockMode::kVoidExtent) {
-    int num_color_vals = DecodeNumColorValues(astc_bits_);
-    if (num_color_vals > 18) {
-      return std::string("Too many color values");
-    }
-
-    // The maximum number of available color bits is the number of
-    // bits between the dual plane bits and the base CEM. This must
-    // be larger than a threshold defined in C.2.24.
-
-    // Dual plane bit starts after weight bits and CEM
-    const int num_partitions = DecodeNumPartitions(astc_bits_);
-    const int dual_plane_start_pos = DecodeDualPlaneBitStartPos(astc_bits_);
-    const int color_start_bit = (num_partitions == 1) ? 17 : 29;
-
-    const int required_color_bits = ((13 * num_color_vals) + 4) / 5;
-    const int available_color_bits = dual_plane_start_pos - color_start_bit;
-    if (available_color_bits < required_color_bits) {
-      return std::string("Not enough color bits");
-    }
-
-    // If we have four partitions and a dual plane then we have a problem.
-    if (num_partitions == 4 && DecodeDualPlaneBit(astc_bits_)) {
-      return std::string("Both four partitions and dual plane specified");
-    }
-  }
-
-  // Otherwise we're OK
-  return { };
-}
-
-bool PhysicalASTCBlock::IsVoidExtent() const {
-  // If it's an error block, it's not a void extent block.
-  if (IsIllegalEncoding()) {
-    return false;
-  }
-
-  return DecodeBlockMode(astc_bits_) == BlockMode::kVoidExtent;
-}
-
-base::Optional<std::array<int, 4>> PhysicalASTCBlock::VoidExtentCoords() const {
-  if (IsIllegalEncoding() || !IsVoidExtent()) {
-    return { };
-  }
-
-  // If void extent coords are all 1's then these are not valid void extent
-  // coords
-  const uint64_t ve_mask = 0xFFFFFFFFFFFFFDFFULL;
-  const uint64_t const_blk_mode = 0xFFFFFFFFFFFFFDFCULL;
-  if ((ve_mask & astc_bits_.LowBits()) == const_blk_mode) {
-    return {};
-  }
-
-  return DecodeVoidExtentCoords(astc_bits_);
-}
-
-bool PhysicalASTCBlock::IsDualPlane() const {
-  // If it's an error block, then we aren't a dual plane block
-  if (IsIllegalEncoding()) {
-    return false;
-  }
-
-  return DecodeDualPlaneBit(astc_bits_);
-}
-
-// Returns the number of weight bits present in this block
-base::Optional<int> PhysicalASTCBlock::NumWeightBits() const {
-  // If it's an error block, then we have no weight bits.
-  if (IsIllegalEncoding()) return { };
-
-  // If it's a void extent block, we have no weight bits
-  if (IsVoidExtent()) return { };
-
-  return DecodeNumWeightBits(astc_bits_);
-}
-
-base::Optional<int> PhysicalASTCBlock::WeightStartBit() const {
-  if (IsIllegalEncoding()) return { };
-  if (IsVoidExtent()) return { };
-
-  return kASTCBlockSizeBits - DecodeNumWeightBits(astc_bits_);
-}
-
-base::Optional<std::array<int, 2>> PhysicalASTCBlock::WeightGridDims() const {
-  std::string error;
-  auto weight_props = DecodeWeightProps(astc_bits_, &error);
-
-  if (!weight_props.hasValue()) return { };
-  if (IsIllegalEncoding()) return { };
-
-  const auto props = weight_props.value();
-  return {{{ props.width, props.height }}};
-}
-
-base::Optional<int> PhysicalASTCBlock::WeightRange() const {
-  std::string error;
-  auto weight_props = DecodeWeightProps(astc_bits_, &error);
-
-  if (!weight_props.hasValue()) return { };
-  if (IsIllegalEncoding()) return { };
-
-  return weight_props.value().range;
-}
-
-base::Optional<int> PhysicalASTCBlock::DualPlaneChannel() const {
-  if (!IsDualPlane()) return { };
-
-  int dual_plane_start_pos = DecodeDualPlaneBitStartPos(astc_bits_);
-  auto plane_bits = base::GetBits(astc_bits_, dual_plane_start_pos, 2);
-  return base::Optional<int>(static_cast<int>(plane_bits.LowBits()));
-}
-
-base::Optional<int> PhysicalASTCBlock::ColorStartBit() const {
-  if (IsVoidExtent()) {
-    return 64;
-  }
-
-  auto num_partitions = NumPartitions();
-  if (!num_partitions) return { };
-
-  return (num_partitions == 1) ? 17 : 29;
-}
-
-base::Optional<int> PhysicalASTCBlock::NumColorValues() const {
-  // If we have a void extent block, then we have four color values
-  if (IsVoidExtent()) {
-    return 4;
-  }
-
-  // If we have an illegal encoding, then we have no color values
-  if (IsIllegalEncoding()) return { };
-
-  return DecodeNumColorValues(astc_bits_);
-}
-
-void PhysicalASTCBlock::GetColorValuesInfo(int* const color_bits,
-                                           int* const color_range) const {
-  // Figure out the range possible for the number of values we have...
-  const int dual_plane_start_pos = DecodeDualPlaneBitStartPos(astc_bits_);
-  const int max_color_bits = dual_plane_start_pos - ColorStartBit().value();
-  const int num_color_values = NumColorValues().value();
-  for (int range = 255; range > 0; --range) {
-    const int bitcount =
-        IntegerSequenceCodec::GetBitCountForRange(num_color_values, range);
-    if (bitcount <= max_color_bits) {
-      if (color_bits != nullptr) {
-        *color_bits = bitcount;
-      }
-
-      if (color_range != nullptr) {
-        *color_range = range;
-      }
-      return;
-    }
-  }
-
-  assert(false &&
-         "This means that even if we have a range of one there aren't "
-         "enough bits to store the color values, and our encoding is "
-         "illegal.");
-}
-
-base::Optional<int> PhysicalASTCBlock::NumColorBits() const {
-  if (IsIllegalEncoding()) return { };
-
-  if (IsVoidExtent()) {
-    return 64;
-  }
-
-  int color_bits;
-  GetColorValuesInfo(&color_bits, nullptr);
-  return color_bits;
-}
-
-base::Optional<int> PhysicalASTCBlock::ColorValuesRange() const {
-  if (IsIllegalEncoding()) return { };
-
-  if (IsVoidExtent()) {
-    return (1 << 16) - 1;
-  }
-
-  int color_range;
-  GetColorValuesInfo(nullptr, &color_range);
-  return color_range;
-}
-
-base::Optional<int> PhysicalASTCBlock::NumPartitions() const {
-  // Error blocks have no partitions
-  if (IsIllegalEncoding()) return { };
-
-  // Void extent blocks have no partitions either
-  if (DecodeBlockMode(astc_bits_) == BlockMode::kVoidExtent) {
-    return { };
-  }
-
-  // All others have some number of partitions
-  return DecodeNumPartitions(astc_bits_);
-}
-
-base::Optional<int> PhysicalASTCBlock::PartitionID() const {
-  auto num_partitions = NumPartitions();
-  if (!num_partitions || num_partitions == 1) return { };
-
-  const uint64_t low_bits = astc_bits_.LowBits();
-  return static_cast<int>(base::GetBits(low_bits, 13, 10));
-}
-
-base::Optional<ColorEndpointMode> PhysicalASTCBlock::GetEndpointMode(
-    int partition) const {
-  // Error block?
-  if (IsIllegalEncoding()) return { };
-
-  // Void extent blocks have no endpoint modes
-  if (DecodeBlockMode(astc_bits_) == BlockMode::kVoidExtent) {
-    return { };
-  }
-
-  // Do we even have a CEM for this partition?
-  if (partition < 0 || DecodeNumPartitions(astc_bits_) <= partition) {
-    return { };
-  }
-
-  return DecodeEndpointMode(astc_bits_, partition);
-}
-
-}  // namespace astc_codec

+ 0 - 128
3rdparty/astc-codec/src/decoder/physical_astc_block.h

@@ -1,128 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#ifndef ASTC_CODEC_DECODER_PHYSICAL_ASTC_BLOCK_H_
-#define ASTC_CODEC_DECODER_PHYSICAL_ASTC_BLOCK_H_
-
-// The logic in this file is based on the ASTC specification, which can be
-// found here:
-// https://www.opengl.org/registry/specs/KHR/texture_compression_astc_hdr.txt
-
-#include "src/base/optional.h"
-#include "src/base/uint128.h"
-#include "src/decoder/types.h"
-
-#include <string>
-
-namespace astc_codec {
-
-// A PhysicalASTCBlock contains all 128 bits and the logic for decoding the
-// various internals of an ASTC block.
-class PhysicalASTCBlock {
- public:
-  // The physical size in bytes of an ASTC block
-  static const size_t kSizeInBytes = 16;
-
-  // Initializes an ASTC block based on the encoded string.
-  explicit PhysicalASTCBlock(const std::string& encoded_block);
-  explicit PhysicalASTCBlock(const base::UInt128 astc_block);
-
-  // Returns the 128 bits of this ASTC block.
-  base::UInt128 GetBlockBits() const { return astc_bits_; }
-
-  // Weights are stored in a grid that may not have the same dimensions
-  // as the block dimensions. This allows us to see what the physical
-  // dimensions are of the grid.
-  base::Optional<std::array<int, 2>> WeightGridDims() const;
-
-  // The weight range is the maximum value a weight can take in the
-  // weight grid.
-  base::Optional<int> WeightRange() const;
-
-  // Returns true if the block encoding specifies a void-extent block. This
-  // kind of block stores a single color to be used for every pixel in the
-  // block.
-  bool IsVoidExtent() const;
-
-  // Returns the values (min_s, max_s, min_t, max_t) as defined in the void
-  // extent block as the range of texture coordinates for which this block is
-  // defined. (See Section C.2.23)
-  base::Optional<std::array<int, 4>> VoidExtentCoords() const;
-
-  // Returns true if the block contains two separate weight grids. One used
-  // for the channel returned by DualPlaneChannel() and one used by the other
-  // channels.
-  bool IsDualPlane() const;
-
-  // Returns the channel used as the "dual plane". The return value is only
-  // meaningful if IsDualPlane() returns true...
-  base::Optional<int> DualPlaneChannel() const;
-
-  // Returns a reason that the encoding doesn't adhere to the specification.
-  // If the encoding is legal, then this returns a nullptr. This allows us to
-  // still use code of the form:
-  //
-  //     if (IsIllegalEncoding()) {
-  //       ... error ...
-  //     }
-  //     ... no error ...
-  //
-  // However, it also helps with debugging since we can find problems with
-  // encodings a lot faster.
-  base::Optional<std::string> IsIllegalEncoding() const;
-
-  // Returns the number of weight bits present in this block.
-  base::Optional<int> NumWeightBits() const;
-
-  // Returns the starting position within the range [0, 127] of the
-  // weight data within the block.
-  base::Optional<int> WeightStartBit() const;
-
-  // Returns the number of endpoint pairs used in this block.
-  base::Optional<int> NumPartitions() const;
-
-  // Returns the seed used to determine the partition for a given
-  // (x, y) coordinate within the block. Determined using the
-  // block size and the function as described in the specification.
-  base::Optional<int> PartitionID() const;
-
-  // Returns the color endpoint mode for the given partition index.
-  base::Optional<ColorEndpointMode> GetEndpointMode(int partition) const;
-
-  // Returns the starting position within the range [0, 127] of the
-  // color data within the block.
-  base::Optional<int> ColorStartBit() const;
-
-  // Returns the number of integers used to represent the color endpoints.
-  base::Optional<int> NumColorValues() const;
-
-  // Returns the number of bits used to represent the color endpoints.
-  base::Optional<int> NumColorBits() const;
-
-  // Returns the maximum value that each of the encoded integers used to
-  // represent the color endpoints can take.
-  base::Optional<int> ColorValuesRange() const;
-
- private:
-  const base::UInt128 astc_bits_;
-
-  // The logic to return the number of color bits and the color values range
-  // is very similar, so it's probably best to abstract it away into its own
-  // function.
-  void GetColorValuesInfo(int* color_bits, int* color_range) const;
-};
-
-}  // namespace astc_codec
-
-#endif  // ASTC_CODEC_DECODER_PHYSICAL_ASTC_BLOCK_H_

+ 0 - 462
3rdparty/astc-codec/src/decoder/quantization.cc

@@ -1,462 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#include "src/decoder/quantization.h"
-#include "src/base/math_utils.h"
-
-#include <algorithm>
-#include <array>
-#include <cassert>
-#include <map>
-#include <memory>
-#include <vector>
-
-namespace astc_codec {
-
-namespace {
-
-// Trit unquantization procedure as described in Section C.2.13
-int GetUnquantizedTritValue(int trit, int bits, int range) {
-  int a = (bits & 1) ? 0x1FF : 0;
-  int b = 0, c = 0;
-  switch (range) {
-    case 5: {
-      b = 0;
-      c = 204;
-    }
-      break;
-
-    case 11: {
-      int x = (bits >> 1) & 0x1;
-      b = (x << 1) | (x << 2) | (x << 4) | (x << 8);
-      c = 93;
-    }
-      break;
-
-    case 23: {
-      int x = (bits >> 1) & 0x3;
-      b = x | (x << 2) | (x << 7);
-      c = 44;
-    }
-      break;
-
-    case 47: {
-      int x = (bits >> 1) & 0x7;
-      b = x | (x << 6);
-      c = 22;
-    }
-      break;
-
-    case 95: {
-      int x = (bits >> 1) & 0xF;
-      b = (x >> 2) | (x << 5);
-      c = 11;
-    }
-      break;
-
-    case 191: {
-      int x = (bits >> 1) & 0x1F;
-      b = (x >> 4) | (x << 4);
-      c = 5;
-    }
-      break;
-
-    default:
-      assert(false && "Illegal trit encoding");
-      break;
-  }
-
-  int t = trit * c + b;
-  t ^= a;
-  t = (a & 0x80) | (t >> 2);
-  return t;
-}
-
-// Quint unquantization procedure as described in Section C.2.13
-int GetUnquantizedQuintValue(int quint, int bits, int range) {
-  int a = (bits & 1) ? 0x1FF : 0;
-  int b = 0, c = 0;
-  switch (range) {
-    case 9: {
-      b = 0;
-      c = 113;
-    }
-      break;
-
-    case 19: {
-      int x = (bits >> 1) & 0x1;
-      b = (x << 2) | (x << 3) | (x << 8);
-      c = 54;
-    }
-      break;
-
-    case 39: {
-      int x = (bits >> 1) & 0x3;
-      b = (x >> 1) | (x << 1) | (x << 7);
-      c = 26;
-    }
-      break;
-
-    case 79: {
-      int x = (bits >> 1) & 0x7;
-      b = (x >> 1) | (x << 6);
-      c = 13;
-    }
-      break;
-
-    case 159: {
-      int x = (bits >> 1) & 0xF;
-      b = (x >> 3) | (x << 5);
-      c = 6;
-    }
-      break;
-
-    default:
-      assert(false && "Illegal quint encoding");
-      break;
-  }
-
-  int t = quint * c + b;
-  t ^= a;
-  t = (a & 0x80) | (t >> 2);
-  return t;
-}
-
-// Trit unquantization procedure as described in Section C.2.17. In the code
-// below, the variables a, b, and c correspond to the columns A, B, and C in
-// the specification.
-int GetUnquantizedTritWeight(int trit, int bits, int range) {
-  int a = (bits & 1) ? 0x7F : 0;
-  int b = 0, c = 0;
-  switch (range) {
-    case 2:
-      return (std::array<int, 3> {{ 0, 32, 63 }})[trit];
-
-    case 5:
-      c = 50;
-      b = 0;
-      break;
-
-    case 11: {
-      c = 23;
-      b = (bits >> 1) & 1;
-      b |= (b << 2) | (b << 6);
-    }
-    break;
-
-    case 23: {
-      c = 11;
-      b = (bits >> 1) & 0x3;
-      b |= (b << 5);
-    }
-    break;
-
-    default:
-      assert(false && "Illegal trit encoding");
-      break;
-  }
-
-  int t = trit * c + b;
-  t ^= a;
-  t = (a & 0x20) | (t >> 2);
-  return t;
-}
-
-// Quint unquantization procedure as described in Section C.2.17. In the code
-// below, the variables a, b, and c correspond to the columns A, B, and C in
-// the specification.
-int GetUnquantizedQuintWeight(int quint, int bits, int range) {
-  int a = (bits & 1) ? 0x7F : 0;
-  int b = 0, c = 0;
-  switch (range) {
-    case 4:
-      return (std::array<int, 5> {{ 0, 16, 32, 47, 63 }})[quint];
-
-    case 9:
-      c = 28;
-      b = 0;
-      break;
-
-    case 19: {
-      c = 13;
-      b = (bits >> 1) & 0x1;
-      b = (b << 1) | (b << 6);
-    }
-    break;
-
-    default:
-      assert(false && "Illegal quint encoding");
-      break;
-  }
-
-  int t = quint * c + b;
-  t ^= a;
-  t = (a & 0x20) | (t >> 2);
-  return t;
-}
-
-// A Quantization map allows us to convert to/from values that are quantized
-// according to the ASTC spec.
-class QuantizationMap {
- public:
-  int Quantize(size_t x) const {
-    return x < quantization_map_.size() ? quantization_map_.at(x) : 0;
-  }
-
-  int Unquantize(size_t x) const {
-    return x < unquantization_map_.size() ? unquantization_map_.at(x) : 0;
-  }
-
- protected:
-  QuantizationMap() { }
-  std::vector<int> quantization_map_;
-  std::vector<int> unquantization_map_;
-
-  void GenerateQuantizationMap() {
-    assert(unquantization_map_.size() > 1);
-    quantization_map_.clear();
-
-    // TODO(google) For weights, we don't need quantization values all the
-    // way up to 256, but it doesn't hurt -- just wastes memory, but the code
-    // is much cleaner this way
-    for (int i = 0; i < 256; ++i) {
-      int best_idx = 0;
-      int best_idx_score = 256;
-      int idx = 0;
-      for (int unquantized_val : unquantization_map_) {
-        const int diff = i - unquantized_val;
-        const int idx_score = diff * diff;
-        if (idx_score < best_idx_score) {
-          best_idx = idx;
-          best_idx_score = idx_score;
-        }
-        idx++;
-      }
-
-      quantization_map_.push_back(best_idx);
-    }
-  }
-};
-
-template<int (*UnquantizationFunc)(int, int, int)>
-class TritQuantizationMap : public QuantizationMap {
- public:
-  explicit TritQuantizationMap(int range) : QuantizationMap() {
-    assert((range + 1) % 3 == 0);
-    const int num_bits_pow_2 = (range + 1) / 3;
-    const int num_bits =
-        num_bits_pow_2 == 0 ? 0 : base::Log2Floor(num_bits_pow_2);
-
-    for (int trit = 0; trit < 3; ++trit) {
-      for (int bits = 0; bits < (1 << num_bits); ++bits) {
-        unquantization_map_.push_back(UnquantizationFunc(trit, bits, range));
-      }
-    }
-
-    GenerateQuantizationMap();
-  }
-};
-
-template<int (*UnquantizationFunc)(int, int, int)>
-class QuintQuantizationMap : public QuantizationMap {
- public:
-  explicit QuintQuantizationMap(int range) : QuantizationMap() {
-    assert((range + 1) % 5 == 0);
-    const int num_bits_pow_2 = (range + 1) / 5;
-    const int num_bits =
-        num_bits_pow_2 == 0 ? 0 : base::Log2Floor(num_bits_pow_2);
-
-    for (int quint = 0; quint < 5; ++quint) {
-      for (int bits = 0; bits < (1 << num_bits); ++bits) {
-        unquantization_map_.push_back(UnquantizationFunc(quint, bits, range));
-      }
-    }
-
-    GenerateQuantizationMap();
-  }
-};
-
-template<int TotalUnquantizedBits>
-class BitQuantizationMap : public QuantizationMap {
- public:
-  explicit BitQuantizationMap<TotalUnquantizedBits>(int range)
-      : QuantizationMap() {
-    // Make sure that if we're using bits then we have a positive power of two.
-    assert(base::CountOnes(range + 1) == 1);
-
-    const int num_bits = base::Log2Floor(range + 1);
-    for (int bits = 0; bits <= range; ++bits) {
-      // Need to replicate bits until we fill up the bits
-      size_t unquantized = bits;
-      int num_unquantized_bits = num_bits;
-      while (num_unquantized_bits < TotalUnquantizedBits) {
-        const int num_dst_bits_to_shift_up =
-            std::min(num_bits, TotalUnquantizedBits - num_unquantized_bits);
-        const int num_src_bits_to_shift_down =
-            num_bits - num_dst_bits_to_shift_up;
-        unquantized <<= num_dst_bits_to_shift_up;
-        unquantized |= bits >> num_src_bits_to_shift_down;
-        num_unquantized_bits += num_dst_bits_to_shift_up;
-      }
-      assert(num_unquantized_bits == TotalUnquantizedBits);
-
-      unquantization_map_.push_back(int(unquantized));
-
-      // Fill half of the quantization map with the previous value for bits
-      // and the other half with the current value for bits
-      if (bits > 0) {
-        const size_t prev_unquant = unquantization_map_.at(bits - 1);
-        while (quantization_map_.size() <= (prev_unquant + unquantized) / 2) {
-          quantization_map_.push_back(bits - 1);
-        }
-      }
-      while (quantization_map_.size() <= unquantized) {
-        quantization_map_.push_back(bits);
-      }
-    }
-
-    assert(quantization_map_.size() == 1 << TotalUnquantizedBits);
-  }
-};
-
-using QMap = std::shared_ptr<QuantizationMap>;
-
-// Returns the quantization map for quantizing color values in [0, 255] with the
-// smallest range that can accommodate |r|
-static const QuantizationMap* GetQuantMapForValueRange(int r) {
-  // Endpoint values can be quantized using bits, trits, or quints. Here we
-  // store the quantization maps for each of the ranges that are supported by
-  // such an encoding. That way we can choose the proper quantization procedure
-  // based on the range of values rather than by having complicated switches and
-  // logic. We must use a std::map here instead of a std::unordered_map because
-  // of the assumption made in std::upper_bound about the iterators being from a
-  // poset.
-  static const auto* const kASTCEndpointQuantization = new std::map<int, QMap> {
-    { 5, QMap(new TritQuantizationMap<GetUnquantizedTritValue>(5)) },
-    { 7, QMap(new BitQuantizationMap<8>(7)) },
-    { 9, QMap(new QuintQuantizationMap<GetUnquantizedQuintValue>(9)) },
-    { 11, QMap(new TritQuantizationMap<GetUnquantizedTritValue>(11)) },
-    { 15, QMap(new BitQuantizationMap<8>(15)) },
-    { 19, QMap(new QuintQuantizationMap<GetUnquantizedQuintValue>(19)) },
-    { 23, QMap(new TritQuantizationMap<GetUnquantizedTritValue>(23)) },
-    { 31, QMap(new BitQuantizationMap<8>(31)) },
-    { 39, QMap(new QuintQuantizationMap<GetUnquantizedQuintValue>(39)) },
-    { 47, QMap(new TritQuantizationMap<GetUnquantizedTritValue>(47)) },
-    { 63, QMap(new BitQuantizationMap<8>(63)) },
-    { 79, QMap(new QuintQuantizationMap<GetUnquantizedQuintValue>(79)) },
-    { 95, QMap(new TritQuantizationMap<GetUnquantizedTritValue>(95)) },
-    { 127, QMap(new BitQuantizationMap<8>(127)) },
-    { 159, QMap(new QuintQuantizationMap<GetUnquantizedQuintValue>(159)) },
-    { 191, QMap(new TritQuantizationMap<GetUnquantizedTritValue>(191)) },
-    { 255, QMap(new BitQuantizationMap<8>(255)) },
-  };
-
-  assert(r < 256);
-  auto itr = kASTCEndpointQuantization->upper_bound(r);
-  if (itr != kASTCEndpointQuantization->begin()) {
-    return (--itr)->second.get();
-  }
-  return nullptr;
-}
-
-// Returns the quantization map for weight values in [0, 63] with the smallest
-// range that can accommodate |r|
-static const QuantizationMap* GetQuantMapForWeightRange(int r) {
-  // Similar to endpoint quantization, weights can also be stored using trits,
-  // quints, or bits. Here we store the quantization maps for each of the ranges
-  // that are supported by such an encoding.
-  static const auto* const kASTCWeightQuantization = new std::map<int, QMap> {
-    { 1, QMap(new BitQuantizationMap<6>(1)) },
-    { 2, QMap(new TritQuantizationMap<GetUnquantizedTritWeight>(2)) },
-    { 3, QMap(new BitQuantizationMap<6>(3)) },
-    { 4, QMap(new QuintQuantizationMap<GetUnquantizedQuintWeight>(4)) },
-    { 5, QMap(new TritQuantizationMap<GetUnquantizedTritWeight>(5)) },
-    { 7, QMap(new BitQuantizationMap<6>(7)) },
-    { 9, QMap(new QuintQuantizationMap<GetUnquantizedQuintWeight>(9)) },
-    { 11, QMap(new TritQuantizationMap<GetUnquantizedTritWeight>(11)) },
-    { 15, QMap(new BitQuantizationMap<6>(15)) },
-    { 19, QMap(new QuintQuantizationMap<GetUnquantizedQuintWeight>(19)) },
-    { 23, QMap(new TritQuantizationMap<GetUnquantizedTritWeight>(23)) },
-    { 31, QMap(new BitQuantizationMap<6>(31)) },
-  };
-
-  assert(r < 32);
-  auto itr = kASTCWeightQuantization->upper_bound(r);
-  if (itr != kASTCWeightQuantization->begin()) {
-    return (--itr)->second.get();
-  }
-  return nullptr;
-}
-
-}  // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-
-int QuantizeCEValueToRange(int value, int range_max_value) {
-  assert(range_max_value >= kEndpointRangeMinValue);
-  assert(range_max_value <= 255);
-  assert(value >= 0);
-  assert(value <= 255);
-
-  const QuantizationMap* map = GetQuantMapForValueRange(range_max_value);
-  return map ? map->Quantize(value) : 0;
-}
-
-int UnquantizeCEValueFromRange(int value, int range_max_value) {
-  assert(range_max_value >= kEndpointRangeMinValue);
-  assert(range_max_value <= 255);
-  assert(value >= 0);
-  assert(value <= range_max_value);
-
-  const QuantizationMap* map = GetQuantMapForValueRange(range_max_value);
-  return map ? map->Unquantize(value) : 0;
-}
-
-int QuantizeWeightToRange(int weight, int range_max_value) {
-  assert(range_max_value >= 1);
-  assert(range_max_value <= kWeightRangeMaxValue);
-  assert(weight >= 0);
-  assert(weight <= 64);
-
-  // The quantization maps that define weight unquantization expect values in
-  // the range [0, 64), but the specification quantizes them to the range
-  // [0, 64] according to C.2.17. This is a slight hack similar to the one in
-  // the unquantization procedure to return the passed in unquantized value to
-  // [0, 64) prior to running it through the quantization procedure.
-  if (weight > 33) {
-    weight -= 1;
-  }
-  const QuantizationMap* map = GetQuantMapForWeightRange(range_max_value);
-  return map ? map->Quantize(weight) : 0;
-}
-
-int UnquantizeWeightFromRange(int weight, int range_max_value) {
-  assert(range_max_value >= 1);
-  assert(range_max_value <= kWeightRangeMaxValue);
-  assert(weight >= 0);
-  assert(weight <= range_max_value);
-  const QuantizationMap* map = GetQuantMapForWeightRange(range_max_value);
-  int dq = map ? map->Unquantize(weight) : 0;
-
-  // Quantized weights are returned in the range [0, 64), but they should be
-  // returned in the range [0, 64], so according to C.2.17 we need to add one
-  // to the result.
-  assert(dq < 64);
-  if (dq > 32) {
-    dq += 1;
-  }
-  return dq;
-}
-
-}  // namespace astc_codec

+ 0 - 65
3rdparty/astc-codec/src/decoder/quantization.h

@@ -1,65 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#ifndef ASTC_CODEC_DECODER_QUANTIZATION_H_
-#define ASTC_CODEC_DECODER_QUANTIZATION_H_
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// ASTC Quantization procedures.
-//
-// The values stored in ASTC blocks tend to be stored in a range much more
-// restricted than the logical range used. For example, sometimes weights are
-// stored in the range from [0, 3] but are used in the range [0, 64]. The
-// process of translating a value to or from this range is known as quantization
-// and dequantization. The ranges to which these values can be (de)quantized
-// are defined by ISERange[Begin|End]() in integer_sequence_codec.h
-
-namespace astc_codec {
-
-// The minimum possible range for a pair of endpoints. If endpoints are
-// quantized to something smaller than this, then it would constitute an
-// illegal ASTC encoding.
-constexpr int kEndpointRangeMinValue = 5;
-
-// The maximum possible range for a weight value. If weights are quantized to
-// something larger than this, then it would constitute an illegal ASTC
-// encoding.
-constexpr int kWeightRangeMaxValue = 31;
-
-// Quantizes a value in the range [0, 255] to [0, |range|]. The quantized values
-// have no correlation to the input values, and there should be no implicit
-// assumptions made about their ordering. Valid values of |range_max_value| are
-// in the interval [5, 255]
-int QuantizeCEValueToRange(int value, int range_max_value);
-
-// Unquantizes a value in the range [0, |range|] to [0, 255]. Performs the
-// inverse procedure of QuantizeValueToRange. Valid values of |range_max_value|
-// are in the interval [5, 255]
-int UnquantizeCEValueFromRange(int value, int range_max_value);
-
-// Quantizes a weight in the range [0, 64] to [0, |range_max_value|]. The
-// quantized values have no correlation to the input values, and there should
-// be no implicit assumptions made about their ordering. Valid values of
-// |range_max_value| are in the interval [1, 31]
-int QuantizeWeightToRange(int weight, int range_max_value);
-
-// Unquantizes a weight in the range [0, |range_max_value|] to [0, 64]. Performs
-// the inverse procedure of QuantizeWeightToRange. Valid values of
-// |range_max_value| are in the interval [1, 31]
-int UnquantizeWeightFromRange(int weight, int range_max_value);
-
-}  // namespace astc_codec
-
-#endif  // ASTC_CODEC_DECODER_QUANTIZATION_H_

+ 0 - 74
3rdparty/astc-codec/src/decoder/types.h

@@ -1,74 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#ifndef ASTC_CODEC_DECODER_ASTC_TYPES_H_
-#define ASTC_CODEC_DECODER_ASTC_TYPES_H_
-
-#include <array>
-#include <string>
-#include <utility>
-
-namespace astc_codec {
-
-// The color endpoint mode determines how the values encoded in the ASTC block
-// are interpreted in order to create the RGBA values for the given endpoint
-// pair. The order of this enum is required to match the ASTC specification in
-// Section C.2.14.
-enum class ColorEndpointMode {
-  kLDRLumaDirect = 0,
-  kLDRLumaBaseOffset,
-  kHDRLumaLargeRange,
-  kHDRLumaSmallRange,
-  kLDRLumaAlphaDirect,
-  kLDRLumaAlphaBaseOffset,
-  kLDRRGBBaseScale,
-  kHDRRGBBaseScale,
-  kLDRRGBDirect,
-  kLDRRGBBaseOffset,
-  kLDRRGBBaseScaleTwoA,
-  kHDRRGBDirect,
-  kLDRRGBADirect,
-  kLDRRGBABaseOffset,
-  kHDRRGBDirectLDRAlpha,
-  kHDRRGBDirectHDRAlpha,
-
-  // The total number of color endpoints defined by the ASTC specification.
-  // This isn't a specific endpoint mode and its sole purpose is to be used
-  // as a constant number.
-  kNumColorEndpointModes
-};
-
-// Returns the class for the given mode as defined in Section C.2.11.
-constexpr int EndpointModeClass(ColorEndpointMode mode) {
-  return static_cast<int>(mode) / 4;
-}
-
-// Returns the number of encoded color values for the given endpoint mode. The
-// number of encoded color values and their range determines the size of the
-// color data in a physical ASTC block. This information is taken from
-// Section C.2.17 of the ASTC specification.
-constexpr int NumColorValuesForEndpointMode(ColorEndpointMode mode) {
-  return (EndpointModeClass(mode) + 1) * 2;
-}
-
-// We define a number of convenience types here that give more logical meaning
-// throughout the ASTC utilities.
-using RgbColor = std::array<int, 3>;
-using RgbaColor = std::array<int, 4>;
-using Endpoint = RgbaColor;
-using EndpointPair = std::pair<Endpoint, Endpoint>;
-
-}  // namespace astc_codec
-
-#endif  // ASTC_CODEC_DECODER_ASTC_TYPES_H_

+ 0 - 122
3rdparty/astc-codec/src/decoder/weight_infill.cc

@@ -1,122 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#include "src/decoder/weight_infill.h"
-#include "src/decoder/integer_sequence_codec.h"
-
-#include <array>
-#include <cmath>
-#include <utility>
-
-namespace astc_codec {
-
-namespace {
-
-// The following functions are based on Section C.2.18 of the ASTC specification
-int GetScaleFactorD(int block_dim) {
-  return static_cast<int>((1024.f + static_cast<float>(block_dim >> 1)) /
-                          static_cast<float>(block_dim - 1));
-}
-
-std::pair<int, int> GetGridSpaceCoordinates(
-    Footprint footprint, int s, int t, int weight_dim_x, int weight_dim_y) {
-  const int ds = GetScaleFactorD(footprint.Width());
-  const int dt = GetScaleFactorD(footprint.Height());
-
-  const int cs = ds * s;
-  const int ct = dt * t;
-
-  const int gs = (cs * (weight_dim_x - 1) + 32) >> 6;
-  const int gt = (ct * (weight_dim_y - 1) + 32) >> 6;
-
-  assert(gt < 1 << 8);
-  assert(gs < 1 << 8);
-
-  return std::make_pair(gs, gt);
-}
-
-// Returns the weight-grid values that are to be used for bilinearly
-// interpolating the weight to its final value. If the returned value
-// is equal to weight_dim_x * weight_dim_y, it may be ignored.
-std::array<int, 4> BilerpGridPointsForWeight(
-    const std::pair<int, int>& grid_space_coords, int weight_dim_x) {
-  const int js = grid_space_coords.first >> 4;
-  const int jt = grid_space_coords.second >> 4;
-
-  std::array<int, 4> result;
-  result[0] = js + weight_dim_x * jt;
-  result[1] = js + weight_dim_x * jt + 1;
-  result[2] = js + weight_dim_x * (jt + 1);
-  result[3] = js + weight_dim_x * (jt + 1) + 1;
-
-  return result;
-}
-
-std::array<int, 4> BilerpGridPointFactorsForWeight(
-    const std::pair<int, int>& grid_space_coords) {
-  const int fs = grid_space_coords.first & 0xF;
-  const int ft = grid_space_coords.second & 0xF;
-
-  std::array<int, 4> result;
-  result[3] = (fs * ft + 8) >> 4;
-  result[2] = ft - result[3];
-  result[1] = fs - result[3];
-  result[0] = 16 - fs - ft + result[3];
-
-  assert(result[0] <= 16);
-  assert(result[1] <= 16);
-  assert(result[2] <= 16);
-  assert(result[3] <= 16);
-
-  return result;
-}
-
-}  // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-
-int CountBitsForWeights(int weight_dim_x, int weight_dim_y,
-                        int target_weight_range) {
-  int num_weights = weight_dim_x * weight_dim_y;
-  return IntegerSequenceCodec::
-      GetBitCountForRange(num_weights, target_weight_range);
-}
-
-std::vector<int> InfillWeights(const std::vector<int>& weights,
-                               Footprint footprint, int dim_x, int dim_y) {
-  std::vector<int> result;
-  result.reserve(footprint.NumPixels());
-  for (int t = 0; t < footprint.Height(); ++t) {
-    for (int s = 0; s < footprint.Width(); ++s) {
-      const auto grid_space_coords =
-          GetGridSpaceCoordinates(footprint, s, t, dim_x, dim_y);
-      const auto grid_pts =
-          BilerpGridPointsForWeight(grid_space_coords, dim_x);
-      const auto grid_factors =
-          BilerpGridPointFactorsForWeight(grid_space_coords);
-
-      int weight = 0;
-      for (int i = 0; i < 4; ++i) {
-        if (grid_pts[i] < dim_x * dim_y) {
-          weight += weights.at(grid_pts[i]) * grid_factors[i];
-        }
-      }
-      result.push_back((weight + 8) >> 4);
-    }
-  }
-
-  return result;
-}
-
-}  // namespace astc_codec

+ 0 - 38
3rdparty/astc-codec/src/decoder/weight_infill.h

@@ -1,38 +0,0 @@
-// Copyright 2018 Google LLC
-//
-// 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
-//
-//     https://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.
-
-#ifndef ASTC_CODEC_DECODER_WEIGHT_INFILL_H_
-#define ASTC_CODEC_DECODER_WEIGHT_INFILL_H_
-
-#include "src/decoder/footprint.h"
-
-#include <vector>
-
-namespace astc_codec {
-
-// Returns the number of bits used to represent the weight grid at the target
-// dimensions and weight range.
-int CountBitsForWeights(int weight_dim_x, int weight_dim_y,
-                        int target_weight_range);
-
-// Performs weight infill of a grid of weights of size |dim_x * dim_y|. The
-// weights are fit using the algorithm laid out in Section C.2.18 of the ASTC
-// specification. Weights are expected to be passed unquantized and the returned
-// grid will be unquantized as well (i.e. each weight within the range [0, 64]).
-std::vector<int> InfillWeights(const std::vector<int>& weights,
-                               Footprint footprint, int dim_x, int dim_y);
-
-}  // namespace astc_codec
-
-#endif  // ASTC_CODEC_DECODER_WEIGHT_INFILL_H_

+ 3 - 15
scripts/bimg.lua

@@ -8,29 +8,17 @@ project "bimg"
 
 
 	includedirs {
 	includedirs {
 		path.join(BIMG_DIR, "include"),
 		path.join(BIMG_DIR, "include"),
-		path.join(BIMG_DIR, "3rdparty/astc-codec"),
-		path.join(BIMG_DIR, "3rdparty/astc-codec/include"),
+		path.join(BIMG_DIR, "3rdparty/astc-encoder/include"),
 		path.join(BIMG_DIR, "3rdparty/tinyexr/deps/miniz"),
 		path.join(BIMG_DIR, "3rdparty/tinyexr/deps/miniz"),
 	}
 	}
 
 
-	local ASTC_CODEC_DIR = path.join(BIMG_DIR, "3rdparty/astc-codec")
-
 	files {
 	files {
 		path.join(BIMG_DIR, "include/**"),
 		path.join(BIMG_DIR, "include/**"),
 		path.join(BIMG_DIR, "src/image.*"),
 		path.join(BIMG_DIR, "src/image.*"),
 		path.join(BIMG_DIR, "src/image_gnf.cpp"),
 		path.join(BIMG_DIR, "src/image_gnf.cpp"),
 
 
-		path.join(ASTC_CODEC_DIR, "src/decoder/astc_file.*"),
-		path.join(ASTC_CODEC_DIR, "src/decoder/codec.*"),
-		path.join(ASTC_CODEC_DIR, "src/decoder/endpoint_codec.*"),
-		path.join(ASTC_CODEC_DIR, "src/decoder/footprint.*"),
-		path.join(ASTC_CODEC_DIR, "src/decoder/integer_sequence_codec.*"),
-		path.join(ASTC_CODEC_DIR, "src/decoder/intermediate_astc_block.*"),
-		path.join(ASTC_CODEC_DIR, "src/decoder/logical_astc_block.*"),
-		path.join(ASTC_CODEC_DIR, "src/decoder/partition.*"),
-		path.join(ASTC_CODEC_DIR, "src/decoder/physical_astc_block.*"),
-		path.join(ASTC_CODEC_DIR, "src/decoder/quantization.*"),
-		path.join(ASTC_CODEC_DIR, "src/decoder/weight_infill.*"),
+		path.join(BIMG_DIR, "3rdparty/astc-encoder/source/**.cpp"),
+		path.join(BIMG_DIR, "3rdparty/astc-encoder/source/**.h"),
 
 
 		path.join(BIMG_DIR, "3rdparty/tinyexr/deps/miniz/miniz.*"),
 		path.join(BIMG_DIR, "3rdparty/tinyexr/deps/miniz/miniz.*"),
 	}
 	}

+ 0 - 2
scripts/bimg_encode.lua

@@ -35,8 +35,6 @@ project "bimg_encode"
 		path.join(BIMG_DIR, "3rdparty/nvtt/**.h"),
 		path.join(BIMG_DIR, "3rdparty/nvtt/**.h"),
 		path.join(BIMG_DIR, "3rdparty/pvrtc/**.cpp"),
 		path.join(BIMG_DIR, "3rdparty/pvrtc/**.cpp"),
 		path.join(BIMG_DIR, "3rdparty/pvrtc/**.h"),
 		path.join(BIMG_DIR, "3rdparty/pvrtc/**.h"),
-		path.join(BIMG_DIR, "3rdparty/astc-encoder/source/**.cpp"),
-		path.join(BIMG_DIR, "3rdparty/astc-encoder/source/**.h"),
 		path.join(BIMG_DIR, "3rdparty/tinyexr/**.h"),
 		path.join(BIMG_DIR, "3rdparty/tinyexr/**.h"),
 		path.join(BIMG_DIR, "3rdparty/iqa/include/**.h"),
 		path.join(BIMG_DIR, "3rdparty/iqa/include/**.h"),
 		path.join(BIMG_DIR, "3rdparty/iqa/source/**.c"),
 		path.join(BIMG_DIR, "3rdparty/iqa/source/**.c"),

+ 47 - 27
src/image.cpp

@@ -6,7 +6,7 @@
 #include "bimg_p.h"
 #include "bimg_p.h"
 #include <bx/hash.h>
 #include <bx/hash.h>
 
 
-#include <astc-codec/astc-codec.h>
+#include <astcenc.h>
 
 
 #include <bx/debug.h>
 #include <bx/debug.h>
 
 
@@ -4918,32 +4918,52 @@ namespace bimg
 		case TextureFormat::ASTC12x12:
 		case TextureFormat::ASTC12x12:
 			if (BX_ENABLED(BIMG_DECODE_ASTC) )
 			if (BX_ENABLED(BIMG_DECODE_ASTC) )
 			{
 			{
-				if (!astc_codec::ASTCDecompressToRGBA(
-					  (const uint8_t*)_src
-					, imageGetSize(NULL, uint16_t(_width), uint16_t(_height), 0, false, false, 1, _srcFormat)
-					, _width
-					, _height
-					, TextureFormat::ASTC4x4  == _srcFormat ? astc_codec::FootprintType::k4x4
-					: TextureFormat::ASTC5x4  == _srcFormat ? astc_codec::FootprintType::k5x4
-					: TextureFormat::ASTC5x5  == _srcFormat ? astc_codec::FootprintType::k5x5
-					: TextureFormat::ASTC6x5  == _srcFormat ? astc_codec::FootprintType::k6x5
-					: TextureFormat::ASTC6x6  == _srcFormat ? astc_codec::FootprintType::k6x6
-					: TextureFormat::ASTC8x5  == _srcFormat ? astc_codec::FootprintType::k8x5
-					: TextureFormat::ASTC8x6  == _srcFormat ? astc_codec::FootprintType::k8x6
-					: TextureFormat::ASTC8x8  == _srcFormat ? astc_codec::FootprintType::k8x8
-					: TextureFormat::ASTC10x5 == _srcFormat ? astc_codec::FootprintType::k10x5
-					: TextureFormat::ASTC10x6 == _srcFormat ? astc_codec::FootprintType::k10x6
-					: TextureFormat::ASTC10x8 == _srcFormat ? astc_codec::FootprintType::k10x8
-					: TextureFormat::ASTC10x10== _srcFormat ? astc_codec::FootprintType::k10x10
-					: TextureFormat::ASTC12x10== _srcFormat ? astc_codec::FootprintType::k12x10
-					:										  astc_codec::FootprintType::k12x12
-					, (uint8_t*)_dst
-					, _width*_height*4
-					, _dstPitch
-					) )
-				{
-					imageCheckerboard(_dst, _width, _height, 16, UINT32_C(0xff000000), UINT32_C(0xffffff00) );
-				}
+					const unsigned int thread_count = 1;
+					const bimg::ImageBlockInfo& astcBlockInfo = bimg::getBlockInfo(_srcFormat);
+					const float quality = ASTCENC_PRE_MEDIUM;
+					const astcenc_profile profile = ASTCENC_PRF_LDR; //Linear LDR color profile
+					astcenc_error status;
+
+					//Create and init config and context
+					astcenc_config config{};
+					const unsigned int astcFlags = ASTCENC_FLG_DECOMPRESS_ONLY;
+					status = astcenc_config_init(profile, astcBlockInfo.blockWidth, astcBlockInfo.blockHeight, 1, quality, astcFlags, &config);
+					if (status != ASTCENC_SUCCESS) {
+						BX_TRACE("astc error in config init %s", astcenc_get_error_string(status));
+						imageCheckerboard(_dst, _width, _height, 16, UINT32_C(0xff000000), UINT32_C(0xffffff00) );
+						break;
+					}
+
+					astcenc_context* context;
+					status = astcenc_context_alloc(&config, thread_count, &context);
+					if (status != ASTCENC_SUCCESS) {
+						BX_TRACE("astc error in context alloc %s", astcenc_get_error_string(status));
+						imageCheckerboard(_dst, _width, _height, 16, UINT32_C(0xff000000), UINT32_C(0xffffff00) );
+						break;
+					}
+
+					//Put image data into an astcenc_image
+					astcenc_image image{};
+					image.dim_x = _width;
+					image.dim_y = _height;
+					image.dim_z = 1;
+					image.data_type = ASTCENC_TYPE_U8;
+					image.data = &_dst;
+					const uint32_t size = imageGetSize(NULL, uint16_t(_width), uint16_t(_height), 0, false, false, 1, _srcFormat);
+
+					static const astcenc_swizzle swizzle { //0123/rgba swizzle corresponds to ASTC_RGBA
+						ASTCENC_SWZ_R, ASTCENC_SWZ_G, ASTCENC_SWZ_B, ASTCENC_SWZ_A
+					};
+					status = astcenc_decompress_image(context, static_cast<const uint8_t*>(_src), size, &image, &swizzle, 0);
+					
+					if (status != ASTCENC_SUCCESS) {
+						BX_TRACE("astc error in compress image %s", astcenc_get_error_string(status));
+						imageCheckerboard(_dst, _width, _height, 16, UINT32_C(0xff000000), UINT32_C(0xffffff00) );
+						astcenc_context_free(context);
+						break;
+					}
+
+					astcenc_context_free(context);
 			}
 			}
 			else
 			else
 			{
 			{

+ 8 - 0
src/image_encode.cpp

@@ -308,11 +308,19 @@ namespace bimg
 			case TextureFormat::PTC14:
 			case TextureFormat::PTC14:
 			case TextureFormat::PTC14A:
 			case TextureFormat::PTC14A:
 			case TextureFormat::ASTC4x4:
 			case TextureFormat::ASTC4x4:
+			case TextureFormat::ASTC5x4:
 			case TextureFormat::ASTC5x5:
 			case TextureFormat::ASTC5x5:
+			case TextureFormat::ASTC6x5:
 			case TextureFormat::ASTC6x6:
 			case TextureFormat::ASTC6x6:
 			case TextureFormat::ASTC8x5:
 			case TextureFormat::ASTC8x5:
 			case TextureFormat::ASTC8x6:
 			case TextureFormat::ASTC8x6:
+			case TextureFormat::ASTC8x8:
 			case TextureFormat::ASTC10x5:
 			case TextureFormat::ASTC10x5:
+			case TextureFormat::ASTC10x6:
+			case TextureFormat::ASTC10x8:
+			case TextureFormat::ASTC10x10:
+			case TextureFormat::ASTC12x10:
+			case TextureFormat::ASTC12x12:
 				{
 				{
 					uint8_t* temp = (uint8_t*)BX_ALLOC(_allocator, _width*_height*_depth*4);
 					uint8_t* temp = (uint8_t*)BX_ALLOC(_allocator, _width*_height*_depth*4);
 					imageDecodeToRgba8(_allocator, temp, _src, _width, _height, _width*4, _srcFormat);
 					imageDecodeToRgba8(_allocator, temp, _src, _width, _height, _width*4, _srcFormat);