[Mesa-dev] [PATCH v2 1/4] mesa: add header for share bptc decompress functions

Denis Pauk pauk.denis at gmail.com
Sat Jun 23 13:19:25 UTC 2018


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.denis at gmail.com>
CC: Marek Olšák <maraeo at 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



More information about the mesa-dev mailing list