⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 texcompress_fxt1.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 4 页
字号:
   for (j = 2 * 2 - 1; j >= 0; j--) {
      for (i = 0; i < n_comp; i++) {
         /* add in colors */
         FX64_SHL(hi, 5);
         FX64_OR32(hi, vec[j][i] >> 3);
      }
   }
   ((Fx64 *)cc)[1] = hi;
}


static void
fxt1_quantize (GLuint *cc, const GLubyte *lines[], GLint comps)
{
   GLint trualpha;
   GLubyte reord[N_TEXELS][MAX_COMP];

   GLubyte input[N_TEXELS][MAX_COMP];
   GLint i, k, l;

   if (comps == 3) {
      /* make the whole block opaque */
      memset(input, -1, sizeof(input));
   }

   /* 8 texels each line */
   for (l = 0; l < 4; l++) {
      for (k = 0; k < 4; k++) {
         for (i = 0; i < comps; i++) {
            input[k + l * 4][i] = *lines[l]++;
         }
      }
      for (; k < 8; k++) {
         for (i = 0; i < comps; i++) {
            input[k + l * 4 + 12][i] = *lines[l]++;
         }
      }
   }

   /* block layout:
    * 00, 01, 02, 03, 08, 09, 0a, 0b
    * 10, 11, 12, 13, 18, 19, 1a, 1b
    * 04, 05, 06, 07, 0c, 0d, 0e, 0f
    * 14, 15, 16, 17, 1c, 1d, 1e, 1f
    */

   /* [dBorca]
    * stupidity flows forth from this
    */
   l = N_TEXELS;
   trualpha = 0;
   if (comps == 4) {
      /* skip all transparent black texels */
      l = 0;
      for (k = 0; k < N_TEXELS; k++) {
         /* test all components against 0 */
         if (!ISTBLACK(input[k])) {
            /* texel is not transparent black */
            COPY_4UBV(reord[l], input[k]);
            if (reord[l][ACOMP] < (255 - ALPHA_TS)) {
               /* non-opaque texel */
               trualpha = !0;
            }
            l++;
         }
      }
   }

#if 0
   if (trualpha) {
      fxt1_quantize_ALPHA0(cc, input, reord, l);
   } else if (l == 0) {
      cc[0] = cc[1] = cc[2] = -1;
      cc[3] = 0;
   } else if (l < N_TEXELS) {
      fxt1_quantize_HI(cc, input, reord, l);
   } else {
      fxt1_quantize_CHROMA(cc, input);
   }
   (void)fxt1_quantize_ALPHA1;
   (void)fxt1_quantize_MIXED1;
   (void)fxt1_quantize_MIXED0;
#else
   if (trualpha) {
      fxt1_quantize_ALPHA1(cc, input);
   } else if (l == 0) {
      cc[0] = cc[1] = cc[2] = ~0u;
      cc[3] = 0;
   } else if (l < N_TEXELS) {
      fxt1_quantize_MIXED1(cc, input);
   } else {
      fxt1_quantize_MIXED0(cc, input);
   }
   (void)fxt1_quantize_ALPHA0;
   (void)fxt1_quantize_HI;
   (void)fxt1_quantize_CHROMA;
#endif
}


static GLint
fxt1_encode (GLuint width, GLuint height, GLint comps,
             const void *source, GLint srcRowStride,
             void *dest, GLint destRowStride)
{
   GLuint x, y;
   const GLubyte *data;
   GLuint *encoded = (GLuint *)dest;
   GLubyte *newSource = NULL;

   /* Replicate image if width is not M8 or height is not M4 */
   if ((width & 7) | (height & 3)) {
      GLint newWidth = (width + 7) & ~7;
      GLint newHeight = (height + 3) & ~3;
      newSource = (GLubyte *)
         _mesa_malloc(comps * newWidth * newHeight * sizeof(GLubyte *));
      _mesa_upscale_teximage2d(width, height, newWidth, newHeight,
                               comps, (const GLchan *) source,
                               srcRowStride, newSource);
      source = newSource;
      width = newWidth;
      height = newHeight;
      srcRowStride = comps * newWidth;
   }

   data = (const GLubyte *) source;
   destRowStride = (destRowStride - width * 2) / 4;
   for (y = 0; y < height; y += 4) {
      GLuint offs = 0 + (y + 0) * srcRowStride;
      for (x = 0; x < width; x += 8) {
         const GLubyte *lines[4];
         lines[0] = &data[offs];
         lines[1] = lines[0] + srcRowStride;
         lines[2] = lines[1] + srcRowStride;
         lines[3] = lines[2] + srcRowStride;
         offs += 8 * comps;
         fxt1_quantize(encoded, lines, comps);
         /* 128 bits per 8x4 block */
         encoded += 4;
      }
      encoded += destRowStride;
   }

   if (newSource != NULL) {
      _mesa_free(newSource);
   }

   return 0;
}


/***************************************************************************\
 * FXT1 decoder
 *
 * The decoder is based on GL_3DFX_texture_compression_FXT1
 * specification and serves as a concept for the encoder.
\***************************************************************************/


/* lookup table for scaling 5 bit colors up to 8 bits */
static const GLubyte _rgb_scale_5[] = {
   0,   8,   16,  25,  33,  41,  49,  58,
   66,  74,  82,  90,  99,  107, 115, 123,
   132, 140, 148, 156, 165, 173, 181, 189,
   197, 206, 214, 222, 230, 239, 247, 255
};

/* lookup table for scaling 6 bit colors up to 8 bits */
static const GLubyte _rgb_scale_6[] = {
   0,   4,   8,   12,  16,  20,  24,  28,
   32,  36,  40,  45,  49,  53,  57,  61,
   65,  69,  73,  77,  81,  85,  89,  93,
   97,  101, 105, 109, 113, 117, 121, 125,
   130, 134, 138, 142, 146, 150, 154, 158,
   162, 166, 170, 174, 178, 182, 186, 190,
   194, 198, 202, 206, 210, 215, 219, 223,
   227, 231, 235, 239, 243, 247, 251, 255
};


#define CC_SEL(cc, which) (((GLuint *)(cc))[(which) / 32] >> ((which) & 31))
#define UP5(c) _rgb_scale_5[(c) & 31]
#define UP6(c, b) _rgb_scale_6[(((c) & 31) << 1) | ((b) & 1)]
#define LERP(n, t, c0, c1) (((n) - (t)) * (c0) + (t) * (c1) + (n) / 2) / (n)
#define ZERO_4UBV(v) *((GLuint *)(v)) = 0


static void
fxt1_decode_1HI (const GLubyte *code, GLint t, GLubyte *rgba)
{
   const GLuint *cc;

   t *= 3;
   cc = (const GLuint *)(code + t / 8);
   t = (cc[0] >> (t & 7)) & 7;

   if (t == 7) {
      ZERO_4UBV(rgba);
   } else {
      cc = (const GLuint *)(code + 12);
      if (t == 0) {
         rgba[BCOMP] = UP5(CC_SEL(cc, 0));
         rgba[GCOMP] = UP5(CC_SEL(cc, 5));
         rgba[RCOMP] = UP5(CC_SEL(cc, 10));
      } else if (t == 6) {
         rgba[BCOMP] = UP5(CC_SEL(cc, 15));
         rgba[GCOMP] = UP5(CC_SEL(cc, 20));
         rgba[RCOMP] = UP5(CC_SEL(cc, 25));
      } else {
         rgba[BCOMP] = LERP(6, t, UP5(CC_SEL(cc, 0)), UP5(CC_SEL(cc, 15)));
         rgba[GCOMP] = LERP(6, t, UP5(CC_SEL(cc, 5)), UP5(CC_SEL(cc, 20)));
         rgba[RCOMP] = LERP(6, t, UP5(CC_SEL(cc, 10)), UP5(CC_SEL(cc, 25)));
      }
      rgba[ACOMP] = 255;
   }
}


static void
fxt1_decode_1CHROMA (const GLubyte *code, GLint t, GLubyte *rgba)
{
   const GLuint *cc;
   GLuint kk;

   cc = (const GLuint *)code;
   if (t & 16) {
      cc++;
      t &= 15;
   }
   t = (cc[0] >> (t * 2)) & 3;

   t *= 15;
   cc = (const GLuint *)(code + 8 + t / 8);
   kk = cc[0] >> (t & 7);
   rgba[BCOMP] = UP5(kk);
   rgba[GCOMP] = UP5(kk >> 5);
   rgba[RCOMP] = UP5(kk >> 10);
   rgba[ACOMP] = 255;
}


static void
fxt1_decode_1MIXED (const GLubyte *code, GLint t, GLubyte *rgba)
{
   const GLuint *cc;
   GLuint col[2][3];
   GLint glsb, selb;

   cc = (const GLuint *)code;
   if (t & 16) {
      t &= 15;
      t = (cc[1] >> (t * 2)) & 3;
      /* col 2 */
      col[0][BCOMP] = (*(const GLuint *)(code + 11)) >> 6;
      col[0][GCOMP] = CC_SEL(cc, 99);
      col[0][RCOMP] = CC_SEL(cc, 104);
      /* col 3 */
      col[1][BCOMP] = CC_SEL(cc, 109);
      col[1][GCOMP] = CC_SEL(cc, 114);
      col[1][RCOMP] = CC_SEL(cc, 119);
      glsb = CC_SEL(cc, 126);
      selb = CC_SEL(cc, 33);
   } else {
      t = (cc[0] >> (t * 2)) & 3;
      /* col 0 */
      col[0][BCOMP] = CC_SEL(cc, 64);
      col[0][GCOMP] = CC_SEL(cc, 69);
      col[0][RCOMP] = CC_SEL(cc, 74);
      /* col 1 */
      col[1][BCOMP] = CC_SEL(cc, 79);
      col[1][GCOMP] = CC_SEL(cc, 84);
      col[1][RCOMP] = CC_SEL(cc, 89);
      glsb = CC_SEL(cc, 125);
      selb = CC_SEL(cc, 1);
   }

   if (CC_SEL(cc, 124) & 1) {
      /* alpha[0] == 1 */

      if (t == 3) {
         ZERO_4UBV(rgba);
      } else {
         if (t == 0) {
            rgba[BCOMP] = UP5(col[0][BCOMP]);
            rgba[GCOMP] = UP5(col[0][GCOMP]);
            rgba[RCOMP] = UP5(col[0][RCOMP]);
         } else if (t == 2) {
            rgba[BCOMP] = UP5(col[1][BCOMP]);
            rgba[GCOMP] = UP6(col[1][GCOMP], glsb);
            rgba[RCOMP] = UP5(col[1][RCOMP]);
         } else {
            rgba[BCOMP] = (UP5(col[0][BCOMP]) + UP5(col[1][BCOMP])) / 2;
            rgba[GCOMP] = (UP5(col[0][GCOMP]) + UP6(col[1][GCOMP], glsb)) / 2;
            rgba[RCOMP] = (UP5(col[0][RCOMP]) + UP5(col[1][RCOMP])) / 2;
         }
         rgba[ACOMP] = 255;
      }
   } else {
      /* alpha[0] == 0 */

      if (t == 0) {
         rgba[BCOMP] = UP5(col[0][BCOMP]);
         rgba[GCOMP] = UP6(col[0][GCOMP], glsb ^ selb);
         rgba[RCOMP] = UP5(col[0][RCOMP]);
      } else if (t == 3) {
         rgba[BCOMP] = UP5(col[1][BCOMP]);
         rgba[GCOMP] = UP6(col[1][GCOMP], glsb);
         rgba[RCOMP] = UP5(col[1][RCOMP]);
      } else {
         rgba[BCOMP] = LERP(3, t, UP5(col[0][BCOMP]), UP5(col[1][BCOMP]));
         rgba[GCOMP] = LERP(3, t, UP6(col[0][GCOMP], glsb ^ selb),
                                  UP6(col[1][GCOMP], glsb));
         rgba[RCOMP] = LERP(3, t, UP5(col[0][RCOMP]), UP5(col[1][RCOMP]));
      }
      rgba[ACOMP] = 255;
   }
}


static void
fxt1_decode_1ALPHA (const GLubyte *code, GLint t, GLubyte *rgba)
{
   const GLuint *cc;

   cc = (const GLuint *)code;
   if (CC_SEL(cc, 124) & 1) {
      /* lerp == 1 */
      GLuint col0[4];

      if (t & 16) {
         t &= 15;
         t = (cc[1] >> (t * 2)) & 3;
         /* col 2 */
         col0[BCOMP] = (*(const GLuint *)(code + 11)) >> 6;
         col0[GCOMP] = CC_SEL(cc, 99);
         col0[RCOMP] = CC_SEL(cc, 104);
         col0[ACOMP] = CC_SEL(cc, 119);
      } else {
         t = (cc[0] >> (t * 2)) & 3;
         /* col 0 */
         col0[BCOMP] = CC_SEL(cc, 64);
         col0[GCOMP] = CC_SEL(cc, 69);
         col0[RCOMP] = CC_SEL(cc, 74);
         col0[ACOMP] = CC_SEL(cc, 109);
      }

      if (t == 0) {
         rgba[BCOMP] = UP5(col0[BCOMP]);
         rgba[GCOMP] = UP5(col0[GCOMP]);
         rgba[RCOMP] = UP5(col0[RCOMP]);
         rgba[ACOMP] = UP5(col0[ACOMP]);
      } else if (t == 3) {
         rgba[BCOMP] = UP5(CC_SEL(cc, 79));
         rgba[GCOMP] = UP5(CC_SEL(cc, 84));
         rgba[RCOMP] = UP5(CC_SEL(cc, 89));
         rgba[ACOMP] = UP5(CC_SEL(cc, 114));
      } else {
         rgba[BCOMP] = LERP(3, t, UP5(col0[BCOMP]), UP5(CC_SEL(cc, 79)));
         rgba[GCOMP] = LERP(3, t, UP5(col0[GCOMP]), UP5(CC_SEL(cc, 84)));
         rgba[RCOMP] = LERP(3, t, UP5(col0[RCOMP]), UP5(CC_SEL(cc, 89)));
         rgba[ACOMP] = LERP(3, t, UP5(col0[ACOMP]), UP5(CC_SEL(cc, 114)));
      }
   } else {
      /* lerp == 0 */

      if (t & 16) {
         cc++;
         t &= 15;
      }
      t = (cc[0] >> (t * 2)) & 3;

      if (t == 3) {
         ZERO_4UBV(rgba);
      } else {
         GLuint kk;
         cc = (const GLuint *)code;
         rgba[ACOMP] = UP5(cc[3] >> (t * 5 + 13));
         t *= 15;
         cc = (const GLuint *)(code + 8 + t / 8);
         kk = cc[0] >> (t & 7);
         rgba[BCOMP] = UP5(kk);
         rgba[GCOMP] = UP5(kk >> 5);
         rgba[RCOMP] = UP5(kk >> 10);
      }
   }
}


void
fxt1_decode_1 (const void *texture, GLint stride, /* in pixels */
               GLint i, GLint j, GLubyte *rgba)
{
   static void (*decode_1[]) (const GLubyte *, GLint, GLubyte *) = {
      fxt1_decode_1HI,     /* cc-high   = "00?" */
      fxt1_decode_1HI,     /* cc-high   = "00?" */
      fxt1_decode_1CHROMA, /* cc-chroma = "010" */
      fxt1_decode_1ALPHA,  /* alpha     = "011" */
      fxt1_decode_1MIXED,  /* mixed     = "1??" */
      fxt1_decode_1MIXED,  /* mixed     = "1??" */
      fxt1_decode_1MIXED,  /* mixed     = "1??" */
      fxt1_decode_1MIXED   /* mixed     = "1??" */
   };

   const GLubyte *code = (const GLubyte *)texture +
                         ((j / 4) * (stride / 8) + (i / 8)) * 16;
   GLint mode = CC_SEL(code, 125);
   GLint t = i & 7;

   if (t & 4) {
      t += 12;
   }
   t += (j & 3) * 4;

   decode_1[mode](code, t, rgba);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -