image: add crn support to the image plugin.
[xonotic/netradiant.git] / libs / crunch / crn_defs.h
1 #ifndef CRND_INCLUDE_CRN_DEFS_H
2 #define CRND_INCLUDE_CRN_DEFS_H
3
4 // Include crnlib.h (only to bring in some basic CRN-related types).
5 #include "crnlib.h"
6
7 #define CRND_LIB_VERSION 104
8 #define CRND_VERSION_STRING "01.04"
9
10 #ifdef _DEBUG
11 #define CRND_BUILD_DEBUG
12 #else
13 #define CRND_BUILD_RELEASE
14 #endif
15
16 // CRN decompression API
17 namespace crnd {
18 typedef unsigned char uint8;
19 typedef signed char int8;
20 typedef unsigned short uint16;
21 typedef signed short int16;
22 typedef unsigned int uint32;
23 typedef uint32 uint32;
24 typedef unsigned int uint;
25 typedef signed int int32;
26 #ifdef __GNUC__
27 typedef unsigned long long uint64;
28 typedef long long int64;
29 #else
30 typedef unsigned __int64 uint64;
31 typedef signed __int64 int64;
32 #endif
33
34 // The crnd library assumes all allocation blocks have at least CRND_MIN_ALLOC_ALIGNMENT alignment.
35 const uint32 CRND_MIN_ALLOC_ALIGNMENT = sizeof(uint32) * 2U;
36
37 // realloc callback:
38 // Used to allocate, resize, or free memory blocks.
39 // If p is NULL, the realloc function attempts to allocate a block of at least size bytes. Returns NULL on out of memory.
40 // *pActual_size must be set to the actual size of the allocated block, which must be greater than or equal to the requested size.
41 // If p is not NULL, and size is 0, the realloc function frees the specified block, and always returns NULL. *pActual_size should be set to 0.
42 // If p is not NULL, and size is non-zero, the realloc function attempts to resize the specified block:
43 //    If movable is false, the realloc function attempts to shrink or expand the block in-place. NULL is returned if the block cannot be resized in place, or if the
44 //    underlying heap implementation doesn't support in-place resizing. Otherwise, the pointer to the original block is returned.
45 //    If movable is true, it is permissible to move the block's contents if it cannot be resized in place. NULL is returned if the block cannot be resized in place, and there
46 //    is not enough memory to relocate the block.
47 //    In all cases, *pActual_size must be set to the actual size of the allocated block, whether it was successfully resized or not.
48 typedef void* (*crnd_realloc_func)(void* p, size_t size, size_t* pActual_size, bool movable, void* pUser_data);
49
50 // msize callback: Returns the size of the memory block in bytes, or 0 if the pointer or block is invalid.
51 typedef size_t (*crnd_msize_func)(void* p, void* pUser_data);
52
53 // crnd_set_memory_callbacks() - Use to override the crnd library's memory allocation functions.
54 // If any input parameters are NULL, the memory callback functions are reset to the default functions.
55 // The default functions call malloc(), free(),  _msize(), _expand(), etc.
56 void crnd_set_memory_callbacks(crnd_realloc_func pRealloc, crnd_msize_func pMSize, void* pUser_data);
57
58 struct crn_file_info {
59   inline crn_file_info()
60       : m_struct_size(sizeof(crn_file_info)) {}
61
62   uint32 m_struct_size;
63   uint32 m_actual_data_size;
64   uint32 m_header_size;
65   uint32 m_total_palette_size;
66   uint32 m_tables_size;
67   uint32 m_levels;
68   uint32 m_level_compressed_size[cCRNMaxLevels];
69   uint32 m_color_endpoint_palette_entries;
70   uint32 m_color_selector_palette_entries;
71   uint32 m_alpha_endpoint_palette_entries;
72   uint32 m_alpha_selector_palette_entries;
73 };
74
75 struct crn_texture_info {
76   inline crn_texture_info()
77       : m_struct_size(sizeof(crn_texture_info)) {}
78
79   uint32 m_struct_size;
80   uint32 m_width;
81   uint32 m_height;
82   uint32 m_levels;
83   uint32 m_faces;
84   uint32 m_bytes_per_block;
85   uint32 m_userdata0;
86   uint32 m_userdata1;
87   crn_format m_format;
88 };
89
90 struct crn_level_info {
91   inline crn_level_info()
92       : m_struct_size(sizeof(crn_level_info)) {}
93
94   uint32 m_struct_size;
95   uint32 m_width;
96   uint32 m_height;
97   uint32 m_faces;
98   uint32 m_blocks_x;
99   uint32 m_blocks_y;
100   uint32 m_bytes_per_block;
101   crn_format m_format;
102 };
103
104 // Returns the FOURCC format code corresponding to the specified CRN format.
105 uint32 crnd_crn_format_to_fourcc(crn_format fmt);
106
107 // Returns the fundamental GPU format given a potentially swizzled DXT5 crn_format.
108 crn_format crnd_get_fundamental_dxt_format(crn_format fmt);
109
110 // Returns the size of the crn_format in bits/texel (either 4 or 8).
111 uint32 crnd_get_crn_format_bits_per_texel(crn_format fmt);
112
113 // Returns the number of bytes per DXTn block (8 or 16).
114 uint32 crnd_get_bytes_per_dxt_block(crn_format fmt);
115
116 // Validates the entire file by checking the header and data CRC's.
117 // This is not something you want to be doing much!
118 // The crn_file_info.m_struct_size field must be set before calling this function.
119 bool crnd_validate_file(const void* pData, uint32 data_size, crn_file_info* pFile_info);
120
121 // Retrieves texture information from the CRN file.
122 // The crn_texture_info.m_struct_size field must be set before calling this function.
123 bool crnd_get_texture_info(const void* pData, uint32 data_size, crn_texture_info* pTexture_info);
124
125 // Retrieves mipmap level specific information from the CRN file.
126 // The crn_level_info.m_struct_size field must be set before calling this function.
127 bool crnd_get_level_info(const void* pData, uint32 data_size, uint32 level_index, crn_level_info* pLevel_info);
128
129 // Transcode/unpack context handle.
130 typedef void* crnd_unpack_context;
131
132 // crnd_unpack_begin() - Decompresses the texture's decoder tables and endpoint/selector palettes.
133 // Once you call this function, you may call crnd_unpack_level() to unpack one or more mip levels.
134 // Don't call this once per mip level (unless you absolutely must)!
135 // This function allocates enough memory to hold: Huffman decompression tables, and the endpoint/selector palettes (color and/or alpha).
136 // Worst case allocation is approx. 200k, assuming all palettes contain 8192 entries.
137 // pData must point to a buffer holding all of the compressed .CRN file data.
138 // This buffer must be stable until crnd_unpack_end() is called.
139 // Returns NULL if out of memory, or if any of the input parameters are invalid.
140 crnd_unpack_context crnd_unpack_begin(const void* pData, uint32 data_size);
141
142 // Returns a pointer to the compressed .CRN data associated with a crnd_unpack_context.
143 // Returns false if any of the input parameters are invalid.
144 bool crnd_get_data(crnd_unpack_context pContext, const void** ppData, uint32* pData_size);
145
146 // crnd_unpack_level() - Transcodes the specified mipmap level to a destination buffer in cached or write combined memory.
147 // pContext - Context created by a call to crnd_unpack_begin().
148 // ppDst - A pointer to an array of 1 or 6 destination buffer pointers. Cubemaps require an array of 6 pointers, 2D textures require an array of 1 pointer.
149 // dst_size_in_bytes - Optional size of each destination buffer. Only used for debugging - OK to set to UINT32_MAX.
150 // row_pitch_in_bytes - The pitch in bytes from one row of DXT blocks to the next. Must be a multiple of 4.
151 // level_index - mipmap level index, where 0 is the largest/first level.
152 // Returns false if any of the input parameters, or the compressed stream, are invalid.
153 // This function does not allocate any memory.
154 bool crnd_unpack_level(
155     crnd_unpack_context pContext,
156     void** ppDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes,
157     uint32 level_index);
158
159 // crnd_unpack_level_segmented() - Unpacks the specified mipmap level from a "segmented" CRN file.
160 // See the crnd_create_segmented_file() API below.
161 // Segmented files allow the user to control where the compressed mipmap data is stored.
162 bool crnd_unpack_level_segmented(
163     crnd_unpack_context pContext,
164     const void* pSrc, uint32 src_size_in_bytes,
165     void** ppDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes,
166     uint32 level_index);
167
168 // crnd_unpack_end() - Frees the decompress tables and unpacked palettes associated with the specified unpack context.
169 // Returns false if the context is NULL, or if it points to an invalid context.
170 // This function frees all memory associated with the context.
171 bool crnd_unpack_end(crnd_unpack_context pContext);
172
173 // The following API's allow the user to create "segmented" CRN files. A segmented file contains multiple pieces:
174 // - Base data: Header + compression tables
175 // - Level data: Individual mipmap levels
176 // This allows mipmap levels from multiple CRN files to be tightly packed together into single files.
177
178 // Returns a pointer to the level's compressed data, and optionally returns the level's compressed data size if pSize is not NULL.
179 const void* crnd_get_level_data(const void* pData, uint32 data_size, uint32 level_index, uint32* pSize);
180
181 // Returns the compressed size of the texture's header and compression tables (but no levels).
182 uint32 crnd_get_segmented_file_size(const void* pData, uint32 data_size);
183
184 // Creates a "segmented" CRN texture from a normal CRN texture. The new texture will be created at pBase_data, and will be crnd_get_base_data_size() bytes long.
185 // base_data_size must be >= crnd_get_base_data_size().
186 // The base data will contain the CRN header and compression tables, but no mipmap data.
187 bool crnd_create_segmented_file(const void* pData, uint32 data_size, void* pBase_data, uint base_data_size);
188
189 }  // namespace crnd
190
191 // Low-level CRN file header cracking.
192 namespace crnd {
193 template <unsigned int N>
194 struct crn_packed_uint {
195   inline crn_packed_uint() {}
196
197   inline crn_packed_uint(unsigned int val) { *this = val; }
198
199   inline crn_packed_uint(const crn_packed_uint& other) { *this = other; }
200
201   inline crn_packed_uint& operator=(const crn_packed_uint& rhs) {
202     if (this != &rhs)
203       memcpy(m_buf, rhs.m_buf, sizeof(m_buf));
204     return *this;
205   }
206
207   inline crn_packed_uint& operator=(unsigned int val) {
208     //CRND_ASSERT((N == 4U) || (val < (1U << (N * 8U))));
209
210     val <<= (8U * (4U - N));
211
212     for (unsigned int i = 0; i < N; i++) {
213       m_buf[i] = static_cast<unsigned char>(val >> 24U);
214       val <<= 8U;
215     }
216
217     return *this;
218   }
219
220   inline operator unsigned int() const {
221     switch (N) {
222       case 1:
223         return m_buf[0];
224       case 2:
225         return (m_buf[0] << 8U) | m_buf[1];
226       case 3:
227         return (m_buf[0] << 16U) | (m_buf[1] << 8U) | (m_buf[2]);
228       default:
229         return (m_buf[0] << 24U) | (m_buf[1] << 16U) | (m_buf[2] << 8U) | (m_buf[3]);
230     }
231   }
232
233   unsigned char m_buf[N];
234 };
235
236 #pragma pack(push)
237 #pragma pack(1)
238 struct crn_palette {
239   crn_packed_uint<3> m_ofs;
240   crn_packed_uint<3> m_size;
241   crn_packed_uint<2> m_num;
242 };
243
244 enum crn_header_flags {
245   // If set, the compressed mipmap level data is not located after the file's base data - it will be separately managed by the user instead.
246   cCRNHeaderFlagSegmented = 1
247 };
248
249 struct crn_header {
250   enum { cCRNSigValue = ('H' << 8) | 'x' };
251
252   crn_packed_uint<2> m_sig;
253   crn_packed_uint<2> m_header_size;
254   crn_packed_uint<2> m_header_crc16;
255
256   crn_packed_uint<4> m_data_size;
257   crn_packed_uint<2> m_data_crc16;
258
259   crn_packed_uint<2> m_width;
260   crn_packed_uint<2> m_height;
261
262   crn_packed_uint<1> m_levels;
263   crn_packed_uint<1> m_faces;
264
265   crn_packed_uint<1> m_format;
266   crn_packed_uint<2> m_flags;
267
268   crn_packed_uint<4> m_reserved;
269   crn_packed_uint<4> m_userdata0;
270   crn_packed_uint<4> m_userdata1;
271
272   crn_palette m_color_endpoints;
273   crn_palette m_color_selectors;
274
275   crn_palette m_alpha_endpoints;
276   crn_palette m_alpha_selectors;
277
278   crn_packed_uint<2> m_tables_size;
279   crn_packed_uint<3> m_tables_ofs;
280
281   // m_level_ofs[] is actually an array of offsets: m_level_ofs[m_levels]
282   crn_packed_uint<4> m_level_ofs[1];
283 };
284
285 const unsigned int cCRNHeaderMinSize = 62U;
286
287 #pragma pack(pop)
288
289 }  // namespace crnd
290
291 #endif  // CRND_INCLUDE_CRN_DEFS_H