diff --git a/bin/crunch_x64.exe b/bin/crunch_x64.exe index a8548ca..84fbd10 100644 Binary files a/bin/crunch_x64.exe and b/bin/crunch_x64.exe differ diff --git a/crnlib/crn_comp.cpp b/crnlib/crn_comp.cpp index fd61601..a8d2e1e 100644 --- a/crnlib/crn_comp.cpp +++ b/crnlib/crn_comp.cpp @@ -690,41 +690,38 @@ bool crn_comp::pack_chunks( } } - for (uint chunk_base = first_chunk; chunk_base < first_chunk + num_chunks; chunk_base += chunk_width) { - for (uint by = 0; by < 2; by++) { - for (uint cx = 0; cx < chunk_width; cx++) { - const chunk_detail& details = m_chunk_details[chunk_base + cx]; - if (!by) { - if (pCodec) - pCodec->encode(details.m_reference_group, m_reference_encoding_dm); - else - m_chunk_encoding_hist.inc_freq(details.m_reference_group); + for (uint by = 0, block_width = chunk_width << 1, b = first_chunk << 2, bEnd = b + (num_chunks << 2); b < bEnd; by++) { + for (uint bx = 0; bx < block_width; bx++, b++) { + if (!(by & 1) && !(bx & 1)) { + uint8 reference_group = m_endpoint_indices[b].reference | m_endpoint_indices[b + block_width].reference << 2 | + m_endpoint_indices[b + 1].reference << 4 | m_endpoint_indices[b + block_width + 1].reference << 6; + if (pCodec) + pCodec->encode(reference_group, m_reference_encoding_dm); + else + m_chunk_encoding_hist.inc_freq(reference_group); + } + for (uint c = 0; c < cNumComps; c++) { + if (endpoint_remap[c]) { + uint index = (*endpoint_remap[c])[m_endpoint_indices[b].component[c]]; + if (!m_endpoint_indices[b].reference) { + int sym = index - endpoint_index[c]; + if (sym < 0) + sym += endpoint_remap[c]->size(); + if (!pCodec) + m_endpoint_index_hist[c ? 1 : 0].inc_freq(sym); + else + pCodec->encode(sym, m_endpoint_index_dm[c ? 1 : 0]); + } + endpoint_index[c] = index; } - for (uint bx = 0; bx < 2; bx++) { - for (uint c = 0; c < cNumComps; c++) { - if (endpoint_remap[c]) { - uint index = (*endpoint_remap[c])[details.m_endpoint_indices[by][bx][c]]; - if (!details.m_endpoint_references[by][bx]) { - int sym = index - endpoint_index[c]; - if (sym < 0) - sym += endpoint_remap[c]->size(); - if (!pCodec) - m_endpoint_index_hist[c ? 1 : 0].inc_freq(sym); - else - pCodec->encode(sym, m_endpoint_index_dm[c ? 1 : 0]); - } - endpoint_index[c] = index; - } - } - for (uint c = 0; c < cNumComps; c++) { - if (selector_remap[c]) { - uint index = (*selector_remap[c])[details.m_selector_indices[by][bx][c]]; - if (!pCodec) - m_selector_index_hist[c ? 1 : 0].inc_freq(index); - else - pCodec->encode(index, m_selector_index_dm[c ? 1 : 0]); - } - } + } + for (uint c = 0; c < cNumComps; c++) { + if (selector_remap[c]) { + uint index = (*selector_remap[c])[m_selector_indices[b].component[c]]; + if (!pCodec) + m_selector_index_hist[c ? 1 : 0].inc_freq(index); + else + pCodec->encode(index, m_selector_index_dm[c ? 1 : 0]); } } } @@ -733,7 +730,6 @@ bool crn_comp::pack_chunks( } bool crn_comp::pack_chunks_simulation( - uint first_chunk, uint num_chunks, uint& total_bits, const crnlib::vector* pColor_endpoint_remap, const crnlib::vector* pColor_selector_remap, @@ -945,7 +941,8 @@ void crn_comp::clear() { utils::zero_object(m_has_comp); - m_chunk_details.clear(); + m_endpoint_indices.clear(); + m_selector_indices.clear(); m_total_chunks = 0; @@ -1106,70 +1103,18 @@ bool crn_comp::quantize_chunks() { for (uint i = 0; i < m_pParams->m_levels; i++) { params.m_levels[i].m_first_chunk = m_levels[i].m_first_chunk; params.m_levels[i].m_num_chunks = m_levels[i].m_num_chunks; + params.m_levels[i].m_chunk_width = m_levels[i].m_chunk_width; } + params.m_endpoint_indices = &m_endpoint_indices; + params.m_selector_indices = &m_selector_indices; + if (!m_hvq.compress(params, m_total_chunks, &m_chunks[0], m_task_pool)) return false; -#if CRNLIB_CREATE_DEBUG_IMAGES - if (params.m_debugging) { - const dxt_hc::pixel_chunk_vec& pixel_chunks = m_hvq.get_compressed_chunk_pixels_final(); - - image_u8 img; - dxt_hc::create_debug_image_from_chunks((m_pParams->m_width + 7) >> 3, (m_pParams->m_height + 7) >> 3, pixel_chunks, &m_hvq.get_chunk_encoding_vec(), img, true, -1); - image_utils::write_to_file("quantized_chunks.tga", img); - } -#endif - return true; } -void crn_comp::create_chunk_indices() { - uint8 endpoint_index_map[8][4] = { - { 0, 0, 0, 0 }, - { 0, 0, 1, 1 }, - { 0, 1, 0, 1 }, - { 0, 0, 1, 2 }, - { 1, 2, 0, 0 }, - { 0, 1, 0, 2 }, - { 1, 0, 2, 0 }, - { 0, 1, 2, 3 }, - }; - - m_chunk_details.resize(m_total_chunks); - - for (uint group = 0; group < m_mip_groups.size(); group++) { - uint chunk_width = m_mip_groups[group].m_chunk_width; - for (uint i = 0; i < m_mip_groups[group].m_num_chunks;) { - for (uint cx = 0; cx < chunk_width; cx++, i++) { - uint chunk_index = m_mip_groups[group].m_first_chunk + i, left_chunk_index = 0, top_chunk_index = 0; - const dxt_hc::chunk_encoding& chunk_encoding = m_hvq.get_chunk_encoding(chunk_index); - for (uint t = 0, by = 0; by < 2; by++) { - for (uint bx = 0; bx < 2; bx++, t++) { - bool left_match = bx || cx; - if (left_match) - left_chunk_index = bx ? chunk_index : chunk_index - 1; - bool top_match = by || i >= chunk_width; - if (top_match) - top_chunk_index = by ? chunk_index : chunk_index - chunk_width; - for (uint c = 0; c < cNumComps; c++) { - if (m_has_comp[c]) { - m_chunk_details[chunk_index].m_endpoint_indices[by][bx][c] = chunk_encoding.m_endpoint_indices[c][endpoint_index_map[chunk_encoding.m_encoding_index][t]]; - left_match = left_match && m_chunk_details[chunk_index].m_endpoint_indices[by][bx][c] == m_chunk_details[left_chunk_index].m_endpoint_indices[by][bx ^ 1][c]; - top_match = top_match && m_chunk_details[chunk_index].m_endpoint_indices[by][bx][c] == m_chunk_details[top_chunk_index].m_endpoint_indices[by ^ 1][bx][c]; - m_chunk_details[chunk_index].m_selector_indices[by][bx][c] = chunk_encoding.m_selector_indices[c][by][bx]; - } - } - uint8 endpoint_reference = left_match ? 1 : top_match ? 2 : 0; - m_chunk_details[chunk_index].m_endpoint_references[by][bx] = endpoint_reference; - m_chunk_details[chunk_index].m_reference_group |= endpoint_reference << (bx << 2 | by << 1); - } - } - } - } - } -} - struct optimize_color_endpoint_codebook_params { crnlib::vector* m_pTrial_color_endpoint_remap; uint m_iter_index; @@ -1223,17 +1168,10 @@ bool crn_comp::optimize_color_endpoint_codebook(crnlib::vector& remapping) uint n = m_hvq.get_color_endpoint_codebook_size(); hist_type xhist(n * n); - uint endpoint_index[2][2] = {}; - for (uint chunk_index = 0; chunk_index < m_chunks.size(); chunk_index++) { - const chunk_detail& details = m_chunk_details[chunk_index]; - for (uint y = 0; y < 2; y++) { - for (uint x = 0; x < 2; x++) { - endpoint_index[y][x] = details.m_endpoint_indices[y][x][cColor]; - if (!details.m_endpoint_references[y][x]) { - update_hist(xhist, endpoint_index[y][x], endpoint_index[y][x ^ 1], n); - update_hist(xhist, endpoint_index[y][x ^ 1], endpoint_index[y][x], n); - } - } + for (uint b = 1; b < m_endpoint_indices.size(); b++) { + if (!m_endpoint_indices[b].reference) { + update_hist(xhist, m_endpoint_indices[b - 1].color, m_endpoint_indices[b].color, n); + update_hist(xhist, m_endpoint_indices[b].color, m_endpoint_indices[b - 1].color, n); } } @@ -1260,7 +1198,7 @@ bool crn_comp::optimize_color_endpoint_codebook(crnlib::vector& remapping) return false; uint total_packed_chunk_bits; - if (!pack_chunks_simulation(0, m_total_chunks, total_packed_chunk_bits, &trial_color_endpoint_remap, NULL, NULL, NULL)) + if (!pack_chunks_simulation(total_packed_chunk_bits, &trial_color_endpoint_remap, NULL, NULL, NULL)) return false; #if CRNLIB_ENABLE_DEBUG_MESSAGES @@ -1353,19 +1291,16 @@ bool crn_comp::optimize_alpha_endpoint_codebook(crnlib::vector& remapping) uint n = m_hvq.get_alpha_endpoint_codebook_size(); hist_type xhist(n * n); - uint endpoint_index[2][2][cNumComps] = {}; - uint min_comp_index = m_has_comp[cAlpha0] ? cAlpha0 : cAlpha1, max_comp_index = m_has_comp[cAlpha1] ? cAlpha1 : cAlpha0; - for (uint chunk_index = 0; chunk_index < m_chunks.size(); chunk_index++) { - const chunk_detail& details = m_chunk_details[chunk_index]; - for (uint y = 0; y < 2; y++) { - for (uint x = 0; x < 2; x++) { - for (uint comp_index = min_comp_index; comp_index <= max_comp_index; comp_index++) { - endpoint_index[y][x][comp_index] = details.m_endpoint_indices[y][x][comp_index]; - if (!details.m_endpoint_references[y][x]) { - update_hist(xhist, endpoint_index[y][x][comp_index], endpoint_index[y][x ^ 1][comp_index], n); - update_hist(xhist, endpoint_index[y][x ^ 1][comp_index], endpoint_index[y][x][comp_index], n); - } - } + bool hasAlpha0 = m_has_comp[cAlpha0], hasAlpha1 = m_has_comp[cAlpha1]; + for (uint b = 1; b < m_endpoint_indices.size(); b++) { + if (!m_endpoint_indices[b].reference) { + if (hasAlpha0) { + update_hist(xhist, m_endpoint_indices[b - 1].alpha0, m_endpoint_indices[b].alpha0, n); + update_hist(xhist, m_endpoint_indices[b].alpha0, m_endpoint_indices[b - 1].alpha0, n); + } + if (hasAlpha1) { + update_hist(xhist, m_endpoint_indices[b - 1].alpha1, m_endpoint_indices[b].alpha1, n); + update_hist(xhist, m_endpoint_indices[b].alpha1, m_endpoint_indices[b - 1].alpha1, n); } } } @@ -1393,7 +1328,7 @@ bool crn_comp::optimize_alpha_endpoint_codebook(crnlib::vector& remapping) return false; uint total_packed_chunk_bits; - if (!pack_chunks_simulation(0, m_total_chunks, total_packed_chunk_bits, NULL, NULL, &trial_alpha_endpoint_remap, NULL)) + if (!pack_chunks_simulation(total_packed_chunk_bits, NULL, NULL, &trial_alpha_endpoint_remap, NULL)) return false; #if CRNLIB_ENABLE_DEBUG_MESSAGES @@ -1557,8 +1492,6 @@ bool crn_comp::compress_internal() { if (!quantize_chunks()) return false; - create_chunk_indices(); - crnlib::vector endpoint_remap[2]; crnlib::vector selector_remap[2]; diff --git a/crnlib/crn_comp.h b/crnlib/crn_comp.h index 818a301..b8a8624 100644 --- a/crnlib/crn_comp.h +++ b/crnlib/crn_comp.h @@ -65,14 +65,8 @@ class crn_comp : public itexture_comp { bool m_has_comp[cNumComps]; - struct chunk_detail { - chunk_detail() { utils::zero_object(*this); } - uint16 m_endpoint_indices[2][2][cNumComps]; - uint16 m_selector_indices[2][2][cNumComps]; - uint8 m_endpoint_references[2][2]; - uint8 m_reference_group; - }; - crnlib::vector m_chunk_details; + crnlib::vector m_endpoint_indices; + crnlib::vector m_selector_indices; uint m_total_chunks; dxt_hc::pixel_chunk_vec m_chunks; @@ -125,7 +119,6 @@ class crn_comp : public itexture_comp { bool alias_images(); void create_chunks(); bool quantize_chunks(); - void create_chunk_indices(); bool pack_chunks( uint group, @@ -137,7 +130,6 @@ class crn_comp : public itexture_comp { const crnlib::vector* pAlpha_selector_remap); bool pack_chunks_simulation( - uint first_chunk, uint num_chunks, uint& total_bits, const crnlib::vector* pColor_endpoint_remap, const crnlib::vector* pColor_selector_remap, diff --git a/crnlib/crn_dxt_hc.cpp b/crnlib/crn_dxt_hc.cpp index 1e652a4..378de04 100644 --- a/crnlib/crn_dxt_hc.cpp +++ b/crnlib/crn_dxt_hc.cpp @@ -46,8 +46,6 @@ void dxt_hc::clear() { m_num_chunks = 0; m_pChunks = NULL; - m_chunk_encoding.clear(); - m_num_alpha_blocks = 0; m_has_color_blocks = false; m_has_alpha0_blocks = false; @@ -194,7 +192,7 @@ bool dxt_hc::compress_internal(const params& p, uint num_chunks, const pixel_chu create_final_debug_image(); - if (!create_chunk_encodings()) + if (!create_block_encodings(p)) return false; return true; @@ -2287,66 +2285,52 @@ void dxt_hc::create_final_debug_image() { } // chunk_index } -bool dxt_hc::create_chunk_encodings() { - m_chunk_encoding.resize(m_num_chunks); +bool dxt_hc::create_block_encodings(const params& p) { + crnlib::vector& m_endpoint_indices = *p.m_endpoint_indices; + crnlib::vector& m_selector_indices = *p.m_selector_indices; - for (uint chunk_index = 0; chunk_index < m_num_chunks; chunk_index++) { - if ((chunk_index & 255) == 0) { - if (!update_progress(19, chunk_index, m_num_chunks)) - return false; - } + uint8 tile_map[8][2][2] = { + {{ 0, 0 }, { 0, 0 }}, + {{ 0, 0 }, { 1, 1 }}, + {{ 0, 1 }, { 0, 1 }}, + {{ 0, 0 }, { 1, 2 }}, + {{ 1, 2 }, { 0, 0 }}, + {{ 0, 1 }, { 0, 2 }}, + {{ 1, 0 }, { 2, 0 }}, + {{ 0, 1 }, { 2, 3 }}, + }; - chunk_encoding& encoding = m_chunk_encoding[chunk_index]; + m_endpoint_indices.resize(m_num_chunks << 2); + m_selector_indices.resize(m_num_chunks << 2); + bool hasBlocks[cNumCompressedChunkVecs] = {m_has_color_blocks, m_num_alpha_blocks > 0, m_num_alpha_blocks > 1}; - for (uint q = 0; q < cNumCompressedChunkVecs; q++) { - bool skip = true; - if (q == cColorChunks) { - if (m_has_color_blocks) - skip = false; - } else if (q <= m_num_alpha_blocks) - skip = false; - - if (skip) - continue; - - CRNLIB_ASSERT(!m_compressed_chunks[q].empty()); - const compressed_chunk& chunk = m_compressed_chunks[q][chunk_index]; - - CRNLIB_ASSERT(chunk.m_encoding_index < cNumChunkEncodings); - encoding.m_encoding_index = static_cast(chunk.m_encoding_index); - - CRNLIB_ASSERT(chunk.m_num_tiles <= cChunkMaxTiles); - encoding.m_num_tiles = static_cast(chunk.m_num_tiles); - - for (uint tile_index = 0; tile_index < chunk.m_num_tiles; tile_index++) { - const compressed_tile& quantized_tile = chunk.m_quantized_tiles[tile_index]; - - if (!q) { - CRNLIB_ASSERT(quantized_tile.m_endpoint_cluster_index < m_color_clusters.size()); - } else { - CRNLIB_ASSERT(quantized_tile.m_endpoint_cluster_index < m_alpha_clusters.size()); - } - - encoding.m_endpoint_indices[q][tile_index] = static_cast(quantized_tile.m_endpoint_cluster_index); - } - - for (uint y = 0; y < cChunkBlockHeight; y++) { - for (uint x = 0; x < cChunkBlockWidth; x++) { - const uint selector_index = chunk.m_selector_cluster_index[y][x]; - - if (!q) { - CRNLIB_ASSERT(selector_index < m_color_selectors.size()); - } else { - CRNLIB_ASSERT(selector_index < m_alpha_selectors.size()); + for (uint level = 0; level < p.m_num_levels; level++) { + uint first_chunk = p.m_levels[level].m_first_chunk; + uint end_chunk = p.m_levels[level].m_first_chunk + p.m_levels[level].m_num_chunks; + uint chunk_width = p.m_levels[level].m_chunk_width; + uint block_width = chunk_width << 1; + for (uint b = first_chunk << 2, cy = 0, chunk_base = first_chunk; chunk_base < end_chunk; chunk_base += chunk_width, cy++) { + for (uint by = 0; by < 2; by++) { + for (uint cx = 0; cx < chunk_width; cx++) { + for (uint bx = 0; bx < 2; bx++, b++) { + bool top_match = cy || by; + bool left_match = top_match || cx || bx; + for (uint c = 0; c < cNumCompressedChunkVecs; c++) { + if (hasBlocks[c]) { + const compressed_chunk& chunk = m_compressed_chunks[c][chunk_base + cx]; + uint16 endpoint_index = chunk.m_quantized_tiles[tile_map[chunk.m_encoding_index][by][bx]].m_endpoint_cluster_index; + left_match = left_match && endpoint_index == m_endpoint_indices[b - 1].component[c]; + top_match = top_match && endpoint_index == m_endpoint_indices[b - block_width].component[c]; + m_endpoint_indices[b].component[c] = endpoint_index; + m_selector_indices[b].component[c] = chunk.m_selector_cluster_index[by][bx]; + } + } + m_endpoint_indices[b].reference = left_match ? 1 : top_match ? 2 : 0; } - - encoding.m_selector_indices[q][y][x] = static_cast(selector_index); } } - - } // q - - } // chunk_index + } + } if (m_has_color_blocks) { m_color_endpoints.resize(m_color_clusters.size()); @@ -2363,46 +2347,6 @@ bool dxt_hc::create_chunk_encodings() { return true; } -void dxt_hc::create_debug_image_from_chunks(uint num_chunks_x, uint num_chunks_y, const pixel_chunk_vec& chunks, const chunk_encoding_vec* pChunk_encodings, image_u8& img, bool serpentine_scan, int comp_index) { - if (chunks.empty()) { - img.set_all(color_quad_u8::make_black()); - return; - } - - img.resize(num_chunks_x * cChunkPixelWidth, num_chunks_y * cChunkPixelHeight); - - for (uint y = 0; y < num_chunks_y; y++) { - for (uint x = 0; x < num_chunks_x; x++) { - uint c = x + y * num_chunks_x; - if ((serpentine_scan) && (y & 1)) - c = (num_chunks_x - 1 - x) + y * num_chunks_x; - - if (comp_index >= 0) { - for (uint cy = 0; cy < cChunkPixelHeight; cy++) - for (uint cx = 0; cx < cChunkPixelWidth; cx++) - img(x * cChunkPixelWidth + cx, y * cChunkPixelHeight + cy) = chunks[c](cx, cy)[comp_index]; - } else { - for (uint cy = 0; cy < cChunkPixelHeight; cy++) - for (uint cx = 0; cx < cChunkPixelWidth; cx++) - img(x * cChunkPixelWidth + cx, y * cChunkPixelHeight + cy) = chunks[c](cx, cy); - } - - if (pChunk_encodings) { - const chunk_encoding& chunk = (*pChunk_encodings)[c]; - const chunk_encoding_desc& encoding_desc = g_chunk_encodings[chunk.m_encoding_index]; - CRNLIB_ASSERT(chunk.m_num_tiles == encoding_desc.m_num_tiles); - for (uint t = 0; t < chunk.m_num_tiles; t++) { - const chunk_tile_desc& tile_desc = encoding_desc.m_tiles[t]; - - img.unclipped_fill_box( - x * 8 + tile_desc.m_x_ofs, y * 8 + tile_desc.m_y_ofs, - tile_desc.m_width + 1, tile_desc.m_height + 1, color_quad_u8(128, 128, 128, 255)); - } - } - } - } -} - bool dxt_hc::update_progress(uint phase_index, uint subphase_index, uint subphase_total) { CRNLIB_ASSERT(crn_get_current_thread_id() == m_main_thread_id); diff --git a/crnlib/crn_dxt_hc.h b/crnlib/crn_dxt_hc.h index d605d53..57c8443 100644 --- a/crnlib/crn_dxt_hc.h +++ b/crnlib/crn_dxt_hc.h @@ -22,6 +22,29 @@ class dxt_hc { dxt_hc(); ~dxt_hc(); + struct endpoint_indices_details { + union { + struct { + uint16 color; + uint16 alpha0; + uint16 alpha1; + }; + uint16 component[3]; + }; + uint8 reference; + }; + + struct selector_indices_details { + union { + struct { + uint16 color; + uint16 alpha0; + uint16 alpha1; + }; + uint16 component[3]; + }; + }; + struct pixel_chunk { pixel_chunk() { clear(); } @@ -99,11 +122,15 @@ class dxt_hc { struct miplevel_desc { uint m_first_chunk; uint m_num_chunks; + uint m_chunk_width; }; // The mip level data is optional! miplevel_desc m_levels[cCRNMaxLevels]; uint m_num_levels; + crnlib::vector *m_endpoint_indices; + crnlib::vector *m_selector_indices; + dxt_format m_format; // If m_hierarchical is false, only 4x4 blocks will be used by the encoder (leading to higher quality/larger files). @@ -126,28 +153,6 @@ class dxt_hc { // Output accessors inline uint get_num_chunks() const { return m_num_chunks; } - struct chunk_encoding { - chunk_encoding() { utils::zero_object(*this); }; - - // Index into g_chunk_encodings. - uint8 m_encoding_index; - - // Number of tiles, endpoint indices. - uint8 m_num_tiles; - - // Color, alpha0, alpha1 - enum { cColorIndex = 0, - cAlpha0Index = 1, - cAlpha1Index = 2 }; - uint16 m_endpoint_indices[3][cChunkMaxTiles]; - uint16 m_selector_indices[3][cChunkBlockHeight][cChunkBlockWidth]; // [block_y][block_x] - }; - - typedef crnlib::vector chunk_encoding_vec; - - inline const chunk_encoding& get_chunk_encoding(uint chunk_index) const { return m_chunk_encoding[chunk_index]; } - inline const chunk_encoding_vec& get_chunk_encoding_vec() const { return m_chunk_encoding; } - struct selectors { selectors() { utils::zero_object(*this); } @@ -201,16 +206,12 @@ class dxt_hc { const pixel_chunk_vec& get_compressed_chunk_pixels_quantized_alpha_selectors() const { return m_dbg_chunk_pixels_quantized_alpha_selectors; } const pixel_chunk_vec& get_compressed_chunk_pixels_final_alpha_selectors() const { return m_dbg_chunk_pixels_final_alpha_selectors; } - static void create_debug_image_from_chunks(uint num_chunks_x, uint num_chunks_y, const pixel_chunk_vec& chunks, const chunk_encoding_vec* pChunk_encodings, image_u8& img, bool serpentine_scan, int comp_index = -1); - private: params m_params; uint m_num_chunks; const pixel_chunk* m_pChunks; - chunk_encoding_vec m_chunk_encoding; - uint m_num_alpha_blocks; // 0, 1, or 2 bool m_has_color_blocks; bool m_has_alpha0_blocks; @@ -416,13 +417,12 @@ class dxt_hc { bool refine_quantized_alpha_endpoints(); bool refine_quantized_alpha_selectors(); void create_final_debug_image(); - bool create_chunk_encodings(); + bool create_block_encodings(const params& p); bool update_progress(uint phase_index, uint subphase_index, uint subphase_total); bool compress_internal(const params& p, uint num_chunks, const pixel_chunk* pChunks); }; CRNLIB_DEFINE_BITWISE_COPYABLE(dxt_hc::pixel_chunk); -CRNLIB_DEFINE_BITWISE_COPYABLE(dxt_hc::chunk_encoding); CRNLIB_DEFINE_BITWISE_COPYABLE(dxt_hc::selectors); } // namespace crnlib