1 // File: crn_decomp.h - Fast CRN->DXTc texture transcoder header file library
2 // Copyright (c) 2010-2016 Richard Geldreich, Jr. and Binomial LLC
3 // See Copyright Notice and license at the end of this file.
5 // This single header file contains *all* of the code necessary to unpack .CRN files to raw DXTn bits.
6 // It does NOT depend on the crn compression library.
8 // Note: This is a single file, stand-alone C++ library which is controlled by the use of the following macro:
9 // If CRND_INCLUDE_CRND_H is NOT defined, the header is included.
11 // Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing
12 #ifndef CRND_INCLUDE_CRND_H
13 #define CRND_INCLUDE_CRND_H
15 // Include crn_defs.h (only to bring in some basic CRN-related types and structures).
22 #elif defined(__APPLE__)
23 #include <malloc/malloc.h>
28 #include <new> // needed for placement new, _msize, _expand
31 #define CRND_RESTRICT __restrict
34 #pragma warning(disable : 4127) // warning C4127: conditional expression is constant
39 #define _WIN32_WINNT 0x500
41 #ifndef WIN32_LEAN_AND_MEAN
42 #define WIN32_LEAN_AND_MEAN
47 #include "windows.h" // only for IsDebuggerPresent(), DebugBreak(), and OutputDebugStringA()
52 const crn_uint8 cUINT8_MIN = 0;
53 const crn_uint8 cUINT8_MAX = 0xFFU;
54 const uint16 cUINT16_MIN = 0;
55 const uint16 cUINT16_MAX = 0xFFFFU;
56 const uint32 cUINT32_MIN = 0;
57 const uint32 cUINT32_MAX = 0xFFFFFFFFU;
59 const int8 cINT8_MIN = -128;
60 const int8 cINT8_MAX = 127;
61 const int16 cINT16_MIN = -32768;
62 const int16 cINT16_MAX = 32767;
63 const int32 cINT32_MIN = (-2147483647 - 1);
64 const int32 cINT32_MAX = 2147483647;
66 enum eClear { cClear };
68 const uint32 cIntBits = 32U;
72 enum { cMin = crnd::cINT32_MIN,
73 cMax = crnd::cINT32_MAX,
78 struct int_traits<int8> {
79 enum { cMin = crnd::cINT8_MIN,
80 cMax = crnd::cINT8_MAX,
84 struct int_traits<int16> {
85 enum { cMin = crnd::cINT16_MIN,
86 cMax = crnd::cINT16_MAX,
90 struct int_traits<int32> {
91 enum { cMin = crnd::cINT32_MIN,
92 cMax = crnd::cINT32_MAX,
97 struct int_traits<uint8> {
99 cMax = crnd::cUINT8_MAX,
103 struct int_traits<uint16> {
105 cMax = crnd::cUINT16_MAX,
109 struct int_traits<uint32> {
111 cMax = crnd::cUINT32_MAX,
115 struct empty_type {};
119 // File: crnd_platform.h
122 bool crnd_is_debugger_present();
123 void crnd_debug_break();
124 void crnd_output_debug_string(const char* p);
126 // actually in crnd_assert.cpp
127 void crnd_assert(const char* pExp, const char* pFile, unsigned line);
128 void crnd_fail(const char* pExp, const char* pFile, unsigned line);
132 // File: crnd_assert.h
134 class decompression_exception : public std::exception {};
136 // HACK: Try to crash less when asked to decode invalid inputs.
137 #define CRND_ASSERT(_exp) (!!(_exp) ? (void)0 : throw decompression_exception())
139 void crnd_trace(const char* pFmt, va_list args);
140 void crnd_trace(const char* pFmt, ...);
144 // File: crnd_helpers.h
147 template <typename T>
149 friend bool operator!=(const T& x, const T& y) { return (!(x == y)); }
150 friend bool operator>(const T& x, const T& y) { return (y < x); }
151 friend bool operator<=(const T& x, const T& y) { return (!(y < x)); }
152 friend bool operator>=(const T& x, const T& y) { return (!(x < y)); }
155 template <typename T>
156 inline T* construct(T* p) {
157 return new (static_cast<void*>(p)) T;
160 template <typename T, typename U>
161 inline T* construct(T* p, const U& init) {
162 return new (static_cast<void*>(p)) T(init);
165 template <typename T>
166 void construct_array(T* p, uint32 n) {
169 new (static_cast<void*>(p)) T;
172 template <typename T, typename U>
173 void construct_array(T* p, uint32 n, const U& init) {
176 new (static_cast<void*>(p)) T(init);
179 template <typename T>
180 inline void destruct(T* p) {
184 template <typename T>
185 inline void destruct_array(T* p, uint32 n) {
191 } // namespace helpers
195 // File: crnd_traits.h
197 template <typename T>
199 enum { cFlag = false };
200 static inline void construct(T* p) { helpers::construct(p); }
201 static inline void construct(T* p, const T& init) { helpers::construct(p, init); }
202 static inline void construct_array(T* p, uint32 n) { helpers::construct_array(p, n); }
203 static inline void destruct(T* p) { helpers::destruct(p); }
204 static inline void destruct_array(T* p, uint32 n) { helpers::destruct_array(p, n); }
207 template <typename T>
208 struct scalar_type<T*> {
209 enum { cFlag = true };
210 static inline void construct(T** p) { memset(p, 0, sizeof(T*)); }
211 static inline void construct(T** p, T* init) { *p = init; }
212 static inline void construct_array(T** p, uint32 n) { memset(p, 0, sizeof(T*) * n); }
213 static inline void destruct(T**) {}
214 static inline void destruct_array(T**, uint32) {}
217 #define CRND_DEFINE_BUILT_IN_TYPE(X) \
219 struct scalar_type<X> { \
220 enum { cFlag = true }; \
221 static inline void construct(X* p) { memset(p, 0, sizeof(X)); } \
222 static inline void construct(X* p, const X& init) { memcpy(p, &init, sizeof(X)); } \
223 static inline void construct_array(X* p, uint32 n) { memset(p, 0, sizeof(X) * n); } \
224 static inline void destruct(X*) {} \
225 static inline void destruct_array(X*, uint32) {} \
228 CRND_DEFINE_BUILT_IN_TYPE(bool)
229 CRND_DEFINE_BUILT_IN_TYPE(char)
230 CRND_DEFINE_BUILT_IN_TYPE(unsigned char)
231 CRND_DEFINE_BUILT_IN_TYPE(short)
232 CRND_DEFINE_BUILT_IN_TYPE(unsigned short)
233 CRND_DEFINE_BUILT_IN_TYPE(int)
234 CRND_DEFINE_BUILT_IN_TYPE(unsigned int)
235 CRND_DEFINE_BUILT_IN_TYPE(long)
236 CRND_DEFINE_BUILT_IN_TYPE(unsigned long)
237 CRND_DEFINE_BUILT_IN_TYPE(int64)
238 CRND_DEFINE_BUILT_IN_TYPE(uint64)
239 CRND_DEFINE_BUILT_IN_TYPE(float)
240 CRND_DEFINE_BUILT_IN_TYPE(double)
241 CRND_DEFINE_BUILT_IN_TYPE(long double)
243 #undef CRND_DEFINE_BUILT_IN_TYPE
245 // See: http://erdani.org/publications/cuj-2004-06.pdf
247 template <typename T>
248 struct bitwise_movable {
249 enum { cFlag = false };
252 // Defines type Q as bitwise movable.
253 #define CRND_DEFINE_BITWISE_MOVABLE(Q) \
255 struct bitwise_movable<Q> { \
256 enum { cFlag = true }; \
259 // From yasli_traits.h:
260 // Credit goes to Boost;
261 // also found in the C++ Templates book by Vandevoorde and Josuttis
263 typedef char (&yes_t)[1];
264 typedef char (&no_t)[2];
267 yes_t class_test(int U::*);
269 no_t class_test(...);
273 enum { value = (sizeof(class_test<T>(0)) == sizeof(yes_t)) };
276 template <typename T>
278 enum { value = false };
281 template <typename T>
282 struct is_pointer<T*> {
283 enum { value = true };
286 #define CRND_IS_POD(T) __is_pod(T)
292 void* crnd_malloc(size_t size, size_t* pActual_size = NULL);
293 void* crnd_realloc(void* p, size_t size, size_t* pActual_size = NULL, bool movable = true);
294 void crnd_free(void* p);
295 size_t crnd_msize(void* p);
297 template <typename T>
298 inline T* crnd_new() {
299 T* p = static_cast<T*>(crnd_malloc(sizeof(T)));
303 return helpers::construct(p);
306 template <typename T>
307 inline T* crnd_new(const T& init) {
308 T* p = static_cast<T*>(crnd_malloc(sizeof(T)));
312 return helpers::construct(p, init);
315 template <typename T>
316 inline T* crnd_new_array(uint32 num) {
320 uint8* q = static_cast<uint8*>(crnd_malloc(CRND_MIN_ALLOC_ALIGNMENT + sizeof(T) * num));
324 T* p = reinterpret_cast<T*>(q + CRND_MIN_ALLOC_ALIGNMENT);
326 reinterpret_cast<uint32*>(p)[-1] = num;
327 reinterpret_cast<uint32*>(p)[-2] = ~num;
329 helpers::construct_array(p, num);
333 template <typename T>
334 inline void crnd_delete(T* p) {
336 helpers::destruct(p);
341 template <typename T>
342 inline void crnd_delete_array(T* p) {
344 const uint32 num = reinterpret_cast<uint32*>(p)[-1];
345 CRND_ASSERT(num && (num == ~reinterpret_cast<uint32*>(p)[-2]));
347 helpers::destruct_array(p, num);
349 crnd_free(reinterpret_cast<uint8*>(p) - CRND_MIN_ALLOC_ALIGNMENT);
358 const float cNearlyInfinite = 1.0e+37f;
360 const float cDegToRad = 0.01745329252f;
361 const float cRadToDeg = 57.29577951f;
363 extern uint32 g_bitmasks[32];
365 // Yes I know these should probably be pass by ref, not val:
366 // http://www.stepanovpapers.com/notes.pdf
367 // Just don't use them on non-simple (non built-in) types!
368 template <typename T>
369 inline T minimum(T a, T b) {
370 return (a < b) ? a : b;
373 template <typename T>
374 inline T minimum(T a, T b, T c) {
375 return minimum(minimum(a, b), c);
378 template <typename T>
379 inline T maximum(T a, T b) {
380 return (a > b) ? a : b;
383 template <typename T>
384 inline T maximum(T a, T b, T c) {
385 return maximum(maximum(a, b), c);
388 template <typename T>
389 inline T clamp(T value, T low, T high) {
390 return (value < low) ? low : ((value > high) ? high : value);
393 template <typename T>
394 inline T square(T value) {
395 return value * value;
398 inline bool is_power_of_2(uint32 x) {
399 return x && ((x & (x - 1U)) == 0U);
402 // From "Hackers Delight"
403 inline int next_pow2(uint32 val) {
413 // Returns the total number of bits needed to encode v.
414 inline uint32 total_bits(uint32 v) {
423 inline uint floor_log2i(uint v) {
432 inline uint ceil_log2i(uint v) {
433 uint l = floor_log2i(v);
434 if ((l != cIntBits) && (v > (1U << l)))
441 // File: crnd_utils.h
444 template <typename T>
445 inline void zero_object(T& obj) {
446 memset(&obj, 0, sizeof(obj));
449 template <typename T>
450 inline void zero_this(T* pObj) {
451 memset(pObj, 0, sizeof(*pObj));
454 template <typename T>
455 inline void swap(T& left, T& right) {
461 inline void invert_buf(void* pBuf, uint32 size) {
462 uint8* p = static_cast<uint8*>(pBuf);
464 const uint32 half_size = size >> 1;
465 for (uint32 i = 0; i < half_size; i++)
466 swap(p[i], p[size - 1U - i]);
469 static inline uint16 swap16(uint16 x) {
470 return static_cast<uint16>((x << 8) | (x >> 8));
472 static inline uint32 swap32(uint32 x) {
473 return ((x << 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x >> 24));
476 uint32 compute_max_mips(uint32 width, uint32 height);
482 // File: crnd_vector.h
484 struct elemental_vector {
489 typedef void (*object_mover)(void* pDst, void* pSrc, uint32 num);
491 bool increase_capacity(uint32 min_new_capacity, bool grow_hint, uint32 element_size, object_mover pRelocate);
495 #pragma warning(push)
496 #pragma warning(disable : 4127) // warning C4127: conditional expression is constant
499 template <typename T>
500 class vector : public helpers::rel_ops<vector<T> > {
503 typedef const T* const_iterator;
504 typedef T value_type;
505 typedef T& reference;
506 typedef const T& const_reference;
508 typedef const T* const_pointer;
514 m_alloc_failed(false) {
517 inline vector(const vector& other)
521 m_alloc_failed(false) {
525 inline vector(uint32 size)
529 m_alloc_failed(false) {
537 // I don't like this. Not at all. But exceptions, or just failing suck worse.
538 inline bool get_alloc_failed() const { return m_alloc_failed; }
539 inline void clear_alloc_failed() { m_alloc_failed = false; }
541 inline bool assign(const vector& other) {
545 if (m_capacity == other.m_size)
550 if (!increase_capacity(other.m_size, false))
554 if (scalar_type<T>::cFlag)
555 memcpy(m_p, other.m_p, other.m_size * sizeof(T));
558 const T* pSrc = other.m_p;
559 for (uint32 i = other.m_size; i > 0; i--)
560 helpers::construct(pDst++, *pSrc++);
563 m_size = other.m_size;
568 inline vector& operator=(const vector& other) {
573 inline const T* begin() const { return m_p; }
574 T* begin() { return m_p; }
576 inline const T* end() const { return m_p + m_size; }
577 T* end() { return m_p + m_size; }
579 inline bool empty() const { return !m_size; }
580 inline uint32 size() const { return m_size; }
581 inline uint32 capacity() const { return m_capacity; }
583 inline const T& operator[](uint32 i) const {
584 CRND_ASSERT(i < m_size);
587 inline T& operator[](uint32 i) {
588 CRND_ASSERT(i < m_size);
592 inline const T& front() const {
601 inline const T& back() const {
603 return m_p[m_size - 1];
607 return m_p[m_size - 1];
610 inline void clear() {
612 scalar_type<T>::destruct_array(m_p, m_size);
619 m_alloc_failed = false;
622 inline bool reserve(uint32 new_capacity) {
623 if (!increase_capacity(new_capacity, false))
629 inline bool resize(uint32 new_size) {
630 if (m_size != new_size) {
631 if (new_size < m_size)
632 scalar_type<T>::destruct_array(m_p + new_size, m_size - new_size);
634 if (new_size > m_capacity) {
635 if (!increase_capacity(new_size, new_size == (m_size + 1)))
639 scalar_type<T>::construct_array(m_p + m_size, new_size - m_size);
648 inline bool push_back(const T& obj) {
649 CRND_ASSERT(!m_p || (&obj < m_p) || (&obj >= (m_p + m_size)));
651 if (m_size >= m_capacity) {
652 if (!increase_capacity(m_size + 1, true))
656 scalar_type<T>::construct(m_p + m_size, obj);
662 inline void pop_back() {
667 scalar_type<T>::destruct(&m_p[m_size]);
671 inline void insert(uint32 index, const T* p, uint32 n) {
672 CRND_ASSERT(index <= m_size);
676 const uint32 orig_size = m_size;
679 const T* pSrc = m_p + orig_size - 1;
680 T* pDst = const_cast<T*>(pSrc) + n;
682 const uint32 num_to_move = orig_size - index;
684 for (uint32 i = 0; i < num_to_move; i++) {
685 CRND_ASSERT((pDst - m_p) < (int)m_size);
692 for (uint32 i = 0; i < n; i++) {
693 CRND_ASSERT((pDst - m_p) < (int)m_size);
698 inline void erase(uint32 start, uint32 n) {
699 CRND_ASSERT((start + n) <= m_size);
704 const uint32 num_to_move = m_size - (start + n);
706 T* pDst = m_p + start;
707 T* pDst_end = pDst + num_to_move;
708 const T* pSrc = m_p + start + n;
710 while (pDst != pDst_end)
713 scalar_type<T>::destruct_array(pDst_end, n);
718 inline void erase(uint32 index) {
722 inline void erase(T* p) {
723 CRND_ASSERT((p >= m_p) && (p < (m_p + m_size)));
727 inline bool operator==(const vector& rhs) const {
728 if (m_size != rhs.m_size)
731 if (scalar_type<T>::cFlag)
732 return memcmp(m_p, rhs.m_p, sizeof(T) * m_size) == 0;
735 const T* pDst = rhs.m_p;
736 for (uint32 i = m_size; i; i--)
737 if (!(*pSrc++ == *pDst++))
745 inline bool operator<(const vector& rhs) const {
746 const uint32 min_size = math::minimum(m_size, rhs.m_size);
749 const T* pSrc_end = m_p + min_size;
750 const T* pDst = rhs.m_p;
752 while ((pSrc < pSrc_end) && (*pSrc == *pDst)) {
758 return *pSrc < *pDst;
760 return m_size < rhs.m_size;
763 void swap(vector& other) {
764 utils::swap(m_p, other.m_p);
765 utils::swap(m_size, other.m_size);
766 utils::swap(m_capacity, other.m_capacity);
775 template <typename Q>
777 enum { cFlag = false };
779 template <typename Q>
780 struct is_vector<vector<Q> > {
781 enum { cFlag = true };
784 static void object_mover(void* pDst_void, void* pSrc_void, uint32 num) {
785 T* pSrc = static_cast<T*>(pSrc_void);
786 T* const pSrc_end = pSrc + num;
787 T* pDst = static_cast<T*>(pDst_void);
789 while (pSrc != pSrc_end) {
790 helpers::construct<T>(pDst, *pSrc);
797 inline bool increase_capacity(uint32 min_new_capacity, bool grow_hint) {
798 if (!reinterpret_cast<elemental_vector*>(this)->increase_capacity(
799 min_new_capacity, grow_hint, sizeof(T),
800 ((scalar_type<T>::cFlag) || (is_vector<T>::cFlag) || (bitwise_movable<T>::cFlag) || CRND_IS_POD(T)) ? NULL : object_mover)) {
801 m_alloc_failed = true;
812 extern void vector_test();
816 // File: crnd_private.h
818 const crn_header* crnd_get_header(const void* pData, uint32 data_size);
824 // crc16() intended for small buffers - doesn't use an acceleration table.
825 const uint16 cInitCRC16 = 0;
826 uint16 crc16(const void* pBuf, uint32 len, uint16 crc = cInitCRC16);
830 // File: crnd_color.h
832 template <typename component_type>
833 struct color_quad_component_traits {
843 struct color_quad_component_traits<int16> {
853 struct color_quad_component_traits<uint16> {
863 struct color_quad_component_traits<int32> {
873 struct color_quad_component_traits<uint32> {
883 struct color_quad_component_traits<float> {
893 struct color_quad_component_traits<double> {
903 #pragma warning(push)
904 #pragma warning(disable : 4201) // warning C4201: nonstandard extension used : nameless struct/union
905 #pragma warning(disable : 4127) // warning C4127: conditional expression is constant
908 template <typename component_type, typename parameter_type>
909 class color_quad : public helpers::rel_ops<color_quad<component_type, parameter_type> > {
910 static parameter_type clamp(parameter_type v) {
911 if (component_traits::cFloat)
914 if (v < component_traits::cMin)
915 return component_traits::cMin;
916 else if (v > component_traits::cMax)
917 return component_traits::cMax;
923 typedef component_type component_t;
924 typedef parameter_type parameter_t;
925 typedef color_quad_component_traits<component_type> component_traits;
927 enum { cNumComps = 4 };
938 component_type c[cNumComps];
941 inline color_quad() {
944 inline color_quad(eClear)
945 : r(0), g(0), b(0), a(0) {
948 inline color_quad(const color_quad& other)
949 : r(other.r), g(other.g), b(other.b), a(other.a) {
952 inline color_quad(parameter_type y, parameter_type alpha = component_traits::cMax) {
956 inline color_quad(parameter_type red, parameter_type green, parameter_type blue, parameter_type alpha = component_traits::cMax) {
957 set(red, green, blue, alpha);
960 template <typename other_component_type, typename other_parameter_type>
961 inline color_quad(const color_quad<other_component_type, other_parameter_type>& other)
962 : r(clamp(other.r)), g(clamp(other.g)), b(clamp(other.b)), a(clamp(other.a)) {
965 inline void clear() {
972 inline color_quad& operator=(const color_quad& other) {
980 template <typename other_component_type, typename other_parameter_type>
981 inline color_quad& operator=(const color_quad<other_component_type, other_parameter_type>& other) {
989 inline color_quad& set(parameter_type y, parameter_type alpha = component_traits::cMax) {
991 r = static_cast<component_type>(y);
992 g = static_cast<component_type>(y);
993 b = static_cast<component_type>(y);
994 a = static_cast<component_type>(alpha);
998 inline color_quad& set(parameter_type red, parameter_type green, parameter_type blue, parameter_type alpha = component_traits::cMax) {
999 r = static_cast<component_type>(clamp(red));
1000 g = static_cast<component_type>(clamp(green));
1001 b = static_cast<component_type>(clamp(blue));
1002 a = static_cast<component_type>(clamp(alpha));
1006 inline color_quad& set_noclamp_rgba(parameter_type red, parameter_type green, parameter_type blue, parameter_type alpha) {
1007 r = static_cast<component_type>(red);
1008 g = static_cast<component_type>(green);
1009 b = static_cast<component_type>(blue);
1010 a = static_cast<component_type>(alpha);
1014 inline color_quad& set_noclamp_rgb(parameter_type red, parameter_type green, parameter_type blue) {
1015 r = static_cast<component_type>(red);
1016 g = static_cast<component_type>(green);
1017 b = static_cast<component_type>(blue);
1021 static inline parameter_type get_min_comp() { return component_traits::cMin; }
1022 static inline parameter_type get_max_comp() { return component_traits::cMax; }
1023 static inline bool get_comps_are_signed() { return component_traits::cSigned; }
1025 inline component_type operator[](uint32 i) const {
1026 CRND_ASSERT(i < cNumComps);
1029 inline component_type& operator[](uint32 i) {
1030 CRND_ASSERT(i < cNumComps);
1034 inline color_quad& set_component(uint32 i, parameter_type f) {
1035 CRND_ASSERT(i < cNumComps);
1037 c[i] = static_cast<component_type>(clamp(f));
1042 inline color_quad& clamp(const color_quad& l, const color_quad& h) {
1043 for (uint32 i = 0; i < cNumComps; i++)
1044 c[i] = static_cast<component_type>(math::clamp<parameter_type>(c[i], l[i], h[i]));
1048 inline color_quad& clamp(parameter_type l, parameter_type h) {
1049 for (uint32 i = 0; i < cNumComps; i++)
1050 c[i] = static_cast<component_type>(math::clamp<parameter_type>(c[i], l, h));
1054 // Returns CCIR 601 luma (consistent with color_utils::RGB_To_Y).
1055 inline parameter_type get_luma() const {
1056 return static_cast<parameter_type>((19595U * r + 38470U * g + 7471U * b + 32768) >> 16U);
1059 // Returns REC 709 luma.
1060 inline parameter_type get_luma_rec709() const {
1061 return static_cast<parameter_type>((13938U * r + 46869U * g + 4729U * b + 32768U) >> 16U);
1064 inline uint32 squared_distance(const color_quad& c, bool alpha = true) const {
1065 return math::square(r - c.r) + math::square(g - c.g) + math::square(b - c.b) + (alpha ? math::square(a - c.a) : 0);
1068 inline bool rgb_equals(const color_quad& rhs) const {
1069 return (r == rhs.r) && (g == rhs.g) && (b == rhs.b);
1072 inline bool operator==(const color_quad& rhs) const {
1073 return (r == rhs.r) && (g == rhs.g) && (b == rhs.b) && (a == rhs.a);
1076 inline bool operator<(const color_quad& rhs) const {
1077 for (uint32 i = 0; i < cNumComps; i++) {
1078 if (c[i] < rhs.c[i])
1080 else if (!(c[i] == rhs.c[i]))
1086 inline color_quad& operator+=(const color_quad& other) {
1087 for (uint32 i = 0; i < 4; i++)
1088 c[i] = static_cast<component_type>(clamp(c[i] + other.c[i]));
1092 inline color_quad& operator-=(const color_quad& other) {
1093 for (uint32 i = 0; i < 4; i++)
1094 c[i] = static_cast<component_type>(clamp(c[i] - other.c[i]));
1098 inline color_quad& operator*=(parameter_type v) {
1099 for (uint32 i = 0; i < 4; i++)
1100 c[i] = static_cast<component_type>(clamp(c[i] * v));
1104 inline color_quad& operator/=(parameter_type v) {
1105 for (uint32 i = 0; i < 4; i++)
1106 c[i] = static_cast<component_type>(c[i] / v);
1110 inline color_quad get_swizzled(uint32 x, uint32 y, uint32 z, uint32 w) const {
1111 CRND_ASSERT((x | y | z | w) < 4);
1112 return color_quad(c[x], c[y], c[z], c[w]);
1115 inline friend color_quad operator+(const color_quad& lhs, const color_quad& rhs) {
1116 color_quad result(lhs);
1121 inline friend color_quad operator-(const color_quad& lhs, const color_quad& rhs) {
1122 color_quad result(lhs);
1127 inline friend color_quad operator*(const color_quad& lhs, parameter_type v) {
1128 color_quad result(lhs);
1133 friend inline color_quad operator/(const color_quad& lhs, parameter_type v) {
1134 color_quad result(lhs);
1139 friend inline color_quad operator*(parameter_type v, const color_quad& rhs) {
1140 color_quad result(rhs);
1145 inline uint32 get_min_component_index(bool alpha = true) const {
1147 uint32 limit = alpha ? cNumComps : (cNumComps - 1);
1148 for (uint32 i = 1; i < limit; i++)
1149 if (c[i] < c[index])
1154 inline uint32 get_max_component_index(bool alpha = true) const {
1156 uint32 limit = alpha ? cNumComps : (cNumComps - 1);
1157 for (uint32 i = 1; i < limit; i++)
1158 if (c[i] > c[index])
1163 inline void get_float4(float* pDst) {
1164 for (uint32 i = 0; i < 4; i++)
1165 pDst[i] = ((*this)[i] - component_traits::cMin) / float(component_traits::cMax - component_traits::cMin);
1168 inline void get_float3(float* pDst) {
1169 for (uint32 i = 0; i < 3; i++)
1170 pDst[i] = ((*this)[i] - component_traits::cMin) / float(component_traits::cMax - component_traits::cMin);
1173 static inline color_quad make_black() {
1174 return color_quad(0, 0, 0, component_traits::cMax);
1177 static inline color_quad make_white() {
1178 return color_quad(component_traits::cMax, component_traits::cMax, component_traits::cMax, component_traits::cMax);
1180 }; // class color_quad
1183 #pragma warning(pop)
1186 template <typename c, typename q>
1187 struct scalar_type<color_quad<c, q> > {
1188 enum { cFlag = true };
1189 static inline void construct(color_quad<c, q>* p) {}
1190 static inline void construct(color_quad<c, q>* p, const color_quad<c, q>& init) { memcpy(p, &init, sizeof(color_quad<c, q>)); }
1191 static inline void construct_array(color_quad<c, q>* p, uint32 n) { p, n; }
1192 static inline void destruct(color_quad<c, q>* p) { p; }
1193 static inline void destruct_array(color_quad<c, q>* p, uint32 n) { p, n; }
1196 typedef color_quad<uint8, int> color_quad_u8;
1197 typedef color_quad<int16, int> color_quad_i16;
1198 typedef color_quad<uint16, int> color_quad_u16;
1199 typedef color_quad<int32, int> color_quad_i32;
1200 typedef color_quad<uint32, uint32> color_quad_u32;
1201 typedef color_quad<float, float> color_quad_f;
1202 typedef color_quad<double, double> color_quad_d;
1211 // cDXT1/1A must appear first!
1219 cDXN_XY, // inverted relative to standard ATI2, 360's DXN
1220 cDXN_YX // standard ATI2
1223 enum dxt_constants {
1224 cDXTBlockShift = 2U,
1225 cDXTBlockSize = 1U << cDXTBlockShift,
1227 cDXT1BytesPerBlock = 8U,
1228 cDXT5NBytesPerBlock = 16U,
1230 cDXT1SelectorBits = 2U,
1231 cDXT1SelectorValues = 1U << cDXT1SelectorBits,
1232 cDXT1SelectorMask = cDXT1SelectorValues - 1U,
1234 cDXT5SelectorBits = 3U,
1235 cDXT5SelectorValues = 1U << cDXT5SelectorBits,
1236 cDXT5SelectorMask = cDXT5SelectorValues - 1U
1239 const float cDXT1MaxLinearValue = 3.0f;
1240 const float cDXT1InvMaxLinearValue = 1.0f / 3.0f;
1242 const float cDXT5MaxLinearValue = 7.0f;
1243 const float cDXT5InvMaxLinearValue = 1.0f / 7.0f;
1245 // Converts DXT1 raw color selector index to a linear value.
1246 extern const uint8 g_dxt1_to_linear[cDXT1SelectorValues];
1248 // Converts DXT5 raw alpha selector index to a linear value.
1249 extern const uint8 g_dxt5_to_linear[cDXT5SelectorValues];
1251 // Converts DXT1 linear color selector index to a raw value (inverse of g_dxt1_to_linear).
1252 extern const uint8 g_dxt1_from_linear[cDXT1SelectorValues];
1254 // Converts DXT5 linear alpha selector index to a raw value (inverse of g_dxt5_to_linear).
1255 extern const uint8 g_dxt5_from_linear[cDXT5SelectorValues];
1257 extern const uint8 g_six_alpha_invert_table[cDXT5SelectorValues];
1258 extern const uint8 g_eight_alpha_invert_table[cDXT5SelectorValues];
1261 uint8 m_low_color[2];
1262 uint8 m_high_color[2];
1264 enum { cNumSelectorBytes = 4 };
1265 uint8 m_selectors[cNumSelectorBytes];
1267 inline void clear() {
1268 utils::zero_this(this);
1271 // These methods assume the in-memory rep is in LE byte order.
1272 inline uint32 get_low_color() const {
1273 return m_low_color[0] | (m_low_color[1] << 8U);
1276 inline uint32 get_high_color() const {
1277 return m_high_color[0] | (m_high_color[1] << 8U);
1280 inline void set_low_color(uint16 c) {
1281 m_low_color[0] = static_cast<uint8>(c & 0xFF);
1282 m_low_color[1] = static_cast<uint8>((c >> 8) & 0xFF);
1285 inline void set_high_color(uint16 c) {
1286 m_high_color[0] = static_cast<uint8>(c & 0xFF);
1287 m_high_color[1] = static_cast<uint8>((c >> 8) & 0xFF);
1290 inline uint32 get_selector(uint32 x, uint32 y) const {
1291 CRND_ASSERT((x < 4U) && (y < 4U));
1292 return (m_selectors[y] >> (x * cDXT1SelectorBits)) & cDXT1SelectorMask;
1295 inline void set_selector(uint32 x, uint32 y, uint32 val) {
1296 CRND_ASSERT((x < 4U) && (y < 4U) && (val < 4U));
1298 m_selectors[y] &= (~(cDXT1SelectorMask << (x * cDXT1SelectorBits)));
1299 m_selectors[y] |= (val << (x * cDXT1SelectorBits));
1302 static uint16 pack_color(const color_quad_u8& color, bool scaled, uint32 bias = 127U);
1303 static uint16 pack_color(uint32 r, uint32 g, uint32 b, bool scaled, uint32 bias = 127U);
1305 static color_quad_u8 unpack_color(uint16 packed_color, bool scaled, uint32 alpha = 255U);
1306 static void unpack_color(uint32& r, uint32& g, uint32& b, uint16 packed_color, bool scaled);
1308 static uint32 get_block_colors3(color_quad_u8* pDst, uint16 color0, uint16 color1);
1309 static uint32 get_block_colors4(color_quad_u8* pDst, uint16 color0, uint16 color1);
1310 // pDst must point to an array at least cDXT1SelectorValues long.
1311 static uint32 get_block_colors(color_quad_u8* pDst, uint16 color0, uint16 color1);
1313 static color_quad_u8 unpack_endpoint(uint32 endpoints, uint32 index, bool scaled, uint32 alpha = 255U);
1314 static uint32 pack_endpoints(uint32 lo, uint32 hi);
1317 CRND_DEFINE_BITWISE_MOVABLE(dxt1_block);
1320 enum { cNumAlphaBytes = 8 };
1321 uint8 m_alpha[cNumAlphaBytes];
1323 void set_alpha(uint32 x, uint32 y, uint32 value, bool scaled);
1324 uint32 get_alpha(uint32 x, uint32 y, bool scaled) const;
1327 CRND_DEFINE_BITWISE_MOVABLE(dxt3_block);
1330 uint8 m_endpoints[2];
1332 enum { cNumSelectorBytes = 6 };
1333 uint8 m_selectors[cNumSelectorBytes];
1335 inline void clear() {
1336 utils::zero_this(this);
1339 inline uint32 get_low_alpha() const {
1340 return m_endpoints[0];
1343 inline uint32 get_high_alpha() const {
1344 return m_endpoints[1];
1347 inline void set_low_alpha(uint32 i) {
1348 CRND_ASSERT(i <= cUINT8_MAX);
1349 m_endpoints[0] = static_cast<uint8>(i);
1352 inline void set_high_alpha(uint32 i) {
1353 CRND_ASSERT(i <= cUINT8_MAX);
1354 m_endpoints[1] = static_cast<uint8>(i);
1357 uint32 get_endpoints_as_word() const { return m_endpoints[0] | (m_endpoints[1] << 8); }
1359 uint32 get_selectors_as_word(uint32 index) {
1360 CRND_ASSERT(index < 3);
1361 return m_selectors[index * 2] | (m_selectors[index * 2 + 1] << 8);
1364 inline uint32 get_selector(uint32 x, uint32 y) const {
1365 CRND_ASSERT((x < 4U) && (y < 4U));
1367 uint32 selector_index = (y * 4) + x;
1368 uint32 bit_index = selector_index * cDXT5SelectorBits;
1370 uint32 byte_index = bit_index >> 3;
1371 uint32 bit_ofs = bit_index & 7;
1373 uint32 v = m_selectors[byte_index];
1374 if (byte_index < (cNumSelectorBytes - 1))
1375 v |= (m_selectors[byte_index + 1] << 8);
1377 return (v >> bit_ofs) & 7;
1380 inline void set_selector(uint32 x, uint32 y, uint32 val) {
1381 CRND_ASSERT((x < 4U) && (y < 4U) && (val < 8U));
1383 uint32 selector_index = (y * 4) + x;
1384 uint32 bit_index = selector_index * cDXT5SelectorBits;
1386 uint32 byte_index = bit_index >> 3;
1387 uint32 bit_ofs = bit_index & 7;
1389 uint32 v = m_selectors[byte_index];
1390 if (byte_index < (cNumSelectorBytes - 1))
1391 v |= (m_selectors[byte_index + 1] << 8);
1393 v &= (~(7 << bit_ofs));
1394 v |= (val << bit_ofs);
1396 m_selectors[byte_index] = static_cast<uint8>(v);
1397 if (byte_index < (cNumSelectorBytes - 1))
1398 m_selectors[byte_index + 1] = static_cast<uint8>(v >> 8);
1401 // Results written to alpha channel.
1402 static uint32 get_block_values6(color_quad_u8* pDst, uint32 l, uint32 h);
1403 static uint32 get_block_values8(color_quad_u8* pDst, uint32 l, uint32 h);
1404 static uint32 get_block_values(color_quad_u8* pDst, uint32 l, uint32 h);
1406 static uint32 get_block_values6(uint32* pDst, uint32 l, uint32 h);
1407 static uint32 get_block_values8(uint32* pDst, uint32 l, uint32 h);
1408 // pDst must point to an array at least cDXT5SelectorValues long.
1409 static uint32 get_block_values(uint32* pDst, uint32 l, uint32 h);
1411 static uint32 unpack_endpoint(uint32 packed, uint32 index);
1412 static uint32 pack_endpoints(uint32 lo, uint32 hi);
1415 CRND_DEFINE_BITWISE_MOVABLE(dxt5_block);
1419 // File: crnd_prefix_coding.h
1421 #define CRND_PREFIX_CODING_USE_FIXED_TABLE_SIZE 1
1423 #define CRND_PREFIX_CODING_USE_FIXED_TABLE_SIZE 0
1427 namespace prefix_coding {
1428 const uint32 cMaxExpectedCodeSize = 16;
1429 const uint32 cMaxSupportedSyms = 8192;
1430 const uint32 cMaxTableBits = 11;
1432 class decoder_tables {
1434 inline decoder_tables()
1435 : m_cur_lookup_size(0), m_lookup(NULL), m_cur_sorted_symbol_order_size(0), m_sorted_symbol_order(NULL) {
1438 inline decoder_tables(const decoder_tables& other)
1439 : m_cur_lookup_size(0), m_lookup(NULL), m_cur_sorted_symbol_order_size(0), m_sorted_symbol_order(NULL) {
1443 decoder_tables& operator=(const decoder_tables& other) {
1449 memcpy(this, &other, sizeof(*this));
1451 if (other.m_lookup) {
1452 m_lookup = crnd_new_array<uint32>(m_cur_lookup_size);
1454 memcpy(m_lookup, other.m_lookup, sizeof(m_lookup[0]) * m_cur_lookup_size);
1457 if (other.m_sorted_symbol_order) {
1458 m_sorted_symbol_order = crnd_new_array<uint16>(m_cur_sorted_symbol_order_size);
1459 if (m_sorted_symbol_order)
1460 memcpy(m_sorted_symbol_order, other.m_sorted_symbol_order, sizeof(m_sorted_symbol_order[0]) * m_cur_sorted_symbol_order_size);
1466 inline void clear() {
1468 crnd_delete_array(m_lookup);
1470 m_cur_lookup_size = 0;
1473 if (m_sorted_symbol_order) {
1474 crnd_delete_array(m_sorted_symbol_order);
1475 m_sorted_symbol_order = NULL;
1476 m_cur_sorted_symbol_order_size = 0;
1480 inline ~decoder_tables() {
1482 crnd_delete_array(m_lookup);
1484 if (m_sorted_symbol_order)
1485 crnd_delete_array(m_sorted_symbol_order);
1488 bool init(uint32 num_syms, const uint8* pCodesizes, uint32 table_bits);
1490 // DO NOT use any complex classes here - it is bitwise copied.
1493 uint32 m_total_used_syms;
1494 uint32 m_table_bits;
1495 uint32 m_table_shift;
1496 uint32 m_table_max_code;
1497 uint32 m_decode_start_code_size;
1499 uint8 m_min_code_size;
1500 uint8 m_max_code_size;
1502 uint32 m_max_codes[cMaxExpectedCodeSize + 1];
1503 int32 m_val_ptrs[cMaxExpectedCodeSize + 1];
1505 uint32 m_cur_lookup_size;
1508 uint32 m_cur_sorted_symbol_order_size;
1509 uint16* m_sorted_symbol_order;
1511 inline uint32 get_unshifted_max_code(uint32 len) const {
1512 CRND_ASSERT((len >= 1) && (len <= cMaxExpectedCodeSize));
1513 uint32 k = m_max_codes[len - 1];
1515 return crnd::cUINT32_MAX;
1516 return (k - 1) >> (16 - len);
1520 } // namespace prefix_coding
1524 // File: crnd_symbol_codec.h
1526 class static_huffman_data_model {
1528 static_huffman_data_model();
1529 static_huffman_data_model(const static_huffman_data_model& other);
1530 ~static_huffman_data_model();
1532 static_huffman_data_model& operator=(const static_huffman_data_model& rhs);
1534 bool init(uint32 total_syms, const uint8* pCode_sizes, uint32 code_size_limit);
1537 inline bool is_valid() const { return m_pDecode_tables != NULL; }
1539 inline uint32 get_total_syms() const { return m_total_syms; }
1541 inline uint32 get_code_size(uint32 sym) const { return m_code_sizes[sym]; }
1543 inline const uint8* get_code_sizes() const { return m_code_sizes.empty() ? NULL : &m_code_sizes[0]; }
1546 uint32 m_total_syms;
1547 crnd::vector<uint8> m_code_sizes;
1548 prefix_coding::decoder_tables* m_pDecode_tables;
1551 bool prepare_decoder_tables();
1552 uint compute_decoder_table_bits() const;
1554 friend class symbol_codec;
1557 class symbol_codec {
1561 bool start_decoding(const uint8* pBuf, uint32 buf_size);
1562 bool decode_receive_static_data_model(static_huffman_data_model& model);
1564 uint32 decode_bits(uint32 num_bits);
1565 uint32 decode(const static_huffman_data_model& model);
1567 uint64 stop_decoding();
1570 const uint8* m_pDecode_buf;
1571 const uint8* m_pDecode_buf_next;
1572 const uint8* m_pDecode_buf_end;
1573 uint32 m_decode_buf_size;
1575 typedef uint32 bit_buf_type;
1576 enum { cBitBufSize = 32U };
1577 bit_buf_type m_bit_buf;
1582 void get_bits_init();
1583 uint32 get_bits(uint32 num_bits);
1589 void crnd_assert(const char* pExp, const char* pFile, unsigned line) {
1592 #if defined(WIN32) && defined(_MSC_VER)
1593 sprintf_s(buf, sizeof(buf), "%s(%u): Assertion failure: \"%s\"\n", pFile, line, pExp);
1595 sprintf(buf, "%s(%u): Assertion failure: \"%s\"\n", pFile, line, pExp);
1598 crnd_output_debug_string(buf);
1602 if (crnd_is_debugger_present())
1606 void crnd_trace(const char* pFmt, va_list args) {
1607 if (crnd_is_debugger_present()) {
1609 #if defined(WIN32) && defined(_MSC_VER)
1610 vsprintf_s(buf, sizeof(buf), pFmt, args);
1612 vsprintf(buf, pFmt, args);
1615 crnd_output_debug_string(buf);
1619 void crnd_trace(const char* pFmt, ...) {
1621 va_start(args, pFmt);
1622 crnd_trace(pFmt, args);
1628 // File: checksum.cpp
1629 // From the public domain stb.h header.
1631 uint16 crc16(const void* pBuf, uint32 len, uint16 crc) {
1634 const uint8* p = reinterpret_cast<const uint8*>(pBuf);
1636 const uint16 q = *p++ ^ (crc >> 8U);
1639 uint16 r = (q >> 4U) ^ q;
1649 return static_cast<uint16>(~crc);
1654 // File: crnd_vector.cpp
1656 bool elemental_vector::increase_capacity(uint32 min_new_capacity, bool grow_hint, uint32 element_size, object_mover pMover) {
1657 CRND_ASSERT(m_size <= m_capacity);
1658 CRND_ASSERT(min_new_capacity < (0x7FFF0000U / element_size));
1660 if (m_capacity >= min_new_capacity)
1663 uint32 new_capacity = min_new_capacity;
1664 if ((grow_hint) && (!math::is_power_of_2(new_capacity)))
1665 new_capacity = math::next_pow2(new_capacity);
1667 CRND_ASSERT(new_capacity && (new_capacity > m_capacity));
1669 const uint32 desired_size = element_size * new_capacity;
1672 void* new_p = crnd_realloc(m_p, desired_size, &actual_size, true);
1677 void* new_p = crnd_malloc(desired_size, &actual_size);
1681 (*pMover)(new_p, m_p, m_size);
1689 if (actual_size > desired_size)
1690 m_capacity = static_cast<uint32>(actual_size / element_size);
1692 m_capacity = new_capacity;
1699 // File: crnd_utils.cpp
1702 uint32 compute_max_mips(uint32 width, uint32 height) {
1703 if ((width | height) == 0)
1706 uint32 num_mips = 1;
1708 while ((width > 1U) || (height > 1U)) {
1717 } // namespace utils
1721 // File: crnd_prefix_coding.cpp
1723 namespace prefix_coding {
1724 bool decoder_tables::init(uint32 num_syms, const uint8* pCodesizes, uint32 table_bits) {
1725 uint32 min_codes[cMaxExpectedCodeSize];
1726 if ((!num_syms) || (table_bits > cMaxTableBits))
1729 m_num_syms = num_syms;
1731 uint32 num_codes[cMaxExpectedCodeSize + 1];
1732 utils::zero_object(num_codes);
1734 for (uint32 i = 0; i < num_syms; i++) {
1735 uint32 c = pCodesizes[i];
1740 uint32 sorted_positions[cMaxExpectedCodeSize + 1];
1742 uint32 cur_code = 0;
1744 uint32 total_used_syms = 0;
1745 uint32 max_code_size = 0;
1746 uint32 min_code_size = cUINT32_MAX;
1747 for (uint32 i = 1; i <= cMaxExpectedCodeSize; i++) {
1748 const uint32 n = num_codes[i];
1751 m_max_codes[i - 1] = 0; //UINT_MAX;
1753 min_code_size = math::minimum(min_code_size, i);
1754 max_code_size = math::maximum(max_code_size, i);
1756 min_codes[i - 1] = cur_code;
1758 m_max_codes[i - 1] = cur_code + n - 1;
1759 m_max_codes[i - 1] = 1 + ((m_max_codes[i - 1] << (16 - i)) | ((1 << (16 - i)) - 1));
1761 m_val_ptrs[i - 1] = total_used_syms;
1763 sorted_positions[i] = total_used_syms;
1766 total_used_syms += n;
1772 m_total_used_syms = total_used_syms;
1774 if (total_used_syms > m_cur_sorted_symbol_order_size) {
1775 m_cur_sorted_symbol_order_size = total_used_syms;
1777 if (!math::is_power_of_2(total_used_syms))
1778 m_cur_sorted_symbol_order_size = math::minimum<uint32>(num_syms, math::next_pow2(total_used_syms));
1780 if (m_sorted_symbol_order)
1781 crnd_delete_array(m_sorted_symbol_order);
1783 m_sorted_symbol_order = crnd_new_array<uint16>(m_cur_sorted_symbol_order_size);
1784 if (!m_sorted_symbol_order)
1788 m_min_code_size = static_cast<uint8>(min_code_size);
1789 m_max_code_size = static_cast<uint8>(max_code_size);
1791 for (uint32 i = 0; i < num_syms; i++) {
1792 uint32 c = pCodesizes[i];
1794 CRND_ASSERT(num_codes[c]);
1796 uint32 sorted_pos = sorted_positions[c]++;
1798 CRND_ASSERT(sorted_pos < total_used_syms);
1800 m_sorted_symbol_order[sorted_pos] = static_cast<uint16>(i);
1804 if (table_bits <= m_min_code_size)
1806 m_table_bits = table_bits;
1809 uint32 table_size = 1 << table_bits;
1810 if (table_size > m_cur_lookup_size) {
1811 m_cur_lookup_size = table_size;
1814 crnd_delete_array(m_lookup);
1816 m_lookup = crnd_new_array<uint32>(table_size);
1821 memset(m_lookup, 0xFF, (uint)sizeof(m_lookup[0]) * (1UL << table_bits));
1823 for (uint32 codesize = 1; codesize <= table_bits; codesize++) {
1824 if (!num_codes[codesize])
1827 const uint32 fillsize = table_bits - codesize;
1828 const uint32 fillnum = 1 << fillsize;
1830 const uint32 min_code = min_codes[codesize - 1];
1831 const uint32 max_code = get_unshifted_max_code(codesize);
1832 const uint32 val_ptr = m_val_ptrs[codesize - 1];
1834 for (uint32 code = min_code; code <= max_code; code++) {
1835 const uint32 sym_index = m_sorted_symbol_order[val_ptr + code - min_code];
1836 CRND_ASSERT(pCodesizes[sym_index] == codesize);
1838 for (uint32 j = 0; j < fillnum; j++) {
1839 const uint32 t = j + (code << fillsize);
1841 CRND_ASSERT(t < (1U << table_bits));
1843 CRND_ASSERT(m_lookup[t] == cUINT32_MAX);
1845 m_lookup[t] = sym_index | (codesize << 16U);
1851 for (uint32 i = 0; i < cMaxExpectedCodeSize; i++)
1852 m_val_ptrs[i] -= min_codes[i];
1854 m_table_max_code = 0;
1855 m_decode_start_code_size = m_min_code_size;
1859 for (i = table_bits; i >= 1; i--) {
1861 m_table_max_code = m_max_codes[i - 1];
1866 m_decode_start_code_size = table_bits + 1;
1867 for (uint32 j = table_bits + 1; j <= max_code_size; j++) {
1869 m_decode_start_code_size = j;
1877 m_max_codes[cMaxExpectedCodeSize] = cUINT32_MAX;
1878 m_val_ptrs[cMaxExpectedCodeSize] = 0xFFFFF;
1880 m_table_shift = 32 - m_table_bits;
1884 } // namespace prefix_codig
1888 // File: crnd_platform.cpp
1890 bool crnd_is_debugger_present() {
1892 return IsDebuggerPresent() != 0;
1898 void crnd_debug_break() {
1904 void crnd_output_debug_string(const char* p) {
1907 OutputDebugStringA(p);
1913 // File: crnd_mem.cpp
1915 const uint32 MAX_POSSIBLE_BLOCK_SIZE = 0x7FFF0000U;
1917 static void* crnd_default_realloc(void* p, size_t size, size_t* pActual_size, bool movable, void*) {
1921 p_new = ::malloc(size);
1925 *pActual_size = p_new ? ::_msize(p_new) : 0;
1926 #elif defined(__APPLE__)
1927 *pActual_size = p_new ? malloc_size(p_new) : 0;
1929 *pActual_size = p_new ? malloc_usable_size(p_new) : 0;
1939 void* p_final_block = p;
1941 p_new = ::_expand(p, size);
1947 p_final_block = p_new;
1949 p_new = ::realloc(p, size);
1952 p_final_block = p_new;
1957 *pActual_size = ::_msize(p_final_block);
1958 #elif defined(__APPLE__)
1959 *pActual_size = ::malloc_size(p_final_block);
1961 *pActual_size = ::malloc_usable_size(p_final_block);
1969 static size_t crnd_default_msize(void* p, void* pUser_data) {
1972 return p ? _msize(p) : 0;
1973 #elif defined(__APPLE__)
1974 return p ? malloc_size(p) : 0;
1976 return p ? malloc_usable_size(p) : 0;
1980 static crnd_realloc_func g_pRealloc = crnd_default_realloc;
1981 static crnd_msize_func g_pMSize = crnd_default_msize;
1982 static void* g_pUser_data;
1984 void crnd_set_memory_callbacks(crnd_realloc_func pRealloc, crnd_msize_func pMSize, void* pUser_data) {
1985 if ((!pRealloc) || (!pMSize)) {
1986 g_pRealloc = crnd_default_realloc;
1987 g_pMSize = crnd_default_msize;
1988 g_pUser_data = NULL;
1990 g_pRealloc = pRealloc;
1992 g_pUser_data = pUser_data;
1996 static inline void crnd_mem_error(const char* p_msg) {
1997 crnd_assert(p_msg, __FILE__, __LINE__);
2000 void* crnd_malloc(size_t size, size_t* pActual_size) {
2001 size = (size + sizeof(uint32) - 1U) & ~(sizeof(uint32) - 1U);
2003 size = sizeof(uint32);
2005 if (size > MAX_POSSIBLE_BLOCK_SIZE) {
2006 crnd_mem_error("crnd_malloc: size too big");
2010 size_t actual_size = size;
2011 uint8* p_new = static_cast<uint8*>((*g_pRealloc)(NULL, size, &actual_size, true, g_pUser_data));
2014 *pActual_size = actual_size;
2016 if ((!p_new) || (actual_size < size)) {
2017 crnd_mem_error("crnd_malloc: out of memory");
2021 CRND_ASSERT(((uint32) reinterpret_cast<uintptr_t>(p_new) & (CRND_MIN_ALLOC_ALIGNMENT - 1)) == 0);
2026 void* crnd_realloc(void* p, size_t size, size_t* pActual_size, bool movable) {
2027 if ((uint32) reinterpret_cast<uintptr_t>(p) & (CRND_MIN_ALLOC_ALIGNMENT - 1)) {
2028 crnd_mem_error("crnd_realloc: bad ptr");
2032 if (size > MAX_POSSIBLE_BLOCK_SIZE) {
2033 crnd_mem_error("crnd_malloc: size too big");
2037 size_t actual_size = size;
2038 void* p_new = (*g_pRealloc)(p, size, &actual_size, movable, g_pUser_data);
2041 *pActual_size = actual_size;
2043 CRND_ASSERT(((uint32) reinterpret_cast<uintptr_t>(p_new) & (CRND_MIN_ALLOC_ALIGNMENT - 1)) == 0);
2048 void crnd_free(void* p) {
2052 if ((uint32) reinterpret_cast<uintptr_t>(p) & (CRND_MIN_ALLOC_ALIGNMENT - 1)) {
2053 crnd_mem_error("crnd_free: bad ptr");
2057 (*g_pRealloc)(p, 0, NULL, true, g_pUser_data);
2060 size_t crnd_msize(void* p) {
2064 if ((uint32) reinterpret_cast<uintptr_t>(p) & (CRND_MIN_ALLOC_ALIGNMENT - 1)) {
2065 crnd_mem_error("crnd_msize: bad ptr");
2069 return (*g_pMSize)(p, g_pUser_data);
2074 // File: crnd_math.cpp
2077 uint32 g_bitmasks[32] =
2079 1U << 0U, 1U << 1U, 1U << 2U, 1U << 3U,
2080 1U << 4U, 1U << 5U, 1U << 6U, 1U << 7U,
2081 1U << 8U, 1U << 9U, 1U << 10U, 1U << 11U,
2082 1U << 12U, 1U << 13U, 1U << 14U, 1U << 15U,
2083 1U << 16U, 1U << 17U, 1U << 18U, 1U << 19U,
2084 1U << 20U, 1U << 21U, 1U << 22U, 1U << 23U,
2085 1U << 24U, 1U << 25U, 1U << 26U, 1U << 27U,
2086 1U << 28U, 1U << 29U, 1U << 30U, 1U << 31U};
2091 // File: crnd_info.cpp
2093 #define CRND_FOURCC(a, b, c, d) ((a) | ((b) << 8U) | ((c) << 16U) | ((d) << 24U))
2095 uint32 crnd_crn_format_to_fourcc(crn_format fmt) {
2098 return CRND_FOURCC('D', 'X', 'T', '1');
2100 return CRND_FOURCC('D', 'X', 'T', '3');
2102 return CRND_FOURCC('D', 'X', 'T', '5');
2104 return CRND_FOURCC('A', '2', 'X', 'Y');
2106 return CRND_FOURCC('A', 'T', 'I', '2');
2108 return CRND_FOURCC('A', 'T', 'I', '1');
2109 case cCRNFmtDXT5_CCxY:
2110 return CRND_FOURCC('C', 'C', 'x', 'Y');
2111 case cCRNFmtDXT5_xGxR:
2112 return CRND_FOURCC('x', 'G', 'x', 'R');
2113 case cCRNFmtDXT5_xGBR:
2114 return CRND_FOURCC('x', 'G', 'B', 'R');
2115 case cCRNFmtDXT5_AGBR:
2116 return CRND_FOURCC('A', 'G', 'B', 'R');
2118 return CRND_FOURCC('E', 'T', 'C', '1');
2120 return CRND_FOURCC('E', 'T', 'C', '2');
2122 return CRND_FOURCC('E', 'T', '2', 'A');
2130 crn_format crnd_get_fundamental_dxt_format(crn_format fmt) {
2132 case cCRNFmtDXT5_CCxY:
2133 case cCRNFmtDXT5_xGxR:
2134 case cCRNFmtDXT5_xGBR:
2135 case cCRNFmtDXT5_AGBR:
2143 uint32 crnd_get_crn_format_bits_per_texel(crn_format fmt) {
2154 case cCRNFmtDXT5_CCxY:
2155 case cCRNFmtDXT5_xGxR:
2156 case cCRNFmtDXT5_xGBR:
2157 case cCRNFmtDXT5_AGBR:
2167 uint32 crnd_get_bytes_per_dxt_block(crn_format fmt) {
2168 return (crnd_get_crn_format_bits_per_texel(fmt) << 4) >> 3;
2171 // TODO: tmp_header isn't used/This function is a helper to support old headers.
2172 const crn_header* crnd_get_header(const void* pData, uint32 data_size) {
2173 if ((!pData) || (data_size < sizeof(crn_header)))
2176 const crn_header& file_header = *static_cast<const crn_header*>(pData);
2177 if (file_header.m_sig != crn_header::cCRNSigValue)
2180 if ((file_header.m_header_size < sizeof(crn_header)) || (data_size < file_header.m_data_size))
2183 return &file_header;
2186 bool crnd_validate_file(const void* pData, uint32 data_size, crn_file_info* pFile_info) {
2188 if (pFile_info->m_struct_size != sizeof(crn_file_info))
2191 memset(&pFile_info->m_struct_size + 1, 0, sizeof(crn_file_info) - sizeof(pFile_info->m_struct_size));
2194 if ((!pData) || (data_size < cCRNHeaderMinSize))
2197 const crn_header* pHeader = crnd_get_header(pData, data_size);
2201 const uint32 header_crc = crc16(&pHeader->m_data_size, (uint32)(pHeader->m_header_size - ((const uint8*)&pHeader->m_data_size - (const uint8*)pHeader)));
2202 if (header_crc != pHeader->m_header_crc16)
2205 const uint32 data_crc = crc16((const uint8*)pData + pHeader->m_header_size, pHeader->m_data_size - pHeader->m_header_size);
2206 if (data_crc != pHeader->m_data_crc16)
2209 if ((pHeader->m_faces != 1) && (pHeader->m_faces != 6))
2211 if ((pHeader->m_width < 1) || (pHeader->m_width > cCRNMaxLevelResolution))
2213 if ((pHeader->m_height < 1) || (pHeader->m_height > cCRNMaxLevelResolution))
2215 if ((pHeader->m_levels < 1) || (pHeader->m_levels > utils::compute_max_mips(pHeader->m_width, pHeader->m_height)))
2217 if (((int)pHeader->m_format < cCRNFmtDXT1) || ((int)pHeader->m_format >= cCRNFmtTotal))
2221 pFile_info->m_actual_data_size = pHeader->m_data_size;
2222 pFile_info->m_header_size = pHeader->m_header_size;
2223 pFile_info->m_total_palette_size = pHeader->m_color_endpoints.m_size + pHeader->m_color_selectors.m_size + pHeader->m_alpha_endpoints.m_size + pHeader->m_alpha_selectors.m_size;
2224 pFile_info->m_tables_size = pHeader->m_tables_size;
2226 pFile_info->m_levels = pHeader->m_levels;
2228 for (uint32 i = 0; i < pHeader->m_levels; i++) {
2229 uint32 next_ofs = pHeader->m_data_size;
2231 // assumes the levels are packed together sequentially
2232 if ((i + 1) < pHeader->m_levels)
2233 next_ofs = pHeader->m_level_ofs[i + 1];
2235 pFile_info->m_level_compressed_size[i] = next_ofs - pHeader->m_level_ofs[i];
2238 pFile_info->m_color_endpoint_palette_entries = pHeader->m_color_endpoints.m_num;
2239 pFile_info->m_color_selector_palette_entries = pHeader->m_color_selectors.m_num;
2241 pFile_info->m_alpha_endpoint_palette_entries = pHeader->m_alpha_endpoints.m_num;
2243 pFile_info->m_alpha_selector_palette_entries = pHeader->m_alpha_selectors.m_num;
2250 bool crnd_get_texture_info(const void* pData, uint32 data_size, crn_texture_info* pInfo) {
2251 if ((!pData) || (data_size < sizeof(crn_header)) || (!pInfo))
2254 if (pInfo->m_struct_size != sizeof(crn_texture_info))
2257 const crn_header* pHeader = crnd_get_header(pData, data_size);
2261 pInfo->m_width = pHeader->m_width;
2262 pInfo->m_height = pHeader->m_height;
2263 pInfo->m_levels = pHeader->m_levels;
2264 pInfo->m_faces = pHeader->m_faces;
2265 pInfo->m_format = static_cast<crn_format>((uint32)pHeader->m_format);
2266 pInfo->m_bytes_per_block = pHeader->m_format == cCRNFmtDXT1 || pHeader->m_format == cCRNFmtDXT5A || pHeader->m_format == cCRNFmtETC1 || pHeader->m_format == cCRNFmtETC2 ? 8 : 16;
2267 pInfo->m_userdata0 = pHeader->m_userdata0;
2268 pInfo->m_userdata1 = pHeader->m_userdata1;
2273 bool crnd_get_level_info(const void* pData, uint32 data_size, uint32 level_index, crn_level_info* pLevel_info) {
2274 if ((!pData) || (data_size < cCRNHeaderMinSize) || (!pLevel_info))
2277 if (pLevel_info->m_struct_size != sizeof(crn_level_info))
2280 const crn_header* pHeader = crnd_get_header(pData, data_size);
2284 if (level_index >= pHeader->m_levels)
2287 uint32 width = math::maximum<uint32>(1U, pHeader->m_width >> level_index);
2288 uint32 height = math::maximum<uint32>(1U, pHeader->m_height >> level_index);
2290 pLevel_info->m_width = width;
2291 pLevel_info->m_height = height;
2292 pLevel_info->m_faces = pHeader->m_faces;
2293 pLevel_info->m_blocks_x = (width + 3) >> 2;
2294 pLevel_info->m_blocks_y = (height + 3) >> 2;
2295 pLevel_info->m_bytes_per_block = ((pHeader->m_format == cCRNFmtDXT1) || (pHeader->m_format == cCRNFmtDXT5A)) ? 8 : 16;
2296 pLevel_info->m_format = static_cast<crn_format>((uint32)pHeader->m_format);
2301 const void* crnd_get_level_data(const void* pData, uint32 data_size, uint32 level_index, uint32* pSize) {
2305 if ((!pData) || (data_size < cCRNHeaderMinSize))
2308 const crn_header* pHeader = crnd_get_header(pData, data_size);
2312 if (level_index >= pHeader->m_levels)
2315 uint32 cur_level_ofs = pHeader->m_level_ofs[level_index];
2318 uint32 next_level_ofs = data_size;
2319 if ((level_index + 1) < (pHeader->m_levels))
2320 next_level_ofs = pHeader->m_level_ofs[level_index + 1];
2322 *pSize = next_level_ofs - cur_level_ofs;
2325 return static_cast<const uint8*>(pData) + cur_level_ofs;
2328 uint32 crnd_get_segmented_file_size(const void* pData, uint32 data_size) {
2329 if ((!pData) || (data_size < cCRNHeaderMinSize))
2332 const crn_header* pHeader = crnd_get_header(pData, data_size);
2336 uint32 size = pHeader->m_header_size;
2338 size = math::maximum(size, pHeader->m_color_endpoints.m_ofs + pHeader->m_color_endpoints.m_size);
2339 size = math::maximum(size, pHeader->m_color_selectors.m_ofs + pHeader->m_color_selectors.m_size);
2340 size = math::maximum(size, pHeader->m_alpha_endpoints.m_ofs + pHeader->m_alpha_endpoints.m_size);
2341 size = math::maximum(size, pHeader->m_alpha_selectors.m_ofs + pHeader->m_alpha_selectors.m_size);
2342 size = math::maximum(size, pHeader->m_tables_ofs + pHeader->m_tables_size);
2347 bool crnd_create_segmented_file(const void* pData, uint32 data_size, void* pBase_data, uint base_data_size) {
2348 if ((!pData) || (data_size < cCRNHeaderMinSize))
2351 const crn_header* pHeader = crnd_get_header(pData, data_size);
2355 if (pHeader->m_flags & cCRNHeaderFlagSegmented)
2358 const uint actual_base_data_size = crnd_get_segmented_file_size(pData, data_size);
2359 if (base_data_size < actual_base_data_size)
2362 memcpy(pBase_data, pData, actual_base_data_size);
2364 crn_header& new_header = *static_cast<crn_header*>(pBase_data);
2365 new_header.m_flags = new_header.m_flags | cCRNHeaderFlagSegmented;
2366 new_header.m_data_size = actual_base_data_size;
2368 new_header.m_data_crc16 = crc16((const uint8*)pBase_data + new_header.m_header_size, new_header.m_data_size - new_header.m_header_size);
2370 new_header.m_header_crc16 = crc16(&new_header.m_data_size, new_header.m_header_size - (uint32)((const uint8*)&new_header.m_data_size - (const uint8*)&new_header));
2372 CRND_ASSERT(crnd_validate_file(&new_header, actual_base_data_size, NULL));
2379 // File: symbol_codec.cpp
2381 static_huffman_data_model::static_huffman_data_model()
2383 m_pDecode_tables(NULL) {
2386 static_huffman_data_model::static_huffman_data_model(const static_huffman_data_model& other)
2388 m_pDecode_tables(NULL) {
2392 static_huffman_data_model::~static_huffman_data_model() {
2393 if (m_pDecode_tables)
2394 crnd_delete(m_pDecode_tables);
2397 static_huffman_data_model& static_huffman_data_model::operator=(const static_huffman_data_model& rhs) {
2401 m_total_syms = rhs.m_total_syms;
2402 m_code_sizes = rhs.m_code_sizes;
2403 if (m_code_sizes.get_alloc_failed()) {
2408 if (rhs.m_pDecode_tables) {
2409 if (m_pDecode_tables)
2410 *m_pDecode_tables = *rhs.m_pDecode_tables;
2412 m_pDecode_tables = crnd_new<prefix_coding::decoder_tables>(*rhs.m_pDecode_tables);
2414 crnd_delete(m_pDecode_tables);
2415 m_pDecode_tables = NULL;
2421 void static_huffman_data_model::clear() {
2423 m_code_sizes.clear();
2424 if (m_pDecode_tables) {
2425 crnd_delete(m_pDecode_tables);
2426 m_pDecode_tables = NULL;
2430 bool static_huffman_data_model::init(uint32 total_syms, const uint8* pCode_sizes, uint32 code_size_limit) {
2431 CRND_ASSERT((total_syms >= 1) && (total_syms <= prefix_coding::cMaxSupportedSyms) && (code_size_limit >= 1));
2433 code_size_limit = math::minimum(code_size_limit, prefix_coding::cMaxExpectedCodeSize);
2435 if (!m_code_sizes.resize(total_syms))
2438 uint32 min_code_size = cUINT32_MAX;
2439 uint32 max_code_size = 0;
2441 for (uint32 i = 0; i < total_syms; i++) {
2442 uint32 s = pCode_sizes[i];
2443 m_code_sizes[i] = static_cast<uint8>(s);
2444 min_code_size = math::minimum(min_code_size, s);
2445 max_code_size = math::maximum(max_code_size, s);
2448 if ((max_code_size < 1) || (max_code_size > 32) || (min_code_size > code_size_limit))
2451 if (max_code_size > code_size_limit)
2454 if (!m_pDecode_tables)
2455 m_pDecode_tables = crnd_new<prefix_coding::decoder_tables>();
2457 if (!m_pDecode_tables->init(m_total_syms, &m_code_sizes[0], compute_decoder_table_bits()))
2463 bool static_huffman_data_model::prepare_decoder_tables() {
2464 uint32 total_syms = m_code_sizes.size();
2466 CRND_ASSERT((total_syms >= 1) && (total_syms <= prefix_coding::cMaxSupportedSyms));
2468 m_total_syms = total_syms;
2470 if (!m_pDecode_tables)
2471 m_pDecode_tables = crnd_new<prefix_coding::decoder_tables>();
2473 return m_pDecode_tables->init(m_total_syms, &m_code_sizes[0], compute_decoder_table_bits());
2476 uint static_huffman_data_model::compute_decoder_table_bits() const {
2477 #if CRND_PREFIX_CODING_USE_FIXED_TABLE_SIZE
2478 return prefix_coding::cMaxTableBits;
2480 uint32 decoder_table_bits = 0;
2481 if (m_total_syms > 16)
2482 decoder_table_bits = static_cast<uint8>(math::minimum(1 + math::ceil_log2i(m_total_syms), prefix_coding::cMaxTableBits));
2483 return decoder_table_bits;
2487 symbol_codec::symbol_codec()
2488 : m_pDecode_buf(NULL),
2489 m_pDecode_buf_next(NULL),
2490 m_pDecode_buf_end(NULL),
2491 m_decode_buf_size(0),
2496 // Code length encoding symbols:
2497 // 0-16 - actual code lengths
2498 const uint32 cMaxCodelengthCodes = 21;
2500 const uint32 cSmallZeroRunCode = 17;
2501 const uint32 cLargeZeroRunCode = 18;
2502 const uint32 cSmallRepeatCode = 19;
2503 const uint32 cLargeRepeatCode = 20;
2505 const uint32 cMinSmallZeroRunSize = 3;
2506 const uint32 cMaxSmallZeroRunSize = 10;
2507 const uint32 cMinLargeZeroRunSize = 11;
2508 const uint32 cMaxLargeZeroRunSize = 138;
2510 const uint32 cSmallMinNonZeroRunSize = 3;
2511 const uint32 cSmallMaxNonZeroRunSize = 6;
2512 const uint32 cLargeMinNonZeroRunSize = 7;
2513 const uint32 cLargeMaxNonZeroRunSize = 70;
2515 const uint32 cSmallZeroRunExtraBits = 3;
2516 const uint32 cLargeZeroRunExtraBits = 7;
2517 const uint32 cSmallNonZeroRunExtraBits = 2;
2518 const uint32 cLargeNonZeroRunExtraBits = 6;
2520 static const uint8 g_most_probable_codelength_codes[] =
2522 cSmallZeroRunCode, cLargeZeroRunCode,
2523 cSmallRepeatCode, cLargeRepeatCode,
2534 const uint32 cNumMostProbableCodelengthCodes = sizeof(g_most_probable_codelength_codes) / sizeof(g_most_probable_codelength_codes[0]);
2536 bool symbol_codec::decode_receive_static_data_model(static_huffman_data_model& model) {
2537 const uint32 total_used_syms = decode_bits(math::total_bits(prefix_coding::cMaxSupportedSyms));
2539 if (!total_used_syms) {
2544 if (!model.m_code_sizes.resize(total_used_syms))
2547 memset(&model.m_code_sizes[0], 0, sizeof(model.m_code_sizes[0]) * total_used_syms);
2549 const uint32 num_codelength_codes_to_send = decode_bits(5);
2550 if ((num_codelength_codes_to_send < 1) || (num_codelength_codes_to_send > cMaxCodelengthCodes))
2553 static_huffman_data_model dm;
2554 if (!dm.m_code_sizes.resize(cMaxCodelengthCodes))
2557 for (uint32 i = 0; i < num_codelength_codes_to_send; i++)
2558 dm.m_code_sizes[g_most_probable_codelength_codes[i]] = static_cast<uint8>(decode_bits(3));
2560 if (!dm.prepare_decoder_tables())
2564 while (ofs < total_used_syms) {
2565 const uint32 num_remaining = total_used_syms - ofs;
2567 uint32 code = decode(dm);
2569 model.m_code_sizes[ofs++] = static_cast<uint8>(code);
2570 else if (code == cSmallZeroRunCode) {
2571 uint32 len = decode_bits(cSmallZeroRunExtraBits) + cMinSmallZeroRunSize;
2572 if (len > num_remaining)
2575 } else if (code == cLargeZeroRunCode) {
2576 uint32 len = decode_bits(cLargeZeroRunExtraBits) + cMinLargeZeroRunSize;
2577 if (len > num_remaining)
2580 } else if ((code == cSmallRepeatCode) || (code == cLargeRepeatCode)) {
2582 if (code == cSmallRepeatCode)
2583 len = decode_bits(cSmallNonZeroRunExtraBits) + cSmallMinNonZeroRunSize;
2585 len = decode_bits(cLargeNonZeroRunExtraBits) + cLargeMinNonZeroRunSize;
2587 if ((!ofs) || (len > num_remaining))
2589 const uint32 prev = model.m_code_sizes[ofs - 1];
2592 const uint32 end = ofs + len;
2594 model.m_code_sizes[ofs++] = static_cast<uint8>(prev);
2601 if (ofs != total_used_syms)
2604 return model.prepare_decoder_tables();
2607 bool symbol_codec::start_decoding(const uint8* pBuf, uint32 buf_size) {
2611 m_pDecode_buf = pBuf;
2612 m_pDecode_buf_next = pBuf;
2613 m_decode_buf_size = buf_size;
2614 m_pDecode_buf_end = pBuf + buf_size;
2621 void symbol_codec::get_bits_init() {
2626 uint32 symbol_codec::decode_bits(uint32 num_bits) {
2630 if (num_bits > 16) {
2631 uint32 a = get_bits(num_bits - 16);
2632 uint32 b = get_bits(16);
2634 return (a << 16) | b;
2636 return get_bits(num_bits);
2639 uint32 symbol_codec::get_bits(uint32 num_bits) {
2640 CRND_ASSERT(num_bits <= 32U);
2642 while (m_bit_count < (int)num_bits) {
2644 if (m_pDecode_buf_next != m_pDecode_buf_end)
2645 c = *m_pDecode_buf_next++;
2648 CRND_ASSERT(m_bit_count <= cBitBufSize);
2650 m_bit_buf |= (c << (cBitBufSize - m_bit_count));
2653 uint32 result = static_cast<uint32>(m_bit_buf >> (cBitBufSize - num_bits));
2655 m_bit_buf <<= num_bits;
2656 m_bit_count -= num_bits;
2661 uint32 symbol_codec::decode(const static_huffman_data_model& model) {
2662 const prefix_coding::decoder_tables* pTables = model.m_pDecode_tables;
2664 if (m_bit_count < 24) {
2665 if (m_bit_count < 16) {
2666 uint32 c0 = 0, c1 = 0;
2667 const uint8* p = m_pDecode_buf_next;
2668 if (p < m_pDecode_buf_end)
2670 if (p < m_pDecode_buf_end)
2672 m_pDecode_buf_next = p;
2674 uint32 c = (c0 << 8) | c1;
2675 m_bit_buf |= (c << (32 - m_bit_count));
2677 uint32 c = (m_pDecode_buf_next < m_pDecode_buf_end) ? *m_pDecode_buf_next++ : 0;
2679 m_bit_buf |= (c << (32 - m_bit_count));
2683 uint32 k = (m_bit_buf >> 16) + 1;
2686 if (k <= pTables->m_table_max_code) {
2687 uint32 t = pTables->m_lookup[m_bit_buf >> (32 - pTables->m_table_bits)];
2689 CRND_ASSERT(t != cUINT32_MAX);
2690 sym = t & cUINT16_MAX;
2693 CRND_ASSERT(model.m_code_sizes[sym] == len);
2695 len = pTables->m_decode_start_code_size;
2698 if (k <= pTables->m_max_codes[len - 1])
2703 int val_ptr = pTables->m_val_ptrs[len - 1] + (m_bit_buf >> (32 - len));
2705 if (((uint32)val_ptr >= model.m_total_syms)) {
2706 // corrupted stream, or a bug
2711 sym = pTables->m_sorted_symbol_order[val_ptr];
2720 uint64 symbol_codec::stop_decoding() {
2721 return static_cast<uint64>(m_pDecode_buf_next - m_pDecode_buf);
2726 // File: crnd_dxt.cpp
2728 const uint8 g_dxt1_to_linear[cDXT1SelectorValues] = {0U, 3U, 1U, 2U};
2729 const uint8 g_dxt1_from_linear[cDXT1SelectorValues] = {0U, 2U, 3U, 1U};
2730 const uint8 g_etc1_from_linear[cDXT1SelectorValues] = {3U, 2U, 0U, 1U};
2732 const uint8 g_dxt5_to_linear[cDXT5SelectorValues] = {0U, 7U, 1U, 2U, 3U, 4U, 5U, 6U};
2733 const uint8 g_dxt5_from_linear[cDXT5SelectorValues] = {0U, 2U, 3U, 4U, 5U, 6U, 7U, 1U};
2735 const uint8 g_six_alpha_invert_table[cDXT5SelectorValues] = {1, 0, 5, 4, 3, 2, 6, 7};
2736 const uint8 g_eight_alpha_invert_table[cDXT5SelectorValues] = {1, 0, 7, 6, 5, 4, 3, 2};
2738 uint16 dxt1_block::pack_color(const color_quad_u8& color, bool scaled, uint32 bias) {
2744 r = (r * 31U + bias) / 255U;
2745 g = (g * 63U + bias) / 255U;
2746 b = (b * 31U + bias) / 255U;
2749 r = math::minimum(r, 31U);
2750 g = math::minimum(g, 63U);
2751 b = math::minimum(b, 31U);
2753 return static_cast<uint16>(b | (g << 5U) | (r << 11U));
2756 uint16 dxt1_block::pack_color(uint32 r, uint32 g, uint32 b, bool scaled, uint32 bias) {
2757 return pack_color(color_quad_u8(r, g, b, 0), scaled, bias);
2760 color_quad_u8 dxt1_block::unpack_color(uint16 packed_color, bool scaled, uint32 alpha) {
2761 uint32 b = packed_color & 31U;
2762 uint32 g = (packed_color >> 5U) & 63U;
2763 uint32 r = (packed_color >> 11U) & 31U;
2766 b = (b << 3U) | (b >> 2U);
2767 g = (g << 2U) | (g >> 4U);
2768 r = (r << 3U) | (r >> 2U);
2771 return color_quad_u8(r, g, b, alpha);
2774 void dxt1_block::unpack_color(uint32& r, uint32& g, uint32& b, uint16 packed_color, bool scaled) {
2775 color_quad_u8 c(unpack_color(packed_color, scaled, 0));
2781 uint32 dxt1_block::get_block_colors3(color_quad_u8* pDst, uint16 color0, uint16 color1) {
2782 color_quad_u8 c0(unpack_color(color0, true));
2783 color_quad_u8 c1(unpack_color(color1, true));
2787 pDst[2].set((c0.r + c1.r) >> 1U, (c0.g + c1.g) >> 1U, (c0.b + c1.b) >> 1U, 255U);
2788 pDst[3].set(0, 0, 0, 0);
2793 uint32 dxt1_block::get_block_colors4(color_quad_u8* pDst, uint16 color0, uint16 color1) {
2794 color_quad_u8 c0(unpack_color(color0, true));
2795 color_quad_u8 c1(unpack_color(color1, true));
2800 // 12/14/09 - Supposed to round according to DX docs, but this conflicts with the OpenGL S3TC spec. ?
2801 // Turns out some GPU's round and some don't. Great.
2802 //pDst[2].set( (c0.r * 2 + c1.r + 1) / 3, (c0.g * 2 + c1.g + 1) / 3, (c0.b * 2 + c1.b + 1) / 3, 255U);
2803 //pDst[3].set( (c1.r * 2 + c0.r + 1) / 3, (c1.g * 2 + c0.g + 1) / 3, (c1.b * 2 + c0.b + 1) / 3, 255U);
2805 pDst[2].set((c0.r * 2 + c1.r) / 3, (c0.g * 2 + c1.g) / 3, (c0.b * 2 + c1.b) / 3, 255U);
2806 pDst[3].set((c1.r * 2 + c0.r) / 3, (c1.g * 2 + c0.g) / 3, (c1.b * 2 + c0.b) / 3, 255U);
2811 uint32 dxt1_block::get_block_colors(color_quad_u8* pDst, uint16 color0, uint16 color1) {
2812 if (color0 > color1)
2813 return get_block_colors4(pDst, color0, color1);
2815 return get_block_colors3(pDst, color0, color1);
2818 color_quad_u8 dxt1_block::unpack_endpoint(uint32 endpoints, uint32 index, bool scaled, uint32 alpha) {
2819 CRND_ASSERT(index < 2);
2820 return unpack_color(static_cast<uint16>((endpoints >> (index * 16U)) & 0xFFFFU), scaled, alpha);
2823 uint32 dxt1_block::pack_endpoints(uint32 lo, uint32 hi) {
2824 CRND_ASSERT((lo <= 0xFFFFU) && (hi <= 0xFFFFU));
2825 return lo | (hi << 16U);
2828 void dxt3_block::set_alpha(uint32 x, uint32 y, uint32 value, bool scaled) {
2829 CRND_ASSERT((x < cDXTBlockSize) && (y < cDXTBlockSize));
2832 CRND_ASSERT(value <= 0xFF);
2833 value = (value * 15U + 128U) / 255U;
2835 CRND_ASSERT(value <= 0xF);
2838 uint32 ofs = (y << 1U) + (x >> 1U);
2839 uint32 c = m_alpha[ofs];
2841 c &= ~(0xF << ((x & 1U) << 2U));
2842 c |= (value << ((x & 1U) << 2U));
2844 m_alpha[ofs] = static_cast<uint8>(c);
2847 uint32 dxt3_block::get_alpha(uint32 x, uint32 y, bool scaled) const {
2848 CRND_ASSERT((x < cDXTBlockSize) && (y < cDXTBlockSize));
2850 uint32 value = m_alpha[(y << 1U) + (x >> 1U)];
2856 value = (value << 4U) | value;
2861 uint32 dxt5_block::get_block_values6(color_quad_u8* pDst, uint32 l, uint32 h) {
2862 pDst[0].a = static_cast<uint8>(l);
2863 pDst[1].a = static_cast<uint8>(h);
2864 pDst[2].a = static_cast<uint8>((l * 4 + h) / 5);
2865 pDst[3].a = static_cast<uint8>((l * 3 + h * 2) / 5);
2866 pDst[4].a = static_cast<uint8>((l * 2 + h * 3) / 5);
2867 pDst[5].a = static_cast<uint8>((l + h * 4) / 5);
2873 uint32 dxt5_block::get_block_values8(color_quad_u8* pDst, uint32 l, uint32 h) {
2874 pDst[0].a = static_cast<uint8>(l);
2875 pDst[1].a = static_cast<uint8>(h);
2876 pDst[2].a = static_cast<uint8>((l * 6 + h) / 7);
2877 pDst[3].a = static_cast<uint8>((l * 5 + h * 2) / 7);
2878 pDst[4].a = static_cast<uint8>((l * 4 + h * 3) / 7);
2879 pDst[5].a = static_cast<uint8>((l * 3 + h * 4) / 7);
2880 pDst[6].a = static_cast<uint8>((l * 2 + h * 5) / 7);
2881 pDst[7].a = static_cast<uint8>((l + h * 6) / 7);
2885 uint32 dxt5_block::get_block_values(color_quad_u8* pDst, uint32 l, uint32 h) {
2887 return get_block_values8(pDst, l, h);
2889 return get_block_values6(pDst, l, h);
2892 uint32 dxt5_block::get_block_values6(uint32* pDst, uint32 l, uint32 h) {
2895 pDst[2] = (l * 4 + h) / 5;
2896 pDst[3] = (l * 3 + h * 2) / 5;
2897 pDst[4] = (l * 2 + h * 3) / 5;
2898 pDst[5] = (l + h * 4) / 5;
2904 uint32 dxt5_block::get_block_values8(uint32* pDst, uint32 l, uint32 h) {
2907 pDst[2] = (l * 6 + h) / 7;
2908 pDst[3] = (l * 5 + h * 2) / 7;
2909 pDst[4] = (l * 4 + h * 3) / 7;
2910 pDst[5] = (l * 3 + h * 4) / 7;
2911 pDst[6] = (l * 2 + h * 5) / 7;
2912 pDst[7] = (l + h * 6) / 7;
2916 uint32 dxt5_block::unpack_endpoint(uint32 packed, uint32 index) {
2917 CRND_ASSERT(index < 2);
2918 return (packed >> (8 * index)) & 0xFF;
2921 uint32 dxt5_block::pack_endpoints(uint32 lo, uint32 hi) {
2922 CRND_ASSERT((lo <= 0xFF) && (hi <= 0xFF));
2923 return lo | (hi << 8U);
2926 uint32 dxt5_block::get_block_values(uint32* pDst, uint32 l, uint32 h) {
2928 return get_block_values8(pDst, l, h);
2930 return get_block_values6(pDst, l, h);
2935 // File: crnd_decode.cpp
2939 class crn_unpacker {
2941 inline crn_unpacker()
2942 : m_magic(cMagicValue),
2948 inline ~crn_unpacker() {
2952 inline bool is_valid() const { return m_magic == cMagicValue; }
2954 bool init(const void* pData, uint32 data_size) {
2955 m_pHeader = crnd_get_header(pData, data_size);
2959 m_pData = static_cast<const uint8*>(pData);
2960 m_data_size = data_size;
2965 if (!decode_palettes())
2972 void** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes,
2973 uint32 level_index) {
2974 uint32 cur_level_ofs = m_pHeader->m_level_ofs[level_index];
2976 uint32 next_level_ofs = m_data_size;
2977 if ((level_index + 1) < (m_pHeader->m_levels))
2978 next_level_ofs = m_pHeader->m_level_ofs[level_index + 1];
2980 CRND_ASSERT(next_level_ofs > cur_level_ofs);
2982 return unpack_level(m_pData + cur_level_ofs, next_level_ofs - cur_level_ofs, pDst, dst_size_in_bytes, row_pitch_in_bytes, level_index);
2986 const void* pSrc, uint32 src_size_in_bytes,
2987 void** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes,
2988 uint32 level_index) {
2990 #ifdef CRND_BUILD_DEBUG
2991 for (uint32 f = 0; f < m_pHeader->m_faces; f++)
2996 const uint32 width = math::maximum(m_pHeader->m_width >> level_index, 1U);
2997 const uint32 height = math::maximum(m_pHeader->m_height >> level_index, 1U);
2998 const uint32 blocks_x = (width + 3U) >> 2U;
2999 const uint32 blocks_y = (height + 3U) >> 2U;
3000 const uint32 block_size = m_pHeader->m_format == cCRNFmtDXT1 || m_pHeader->m_format == cCRNFmtDXT5A || m_pHeader->m_format == cCRNFmtETC1 || m_pHeader->m_format == cCRNFmtETC2 ? 8 : 16;
3002 uint32 minimal_row_pitch = block_size * blocks_x;
3003 if (!row_pitch_in_bytes)
3004 row_pitch_in_bytes = minimal_row_pitch;
3005 else if ((row_pitch_in_bytes < minimal_row_pitch) || (row_pitch_in_bytes & 3))
3007 if (dst_size_in_bytes < row_pitch_in_bytes * blocks_y)
3010 if (!m_codec.start_decoding(static_cast<const crnd::uint8*>(pSrc), src_size_in_bytes))
3013 bool status = false;
3014 switch (m_pHeader->m_format) {
3016 status = unpack_dxt1((uint8**)pDst, row_pitch_in_bytes, blocks_x, blocks_y);
3019 case cCRNFmtDXT5_CCxY:
3020 case cCRNFmtDXT5_xGBR:
3021 case cCRNFmtDXT5_AGBR:
3022 case cCRNFmtDXT5_xGxR:
3023 status = unpack_dxt5((uint8**)pDst, row_pitch_in_bytes, blocks_x, blocks_y);
3026 status = unpack_dxt5a((uint8**)pDst, row_pitch_in_bytes, blocks_x, blocks_y);
3030 status = unpack_dxn((uint8**)pDst, row_pitch_in_bytes, blocks_x, blocks_y);
3033 status = unpack_etc1((uint8**)pDst, row_pitch_in_bytes, blocks_x, blocks_y);
3036 status = unpack_etc1((uint8**)pDst, row_pitch_in_bytes, blocks_x, blocks_y);
3039 status = unpack_etc2a((uint8**)pDst, row_pitch_in_bytes, blocks_x, blocks_y);
3047 m_codec.stop_decoding();
3051 inline const void* get_data() const { return m_pData; }
3052 inline uint32 get_data_size() const { return m_data_size; }
3055 enum { cMagicValue = 0x1EF9CABD };
3058 const uint8* m_pData;
3060 const crn_header* m_pHeader;
3062 symbol_codec m_codec;
3064 static_huffman_data_model m_reference_encoding_dm;
3065 static_huffman_data_model m_endpoint_delta_dm[2];
3066 static_huffman_data_model m_selector_delta_dm[2];
3068 crnd::vector<uint32> m_color_endpoints;
3069 crnd::vector<uint32> m_color_selectors;
3071 crnd::vector<uint16> m_alpha_endpoints;
3072 crnd::vector<uint16> m_alpha_selectors;
3074 struct block_buffer_element {
3075 uint16 endpoint_reference;
3076 uint16 color_endpoint_index;
3077 uint16 alpha0_endpoint_index;
3078 uint16 alpha1_endpoint_index;
3080 crnd::vector<block_buffer_element> m_block_buffer;
3082 bool init_tables() {
3083 if (!m_codec.start_decoding(m_pData + m_pHeader->m_tables_ofs, m_pHeader->m_tables_size))
3086 if (!m_codec.decode_receive_static_data_model(m_reference_encoding_dm))
3089 if ((!m_pHeader->m_color_endpoints.m_num) && (!m_pHeader->m_alpha_endpoints.m_num))
3092 if (m_pHeader->m_color_endpoints.m_num) {
3093 if (!m_codec.decode_receive_static_data_model(m_endpoint_delta_dm[0]))
3095 if (!m_codec.decode_receive_static_data_model(m_selector_delta_dm[0]))
3099 if (m_pHeader->m_alpha_endpoints.m_num) {
3100 if (!m_codec.decode_receive_static_data_model(m_endpoint_delta_dm[1]))
3102 if (!m_codec.decode_receive_static_data_model(m_selector_delta_dm[1]))
3106 m_codec.stop_decoding();
3111 bool decode_palettes() {
3112 if (m_pHeader->m_color_endpoints.m_num) {
3113 if (!decode_color_endpoints())
3115 if (!decode_color_selectors())
3119 if (m_pHeader->m_alpha_endpoints.m_num) {
3120 if (!decode_alpha_endpoints())
3122 if (!(m_pHeader->m_format == cCRNFmtETC2A ? decode_alpha_selectors_etc() : decode_alpha_selectors()))
3129 bool decode_color_endpoints() {
3130 const uint32 num_color_endpoints = m_pHeader->m_color_endpoints.m_num;
3131 const bool has_etc_color_blocks = m_pHeader->m_format == cCRNFmtETC1 || m_pHeader->m_format == cCRNFmtETC2 || m_pHeader->m_format == cCRNFmtETC2A;
3133 if (!m_color_endpoints.resize(num_color_endpoints))
3136 if (!m_codec.start_decoding(m_pData + m_pHeader->m_color_endpoints.m_ofs, m_pHeader->m_color_endpoints.m_size))
3139 static_huffman_data_model dm[2];
3140 for (uint32 i = 0; i < (has_etc_color_blocks ? 1 : 2); i++)
3141 if (!m_codec.decode_receive_static_data_model(dm[i]))
3144 uint32 a = 0, b = 0, c = 0;
3145 uint32 d = 0, e = 0, f = 0;
3147 uint32* CRND_RESTRICT pDst = &m_color_endpoints[0];
3149 for (uint32 i = 0; i < num_color_endpoints; i++) {
3150 if (has_etc_color_blocks) {
3151 for (b = 0; b < 32; b += 8)
3152 a += m_codec.decode(dm[0]) << b;
3153 *pDst++ = a &= 0x1F1F1F1F;
3155 a = (a + m_codec.decode(dm[0])) & 31;
3156 b = (b + m_codec.decode(dm[1])) & 63;
3157 c = (c + m_codec.decode(dm[0])) & 31;
3158 d = (d + m_codec.decode(dm[0])) & 31;
3159 e = (e + m_codec.decode(dm[1])) & 63;
3160 f = (f + m_codec.decode(dm[0])) & 31;
3161 *pDst++ = c | (b << 5U) | (a << 11U) | (f << 16U) | (e << 21U) | (d << 27U);
3165 m_codec.stop_decoding();
3170 bool decode_color_selectors() {
3171 const bool has_etc_color_blocks = m_pHeader->m_format == cCRNFmtETC1 || m_pHeader->m_format == cCRNFmtETC2 || m_pHeader->m_format == cCRNFmtETC2A;
3172 m_codec.start_decoding(m_pData + m_pHeader->m_color_selectors.m_ofs, m_pHeader->m_color_selectors.m_size);
3173 static_huffman_data_model dm;
3174 m_codec.decode_receive_static_data_model(dm);
3175 m_color_selectors.resize(m_pHeader->m_color_selectors.m_num << (has_etc_color_blocks ? 1 : 0));
3176 for (uint32 s = 0, i = 0; i < m_pHeader->m_color_selectors.m_num; i++) {
3177 for (uint32 j = 0; j < 32; j += 4)
3178 s ^= m_codec.decode(dm) << j;
3179 if (has_etc_color_blocks) {
3180 for (uint32 selector = (~s & 0xAAAAAAAA) | (~(s ^ s >> 1) & 0x55555555), t = 8, h = 0; h < 4; h++, t -= 15) {
3181 for (uint32 w = 0; w < 4; w++, t += 4) {
3182 uint32 s0 = selector >> (w << 3 | h << 1);
3183 m_color_selectors[i << 1] |= ((s0 >> 1 & 1) | (s0 & 1) << 16) << (t & 15);
3184 uint32 s1 = selector >> (h << 3 | w << 1);
3185 m_color_selectors[i << 1 | 1] |= ((s1 >> 1 & 1) | (s1 & 1) << 16) << (t & 15);
3189 m_color_selectors[i] = ((s ^ s << 1) & 0xAAAAAAAA) | (s >> 1 & 0x55555555);
3192 m_codec.stop_decoding();
3196 bool decode_alpha_endpoints() {
3197 const uint32 num_alpha_endpoints = m_pHeader->m_alpha_endpoints.m_num;
3199 if (!m_codec.start_decoding(m_pData + m_pHeader->m_alpha_endpoints.m_ofs, m_pHeader->m_alpha_endpoints.m_size))
3202 static_huffman_data_model dm;
3203 if (!m_codec.decode_receive_static_data_model(dm))
3206 if (!m_alpha_endpoints.resize(num_alpha_endpoints))
3209 uint16* CRND_RESTRICT pDst = &m_alpha_endpoints[0];
3210 uint32 a = 0, b = 0;
3212 for (uint32 i = 0; i < num_alpha_endpoints; i++) {
3213 a = (a + m_codec.decode(dm)) & 255;
3214 b = (b + m_codec.decode(dm)) & 255;
3215 *pDst++ = (uint16)(a | (b << 8));
3218 m_codec.stop_decoding();
3223 bool decode_alpha_selectors() {
3224 m_codec.start_decoding(m_pData + m_pHeader->m_alpha_selectors.m_ofs, m_pHeader->m_alpha_selectors.m_size);
3225 static_huffman_data_model dm;
3226 m_codec.decode_receive_static_data_model(dm);
3227 m_alpha_selectors.resize(m_pHeader->m_alpha_selectors.m_num * 3);
3228 uint8 dxt5_from_linear[64];
3229 for (uint32 i = 0; i < 64; i++)
3230 dxt5_from_linear[i] = g_dxt5_from_linear[i & 7] | g_dxt5_from_linear[i >> 3] << 3;
3231 for (uint32 s0_linear = 0, s1_linear = 0, i = 0; i < m_alpha_selectors.size();) {
3232 uint32 s0 = 0, s1 = 0;
3233 for (uint32 j = 0; j < 24; s0 |= dxt5_from_linear[s0_linear >> j & 0x3F] << j, j += 6)
3234 s0_linear ^= m_codec.decode(dm) << j;
3235 for (uint32 j = 0; j < 24; s1 |= dxt5_from_linear[s1_linear >> j & 0x3F] << j, j += 6)
3236 s1_linear ^= m_codec.decode(dm) << j;
3237 m_alpha_selectors[i++] = s0;
3238 m_alpha_selectors[i++] = s0 >> 16 | s1 << 8;
3239 m_alpha_selectors[i++] = s1 >> 8;
3241 m_codec.stop_decoding();
3245 bool decode_alpha_selectors_etc() {
3246 m_codec.start_decoding(m_pData + m_pHeader->m_alpha_selectors.m_ofs, m_pHeader->m_alpha_selectors.m_size);
3247 static_huffman_data_model dm;
3248 m_codec.decode_receive_static_data_model(dm);
3249 m_alpha_selectors.resize(m_pHeader->m_alpha_selectors.m_num * 6);
3250 uint8 s_linear[8] = {};
3251 uint8* data = (uint8*)m_alpha_selectors.begin();
3252 for (uint i = 0; i < m_alpha_selectors.size(); i += 6, data += 12) {
3253 for (uint s_group = 0, p = 0; p < 16; p++) {
3254 s_group = p & 1 ? s_group >> 3 : s_linear[p >> 1] ^= m_codec.decode(dm);
3255 uint8 s = s_group & 7;
3258 uint8 d = 3 * (p + 1);
3259 uint8 byte_offset = d >> 3;
3260 uint8 bit_offset = d & 7;
3261 data[byte_offset] |= s << (8 - bit_offset);
3263 data[byte_offset - 1] |= s >> bit_offset;
3264 d += 9 * ((p & 3) - (p >> 2));
3265 byte_offset = d >> 3;
3267 data[byte_offset + 6] |= s << (8 - bit_offset);
3269 data[byte_offset + 5] |= s >> bit_offset;
3272 m_codec.stop_decoding();
3276 static inline uint32 tiled_offset_2d_outer(uint32 y, uint32 AlignedWidth, uint32 LogBpp) {
3277 uint32 Macro = ((y >> 5) * (AlignedWidth >> 5)) << (LogBpp + 7);
3278 uint32 Micro = ((y & 6) << 2) << LogBpp;
3281 ((Micro & ~15) << 1) +
3283 ((y & 8) << (3 + LogBpp)) + ((y & 1) << 4);
3286 static inline uint32 tiled_offset_2d_inner(uint32 x, uint32 y, uint32 LogBpp, uint32 BaseOffset) {
3287 uint32 Macro = (x >> 5) << (LogBpp + 7);
3288 uint32 Micro = (x & 7) << LogBpp;
3289 uint32 Offset = BaseOffset + Macro + ((Micro & ~15) << 1) + (Micro & 15);
3291 return ((Offset & ~511) << 3) + ((Offset & 448) << 2) + (Offset & 63) +
3293 (((((y & 8) >> 2) + (x >> 3)) & 3) << 6);
3296 static inline void limit(uint& x, uint n) {
3298 int msk = (v >> 31);
3299 x = (x & msk) | (v & ~msk);
3302 bool unpack_dxt1(uint8** pDst, uint32 output_pitch_in_bytes, uint32 output_width, uint32 output_height) {
3303 const uint32 num_color_endpoints = m_color_endpoints.size();
3304 const uint32 width = (output_width + 1) & ~1;
3305 const uint32 height = (output_height + 1) & ~1;
3306 const int32 delta_pitch_in_dwords = (output_pitch_in_bytes >> 2) - (width << 1);
3308 if (m_block_buffer.size() < width)
3309 m_block_buffer.resize(width);
3311 uint32 color_endpoint_index = 0;
3312 uint8 reference_group = 0;
3314 for (uint32 f = 0; f < m_pHeader->m_faces; f++) {
3315 uint32* pData = (uint32*)pDst[f];
3316 for (uint32 y = 0; y < height; y++, pData += delta_pitch_in_dwords) {
3317 bool visible = y < output_height;
3318 for (uint32 x = 0; x < width; x++, pData += 2) {
3319 visible = visible && x < output_width;
3320 if (!(y & 1) && !(x & 1))
3321 reference_group = m_codec.decode(m_reference_encoding_dm);
3322 block_buffer_element &buffer = m_block_buffer[x];
3323 uint8 endpoint_reference;
3325 endpoint_reference = buffer.endpoint_reference;
3327 endpoint_reference = reference_group & 3;
3328 reference_group >>= 2;
3329 buffer.endpoint_reference = reference_group & 3;
3330 reference_group >>= 2;
3332 if (!endpoint_reference) {
3333 color_endpoint_index += m_codec.decode(m_endpoint_delta_dm[0]);
3334 if (color_endpoint_index >= num_color_endpoints)
3335 color_endpoint_index -= num_color_endpoints;
3336 buffer.color_endpoint_index = color_endpoint_index;
3337 } else if (endpoint_reference == 1) {
3338 buffer.color_endpoint_index = color_endpoint_index;
3340 color_endpoint_index = buffer.color_endpoint_index;
3342 uint32 color_selector_index = m_codec.decode(m_selector_delta_dm[0]);
3344 pData[0] = m_color_endpoints[color_endpoint_index];
3345 pData[1] = m_color_selectors[color_selector_index];
3353 bool unpack_dxt5(uint8** pDst, uint32 row_pitch_in_bytes, uint32 output_width, uint32 output_height) {
3354 const uint32 num_color_endpoints = m_color_endpoints.size();
3355 const uint32 num_alpha_endpoints = m_alpha_endpoints.size();
3356 const uint32 width = (output_width + 1) & ~1;
3357 const uint32 height = (output_height + 1) & ~1;
3358 const int32 delta_pitch_in_dwords = (row_pitch_in_bytes >> 2) - (width << 2);
3360 if (m_block_buffer.size() < width)
3361 m_block_buffer.resize(width);
3363 uint32 color_endpoint_index = 0;
3364 uint32 alpha0_endpoint_index = 0;
3365 uint8 reference_group = 0;
3367 for (uint32 f = 0; f < m_pHeader->m_faces; f++) {
3368 uint32* pData = (uint32*)pDst[f];
3369 for (uint32 y = 0; y < height; y++, pData += delta_pitch_in_dwords) {
3370 bool visible = y < output_height;
3371 for (uint32 x = 0; x < width; x++, pData += 4) {
3372 visible = visible && x < output_width;
3373 if (!(y & 1) && !(x & 1))
3374 reference_group = m_codec.decode(m_reference_encoding_dm);
3375 block_buffer_element &buffer = m_block_buffer[x];
3376 uint8 endpoint_reference;
3378 endpoint_reference = buffer.endpoint_reference;
3380 endpoint_reference = reference_group & 3;
3381 reference_group >>= 2;
3382 buffer.endpoint_reference = reference_group & 3;
3383 reference_group >>= 2;
3385 if (!endpoint_reference) {
3386 color_endpoint_index += m_codec.decode(m_endpoint_delta_dm[0]);
3387 if (color_endpoint_index >= num_color_endpoints)
3388 color_endpoint_index -= num_color_endpoints;
3389 buffer.color_endpoint_index = color_endpoint_index;
3390 alpha0_endpoint_index += m_codec.decode(m_endpoint_delta_dm[1]);
3391 if (alpha0_endpoint_index >= num_alpha_endpoints)
3392 alpha0_endpoint_index -= num_alpha_endpoints;
3393 buffer.alpha0_endpoint_index = alpha0_endpoint_index;
3394 } else if (endpoint_reference == 1) {
3395 buffer.color_endpoint_index = color_endpoint_index;
3396 buffer.alpha0_endpoint_index = alpha0_endpoint_index;
3398 color_endpoint_index = buffer.color_endpoint_index;
3399 alpha0_endpoint_index = buffer.alpha0_endpoint_index;
3401 uint32 color_selector_index = m_codec.decode(m_selector_delta_dm[0]);
3402 uint32 alpha0_selector_index = m_codec.decode(m_selector_delta_dm[1]);
3404 const uint16* pAlpha0_selectors = &m_alpha_selectors[alpha0_selector_index * 3];
3405 pData[0] = m_alpha_endpoints[alpha0_endpoint_index] | (pAlpha0_selectors[0] << 16);
3406 pData[1] = pAlpha0_selectors[1] | (pAlpha0_selectors[2] << 16);
3407 pData[2] = m_color_endpoints[color_endpoint_index];
3408 pData[3] = m_color_selectors[color_selector_index];
3416 bool unpack_dxn(uint8** pDst, uint32 row_pitch_in_bytes, uint32 output_width, uint32 output_height) {
3417 const uint32 num_alpha_endpoints = m_alpha_endpoints.size();
3418 const uint32 width = (output_width + 1) & ~1;
3419 const uint32 height = (output_height + 1) & ~1;
3420 const int32 delta_pitch_in_dwords = (row_pitch_in_bytes >> 2) - (width << 2);
3422 if (m_block_buffer.size() < width)
3423 m_block_buffer.resize(width);
3425 uint32 alpha0_endpoint_index = 0;
3426 uint32 alpha1_endpoint_index = 0;
3427 uint8 reference_group = 0;
3429 for (uint32 f = 0; f < m_pHeader->m_faces; f++) {
3430 uint32* pData = (uint32*)pDst[f];
3431 for (uint32 y = 0; y < height; y++, pData += delta_pitch_in_dwords) {
3432 bool visible = y < output_height;
3433 for (uint32 x = 0; x < width; x++, pData += 4) {
3434 visible = visible && x < output_width;
3435 if (!(y & 1) && !(x & 1))
3436 reference_group = m_codec.decode(m_reference_encoding_dm);
3437 block_buffer_element &buffer = m_block_buffer[x];
3438 uint8 endpoint_reference;
3440 endpoint_reference = buffer.endpoint_reference;
3442 endpoint_reference = reference_group & 3;
3443 reference_group >>= 2;
3444 buffer.endpoint_reference = reference_group & 3;
3445 reference_group >>= 2;
3447 if (!endpoint_reference) {
3448 alpha0_endpoint_index += m_codec.decode(m_endpoint_delta_dm[1]);
3449 if (alpha0_endpoint_index >= num_alpha_endpoints)
3450 alpha0_endpoint_index -= num_alpha_endpoints;
3451 buffer.alpha0_endpoint_index = alpha0_endpoint_index;
3452 alpha1_endpoint_index += m_codec.decode(m_endpoint_delta_dm[1]);
3453 if (alpha1_endpoint_index >= num_alpha_endpoints)
3454 alpha1_endpoint_index -= num_alpha_endpoints;
3455 buffer.alpha1_endpoint_index = alpha1_endpoint_index;
3456 } else if (endpoint_reference == 1) {
3457 buffer.alpha0_endpoint_index = alpha0_endpoint_index;
3458 buffer.alpha1_endpoint_index = alpha1_endpoint_index;
3460 alpha0_endpoint_index = buffer.alpha0_endpoint_index;
3461 alpha1_endpoint_index = buffer.alpha1_endpoint_index;
3463 uint32 alpha0_selector_index = m_codec.decode(m_selector_delta_dm[1]);
3464 uint32 alpha1_selector_index = m_codec.decode(m_selector_delta_dm[1]);
3466 const uint16* pAlpha0_selectors = &m_alpha_selectors[alpha0_selector_index * 3];
3467 const uint16* pAlpha1_selectors = &m_alpha_selectors[alpha1_selector_index * 3];
3468 pData[0] = m_alpha_endpoints[alpha0_endpoint_index] | (pAlpha0_selectors[0] << 16);
3469 pData[1] = pAlpha0_selectors[1] | (pAlpha0_selectors[2] << 16);
3470 pData[2] = m_alpha_endpoints[alpha1_endpoint_index] | (pAlpha1_selectors[0] << 16);
3471 pData[3] = pAlpha1_selectors[1] | (pAlpha1_selectors[2] << 16);
3479 bool unpack_dxt5a(uint8** pDst, uint32 row_pitch_in_bytes, uint32 output_width, uint32 output_height) {
3480 const uint32 num_alpha_endpoints = m_alpha_endpoints.size();
3481 const uint32 width = (output_width + 1) & ~1;
3482 const uint32 height = (output_height + 1) & ~1;
3483 const int32 delta_pitch_in_dwords = (row_pitch_in_bytes >> 2) - (width << 1);
3485 if (m_block_buffer.size() < width)
3486 m_block_buffer.resize(width);
3488 uint32 alpha0_endpoint_index = 0;
3489 uint8 reference_group = 0;
3491 for (uint32 f = 0; f < m_pHeader->m_faces; f++) {
3492 uint32* pData = (uint32*)pDst[f];
3493 for (uint32 y = 0; y < height; y++, pData += delta_pitch_in_dwords) {
3494 bool visible = y < output_height;
3495 for (uint32 x = 0; x < width; x++, pData += 2) {
3496 visible = visible && x < output_width;
3497 if (!(y & 1) && !(x & 1))
3498 reference_group = m_codec.decode(m_reference_encoding_dm);
3499 block_buffer_element &buffer = m_block_buffer[x];
3500 uint8 endpoint_reference;
3502 endpoint_reference = buffer.endpoint_reference;
3504 endpoint_reference = reference_group & 3;
3505 reference_group >>= 2;
3506 buffer.endpoint_reference = reference_group & 3;
3507 reference_group >>= 2;
3509 if (!endpoint_reference) {
3510 alpha0_endpoint_index += m_codec.decode(m_endpoint_delta_dm[1]);
3511 if (alpha0_endpoint_index >= num_alpha_endpoints)
3512 alpha0_endpoint_index -= num_alpha_endpoints;
3513 buffer.alpha0_endpoint_index = alpha0_endpoint_index;
3514 } else if (endpoint_reference == 1) {
3515 buffer.alpha0_endpoint_index = alpha0_endpoint_index;
3517 alpha0_endpoint_index = buffer.alpha0_endpoint_index;
3519 uint32 alpha0_selector_index = m_codec.decode(m_selector_delta_dm[1]);
3521 const uint16* pAlpha0_selectors = &m_alpha_selectors[alpha0_selector_index * 3];
3522 pData[0] = m_alpha_endpoints[alpha0_endpoint_index] | (pAlpha0_selectors[0] << 16);
3523 pData[1] = pAlpha0_selectors[1] | (pAlpha0_selectors[2] << 16);
3531 bool unpack_etc1(uint8** pDst, uint32 output_pitch_in_bytes, uint32 output_width, uint32 output_height) {
3532 const uint32 num_color_endpoints = m_color_endpoints.size();
3533 const uint32 width = (output_width + 1) & ~1;
3534 const uint32 height = (output_height + 1) & ~1;
3535 const int32 delta_pitch_in_dwords = (output_pitch_in_bytes >> 2) - (width << 1);
3537 if (m_block_buffer.size() < width << 1)
3538 m_block_buffer.resize(width << 1);
3540 uint32 color_endpoint_index = 0, diagonal_color_endpoint_index = 0;
3541 uint8 reference_group = 0;
3543 for (uint32 f = 0; f < m_pHeader->m_faces; f++) {
3544 uint32* pData = (uint32*)pDst[f];
3545 for (uint32 y = 0; y < height; y++, pData += delta_pitch_in_dwords) {
3546 bool visible = y < output_height;
3547 for (uint32 x = 0; x < width; x++, pData += 2) {
3548 visible = visible && x < output_width;
3549 block_buffer_element &buffer = m_block_buffer[x << 1];
3550 uint8 endpoint_reference, block_endpoint[4], e0[4], e1[4];
3552 endpoint_reference = buffer.endpoint_reference;
3554 reference_group = m_codec.decode(m_reference_encoding_dm);
3555 endpoint_reference = (reference_group & 3) | (reference_group >> 2 & 12);
3556 buffer.endpoint_reference = (reference_group >> 2 & 3) | (reference_group >> 4 & 12);
3558 if (!(endpoint_reference & 3)) {
3559 color_endpoint_index += m_codec.decode(m_endpoint_delta_dm[0]);
3560 if (color_endpoint_index >= num_color_endpoints)
3561 color_endpoint_index -= num_color_endpoints;
3562 buffer.color_endpoint_index = color_endpoint_index;
3563 } else if ((endpoint_reference & 3) == 1) {
3564 buffer.color_endpoint_index = color_endpoint_index;
3565 } else if ((endpoint_reference & 3) == 3) {
3566 buffer.color_endpoint_index = color_endpoint_index = diagonal_color_endpoint_index;
3568 color_endpoint_index = buffer.color_endpoint_index;
3570 endpoint_reference >>= 2;
3571 *(uint32*)&e0 = m_color_endpoints[color_endpoint_index];
3572 uint32 selector_index = m_codec.decode(m_selector_delta_dm[0]);
3573 if (endpoint_reference) {
3574 color_endpoint_index += m_codec.decode(m_endpoint_delta_dm[0]);
3575 if (color_endpoint_index >= num_color_endpoints)
3576 color_endpoint_index -= num_color_endpoints;
3578 diagonal_color_endpoint_index = m_block_buffer[x << 1 | 1].color_endpoint_index;
3579 m_block_buffer[x << 1 | 1].color_endpoint_index = color_endpoint_index;
3580 *(uint32*)&e1 = m_color_endpoints[color_endpoint_index];
3582 uint32 flip = endpoint_reference >> 1 ^ 1, diff = 1;
3583 for (uint c = 0; diff && c < 3; c++)
3584 diff = e0[c] + 3 >= e1[c] && e1[c] + 4 >= e0[c] ? diff : 0;
3585 for (uint c = 0; c < 3; c++)
3586 block_endpoint[c] = diff ? e0[c] << 3 | ((e1[c] - e0[c]) & 7) : (e0[c] << 3 & 0xF0) | e1[c] >> 1;
3587 block_endpoint[3] = e0[3] << 5 | e1[3] << 2 | diff << 1 | flip;
3588 pData[0] = *(uint32*)&block_endpoint;
3589 pData[1] = m_color_selectors[selector_index << 1 | flip];
3597 bool unpack_etc2a(uint8** pDst, uint32 output_pitch_in_bytes, uint32 output_width, uint32 output_height) {
3598 const uint32 num_color_endpoints = m_color_endpoints.size();
3599 const uint32 num_alpha_endpoints = m_alpha_endpoints.size();
3600 const uint32 width = (output_width + 1) & ~1;
3601 const uint32 height = (output_height + 1) & ~1;
3602 const int32 delta_pitch_in_dwords = (output_pitch_in_bytes >> 2) - (width << 2);
3604 if (m_block_buffer.size() < width << 1)
3605 m_block_buffer.resize(width << 1);
3607 uint32 color_endpoint_index = 0, diagonal_color_endpoint_index = 0, alpha0_endpoint_index = 0, diagonal_alpha0_endpoint_index = 0;
3608 uint8 reference_group = 0;
3610 for (uint32 f = 0; f < m_pHeader->m_faces; f++) {
3611 uint32* pData = (uint32*)pDst[f];
3612 for (uint32 y = 0; y < height; y++, pData += delta_pitch_in_dwords) {
3613 bool visible = y < output_height;
3614 for (uint32 x = 0; x < width; x++, pData += 4) {
3615 visible = visible && x < output_width;
3616 block_buffer_element &buffer = m_block_buffer[x << 1];
3617 uint8 endpoint_reference, block_endpoint[4], e0[4], e1[4];
3619 endpoint_reference = buffer.endpoint_reference;
3621 reference_group = m_codec.decode(m_reference_encoding_dm);
3622 endpoint_reference = (reference_group & 3) | (reference_group >> 2 & 12);
3623 buffer.endpoint_reference = (reference_group >> 2 & 3) | (reference_group >> 4 & 12);
3625 if (!(endpoint_reference & 3)) {
3626 color_endpoint_index += m_codec.decode(m_endpoint_delta_dm[0]);
3627 if (color_endpoint_index >= num_color_endpoints)
3628 color_endpoint_index -= num_color_endpoints;
3629 alpha0_endpoint_index += m_codec.decode(m_endpoint_delta_dm[1]);
3630 if (alpha0_endpoint_index >= num_alpha_endpoints)
3631 alpha0_endpoint_index -= num_alpha_endpoints;
3632 buffer.color_endpoint_index = color_endpoint_index;
3633 buffer.alpha0_endpoint_index = alpha0_endpoint_index;
3634 } else if ((endpoint_reference & 3) == 1) {
3635 buffer.color_endpoint_index = color_endpoint_index;
3636 buffer.alpha0_endpoint_index = alpha0_endpoint_index;
3637 } else if ((endpoint_reference & 3) == 3) {
3638 buffer.color_endpoint_index = color_endpoint_index = diagonal_color_endpoint_index;
3639 buffer.alpha0_endpoint_index = alpha0_endpoint_index = diagonal_alpha0_endpoint_index;
3641 color_endpoint_index = buffer.color_endpoint_index;
3642 alpha0_endpoint_index = buffer.alpha0_endpoint_index;
3644 endpoint_reference >>= 2;
3645 *(uint32*)&e0 = m_color_endpoints[color_endpoint_index];
3646 uint32 color_selector_index = m_codec.decode(m_selector_delta_dm[0]);
3647 uint32 alpha0_selector_index = m_codec.decode(m_selector_delta_dm[1]);
3648 if (endpoint_reference) {
3649 color_endpoint_index += m_codec.decode(m_endpoint_delta_dm[0]);
3650 if (color_endpoint_index >= num_color_endpoints)
3651 color_endpoint_index -= num_color_endpoints;
3653 *(uint32*)&e1 = m_color_endpoints[color_endpoint_index];
3654 diagonal_color_endpoint_index = m_block_buffer[x << 1 | 1].color_endpoint_index;
3655 diagonal_alpha0_endpoint_index = m_block_buffer[x << 1 | 1].alpha0_endpoint_index;
3656 m_block_buffer[x << 1 | 1].color_endpoint_index = color_endpoint_index;
3657 m_block_buffer[x << 1 | 1].alpha0_endpoint_index = alpha0_endpoint_index;
3659 uint32 flip = endpoint_reference >> 1 ^ 1, diff = 1;
3660 for (uint c = 0; diff && c < 3; c++)
3661 diff = e0[c] + 3 >= e1[c] && e1[c] + 4 >= e0[c] ? diff : 0;
3662 for (uint c = 0; c < 3; c++)
3663 block_endpoint[c] = diff ? e0[c] << 3 | ((e1[c] - e0[c]) & 7) : (e0[c] << 3 & 0xF0) | e1[c] >> 1;
3664 block_endpoint[3] = e0[3] << 5 | e1[3] << 2 | diff << 1 | flip;
3665 const uint16* pAlpha0_selectors = &m_alpha_selectors[alpha0_selector_index * 6 + (flip ? 3 : 0)];
3666 pData[0] = m_alpha_endpoints[alpha0_endpoint_index] | pAlpha0_selectors[0] << 16;
3667 pData[1] = pAlpha0_selectors[1] | pAlpha0_selectors[2] << 16;
3668 pData[2] = *(uint32*)&block_endpoint;
3669 pData[3] = m_color_selectors[color_selector_index << 1 | flip];
3679 crnd_unpack_context crnd_unpack_begin(const void* pData, uint32 data_size) {
3680 if ((!pData) || (data_size < cCRNHeaderMinSize))
3683 crn_unpacker* p = crnd_new<crn_unpacker>();
3687 if (!p->init(pData, data_size)) {
3695 bool crnd_get_data(crnd_unpack_context pContext, const void** ppData, uint32* pData_size) {
3699 crn_unpacker* pUnpacker = static_cast<crn_unpacker*>(pContext);
3701 if (!pUnpacker->is_valid())
3705 *ppData = pUnpacker->get_data();
3708 *pData_size = pUnpacker->get_data_size();
3713 bool crnd_unpack_level(
3714 crnd_unpack_context pContext,
3715 void** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes,
3716 uint32 level_index) {
3717 if ((!pContext) || (!pDst) || (dst_size_in_bytes < 8U) || (level_index >= cCRNMaxLevels))
3720 crn_unpacker* pUnpacker = static_cast<crn_unpacker*>(pContext);
3722 if (!pUnpacker->is_valid())
3725 return pUnpacker->unpack_level(pDst, dst_size_in_bytes, row_pitch_in_bytes, level_index);
3728 bool crnd_unpack_level_segmented(
3729 crnd_unpack_context pContext,
3730 const void* pSrc, uint32 src_size_in_bytes,
3731 void** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes,
3732 uint32 level_index) {
3733 if ((!pContext) || (!pSrc) || (!pDst) || (dst_size_in_bytes < 8U) || (level_index >= cCRNMaxLevels))
3736 crn_unpacker* pUnpacker = static_cast<crn_unpacker*>(pContext);
3738 if (!pUnpacker->is_valid())
3741 return pUnpacker->unpack_level(pSrc, src_size_in_bytes, pDst, dst_size_in_bytes, row_pitch_in_bytes, level_index);
3744 bool crnd_unpack_end(crnd_unpack_context pContext) {
3748 crn_unpacker* pUnpacker = static_cast<crn_unpacker*>(pContext);
3750 if (!pUnpacker->is_valid())
3753 crnd_delete(pUnpacker);
3760 #endif // CRND_INCLUDE_CRND_H
3762 //------------------------------------------------------------------------------
3764 // crn_decomp.h uses the ZLIB license:
3765 // http://opensource.org/licenses/Zlib
3767 // Copyright (c) 2010-2016 Richard Geldreich, Jr. and Binomial LLC
3769 // This software is provided 'as-is', without any express or implied
3770 // warranty. In no event will the authors be held liable for any damages
3771 // arising from the use of this software.
3773 // Permission is granted to anyone to use this software for any purpose,
3774 // including commercial applications, and to alter it and redistribute it
3775 // freely, subject to the following restrictions:
3777 // 1. The origin of this software must not be misrepresented; you must not
3778 // claim that you wrote the original software. If you use this software
3779 // in a product, an acknowledgment in the product documentation would be
3780 // appreciated but is not required.
3782 // 2. Altered source versions must be plainly marked as such, and must not be
3783 // misrepresented as being the original software.
3785 // 3. This notice may not be removed or altered from any source distribution.
3787 //------------------------------------------------------------------------------