OSDN Git Service

add Android.mk to build for android
[android-x86/external-s2tc.git] / s2tc_libtxc_dxtn.cpp
index a470148..077270d 100644 (file)
@@ -1,23 +1,51 @@
-#include "libtxc_dxtn.h"
+/*
+ * Copyright (C) 2011  Rudolf Polzer   All Rights Reserved.
+ *
+ * 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 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
+ * RUDOLF POLZER 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.
+ */
+#define S2TC_LICENSE_IDENTIFIER s2tc_libtxc_dxtn_license
+#include "s2tc_license.h"
+
+extern "C"
+{
+#include "txc_dxtn.h"
+};
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#include "s2tc_compressor.h"
+#include "s2tc_algorithm.h"
+#include "s2tc_common.h"
 
 void fetch_2d_texel_rgb_dxt1(GLint srcRowStride, const GLubyte *pixdata,
                             GLint i, GLint j, GLvoid *texel)
 {
        // fetches a single texel (i,j) into pixdata (RGB)
        GLubyte *t = (GLubyte *) texel;
-       const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8);
+       const GLubyte *blksrc = (pixdata + (((srcRowStride + 3) >> 2) * (j >> 2) + (i >> 2)) * 8);
        unsigned int c  = blksrc[0] + 256*blksrc[1];
        unsigned int c1 = blksrc[2] + 256*blksrc[3];
-       int b = (blksrc[4 + (j % 4)] >> (2 * (i % 4))) & 0x03;
+       int b = (blksrc[4 + (j & 3)] >> (2 * (i & 3))) & 0x03;
        switch(b)
        {
                case 0:                        break;
                case 1:  c = c1;               break;
-               case 3:  if(c1 > c) { c = 0;   break; }
+               case 3:  if(c1 >= c) { c = 0;  break; }
                default: if((i^j) & 1) c = c1; break;
        }
        t[0] = ((c >> 11) & 0x1F); t[0] = (t[0] << 3) | (t[0] >> 2);
@@ -31,15 +59,15 @@ void fetch_2d_texel_rgba_dxt1(GLint srcRowStride, const GLubyte *pixdata,
 {
        // fetches a single texel (i,j) into pixdata (RGBA)
        GLubyte *t = (GLubyte *) texel;
-       const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8);
+       const GLubyte *blksrc = (pixdata + (((srcRowStride + 3) >> 2) * (j >> 2) + (i >> 2)) * 8);
        unsigned int c  = blksrc[0] + 256*blksrc[1];
        unsigned int c1 = blksrc[2] + 256*blksrc[3];
-       int b = (blksrc[4 + (j % 4)] >> (2 * (i % 4))) & 0x03;
+       int b = (blksrc[4 + (j & 3)] >> (2 * (i & 3))) & 0x03;
        switch(b)
        {
                case 0:                        t[3] = 255; break;
                case 1:  c = c1;               t[3] = 255; break;
-               case 3:  if(c1 > c) { c = 0;   t[3] =   0; break; }
+               case 3:  if(c1 >= c) { c = 0;  t[3] =   0; break; }
                default: if((i^j) & 1) c = c1; t[3] = 255; break;
        }
        t[0] = ((c >> 11) & 0x1F); t[0] = (t[0] << 3) | (t[0] >> 2);
@@ -52,10 +80,10 @@ void fetch_2d_texel_rgba_dxt3(GLint srcRowStride, const GLubyte *pixdata,
 {
        // fetches a single texel (i,j) into pixdata (RGBA)
        GLubyte *t = (GLubyte *) texel;
-       const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 16);
+       const GLubyte *blksrc = (pixdata + (((srcRowStride + 3) >> 2) * (j >> 2) + (i >> 2)) * 16);
        unsigned int c  = blksrc[8] + 256*blksrc[9];
        unsigned int c1 = blksrc[10] + 256*blksrc[11];
-       int b = (blksrc[12 + (j % 4)] >> (2 * (i % 4))) & 0x03;
+       int b = (blksrc[12 + (j & 3)] >> (2 * (i & 3))) & 0x03;
        switch(b)
        {
                case 0:                        break;
@@ -65,7 +93,7 @@ void fetch_2d_texel_rgba_dxt3(GLint srcRowStride, const GLubyte *pixdata,
        t[0] = ((c >> 11) & 0x1F); t[0] = (t[0] << 3) | (t[0] >> 2);
        t[1] = ((c >>  5) & 0x3F); t[1] = (t[1] << 2) | (t[1] >> 4);
        t[2] = ((c      ) & 0x1F); t[2] = (t[2] << 3) | (t[2] >> 2);
-       int a = (blksrc[(j % 4) * 2 + (i % 4) / 2] >> (4 * (i % 4) % 2)) & 0x0F;
+       int a = (blksrc[(j & 3) * 2 + ((i & 3) >> 1)] >> (4 * (i & 1))) & 0x0F;
        t[3] = a | (a << 4);
 }
 
@@ -74,10 +102,10 @@ void fetch_2d_texel_rgba_dxt5(GLint srcRowStride, const GLubyte *pixdata,
 {
        // fetches a single texel (i,j) into pixdata (RGBA)
        GLubyte *t = (GLubyte *) texel;
-       const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 16);
+       const GLubyte *blksrc = (pixdata + (((srcRowStride + 3) >> 2) * (j >> 2) + (i >> 2)) * 16);
        unsigned int c  = blksrc[8] + 256*blksrc[9];
        unsigned int c1 = blksrc[10] + 256*blksrc[11];
-       int b = (blksrc[12 + (j % 4)] >> (2 * (i % 4))) & 0x03;
+       int b = (blksrc[12 + (j & 3)] >> (2 * (i & 3))) & 0x03;
        switch(b)
        {
                case 0:                        break;
@@ -90,29 +118,29 @@ void fetch_2d_texel_rgba_dxt5(GLint srcRowStride, const GLubyte *pixdata,
 
        unsigned int a  = blksrc[0];
        unsigned int a1 = blksrc[1];
-       int abit = ((j % 4) * 4 + (i % 4)) * 3;
+       int abit = ((j & 3) * 4 + (i & 3)) * 3;
        int ab = 0;
-       if(blksrc[(abit / 8) + 2] & (1 << (abit % 8)))
+       if(testbit(&blksrc[2], abit))
                ab |= 1;
        ++abit;
-       if(blksrc[(abit / 8) + 2] & (1 << (abit % 8)))
+       if(testbit(&blksrc[2], abit))
                ab |= 2;
        ++abit;
-       if(blksrc[(abit / 8) + 2] & (1 << (abit % 8)))
+       if(testbit(&blksrc[2], abit))
                ab |= 4;
        switch(ab)
        {
-               case 0:                        break;
-               case 1:  a = a1;               break;
-               case 6:  a = 0;                break;
-               case 7:  a = 255;              break;
-               default: if((i^j) & 1) a = a1; break;
+               case 0:                         break;
+               case 1:  a = a1;                break;
+               case 6:  if(a1 >= a) { a = 0;   break; }
+               case 7:  if(a1 >= a) { a = 255; break; }
+               default: if((i^j) & 1) a = a1;  break;
        }
        t[3] = a;
 }
 
 void tx_compress_dxtn(GLint srccomps, GLint width, GLint height,
-                     const GLubyte *srcPixData, GLenum destFormat,
+                     const GLubyte *srcPixData, GLenum destformat,
                      GLubyte *dest, GLint dstRowStride)
 {
        // compresses width*height pixels (RGB or RGBA depending on srccomps) at srcPixData (packed) to destformat (dest, dstRowStride)
@@ -125,29 +153,24 @@ void tx_compress_dxtn(GLint srccomps, GLint width, GLint height,
        unsigned char *srcaddr;
        DxtMode dxt;
 
-       switch (destFormat) {
-               case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
-               case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-                       dxt = DXT1;
-                       rgb565_image(rgba, srcPixData, width, height, srccomps, 0, 1);
-                       break;
-               case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
-                       dxt = DXT3;
-                       rgb565_image(rgba, srcPixData, width, height, srccomps, 0, 4);
-                       break;
-               case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
-                       dxt = DXT5;
-                       rgb565_image(rgba, srcPixData, width, height, srccomps, 0, 8);
-                       break;
-               default:
-                       free(rgba);
-                       fprintf(stderr, "libdxtn: Bad dstFormat %d in tx_compress_dxtn\n", destFormat);
-                       return;
-       }
-
        ColorDistMode cd = WAVG;
        int nrandom = -1;
-       bool refine = true;
+       RefinementMode refine = REFINE_ALWAYS;
+       DitherMode dither = DITHER_SIMPLE;
+       {
+               const char *v = getenv("S2TC_DITHER_MODE");
+               if(v)
+               {
+                       if(!strcasecmp(v, "NONE"))
+                               dither = DITHER_NONE;
+                       else if(!strcasecmp(v, "SIMPLE"))
+                               dither = DITHER_SIMPLE;
+                       else if(!strcasecmp(v, "FLOYDSTEINBERG"))
+                               dither = DITHER_FLOYDSTEINBERG;
+                       else
+                               fprintf(stderr, "Invalid dither mode: %s\n", v);
+               }
+       }
        {
                const char *v = getenv("S2TC_COLORDIST_MODE");
                if(v)
@@ -160,12 +183,12 @@ void tx_compress_dxtn(GLint srccomps, GLint width, GLint height,
                                cd = SRGB;
                        else if(!strcasecmp(v, "SRGB_MIXED"))
                                cd = SRGB_MIXED;
-                       else if(!strcasecmp(v, "LAB"))
-                               cd = LAB;
                        else if(!strcasecmp(v, "AVG"))
                                cd = AVG;
                        else if(!strcasecmp(v, "WAVG"))
                                cd = WAVG;
+                       else if(!strcasecmp(v, "W0AVG"))
+                               cd = W0AVG;
                        else if(!strcasecmp(v, "NORMALMAP"))
                                cd = NORMALMAP;
                        else
@@ -180,11 +203,40 @@ void tx_compress_dxtn(GLint srccomps, GLint width, GLint height,
        {
                const char *v = getenv("S2TC_REFINE_COLORS");
                if(v)
-                       refine = atoi(v);
+               {
+                       if(!strcasecmp(v, "NEVER"))
+                               refine = REFINE_NEVER;
+                       else if(!strcasecmp(v, "ALWAYS"))
+                               refine = REFINE_ALWAYS;
+                       else if(!strcasecmp(v, "LOOP"))
+                               refine = REFINE_LOOP;
+                       else
+                               fprintf(stderr, "Invalid refinement mode: %s\n", v);
+               }
+       }
+
+       switch (destformat) {
+               case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+               case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+                       dxt = DXT1;
+                       rgb565_image(rgba, srcPixData, width, height, srccomps, 1, dither);
+                       break;
+               case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+                       dxt = DXT3;
+                       rgb565_image(rgba, srcPixData, width, height, srccomps, 4, dither);
+                       break;
+               case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+                       dxt = DXT5;
+                       rgb565_image(rgba, srcPixData, width, height, srccomps, 8, dither);
+                       break;
+               default:
+                       free(rgba);
+                       fprintf(stderr, "libdxtn: Bad dstFormat %d in tx_compress_dxtn\n", destformat);
+                       return;
        }
 
        s2tc_encode_block_func_t encode_block = s2tc_encode_block_func(dxt, cd, nrandom, refine);
-       switch (destFormat) {
+       switch (destformat) {
                case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
                case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
                        /* hmm we used to get called without dstRowStride... */