]> git.cworth.org Git - vogl/blob - src/voglcore/vogl.h
Initial vogl checkin
[vogl] / src / voglcore / vogl.h
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  *
25  **************************************************************************/
26
27 // File: vogl.h
28 //
29 // Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing
30 #ifndef VOGL_H
31 #define VOGL_H
32
33 #ifdef _MSC_VER
34 #pragma warning (disable: 4127) //  conditional expression is constant
35 #endif
36
37 #define VOGL_VERSION 104
38
39 #define VOGL_SUPPORT_ATI_COMPRESS 0
40 #define VOGL_SUPPORT_SQUISH 0
41
42 typedef unsigned char   vogl_uint8;
43 typedef unsigned short  vogl_uint16;
44 typedef unsigned int    vogl_uint32;
45 typedef signed char     vogl_int8;
46 typedef signed short    vogl_int16;
47 typedef signed int      vogl_int32;
48 typedef unsigned int    vogl_bool;
49
50 enum vogl_file_type
51 {
52    // .CRN
53    cCRNFileTypeCRN = 0,
54
55    // .DDS using regular DXT or clustered DXT
56    cCRNFileTypeDDS,
57
58    cCRNFileTypeForceDWORD = 0xFFFFFFFF
59 };
60
61 // Supported compressed pixel formats.
62 // Basically all the standard DX9 formats, with some swizzled DXT5 formats
63 // (most of them supported by ATI's Compressonator), along with some ATI/X360 GPU specific formats.
64 enum vogl_format
65 {
66    cCRNFmtInvalid = -1,
67
68    cCRNFmtDXT1 = 0,
69
70    cCRNFmtFirstValid = cCRNFmtDXT1,
71
72    // cCRNFmtDXT3 is not currently supported when writing to CRN - only DDS.
73    cCRNFmtDXT3,
74
75    cCRNFmtDXT5,
76
77    // Various DXT5 derivatives
78    cCRNFmtDXT5_CCxY,    // Luma-chroma
79    cCRNFmtDXT5_xGxR,    // Swizzled 2-component
80    cCRNFmtDXT5_xGBR,    // Swizzled 3-component
81    cCRNFmtDXT5_AGBR,    // Swizzled 4-component
82
83    // ATI 3DC and X360 DXN
84    cCRNFmtDXN_XY,
85    cCRNFmtDXN_YX,
86
87    // DXT5 alpha blocks only
88    cCRNFmtDXT5A,
89
90    cCRNFmtETC1,
91
92    cCRNFmtTotal,
93
94    cCRNFmtForceDWORD = 0xFFFFFFFF
95 };
96
97 // Various library/file format limits.
98 enum vogl_limits
99 {
100    // Max. mipmap level resolution on any axis.
101    cCRNMaxLevelResolution     = 4096,
102
103    cCRNMinPaletteSize         = 8,
104    cCRNMaxPaletteSize         = 8192,
105
106    cCRNMaxFaces               = 6,
107    cCRNMaxLevels              = 16,
108
109    cCRNMaxHelperThreads       = 16,
110
111    cCRNMinQualityLevel        = 0,
112    cCRNMaxQualityLevel        = 255
113 };
114
115 // CRN/DDS compression flags.
116 // See the m_flags member in the vogl_comp_params struct, below.
117 enum vogl_comp_flags
118 {
119    // Enables perceptual colorspace distance metrics if set.
120    // Important: Be sure to disable this when compressing non-sRGB colorspace images, like normal maps!
121    // Default: Set
122    cCRNCompFlagPerceptual = 1,
123
124    // Enables (up to) 8x8 macroblock usage if set. If disabled, only 4x4 blocks are allowed.
125    // Compression ratio will be lower when disabled, but may cut down on blocky artifacts because the process used to determine
126    // where large macroblocks can be used without artifacts isn't perfect.
127    // Default: Set.
128    cCRNCompFlagHierarchical = 2,
129
130    // cCRNCompFlagQuick disables several output file optimizations - intended for things like quicker previews.
131    // Default: Not set.
132    cCRNCompFlagQuick = 4,
133
134    // DXT1: OK to use DXT1 alpha blocks for better quality or DXT1A transparency.
135    // DXT5: OK to use both DXT5 block types.
136    // Currently only used when writing to .DDS files, as .CRN uses only a subset of the possible DXTn block types.
137    // Default: Set.
138    cCRNCompFlagUseBothBlockTypes = 8,
139
140    // OK to use DXT1A transparent indices to encode black (assumes pixel shader ignores fetched alpha).
141    // Currently only used when writing to .DDS files, .CRN never uses alpha blocks.
142    // Default: Not set.
143    cCRNCompFlagUseTransparentIndicesForBlack = 16,
144
145    // Disables endpoint caching, for more deterministic output.
146    // Currently only used when writing to .DDS files.
147    // Default: Not set.
148    cCRNCompFlagDisableEndpointCaching = 32,
149
150    // If enabled, use the cCRNColorEndpointPaletteSize, etc. params to control the CRN palette sizes. Only useful when writing to .CRN files.
151    // Default: Not set.
152    cCRNCompFlagManualPaletteSizes = 64,
153
154    // If enabled, DXT1A alpha blocks are used to encode single bit transparency.
155    // Default: Not set.
156    cCRNCompFlagDXT1AForTransparency = 128,
157
158    // If enabled, the DXT1 compressor's color distance metric assumes the pixel shader will be converting the fetched RGB results to luma (Y part of YCbCr).
159    // This increases quality when compressing grayscale images, because the compressor can spread the luma error amoung all three channels (i.e. it can generate blocks
160    // with some chroma present if doing so will ultimately lead to lower luma error).
161    // Only enable on grayscale source images.
162    // Default: Not set.
163    cCRNCompFlagGrayscaleSampling = 256,
164
165    // If enabled, debug information will be output during compression.
166    // Default: Not set.
167    cCRNCompFlagDebugging = 0x80000000,
168
169    cCRNCompFlagForceDWORD = 0xFFFFFFFF
170 };
171
172 // Controls DXTn quality vs. speed control - only used when compressing to .DDS.
173 enum vogl_dxt_quality
174 {
175    cCRNDXTQualitySuperFast,
176    cCRNDXTQualityFast,
177    cCRNDXTQualityNormal,
178    cCRNDXTQualityBetter,
179    cCRNDXTQualityUber,
180
181    cCRNDXTQualityTotal,
182
183    cCRNDXTQualityForceDWORD = 0xFFFFFFFF
184 };
185
186 // Which DXTn compressor to use when compressing to plain (non-clustered) .DDS.
187 enum vogl_dxt_compressor_type
188 {
189    cCRNDXTCompressorCRN,      // Use voglcore's ETC1 or DXTc block compressor (default, highest quality, comparable or better than ati_compress or squish, and voglcore's ETC1 is a lot faster with similiar quality to Erricson's)
190    cCRNDXTCompressorCRNF,     // Use voglcore's "fast" DXTc block compressor
191    cCRNDXTCompressorRYG,      // Use RYG's DXTc block compressor (low quality, but very fast)
192
193 #if VOGL_SUPPORT_ATI_COMPRESS
194    cCRNDXTCompressorATI,
195 #endif
196
197 #if VOGL_SUPPORT_SQUISH
198    cCRNDXTCompressorSquish,
199 #endif
200
201    cCRNTotalDXTCompressors,
202
203    cCRNDXTCompressorForceDWORD = 0xFFFFFFFF
204 };
205
206 // Progress callback function.
207 // Processing will stop prematurely (and fail) if the callback returns false.
208 // phase_index, total_phases - high level progress
209 // subphase_index, total_subphases - progress within current phase
210 typedef vogl_bool (*vogl_progress_callback_func)(vogl_uint32 phase_index, vogl_uint32 total_phases, vogl_uint32 subphase_index, vogl_uint32 total_subphases, void* pUser_data_ptr);
211
212 // CRN/DDS compression parameters struct.
213 struct vogl_comp_params
214 {
215    inline vogl_comp_params() { clear(); }
216
217    // Clear struct to default parameters.
218    inline void clear()
219    {
220       m_size_of_obj = sizeof(*this);
221       m_file_type = cCRNFileTypeCRN;
222       m_faces = 1;
223       m_width = 0;
224       m_height = 0;
225       m_levels = 1;
226       m_format = cCRNFmtDXT1;
227       m_flags = cCRNCompFlagPerceptual | cCRNCompFlagHierarchical | cCRNCompFlagUseBothBlockTypes;
228
229       for (vogl_uint32 f = 0; f < cCRNMaxFaces; f++)
230          for (vogl_uint32 l = 0; l < cCRNMaxLevels; l++)
231             m_pImages[f][l] = NULL;
232
233       m_target_bitrate = 0.0f;
234       m_quality_level = cCRNMaxQualityLevel;
235       m_dxt1a_alpha_threshold = 128;
236       m_dxt_quality = cCRNDXTQualityUber;
237       m_dxt_compressor_type = cCRNDXTCompressorCRN;
238       m_alpha_component = 3;
239
240       m_vogl_adaptive_tile_color_psnr_derating = 2.0f;
241       m_vogl_adaptive_tile_alpha_psnr_derating = 2.0f;
242       m_vogl_color_endpoint_palette_size = 0;
243       m_vogl_color_selector_palette_size = 0;
244       m_vogl_alpha_endpoint_palette_size = 0;
245       m_vogl_alpha_selector_palette_size = 0;
246
247       m_num_helper_threads = 0;
248       m_userdata0 = 0;
249       m_userdata1 = 0;
250       m_pProgress_func = NULL;
251       m_pProgress_func_data = NULL;
252    }
253
254    inline bool operator== (const vogl_comp_params& rhs) const
255    {
256 #define VOGL_COMP(x) do { if ((x) != (rhs.x)) return false; } while(0)
257       VOGL_COMP(m_size_of_obj);
258       VOGL_COMP(m_file_type);
259       VOGL_COMP(m_faces);
260       VOGL_COMP(m_width);
261       VOGL_COMP(m_height);
262       VOGL_COMP(m_levels);
263       VOGL_COMP(m_format);
264       VOGL_COMP(m_flags);
265       VOGL_COMP(m_target_bitrate);
266       VOGL_COMP(m_quality_level);
267       VOGL_COMP(m_dxt1a_alpha_threshold);
268       VOGL_COMP(m_dxt_quality);
269       VOGL_COMP(m_dxt_compressor_type);
270       VOGL_COMP(m_alpha_component);
271       VOGL_COMP(m_vogl_adaptive_tile_color_psnr_derating);
272       VOGL_COMP(m_vogl_adaptive_tile_alpha_psnr_derating);
273       VOGL_COMP(m_vogl_color_endpoint_palette_size);
274       VOGL_COMP(m_vogl_color_selector_palette_size);
275       VOGL_COMP(m_vogl_alpha_endpoint_palette_size);
276       VOGL_COMP(m_vogl_alpha_selector_palette_size);
277       VOGL_COMP(m_num_helper_threads);
278       VOGL_COMP(m_userdata0);
279       VOGL_COMP(m_userdata1);
280       VOGL_COMP(m_pProgress_func);
281       VOGL_COMP(m_pProgress_func_data);
282
283       for (vogl_uint32 f = 0; f < cCRNMaxFaces; f++)
284          for (vogl_uint32 l = 0; l < cCRNMaxLevels; l++)
285             VOGL_COMP(m_pImages[f][l]);
286
287 #undef VOGL_COMP
288       return true;
289    }
290
291    // Returns true if the input parameters are reasonable.
292    inline bool check() const
293    {
294       if ( (m_file_type > cCRNFileTypeDDS) ||
295          (((int)m_quality_level < (int)cCRNMinQualityLevel) || ((int)m_quality_level > (int)cCRNMaxQualityLevel)) ||
296          (m_dxt1a_alpha_threshold > 255) ||
297          ((m_faces != 1) && (m_faces != 6)) ||
298          ((m_width < 1) || (m_width > cCRNMaxLevelResolution)) ||
299          ((m_height < 1) || (m_height > cCRNMaxLevelResolution)) ||
300          ((m_levels < 1) || (m_levels > cCRNMaxLevels)) ||
301          ((m_format < cCRNFmtDXT1) || (m_format >= cCRNFmtTotal)) ||
302          ((m_vogl_color_endpoint_palette_size) && ((m_vogl_color_endpoint_palette_size < cCRNMinPaletteSize) || (m_vogl_color_endpoint_palette_size > cCRNMaxPaletteSize))) ||
303          ((m_vogl_color_selector_palette_size) && ((m_vogl_color_selector_palette_size < cCRNMinPaletteSize) || (m_vogl_color_selector_palette_size > cCRNMaxPaletteSize))) ||
304          ((m_vogl_alpha_endpoint_palette_size) && ((m_vogl_alpha_endpoint_palette_size < cCRNMinPaletteSize) || (m_vogl_alpha_endpoint_palette_size > cCRNMaxPaletteSize))) ||
305          ((m_vogl_alpha_selector_palette_size) && ((m_vogl_alpha_selector_palette_size < cCRNMinPaletteSize) || (m_vogl_alpha_selector_palette_size > cCRNMaxPaletteSize))) ||
306          (m_alpha_component > 3) ||
307          (m_num_helper_threads > cCRNMaxHelperThreads) ||
308          (m_dxt_quality > cCRNDXTQualityUber) ||
309          (m_dxt_compressor_type >= cCRNTotalDXTCompressors) )
310       {
311          return false;
312       }
313       return true;
314    }
315
316    // Helper to set/get flags from m_flags member.
317    inline bool get_flag(vogl_comp_flags flag) const { return (m_flags & flag) != 0; }
318    inline void set_flag(vogl_comp_flags flag, bool val) { m_flags &= ~flag; if (val) m_flags |= flag; }
319
320    vogl_uint32                 m_size_of_obj;
321
322    vogl_file_type              m_file_type;               // Output file type: cCRNFileTypeCRN or cCRNFileTypeDDS.
323
324    vogl_uint32                 m_faces;                   // 1 (2D map) or 6 (cubemap)
325    vogl_uint32                 m_width;                   // [1,cCRNMaxLevelResolution], non-power of 2 OK, non-square OK
326    vogl_uint32                 m_height;                  // [1,cCRNMaxLevelResolution], non-power of 2 OK, non-square OK
327    vogl_uint32                 m_levels;                  // [1,cCRNMaxLevelResolution], non-power of 2 OK, non-square OK
328
329    vogl_format                 m_format;                  // Output pixel format.
330
331    vogl_uint32                 m_flags;                   // see vogl_comp_flags enum
332
333    // Array of pointers to 32bpp input images.
334    const vogl_uint32*          m_pImages[cCRNMaxFaces][cCRNMaxLevels];
335
336    // Target bitrate - if non-zero, the compressor will use an interpolative search to find the
337    // highest quality level that is <= the target bitrate. If it fails to find a bitrate high enough, it'll
338    // try disabling adaptive block sizes (cCRNCompFlagHierarchical flag) and redo the search. This process can be pretty slow.
339    float                      m_target_bitrate;
340
341    // Desired quality level.
342    // Currently, CRN and DDS quality levels are not compatible with eachother from an image quality standpoint.
343    vogl_uint32                 m_quality_level;           // [cCRNMinQualityLevel, cCRNMaxQualityLevel]
344
345    // DXTn compression parameters.
346    vogl_uint32                 m_dxt1a_alpha_threshold;
347    vogl_dxt_quality            m_dxt_quality;
348    vogl_dxt_compressor_type    m_dxt_compressor_type;
349
350    // Alpha channel's component. Defaults to 3.
351    vogl_uint32                 m_alpha_component;
352
353    // Various low-level CRN specific parameters.
354    float                      m_vogl_adaptive_tile_color_psnr_derating;
355    float                      m_vogl_adaptive_tile_alpha_psnr_derating;
356
357    vogl_uint32                 m_vogl_color_endpoint_palette_size;  // [cCRNMinPaletteSize,cCRNMaxPaletteSize]
358    vogl_uint32                 m_vogl_color_selector_palette_size;  // [cCRNMinPaletteSize,cCRNMaxPaletteSize]
359
360    vogl_uint32                 m_vogl_alpha_endpoint_palette_size;  // [cCRNMinPaletteSize,cCRNMaxPaletteSize]
361    vogl_uint32                 m_vogl_alpha_selector_palette_size;  // [cCRNMinPaletteSize,cCRNMaxPaletteSize]
362
363    // Number of helper threads to create during compression. 0=no threading.
364    vogl_uint32                 m_num_helper_threads;
365
366    // CRN userdata0 and userdata1 members, which are written directly to the header of the output file.
367    vogl_uint32                 m_userdata0;
368    vogl_uint32                 m_userdata1;
369
370    // User provided progress callback.
371    vogl_progress_callback_func m_pProgress_func;
372    void*                      m_pProgress_func_data;
373 };
374
375 // Mipmap generator's mode.
376 enum vogl_mip_mode
377 {
378    cCRNMipModeUseSourceOrGenerateMips,       // Use source texture's mipmaps if it has any, otherwise generate new mipmaps
379    cCRNMipModeUseSourceMips,                 // Use source texture's mipmaps if it has any, otherwise the output has no mipmaps
380    cCRNMipModeGenerateMips,                  // Always generate new mipmaps
381    cCRNMipModeNoMips,                        // Output texture has no mipmaps
382
383    cCRNMipModeTotal,
384
385    cCRNModeForceDWORD = 0xFFFFFFFF
386 };
387
388 const char* vogl_get_mip_mode_desc(vogl_mip_mode m);
389 const char* vogl_get_mip_mode_name(vogl_mip_mode m);
390
391 // Mipmap generator's filter kernel.
392 enum vogl_mip_filter
393 {
394    cCRNMipFilterBox,
395    cCRNMipFilterTent,
396    cCRNMipFilterLanczos4,
397    cCRNMipFilterMitchell,
398    cCRNMipFilterKaiser,                      // Kaiser=default mipmap filter
399
400    cCRNMipFilterTotal,
401
402    cCRNMipFilterForceDWORD = 0xFFFFFFFF
403 };
404
405 const char* vogl_get_mip_filter_name(vogl_mip_filter f);
406
407 // Mipmap generator's scale mode.
408 enum vogl_scale_mode
409 {
410    cCRNSMDisabled,
411    cCRNSMAbsolute,
412    cCRNSMRelative,
413    cCRNSMLowerPow2,
414    cCRNSMNearestPow2,
415    cCRNSMNextPow2,
416
417    cCRNSMTotal,
418
419    cCRNSMForceDWORD = 0xFFFFFFFF
420 };
421
422 const char* vogl_get_scale_mode_desc(vogl_scale_mode sm);
423
424 // Mipmap generator parameters.
425 struct vogl_mipmap_params
426 {
427    inline vogl_mipmap_params() { clear(); }
428
429    inline void clear()
430    {
431       m_size_of_obj = sizeof(*this);
432       m_mode = cCRNMipModeUseSourceOrGenerateMips;
433       m_filter = cCRNMipFilterKaiser;
434       m_gamma_filtering = true;
435       m_gamma = 2.2f;
436       // Default "blurriness" factor of .9 actually sharpens the output a little.
437       m_blurriness = .9f;
438       m_renormalize = false;
439       m_tiled = false;
440       m_max_levels = cCRNMaxLevels;
441       m_min_mip_size = 1;
442
443       m_scale_mode = cCRNSMDisabled;
444       m_scale_x = 1.0f;
445       m_scale_y = 1.0f;
446
447       m_window_left = 0;
448       m_window_top = 0;
449       m_window_right = 0;
450       m_window_bottom = 0;
451
452       m_clamp_scale = false;
453       m_clamp_width = 0;
454       m_clamp_height = 0;
455    }
456
457    inline bool check() const { return true; }
458
459    inline bool operator== (const vogl_mipmap_params& rhs) const
460    {
461 #define VOGL_COMP(x) do { if ((x) != (rhs.x)) return false; } while(0)
462       VOGL_COMP(m_size_of_obj);
463       VOGL_COMP(m_mode);
464       VOGL_COMP(m_filter);
465       VOGL_COMP(m_gamma_filtering);
466       VOGL_COMP(m_gamma);
467       VOGL_COMP(m_blurriness);
468       VOGL_COMP(m_renormalize);
469       VOGL_COMP(m_tiled);
470       VOGL_COMP(m_max_levels);
471       VOGL_COMP(m_min_mip_size);
472       VOGL_COMP(m_scale_mode);
473       VOGL_COMP(m_scale_x);
474       VOGL_COMP(m_scale_y);
475       VOGL_COMP(m_window_left);
476       VOGL_COMP(m_window_top);
477       VOGL_COMP(m_window_right);
478       VOGL_COMP(m_window_bottom);
479       VOGL_COMP(m_clamp_scale);
480       VOGL_COMP(m_clamp_width);
481       VOGL_COMP(m_clamp_height);
482       return true;
483 #undef VOGL_COMP
484    }
485    vogl_uint32     m_size_of_obj;
486
487    vogl_mip_mode   m_mode;
488    vogl_mip_filter m_filter;
489
490    vogl_bool       m_gamma_filtering;
491    float          m_gamma;
492
493    float          m_blurriness;
494
495    vogl_uint32     m_max_levels;
496    vogl_uint32     m_min_mip_size;
497
498    vogl_bool       m_renormalize;
499    vogl_bool       m_tiled;
500
501    vogl_scale_mode m_scale_mode;
502    float          m_scale_x;
503    float          m_scale_y;
504
505    vogl_uint32     m_window_left;
506    vogl_uint32     m_window_top;
507    vogl_uint32     m_window_right;
508    vogl_uint32     m_window_bottom;
509
510    vogl_bool       m_clamp_scale;
511    vogl_uint32     m_clamp_width;
512    vogl_uint32     m_clamp_height;
513 };
514
515 // -------- High-level helper function definitions for CDN/DDS compression.
516
517 #ifndef VOGL_MIN_ALLOC_ALIGNMENT
518 #define VOGL_MIN_ALLOC_ALIGNMENT sizeof(size_t) * 2
519 #endif
520
521 // -------- String helpers.
522
523 // Converts a vogl_file_type to a string.
524 const char* vogl_get_file_type_ext(vogl_file_type file_type);
525
526 // Converts a vogl_format to a string.
527 const char* vogl_get_format_string(vogl_format fmt);
528
529 #endif // VOGL_H
530