Make functions public: * fetch_rgba_unorm_from_block * fetch_rgb_float_from_block * compress_rgba_unorm * compress_rgb_float
Create decompress functions: * decompress_rgba_unorm * decompress_rgb_float Functions will be reused in gallium/auxiliary code. v2: Add block decompress function Signed-off-by: Denis Pauk <pauk.de...@gmail.com> CC: Marek Olšák <mar...@gmail.com> --- src/mesa/Makefile.sources | 1 + src/mesa/main/texcompress_bptc.c | 303 ++++++++++++++++++++++++- src/mesa/main/texcompress_bptc_share.h | 58 +++++ 3 files changed, 358 insertions(+), 4 deletions(-) create mode 100644 src/mesa/main/texcompress_bptc_share.h diff --git a/src/mesa/Makefile.sources b/src/mesa/Makefile.sources index 00aba0a2f7..d644112e6a 100644 --- a/src/mesa/Makefile.sources +++ b/src/mesa/Makefile.sources @@ -216,6 +216,7 @@ MAIN_FILES = \ main/texcompress.c \ main/texcompress_bptc.c \ main/texcompress_bptc.h \ + main/texcompress_bptc_share.h \ main/texcompress_cpal.c \ main/texcompress_cpal.h \ main/texcompress_etc.c \ diff --git a/src/mesa/main/texcompress_bptc.c b/src/mesa/main/texcompress_bptc.c index fd37be97f3..74828d63db 100644 --- a/src/mesa/main/texcompress_bptc.c +++ b/src/mesa/main/texcompress_bptc.c @@ -29,6 +29,7 @@ #include <stdbool.h> #include "texcompress.h" #include "texcompress_bptc.h" +#include "texcompress_bptc_share.h" #include "util/format_srgb.h" #include "util/half_float.h" #include "texstore.h" @@ -535,7 +536,7 @@ apply_rotation(int rotation, result[3] = t; } -static void +void fetch_rgba_unorm_from_block(const uint8_t *block, uint8_t *result, int texel) @@ -657,6 +658,173 @@ fetch_rgba_unorm_from_block(const uint8_t *block, apply_rotation(rotation, result); } +static void +decompress_rgba_unorm_block(int src_width, int src_height, + const uint8_t *block, + uint8_t *dst_row, int dst_rowstride) +{ + int mode_num = ffs(block[0]); + const struct bptc_unorm_mode *mode; + int bit_offset, secondary_bit_offset; + int partition_num; + int subset_num; + int rotation; + int index_selection; + int index_bits; + int indices[2]; + int index; + int anchors_before_texel; + bool anchor; + uint8_t endpoints[3 * 2][4]; + uint32_t subsets; + int component; + unsigned x, y; + + if (mode_num == 0) { + /* According to the spec this mode is reserved and shouldn't be used. */ + for(y = 0; y < src_height; y += 1) { + uint8_t *result = dst_row; + memset(result, 0, 4 * src_width); + for(x = 0; x < src_width; x += 1) { + result[3] = 0xff; + result += 4; + } + dst_row += dst_rowstride; + } + return; + } + + mode = bptc_unorm_modes + mode_num - 1; + bit_offset = mode_num; + + partition_num = extract_bits(block, bit_offset, mode->n_partition_bits); + bit_offset += mode->n_partition_bits; + + switch (mode->n_subsets) { + case 1: + subsets = 0; + break; + case 2: + subsets = partition_table1[partition_num]; + break; + case 3: + subsets = partition_table2[partition_num]; + break; + default: + assert(false); + return; + } + + if (mode->has_rotation_bits) { + rotation = extract_bits(block, bit_offset, 2); + bit_offset += 2; + } else { + rotation = 0; + } + + if (mode->has_index_selection_bit) { + index_selection = extract_bits(block, bit_offset, 1); + bit_offset++; + } else { + index_selection = 0; + } + + bit_offset = extract_unorm_endpoints(mode, block, bit_offset, endpoints); + + for(y = 0; y < src_height; y += 1) { + uint8_t *result = dst_row; + for(x = 0; x < src_width; x += 1) { + int texel; + texel = x + y * 4; + + anchors_before_texel = count_anchors_before_texel(mode->n_subsets, + partition_num, + texel); + + /* Calculate the offset to the secondary index */ + secondary_bit_offset = (bit_offset + + BLOCK_SIZE * BLOCK_SIZE * mode->n_index_bits - + mode->n_subsets + + mode->n_secondary_index_bits * texel - + anchors_before_texel); + + /* Calculate the offset to the primary index for this texel */ + bit_offset += mode->n_index_bits * texel - anchors_before_texel; + + subset_num = (subsets >> (texel * 2)) & 3; + + anchor = is_anchor(mode->n_subsets, partition_num, texel); + + index_bits = mode->n_index_bits; + if (anchor) + index_bits--; + indices[0] = extract_bits(block, bit_offset, index_bits); + + if (mode->n_secondary_index_bits) { + index_bits = mode->n_secondary_index_bits; + if (anchor) + index_bits--; + indices[1] = extract_bits(block, secondary_bit_offset, index_bits); + } + + index = indices[index_selection]; + index_bits = (index_selection ? + mode->n_secondary_index_bits : + mode->n_index_bits); + + for (component = 0; component < 3; component++) + result[component] = interpolate(endpoints[subset_num * 2][component], + endpoints[subset_num * 2 + 1][component], + index, + index_bits); + + /* Alpha uses the opposite index from the color components */ + if (mode->n_secondary_index_bits && !index_selection) { + index = indices[1]; + index_bits = mode->n_secondary_index_bits; + } else { + index = indices[0]; + index_bits = mode->n_index_bits; + } + + result[3] = interpolate(endpoints[subset_num * 2][3], + endpoints[subset_num * 2 + 1][3], + index, + index_bits); + + apply_rotation(rotation, result); + result += 4; + } + dst_row += dst_rowstride; + } +} + +void +decompress_rgba_unorm(int width, int height, + const uint8_t *src, int src_rowstride, + uint8_t *dst, int dst_rowstride) +{ + int src_row_diff; + int y, x; + + if (src_rowstride >= width * 4) + src_row_diff = src_rowstride - ((width + 3) & ~3) * 4; + else + src_row_diff = 0; + + for (y = 0; y < height; y += BLOCK_SIZE) { + for (x = 0; x < width; x += BLOCK_SIZE) { + decompress_rgba_unorm_block(MIN2(width - x, BLOCK_SIZE), + MIN2(height - y, BLOCK_SIZE), + src, + dst + x * 4 + y * dst_rowstride, + dst_rowstride); + src += BLOCK_BYTES; + } + src += src_row_diff; + } +} + static void fetch_bptc_rgba_unorm_bytes(const GLubyte *map, GLint rowStride, GLint i, GLint j, @@ -840,7 +1008,7 @@ finish_signed_unquantize(int32_t value) return value * 31 / 32; } -static void +void fetch_rgb_float_from_block(const uint8_t *block, float *result, int texel, @@ -921,6 +1089,133 @@ fetch_rgb_float_from_block(const uint8_t *block, result[3] = 1.0f; } +static void +decompress_rgb_float_block(unsigned src_width, unsigned src_height, + const uint8_t *block, + float *dst_row, unsigned dst_rowstride, + bool is_signed) +{ + int mode_num; + const struct bptc_float_mode *mode; + int bit_offset; + int partition_num; + int subset_num; + int index_bits; + int index; + int anchors_before_texel; + int32_t endpoints[2 * 2][3]; + uint32_t subsets; + int n_subsets; + int component; + int32_t value; + unsigned x, y; + + if (block[0] & 0x2) { + mode_num = (((block[0] >> 1) & 0xe) | (block[0] & 1)) + 2; + bit_offset = 5; + } else { + mode_num = block[0] & 3; + bit_offset = 2; + } + + mode = bptc_float_modes + mode_num; + + if (mode->reserved) { + for(y = 0; y < src_height; y += 1) { + float *result = dst_row; + memset(result, 0, sizeof result[0] * 4 * src_width); + for(x = 0; x < src_width; x += 1) { + result[3] = 1.0f; + result += 4; + } + dst_row += dst_rowstride / sizeof dst_row[0]; + } + return; + } + + bit_offset = extract_float_endpoints(mode, block, bit_offset, + endpoints, is_signed); + + if (mode->n_partition_bits) { + partition_num = extract_bits(block, bit_offset, mode->n_partition_bits); + bit_offset += mode->n_partition_bits; + + subsets = partition_table1[partition_num]; + n_subsets = 2; + } else { + partition_num = 0; + subsets = 0; + n_subsets = 1; + } + + for(y = 0; y < src_height; y += 1) { + float *result = dst_row; + for(x = 0; x < src_width; x += 1) { + int texel; + + texel = x + y * 4; + + anchors_before_texel = + count_anchors_before_texel(n_subsets, partition_num, texel); + + /* Calculate the offset to the primary index for this texel */ + bit_offset += mode->n_index_bits * texel - anchors_before_texel; + + subset_num = (subsets >> (texel * 2)) & 3; + + index_bits = mode->n_index_bits; + if (is_anchor(n_subsets, partition_num, texel)) + index_bits--; + index = extract_bits(block, bit_offset, index_bits); + + for (component = 0; component < 3; component++) { + value = interpolate(endpoints[subset_num * 2][component], + endpoints[subset_num * 2 + 1][component], + index, + mode->n_index_bits); + + if (is_signed) + value = finish_signed_unquantize(value); + else + value = finish_unsigned_unquantize(value); + + result[component] = _mesa_half_to_float(value); + } + + result[3] = 1.0f; + result += 4; + } + dst_row += dst_rowstride / sizeof dst_row[0]; + } +} + +void +decompress_rgb_float(int width, int height, + const uint8_t *src, int src_rowstride, + float *dst, int dst_rowstride, bool is_signed) +{ + int src_row_diff; + int y, x; + + if (src_rowstride >= width * 4) + src_row_diff = src_rowstride - ((width + 3) & ~3) * 4; + else + src_row_diff = 0; + + for (y = 0; y < height; y += BLOCK_SIZE) { + for (x = 0; x < width; x += BLOCK_SIZE) { + decompress_rgb_float_block(MIN2(width - x, BLOCK_SIZE), + MIN2(height - y, BLOCK_SIZE), + src, + (dst + x * 4 + + (y * dst_rowstride / sizeof dst[0])), + dst_rowstride, is_signed); + src += BLOCK_BYTES; + } + src += src_row_diff; + } +} + static void fetch_bptc_rgb_float(const GLubyte *map, GLint rowStride, GLint i, GLint j, @@ -1247,7 +1542,7 @@ compress_rgba_unorm_block(int src_width, int src_height, endpoints); } -static void +void compress_rgba_unorm(int width, int height, const uint8_t *src, int src_rowstride, uint8_t *dst, int dst_rowstride) @@ -1555,7 +1850,7 @@ compress_rgb_float_block(int src_width, int src_height, endpoints); } -static void +void compress_rgb_float(int width, int height, const float *src, int src_rowstride, uint8_t *dst, int dst_rowstride, diff --git a/src/mesa/main/texcompress_bptc_share.h b/src/mesa/main/texcompress_bptc_share.h new file mode 100644 index 0000000000..b62e58806f --- /dev/null +++ b/src/mesa/main/texcompress_bptc_share.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef TEXCOMPRESS_BPTC_SHARE_H +#define TEXCOMPRESS_BPTC_SHARE_H + +void +fetch_rgba_unorm_from_block(const uint8_t *block, + uint8_t *result, + int texel); +void +fetch_rgb_float_from_block(const uint8_t *block, + float *result, + int texel, + bool is_signed); + +void +compress_rgb_float(int width, int height, + const float *src, int src_rowstride, + uint8_t *dst, int dst_rowstride, + bool is_signed); + +void +compress_rgba_unorm(int width, int height, + const uint8_t *src, int src_rowstride, + uint8_t *dst, int dst_rowstride); + +void +decompress_rgba_unorm(int width, int height, + const uint8_t *src, int src_rowstride, + uint8_t *dst, int dst_rowstride); + +void +decompress_rgb_float(int width, int height, + const uint8_t *src, int src_rowstride, + float *dst, int dst_rowstride, bool is_signed); + +#endif -- 2.17.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev