mirror of
https://github.com/BinomialLLC/basis_universal.git
synced 2026-08-08 14:29:07 +00:00
ETC1S->DXT5A transcoding bugfix on solid color blocks
Adding development messages support Adding a few new transcoder get methods to help with creating C-style wrappers
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "basisu_transcoder.h"
|
||||
#include "basisu_file_headers.h"
|
||||
#include <limits.h>
|
||||
@@ -41,6 +42,9 @@ namespace basisu
|
||||
|
||||
void debug_printf(const char *pFmt, ...)
|
||||
{
|
||||
#if BASISU_DEVEL_MESSAGES
|
||||
g_debug_printf = true;
|
||||
#endif
|
||||
if (g_debug_printf)
|
||||
{
|
||||
va_list args;
|
||||
@@ -2411,6 +2415,8 @@ namespace basist
|
||||
pDst_block->m_selectors[1] = 0;
|
||||
pDst_block->m_selectors[2] = 0;
|
||||
pDst_block->m_selectors[3] = 0;
|
||||
pDst_block->m_selectors[4] = 0;
|
||||
pDst_block->m_selectors[5] = 0;
|
||||
return;
|
||||
}
|
||||
else if (pSelector->m_num_unique_selectors == 2)
|
||||
@@ -2425,6 +2431,7 @@ namespace basist
|
||||
pDst_block->set_low_alpha(g0);
|
||||
pDst_block->set_high_alpha(g1);
|
||||
|
||||
// TODO: Optimize this
|
||||
for (uint32_t y = 0; y < 4; y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < 4; x++)
|
||||
@@ -3260,13 +3267,22 @@ namespace basist
|
||||
huffman_decoding_table color5_delta_model, inten5_delta_model;
|
||||
|
||||
if (!sym_codec.init(pEndpoints_data, endpoints_data_size))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 0\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sym_codec.read_huffman_table(color5_delta_model))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 1\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sym_codec.read_huffman_table(inten5_delta_model))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 2\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_endpoints.resize(num_endpoints);
|
||||
|
||||
@@ -3284,13 +3300,19 @@ namespace basist
|
||||
int g5 = prev_color5.g + delta_g5;
|
||||
int b5 = prev_color5.b + delta_b5;
|
||||
if (static_cast<uint32_t>(r5 | g5 | b5) > 31)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 3\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_endpoints[i].m_color5.set(r5, g5, b5, 0);
|
||||
|
||||
int inten5 = prev_inten5 + delta_inten5;
|
||||
if ((inten5 < 0) || (inten5 > 7))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 4\n");
|
||||
return false;
|
||||
}
|
||||
m_endpoints[i].m_inten5 = static_cast<uint8_t>(inten5);
|
||||
|
||||
prev_color5 = m_endpoints[i].m_color5;
|
||||
@@ -3302,7 +3324,10 @@ namespace basist
|
||||
m_selectors.resize(num_selectors);
|
||||
|
||||
if (!sym_codec.init(pSelectors_data, selectors_data_size))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 5\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
basist::huffman_decoding_table delta_selector_pal_model;
|
||||
|
||||
@@ -3318,7 +3343,10 @@ namespace basist
|
||||
if (mod_bits)
|
||||
{
|
||||
if (!sym_codec.read_huffman_table(mod_model))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 6\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//uint32_t total_mod_bits = 0;
|
||||
@@ -3353,13 +3381,19 @@ namespace basist
|
||||
|
||||
basist::huffman_decoding_table uses_global_cb_bitflags_model;
|
||||
if (!sym_codec.read_huffman_table(uses_global_cb_bitflags_model))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 7\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
basist::huffman_decoding_table global_mod_indices_model;
|
||||
if (mod_bits)
|
||||
{
|
||||
if (!sym_codec.read_huffman_table(global_mod_indices_model))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 8\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t cur_uses_global_cb_bitflags = 0;
|
||||
@@ -3470,19 +3504,34 @@ namespace basist
|
||||
{
|
||||
basist::bitwise_decoder sym_codec;
|
||||
if (!sym_codec.init(pTable_data, table_data_size))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_tables: fail 0\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sym_codec.read_huffman_table(m_template_model))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_tables: fail 1\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sym_codec.read_huffman_table(m_delta_endpoint_model))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_tables: fail 2\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sym_codec.read_huffman_table(m_delta_selector_model))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_tables: fail 3\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sym_codec.read_huffman_table(m_selector_history_buf_rle_model))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_tables: fail 4\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_selector_history_buf_size = sym_codec.get_bits(13);
|
||||
|
||||
@@ -3502,10 +3551,13 @@ namespace basist
|
||||
const uint32_t total_macroblock_blocks = num_macroblocks_x * num_macroblocks_y * 4;
|
||||
|
||||
basist::bitwise_decoder sym_codec;
|
||||
|
||||
|
||||
if (!sym_codec.init(pImage_data, image_data_size))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::transcode_slice: sym_codec.init failed\n");
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
approx_move_to_front selector_history_buf(m_selector_history_buf_size);
|
||||
|
||||
int prev_endpoint_index = 0;
|
||||
@@ -3531,10 +3583,13 @@ namespace basist
|
||||
{
|
||||
pPVRTC_work_mem = malloc(num_blocks_x * num_blocks_y * (sizeof(decoder_etc_block) + sizeof(uint32_t)));
|
||||
if (!pPVRTC_work_mem)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::transcode_slice: malloc failed\n");
|
||||
return false;
|
||||
}
|
||||
pPVRTC_endpoints = (uint32_t *)&((decoder_etc_block*)pPVRTC_work_mem)[num_blocks_x * num_blocks_y];
|
||||
}
|
||||
|
||||
|
||||
for (uint32_t macroblock_y = 0; macroblock_y < num_macroblocks_y; macroblock_y++)
|
||||
{
|
||||
const int x_start = (macroblock_y & 1) ? (num_macroblocks_x - 1) : 0;
|
||||
@@ -3808,18 +3863,24 @@ namespace basist
|
||||
const basis_file_header *pHeader = reinterpret_cast<const basis_file_header*>(pData);
|
||||
|
||||
if (crc16(&pHeader->m_data_size, sizeof(basis_file_header) - BASISU_OFFSETOF(basis_file_header, m_data_size), 0) != pHeader->m_header_crc16)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: header CRC check failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (full_validation)
|
||||
{
|
||||
if (crc16(reinterpret_cast<const uint8_t*>(pData) + sizeof(basis_file_header), pHeader->m_data_size, 0) != pHeader->m_data_crc16)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: data CRC check failed\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool basisu_transcoder::validate_header(const void* pData, uint32_t data_size) const
|
||||
|
||||
bool basisu_transcoder::validate_header_quick(const void* pData, uint32_t data_size) const
|
||||
{
|
||||
if (data_size <= sizeof(basis_file_header))
|
||||
return false;
|
||||
@@ -3827,28 +3888,70 @@ namespace basist
|
||||
const basis_file_header *pHeader = reinterpret_cast<const basis_file_header*>(pData);
|
||||
|
||||
if ((pHeader->m_sig != basis_file_header::cBASISSigValue) || (pHeader->m_ver != BASISD_SUPPORTED_BASIS_VERSION) || (pHeader->m_header_size != sizeof(basis_file_header)))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: header has an invalid signature, or file version is unsupported\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t expected_file_size = sizeof(basis_file_header) + pHeader->m_data_size;
|
||||
if (data_size < expected_file_size)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: source buffer is too small\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool basisu_transcoder::validate_header(const void* pData, uint32_t data_size) const
|
||||
{
|
||||
if (data_size <= sizeof(basis_file_header))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: input source buffer is too small\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
const basis_file_header *pHeader = reinterpret_cast<const basis_file_header*>(pData);
|
||||
|
||||
if ((pHeader->m_sig != basis_file_header::cBASISSigValue) || (pHeader->m_ver != BASISD_SUPPORTED_BASIS_VERSION) || (pHeader->m_header_size != sizeof(basis_file_header)))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: header has an invalid signature, or file version is unsupported\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t expected_file_size = sizeof(basis_file_header) + pHeader->m_data_size;
|
||||
if (data_size < expected_file_size)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: input source buffer is too small, or header is corrupted\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((!pHeader->m_total_images) || (!pHeader->m_total_slices))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: invalid basis file (total images or slices are 0)\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pHeader->m_total_images > pHeader->m_total_slices)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: invalid basis file (too many images)\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pHeader->m_flags & cBASISHeaderFlagHasAlphaSlices)
|
||||
{
|
||||
// Must have an even # of slices if the .basis file has alpha
|
||||
if (pHeader->m_total_slices & 1)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: invalid basis file (odd number of slices)\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((pHeader->m_flags & cBASISHeaderFlagETC1S) == 0)
|
||||
{
|
||||
// We only support ETC1S in basis universal
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: invalid basis file (ETC1S flag check)\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3857,8 +3960,11 @@ namespace basist
|
||||
|
||||
uint32_t basisu_transcoder::get_total_images(const void *pData, uint32_t data_size) const
|
||||
{
|
||||
if (!validate_header(pData, data_size))
|
||||
if (!validate_header_quick(pData, data_size))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: header validation failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const basis_file_header *pHeader = static_cast<const basis_file_header *>(pData);
|
||||
|
||||
@@ -3867,17 +3973,26 @@ namespace basist
|
||||
|
||||
bool basisu_transcoder::get_image_info(const void *pData, uint32_t data_size, basisu_image_info &image_info, uint32_t image_index) const
|
||||
{
|
||||
if (!validate_header(pData, data_size))
|
||||
if (!validate_header_quick(pData, data_size))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_image_info: header validation failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
int slice_index = find_first_slice_index(pData, data_size, image_index, 0);
|
||||
if (slice_index < 0)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_image_info: invalid slice index\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
const basis_file_header *pHeader = static_cast<const basis_file_header *>(pData);
|
||||
|
||||
if (image_index >= pHeader->m_total_images)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_image_info: invalid image_index\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
const basis_slice_desc *pSlice_descs = reinterpret_cast<const basis_slice_desc *>(static_cast<const uint8_t *>(pData) + pHeader->m_slice_desc_file_ofs);
|
||||
|
||||
@@ -3904,20 +4019,98 @@ namespace basist
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool basisu_transcoder::get_image_level_info(const void *pData, uint32_t data_size, basisu_image_level_info &image_info, uint32_t image_index, uint32_t level_index) const
|
||||
|
||||
uint32_t basisu_transcoder::get_total_image_levels(const void *pData, uint32_t data_size, uint32_t image_index) const
|
||||
{
|
||||
if (!validate_header(pData, data_size))
|
||||
if (!validate_header_quick(pData, data_size))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_total_image_levels: header validation failed\n");
|
||||
return false;
|
||||
|
||||
int slice_index = find_first_slice_index(pData, data_size, image_index, level_index);
|
||||
}
|
||||
|
||||
int slice_index = find_first_slice_index(pData, data_size, image_index, 0);
|
||||
if (slice_index < 0)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_total_image_levels: failed finding slice\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
const basis_file_header *pHeader = static_cast<const basis_file_header *>(pData);
|
||||
|
||||
if (image_index >= pHeader->m_total_images)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_total_image_levels: invalid image_index\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
const basis_slice_desc *pSlice_descs = reinterpret_cast<const basis_slice_desc *>(static_cast<const uint8_t *>(pData) + pHeader->m_slice_desc_file_ofs);
|
||||
|
||||
uint32_t total_levels = 1;
|
||||
for (uint32_t i = slice_index + 1; i < pHeader->m_total_slices; i++)
|
||||
if (pSlice_descs[i].m_image_index == image_index)
|
||||
total_levels = basisu::maximum<uint32_t>(total_levels, pSlice_descs[i].m_level_index + 1);
|
||||
else
|
||||
break;
|
||||
|
||||
return total_levels;
|
||||
}
|
||||
|
||||
bool basisu_transcoder::get_image_level_desc(const void *pData, uint32_t data_size, uint32_t image_index, uint32_t level_index, uint32_t &orig_width, uint32_t &orig_height, uint32_t &total_blocks) const
|
||||
{
|
||||
if (!validate_header_quick(pData, data_size))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_image_level_desc: header validation failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
int slice_index = find_first_slice_index(pData, data_size, image_index, level_index);
|
||||
if (slice_index < 0)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_image_level_desc: failed finding slice\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
const basis_file_header *pHeader = static_cast<const basis_file_header *>(pData);
|
||||
|
||||
if (image_index >= pHeader->m_total_images)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_image_level_desc: invalid image_index\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
const basis_slice_desc *pSlice_descs = reinterpret_cast<const basis_slice_desc *>(static_cast<const uint8_t *>(pData) + pHeader->m_slice_desc_file_ofs);
|
||||
|
||||
const basis_slice_desc &slice_desc = pSlice_descs[slice_index];
|
||||
|
||||
orig_width = slice_desc.m_orig_width;
|
||||
orig_height = slice_desc.m_orig_height;
|
||||
total_blocks = slice_desc.m_num_blocks_x * slice_desc.m_num_blocks_y;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool basisu_transcoder::get_image_level_info(const void *pData, uint32_t data_size, basisu_image_level_info &image_info, uint32_t image_index, uint32_t level_index) const
|
||||
{
|
||||
if (!validate_header_quick(pData, data_size))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_image_level_info: validate_file_checksums failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
int slice_index = find_first_slice_index(pData, data_size, image_index, level_index);
|
||||
if (slice_index < 0)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_image_level_info: failed finding slice\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
const basis_file_header *pHeader = static_cast<const basis_file_header *>(pData);
|
||||
|
||||
if (image_index >= pHeader->m_total_images)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_image_level_info: invalid image_index\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
const basis_slice_desc *pSlice_descs = reinterpret_cast<const basis_slice_desc *>(static_cast<const uint8_t *>(pData) + pHeader->m_slice_desc_file_ofs);
|
||||
|
||||
@@ -3941,7 +4134,10 @@ namespace basist
|
||||
bool basisu_transcoder::get_file_info(const void* pData, uint32_t data_size, basisu_file_info & file_info) const
|
||||
{
|
||||
if (!validate_file_checksums(pData, data_size, false))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::get_file_info: validate_file_checksums failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
const basis_file_header* pHeader = static_cast<const basis_file_header*>(pData);
|
||||
const basis_slice_desc* pSlice_descs = reinterpret_cast<const basis_slice_desc*>(static_cast<const uint8_t*>(pData) + pHeader->m_slice_desc_file_ofs);
|
||||
@@ -3999,10 +4195,19 @@ namespace basist
|
||||
return true;
|
||||
}
|
||||
|
||||
bool basisu_transcoder::start_decoding(const void *pData, uint32_t data_size) const
|
||||
bool basisu_transcoder::start_transcoding(const void *pData, uint32_t data_size) const
|
||||
{
|
||||
if (!validate_header(pData, data_size))
|
||||
if (m_lowlevel_decoder.m_endpoints.size())
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: already called start_transcoding\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!validate_header_quick(pData, data_size))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: header validation failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
const basis_file_header *pHeader = reinterpret_cast<const basis_file_header*>(pData);
|
||||
|
||||
@@ -4012,11 +4217,13 @@ namespace basist
|
||||
pHeader->m_total_endpoints, pDataU8 + pHeader->m_endpoint_cb_file_ofs, pHeader->m_endpoint_cb_file_size,
|
||||
pHeader->m_total_selectors, pDataU8 + pHeader->m_selector_cb_file_ofs, pHeader->m_selector_cb_file_size))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: decode_palettes failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_lowlevel_decoder.decode_tables(pDataU8 + pHeader->m_tables_file_ofs, pHeader->m_tables_file_size))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: decode_tables failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -4026,27 +4233,43 @@ namespace basist
|
||||
bool basisu_transcoder::transcode_slice(const void *pData, uint32_t data_size, uint32_t slice_index, void *pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks, block_format fmt,
|
||||
uint32_t output_stride, uint32_t decode_flags) const
|
||||
{
|
||||
if (!m_lowlevel_decoder.m_endpoints.size())
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: must call start_transcoding first\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (decode_flags & cDecodeFlagsPVRTCDecodeToNextPow2)
|
||||
{
|
||||
// TODO: Not yet supported
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: cDecodeFlagsPVRTCDecodeToNextPow2 currently unsupported\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!validate_header(pData, data_size))
|
||||
|
||||
if (!validate_header_quick(pData, data_size))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: header validation failed\n");
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
const basis_file_header *pHeader = reinterpret_cast<const basis_file_header *>(pData);
|
||||
|
||||
const uint8_t *pDataU8 = static_cast<const uint8_t* >(pData);
|
||||
|
||||
if (slice_index >= pHeader->m_total_slices)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: slice_index >= pHeader->m_total_slices\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
const basis_slice_desc &slice_desc = reinterpret_cast<const basis_slice_desc *>(pDataU8 + pHeader->m_slice_desc_file_ofs)[slice_index];
|
||||
|
||||
uint32_t total_blocks = slice_desc.m_num_blocks_x * slice_desc.m_num_blocks_y;
|
||||
if (output_blocks_buf_size_in_blocks < total_blocks)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: output_blocks_buf_size_in_blocks < total_blocks\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fmt != cETC1)
|
||||
{
|
||||
@@ -4055,11 +4278,12 @@ namespace basist
|
||||
if ((!basisu::is_pow2(slice_desc.m_num_blocks_x * 4)) || (!basisu::is_pow2(slice_desc.m_num_blocks_y * 4)))
|
||||
{
|
||||
// PVRTC1 only supports power of 2 dimensions
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: PVRTC1 only supports power of 2 dimensions\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return m_lowlevel_decoder.transcode_slice(pOutput_blocks, slice_desc.m_num_blocks_x, slice_desc.m_num_blocks_y,
|
||||
pDataU8 + slice_desc.m_file_ofs, slice_desc.m_file_size,
|
||||
fmt, output_stride, (decode_flags & cDecodeFlagsPVRTCWrapAddressing) != 0, (decode_flags & cDecodeFlagsBC1ForbidThreeColorBlocks) == 0);
|
||||
@@ -4080,14 +4304,19 @@ namespace basist
|
||||
if ((slice_desc.m_image_index == image_index) && (slice_desc.m_level_index == level_index))
|
||||
return slice_iter;
|
||||
}
|
||||
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::find_first_slice_index: didn't find slice\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int basisu_transcoder::find_slice(const void *pData, uint32_t data_size, uint32_t image_index, uint32_t level_index, bool alpha_data) const
|
||||
{
|
||||
if (!validate_header(pData, data_size))
|
||||
if (!validate_header_quick(pData, data_size))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::find_slice: header validation failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
const basis_file_header *pHeader = reinterpret_cast<const basis_file_header*>(pData);
|
||||
const uint8_t *pDataU8 = static_cast<const uint8_t*>(pData);
|
||||
@@ -4105,6 +4334,8 @@ namespace basist
|
||||
return slice_iter;
|
||||
}
|
||||
}
|
||||
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::find_slice: didn't find slice\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -4155,16 +4386,28 @@ namespace basist
|
||||
transcoder_texture_format fmt,
|
||||
uint32_t decode_flags) const
|
||||
{
|
||||
|
||||
|
||||
if (!m_lowlevel_decoder.m_endpoints.size())
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: must call start_transcoding() first\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool transcode_alpha_data_to_opaque_formats = (decode_flags & cDecodeFlagsTranscodeAlphaDataToOpaqueFormats) != 0;
|
||||
|
||||
if (decode_flags & cDecodeFlagsPVRTCDecodeToNextPow2)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: cDecodeFlagsPVRTCDecodeToNextPow2 currently unsupported\n");
|
||||
// TODO: Not yet supported
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!validate_header(pData, data_size))
|
||||
if (!validate_header_quick(pData, data_size))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: header validation failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
const basis_file_header *pHeader = reinterpret_cast<const basis_file_header*>(pData);
|
||||
|
||||
@@ -4177,6 +4420,7 @@ namespace basist
|
||||
int slice_index = find_first_slice_index(pData, data_size, image_index, level_index);
|
||||
if (slice_index < 0)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: failed finding slice index\n");
|
||||
// Unable to find the requested image/level
|
||||
return false;
|
||||
}
|
||||
@@ -4195,6 +4439,8 @@ namespace basist
|
||||
|
||||
if (pSlice_descs[slice_index].m_flags & cSliceDescFlagsIsAlphaData)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: alpha basis file has out of order alpha slice\n");
|
||||
|
||||
// The first slice shouldn't have alpha data in a properly formed basis file
|
||||
return false;
|
||||
}
|
||||
@@ -4204,6 +4450,7 @@ namespace basist
|
||||
// The alpha data should immediately follow the color data, and have the same resolution.
|
||||
if ((slice_index + 1U) >= pHeader->m_total_slices)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: alpha basis file has missing alpha slice\n");
|
||||
// basis file is missing the alpha slice
|
||||
return false;
|
||||
}
|
||||
@@ -4211,12 +4458,14 @@ namespace basist
|
||||
// Basic sanity checks
|
||||
if ((pSlice_descs[slice_index + 1].m_flags & cSliceDescFlagsIsAlphaData) == 0)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: alpha basis file has missing alpha slice (flag check)\n");
|
||||
// This slice should have alpha data
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((pSlice_descs[slice_index].m_num_blocks_x != pSlice_descs[slice_index + 1].m_num_blocks_x) || (pSlice_descs[slice_index].m_num_blocks_y != pSlice_descs[slice_index + 1].m_num_blocks_y))
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: alpha basis file slice dimensions bad\n");
|
||||
// Alpha slice should have been the same res as the color slice
|
||||
return false;
|
||||
}
|
||||
@@ -4238,7 +4487,7 @@ namespace basist
|
||||
bool status = false;
|
||||
|
||||
const uint32_t total_slice_blocks = pSlice_descs[slice_index].m_num_blocks_x * pSlice_descs[slice_index].m_num_blocks_y;
|
||||
|
||||
|
||||
switch (fmt)
|
||||
{
|
||||
case cTFETC1:
|
||||
@@ -4251,6 +4500,10 @@ namespace basist
|
||||
slice_index_to_decode++;
|
||||
|
||||
status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks, cETC1, bytes_per_block, decode_flags);
|
||||
if (!status)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to ETC1 failed\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case cTFBC1:
|
||||
@@ -4266,6 +4519,10 @@ namespace basist
|
||||
slice_index_to_decode++;
|
||||
|
||||
status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks, cBC1, bytes_per_block, decode_flags);
|
||||
if (!status)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to BC1 failed\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case cTFBC4:
|
||||
@@ -4281,6 +4538,10 @@ namespace basist
|
||||
slice_index_to_decode++;
|
||||
|
||||
status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks, cBC4, bytes_per_block, decode_flags);
|
||||
if (!status)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to BC4 failed\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case cTFPVRTC1_4_OPAQUE_ONLY:
|
||||
@@ -4296,6 +4557,10 @@ namespace basist
|
||||
slice_index_to_decode++;
|
||||
|
||||
status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks, cPVRTC1_4_OPAQUE_ONLY, bytes_per_block, decode_flags);
|
||||
if (!status)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to PVRTC1 4 opaque only failed\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case cTFBC7_M6_OPAQUE_ONLY:
|
||||
@@ -4311,6 +4576,10 @@ namespace basist
|
||||
slice_index_to_decode++;
|
||||
|
||||
status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks, cBC7_M6_OPAQUE_ONLY, bytes_per_block, decode_flags);
|
||||
if (!status)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to BC7 m6 opaque only failed\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case cTFETC2:
|
||||
@@ -4335,6 +4604,14 @@ namespace basist
|
||||
{
|
||||
// Now decode the color data
|
||||
status = transcode_slice(pData, data_size, slice_index, (uint8_t*)pOutput_blocks + 8, output_blocks_buf_size_in_blocks, cETC1, 16, decode_flags);
|
||||
if (!status)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to ETC2 RGB failed\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to ETC2 A failed\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -4342,8 +4619,12 @@ namespace basist
|
||||
{
|
||||
#if !BASISD_SUPPORT_DXT1
|
||||
return false;
|
||||
#endif
|
||||
#if !BASISD_SUPPORT_DXT5A
|
||||
return false;
|
||||
#endif
|
||||
assert(total_slices == 2);
|
||||
|
||||
// First decode the alpha data
|
||||
if (basis_file_has_alpha_slices)
|
||||
{
|
||||
@@ -4359,7 +4640,16 @@ namespace basist
|
||||
{
|
||||
// Now decode the color data. Forbid 3 color blocks, which aren't allowed in BC3.
|
||||
status = transcode_slice(pData, data_size, slice_index, (uint8_t*)pOutput_blocks + 8, output_blocks_buf_size_in_blocks, cBC1, 16, decode_flags | cDecodeFlagsBC1ForbidThreeColorBlocks);
|
||||
if (!status)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to BC3 RGB failed\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to BC3 A failed\n");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case cTFBC5:
|
||||
@@ -4376,6 +4666,10 @@ namespace basist
|
||||
{
|
||||
// Decode the G data (actually the green channel of the alpha data slice in the basis file)
|
||||
status = transcode_slice(pData, data_size, slice_index + 1, (uint8_t*)pOutput_blocks + 8, output_blocks_buf_size_in_blocks, cBC4, 16, decode_flags);
|
||||
if (!status)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to BC5 1 failed\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4383,11 +4677,16 @@ namespace basist
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: transcode_slice() to BC5 channel 0 failed\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
assert(0);
|
||||
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: Invalid fmt\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -4411,6 +4710,7 @@ namespace basist
|
||||
return 16;
|
||||
default:
|
||||
assert(0);
|
||||
BASISU_DEVEL_ERROR("basis_get_basisu_texture_format: Invalid fmt\n");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
@@ -4430,6 +4730,7 @@ namespace basist
|
||||
case cTFBC5: return "BC5";
|
||||
default:
|
||||
assert(0);
|
||||
BASISU_DEVEL_ERROR("basis_get_basisu_texture_format: Invalid fmt\n");
|
||||
break;
|
||||
}
|
||||
return "";
|
||||
@@ -4462,6 +4763,7 @@ namespace basist
|
||||
case cTFBC5: return basisu::cBC5;
|
||||
default:
|
||||
assert(0);
|
||||
BASISU_DEVEL_ERROR("basis_get_basisu_texture_format: Invalid fmt\n");
|
||||
break;
|
||||
}
|
||||
return basisu::cInvalidTextureFormat;
|
||||
|
||||
Reference in New Issue
Block a user