Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (C) 2011 LunarG, Inc.
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21.  * DEALINGS IN THE SOFTWARE.
  22.  */
  23.  
  24. /*
  25.  * Included by texcompress_etc1 and gallium to define ETC1 decoding routines.
  26.  */
  27.  
  28. struct TAG(etc1_block) {
  29.    uint32_t pixel_indices;
  30.    int flipped;
  31.    const int *modifier_tables[2];
  32.    UINT8_TYPE base_colors[2][3];
  33. };
  34.  
  35. static UINT8_TYPE
  36. TAG(etc1_base_color_diff_hi)(UINT8_TYPE in)
  37. {
  38.    return (in & 0xf8) | (in >> 5);
  39. }
  40.  
  41. static UINT8_TYPE
  42. TAG(etc1_base_color_diff_lo)(UINT8_TYPE in)
  43. {
  44.    static const int lookup[8] = { 0, 1, 2, 3, -4, -3, -2, -1 };
  45.  
  46.    in = (in >> 3) + lookup[in & 0x7];
  47.  
  48.    return (in << 3) | (in >> 2);
  49. }
  50.  
  51. static UINT8_TYPE
  52. TAG(etc1_base_color_ind_hi)(UINT8_TYPE in)
  53. {
  54.    return (in & 0xf0) | ((in & 0xf0) >> 4);
  55. }
  56.  
  57. static UINT8_TYPE
  58. TAG(etc1_base_color_ind_lo)(UINT8_TYPE in)
  59. {
  60.    return ((in & 0xf) << 4) | (in & 0xf);
  61. }
  62.  
  63. static UINT8_TYPE
  64. TAG(etc1_clamp)(UINT8_TYPE base, int modifier)
  65. {
  66.    int tmp = (int) base + modifier;
  67.  
  68.    /* CLAMP(tmp, 0, 255) */
  69.    return (UINT8_TYPE) ((tmp < 0) ? 0 : ((tmp > 255) ? 255 : tmp));
  70. }
  71.  
  72. static const int TAG(etc1_modifier_tables)[8][4] = {
  73.    {  2,   8,  -2,   -8},
  74.    {  5,  17,  -5,  -17},
  75.    {  9,  29,  -9,  -29},
  76.    { 13,  42, -13,  -42},
  77.    { 18,  60, -18,  -60},
  78.    { 24,  80, -24,  -80},
  79.    { 33, 106, -33, -106},
  80.    { 47, 183, -47, -183}
  81. };
  82.  
  83. static void
  84. TAG(etc1_parse_block)(struct TAG(etc1_block) *block, const UINT8_TYPE *src)
  85. {
  86.    if (src[3] & 0x2) {
  87.       /* differential mode */
  88.       block->base_colors[0][0] = (int) TAG(etc1_base_color_diff_hi)(src[0]);
  89.       block->base_colors[1][0] = (int) TAG(etc1_base_color_diff_lo)(src[0]);
  90.       block->base_colors[0][1] = (int) TAG(etc1_base_color_diff_hi)(src[1]);
  91.       block->base_colors[1][1] = (int) TAG(etc1_base_color_diff_lo)(src[1]);
  92.       block->base_colors[0][2] = (int) TAG(etc1_base_color_diff_hi)(src[2]);
  93.       block->base_colors[1][2] = (int) TAG(etc1_base_color_diff_lo)(src[2]);
  94.    }
  95.    else {
  96.       /* individual mode */
  97.       block->base_colors[0][0] = (int) TAG(etc1_base_color_ind_hi)(src[0]);
  98.       block->base_colors[1][0] = (int) TAG(etc1_base_color_ind_lo)(src[0]);
  99.       block->base_colors[0][1] = (int) TAG(etc1_base_color_ind_hi)(src[1]);
  100.       block->base_colors[1][1] = (int) TAG(etc1_base_color_ind_lo)(src[1]);
  101.       block->base_colors[0][2] = (int) TAG(etc1_base_color_ind_hi)(src[2]);
  102.       block->base_colors[1][2] = (int) TAG(etc1_base_color_ind_lo)(src[2]);
  103.    }
  104.  
  105.    /* pick modifier tables */
  106.    block->modifier_tables[0] = TAG(etc1_modifier_tables)[(src[3] >> 5) & 0x7];
  107.    block->modifier_tables[1] = TAG(etc1_modifier_tables)[(src[3] >> 2) & 0x7];
  108.  
  109.    block->flipped = (src[3] & 0x1);
  110.  
  111.    block->pixel_indices =
  112.       (src[4] << 24) | (src[5] << 16) | (src[6] << 8) | src[7];
  113. }
  114.  
  115. static void
  116. TAG(etc1_fetch_texel)(const struct TAG(etc1_block) *block,
  117.       int x, int y, UINT8_TYPE *dst)
  118. {
  119.    const UINT8_TYPE *base_color;
  120.    int modifier, bit, idx, blk;
  121.  
  122.    /* get pixel index */
  123.    bit = y + x * 4;
  124.    idx = ((block->pixel_indices >> (15 + bit)) & 0x2) |
  125.          ((block->pixel_indices >>      (bit)) & 0x1);
  126.  
  127.    /* get subblock */
  128.    blk = (block->flipped) ? (y >= 2) : (x >= 2);
  129.  
  130.    base_color = block->base_colors[blk];
  131.    modifier = block->modifier_tables[blk][idx];
  132.  
  133.    dst[0] = TAG(etc1_clamp)(base_color[0], modifier);
  134.    dst[1] = TAG(etc1_clamp)(base_color[1], modifier);
  135.    dst[2] = TAG(etc1_clamp)(base_color[2], modifier);
  136. }
  137.  
  138. static void
  139. etc1_unpack_rgba8888(uint8_t *dst_row,
  140.                      unsigned dst_stride,
  141.                      const uint8_t *src_row,
  142.                      unsigned src_stride,
  143.                      unsigned width,
  144.                      unsigned height)
  145. {
  146.    const unsigned bw = 4, bh = 4, bs = 8, comps = 4;
  147.    struct etc1_block block;
  148.    unsigned x, y, i, j;
  149.  
  150.    for (y = 0; y < height; y += bh) {
  151.       const uint8_t *src = src_row;
  152.  
  153.       for (x = 0; x < width; x+= bw) {
  154.          etc1_parse_block(&block, src);
  155.  
  156.          for (j = 0; j < MIN2(bh, height - y); j++) {
  157.             uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
  158.             for (i = 0; i < MIN2(bw, width - x); i++) {
  159.                etc1_fetch_texel(&block, i, j, dst);
  160.                dst[3] = 255;
  161.                dst += comps;
  162.             }
  163.          }
  164.  
  165.          src += bs;
  166.       }
  167.  
  168.       src_row += src_stride;
  169.    }
  170. }
  171.