1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
4 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
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:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
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
25 **************************************************************************/
27 // File: vogl_dxt_image.h
30 #include "vogl_core.h"
31 #include "vogl_dxt1.h"
32 #include "vogl_dxt5a.h"
33 #include "vogl_image.h"
34 #include "vogl_rg_etc1.h"
36 #define VOGL_SUPPORT_ATI_COMPRESS 0
46 dxt_image(const dxt_image &other);
47 dxt_image &operator=(const dxt_image &rhs);
51 inline bool is_valid() const
53 return m_blocks_x > 0;
56 uint get_width() const
60 uint get_height() const
65 uint get_blocks_x() const
69 uint get_blocks_y() const
73 uint get_total_blocks() const
75 return m_blocks_x * m_blocks_y;
78 uint get_elements_per_block() const
80 return m_num_elements_per_block;
82 uint get_bytes_per_block() const
84 return m_bytes_per_block;
87 dxt_format get_format() const
92 bool has_color() const
94 return (m_format == cDXT1) || (m_format == cDXT1A) || (m_format == cDXT3) || (m_format == cDXT5) || (m_format == cETC1);
97 // Will be pretty slow if the image is DXT1, as this method scans for alpha blocks/selectors.
98 bool has_alpha() const;
103 cColorDXT1, // DXT1 color block
104 cAlphaDXT3, // DXT3 alpha block (only)
105 cAlphaDXT5, // DXT5 alpha block (only)
106 cColorETC1, // ETC1 color block
109 element_type get_element_type(uint element_index) const
111 VOGL_ASSERT(element_index < m_num_elements_per_block);
112 return m_element_type[element_index];
115 //Returns -1 for RGB, or [0,3]
116 int8 get_element_component_index(uint element_index) const
118 VOGL_ASSERT(element_index < m_num_elements_per_block);
119 return m_element_component_index[element_index];
126 uint get_le_word(uint index) const
128 VOGL_ASSERT(index < 4);
129 return m_bytes[index * 2] | (m_bytes[index * 2 + 1] << 8);
131 uint get_be_word(uint index) const
133 VOGL_ASSERT(index < 4);
134 return m_bytes[index * 2 + 1] | (m_bytes[index * 2] << 8);
137 void set_le_word(uint index, uint val)
139 VOGL_ASSERT((index < 4) && (val <= cUINT16_MAX));
140 m_bytes[index * 2] = static_cast<uint8>(val & 0xFF);
141 m_bytes[index * 2 + 1] = static_cast<uint8>((val >> 8) & 0xFF);
143 void set_be_word(uint index, uint val)
145 VOGL_ASSERT((index < 4) && (val <= cUINT16_MAX));
146 m_bytes[index * 2 + 1] = static_cast<uint8>(val & 0xFF);
147 m_bytes[index * 2] = static_cast<uint8>((val >> 8) & 0xFF);
152 memset(this, 0, sizeof(*this));
156 typedef vogl::vector<element> element_vec;
158 bool init(dxt_format fmt, uint width, uint height, bool clear_elements);
159 bool init(dxt_format fmt, uint width, uint height, uint num_elements, element *pElements, bool create_copy);
170 m_quality = cCRNDXTQualityUber;
173 m_grayscale_sampling = false;
174 m_use_both_block_types = true;
175 m_endpoint_caching = true;
176 m_compressor = cCRNDXTCompressorCRN;
177 m_pProgress_callback = NULL;
178 m_pProgress_callback_user_data_ptr = NULL;
179 m_dxt1a_alpha_threshold = 128;
180 m_num_helper_threads = 0;
181 m_progress_start = 0;
182 m_progress_range = 100;
183 m_use_transparent_indices_for_black = false;
185 m_color_weights[0] = 1;
186 m_color_weights[1] = 1;
187 m_color_weights[2] = 1;
190 void init(const vogl_comp_params ¶ms)
192 m_perceptual = (params.m_flags & cCRNCompFlagPerceptual) != 0;
193 m_num_helper_threads = params.m_num_helper_threads;
194 m_use_both_block_types = (params.m_flags & cCRNCompFlagUseBothBlockTypes) != 0;
195 m_use_transparent_indices_for_black = (params.m_flags & cCRNCompFlagUseTransparentIndicesForBlack) != 0;
196 m_dxt1a_alpha_threshold = params.m_dxt1a_alpha_threshold;
197 m_quality = params.m_dxt_quality;
198 m_endpoint_caching = (params.m_flags & cCRNCompFlagDisableEndpointCaching) == 0;
199 m_grayscale_sampling = (params.m_flags & cCRNCompFlagGrayscaleSampling) != 0;
200 m_compressor = params.m_dxt_compressor_type;
203 uint m_dxt1a_alpha_threshold;
205 uint m_num_helper_threads;
207 vogl_dxt_quality m_quality;
209 vogl_dxt_compressor_type m_compressor;
213 bool m_grayscale_sampling;
214 bool m_use_both_block_types;
215 bool m_endpoint_caching;
216 bool m_use_transparent_indices_for_black;
218 typedef bool (*progress_callback_func)(uint percentage_complete, void *pUser_data_ptr);
219 progress_callback_func m_pProgress_callback;
220 void *m_pProgress_callback_user_data_ptr;
222 uint m_progress_start;
223 uint m_progress_range;
225 task_pool *m_pTask_pool;
227 int m_color_weights[3];
230 bool init(dxt_format fmt, const image_u8 &img, const pack_params &p = dxt_image::pack_params());
232 bool unpack(image_u8 &img) const;
236 uint get_total_elements() const
238 return m_elements.size();
241 const element_vec &get_element_vec() const
245 element_vec &get_element_vec()
250 const element &get_element(uint block_x, uint block_y, uint element_index) const;
251 element &get_element(uint block_x, uint block_y, uint element_index);
253 const element *get_element_ptr() const
257 element *get_element_ptr()
262 uint get_size_in_bytes() const
264 return m_elements.size() * sizeof(element);
266 uint get_row_pitch_in_bytes() const
268 return m_blocks_x * m_bytes_per_block;
271 color_quad_u8 get_pixel(uint x, uint y) const;
272 uint get_pixel_alpha(uint x, uint y, uint element_index) const;
274 void set_pixel(uint x, uint y, const color_quad_u8 &c, bool perceptual = true);
276 // get_block_pixels() only sets those components stored in the image!
277 bool get_block_pixels(uint block_x, uint block_y, color_quad_u8 *pPixels) const;
279 struct set_block_pixels_context
281 dxt1_endpoint_optimizer m_dxt1_optimizer;
282 dxt5_endpoint_optimizer m_dxt5_optimizer;
285 void set_block_pixels(uint block_x, uint block_y, const color_quad_u8 *pPixels, const pack_params &p, set_block_pixels_context &context);
286 void set_block_pixels(uint block_x, uint block_y, const color_quad_u8 *pPixels, const pack_params &p);
288 void get_block_endpoints(uint block_x, uint block_y, uint element_index, uint &packed_low_endpoint, uint &packed_high_endpoint) const;
290 // Returns a value representing the component(s) that where actually set, where -1 = RGB.
291 // This method does not always set every component!
292 int get_block_endpoints(uint block_x, uint block_y, uint element_index, color_quad_u8 &low_endpoint, color_quad_u8 &high_endpoint, bool scaled = true) const;
294 // pColors should point to a 16 entry array, to handle DXT3.
295 // Returns the number of block colors: 3, 4, 6, 8, or 16.
296 uint get_block_colors(uint block_x, uint block_y, uint element_index, color_quad_u8 *pColors, uint subblock_index = 0);
298 uint get_subblock_index(uint x, uint y, uint element_index) const;
299 uint get_total_subblocks(uint element_index) const;
301 uint get_selector(uint x, uint y, uint element_index) const;
303 void change_dxt1_to_dxt1a();
305 bool can_flip(uint axis_index);
307 // Returns true if the texture can actually be flipped.
312 element_vec m_elements;
313 element *m_pElements;
321 uint m_total_elements;
323 uint m_num_elements_per_block; // 1 or 2
324 uint m_bytes_per_block; // 8 or 16
326 int8 m_element_component_index[2];
327 element_type m_element_type[2];
329 dxt_format m_format; // DXT1, 1A, 3, 5, N/3DC, or 5A
331 bool init_internal(dxt_format fmt, uint width, uint height);
332 void init_task(uint64_t data, void *pData_ptr);
334 #if VOGL_SUPPORT_ATI_COMPRESS
335 bool init_ati_compress(dxt_format fmt, const image_u8 &img, const pack_params &p);
338 void flip_col(uint x);
339 void flip_row(uint y);