1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * libtxc_dxtn 3bf215546Sopenharmony_ci * Version: 1.0 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Copyright (C) 2004 Roland Scheidegger All Rights Reserved. 6bf215546Sopenharmony_ci * 7bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 8bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 9bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 10bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 12bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included 15bf215546Sopenharmony_ci * in all copies or substantial portions of the Software. 16bf215546Sopenharmony_ci * 17bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20bf215546Sopenharmony_ci * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21bf215546Sopenharmony_ci * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22bf215546Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#ifndef TEXCOMPRESS_S3TC_TMP_H 26bf215546Sopenharmony_ci#define TEXCOMPRESS_S3TC_TMP_H 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#ifdef __APPLE__ 29bf215546Sopenharmony_ci#include <OpenGL/gl.h> 30bf215546Sopenharmony_ci#else 31bf215546Sopenharmony_ci#include <GL/gl.h> 32bf215546Sopenharmony_ci#endif 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_citypedef GLubyte GLchan; 35bf215546Sopenharmony_ci#define UBYTE_TO_CHAN(b) (b) 36bf215546Sopenharmony_ci#define CHAN_MAX 255 37bf215546Sopenharmony_ci#define RCOMP 0 38bf215546Sopenharmony_ci#define GCOMP 1 39bf215546Sopenharmony_ci#define BCOMP 2 40bf215546Sopenharmony_ci#define ACOMP 3 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci#define EXP5TO8R(packedcol) \ 43bf215546Sopenharmony_ci ((((packedcol) >> 8) & 0xf8) | (((packedcol) >> 13) & 0x7)) 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci#define EXP6TO8G(packedcol) \ 46bf215546Sopenharmony_ci ((((packedcol) >> 3) & 0xfc) | (((packedcol) >> 9) & 0x3)) 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci#define EXP5TO8B(packedcol) \ 49bf215546Sopenharmony_ci ((((packedcol) << 3) & 0xf8) | (((packedcol) >> 2) & 0x7)) 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci#define EXP4TO8(col) \ 52bf215546Sopenharmony_ci ((col) | ((col) << 4)) 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci/* inefficient. To be efficient, it would be necessary to decode 16 pixels at once */ 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_cistatic void dxt135_decode_imageblock ( const GLubyte *img_block_src, 57bf215546Sopenharmony_ci GLint i, GLint j, GLuint dxt_type, GLvoid *texel ) { 58bf215546Sopenharmony_ci GLchan *rgba = (GLchan *) texel; 59bf215546Sopenharmony_ci const GLushort color0 = img_block_src[0] | (img_block_src[1] << 8); 60bf215546Sopenharmony_ci const GLushort color1 = img_block_src[2] | (img_block_src[3] << 8); 61bf215546Sopenharmony_ci const GLuint bits = img_block_src[4] | (img_block_src[5] << 8) | 62bf215546Sopenharmony_ci (img_block_src[6] << 16) | ((GLuint)img_block_src[7] << 24); 63bf215546Sopenharmony_ci /* What about big/little endian? */ 64bf215546Sopenharmony_ci GLubyte bit_pos = 2 * (j * 4 + i) ; 65bf215546Sopenharmony_ci GLubyte code = (GLubyte) ((bits >> bit_pos) & 3); 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci rgba[ACOMP] = CHAN_MAX; 68bf215546Sopenharmony_ci switch (code) { 69bf215546Sopenharmony_ci case 0: 70bf215546Sopenharmony_ci rgba[RCOMP] = UBYTE_TO_CHAN( EXP5TO8R(color0) ); 71bf215546Sopenharmony_ci rgba[GCOMP] = UBYTE_TO_CHAN( EXP6TO8G(color0) ); 72bf215546Sopenharmony_ci rgba[BCOMP] = UBYTE_TO_CHAN( EXP5TO8B(color0) ); 73bf215546Sopenharmony_ci break; 74bf215546Sopenharmony_ci case 1: 75bf215546Sopenharmony_ci rgba[RCOMP] = UBYTE_TO_CHAN( EXP5TO8R(color1) ); 76bf215546Sopenharmony_ci rgba[GCOMP] = UBYTE_TO_CHAN( EXP6TO8G(color1) ); 77bf215546Sopenharmony_ci rgba[BCOMP] = UBYTE_TO_CHAN( EXP5TO8B(color1) ); 78bf215546Sopenharmony_ci break; 79bf215546Sopenharmony_ci case 2: 80bf215546Sopenharmony_ci if ((dxt_type > 1) || (color0 > color1)) { 81bf215546Sopenharmony_ci rgba[RCOMP] = UBYTE_TO_CHAN( ((EXP5TO8R(color0) * 2 + EXP5TO8R(color1)) / 3) ); 82bf215546Sopenharmony_ci rgba[GCOMP] = UBYTE_TO_CHAN( ((EXP6TO8G(color0) * 2 + EXP6TO8G(color1)) / 3) ); 83bf215546Sopenharmony_ci rgba[BCOMP] = UBYTE_TO_CHAN( ((EXP5TO8B(color0) * 2 + EXP5TO8B(color1)) / 3) ); 84bf215546Sopenharmony_ci } 85bf215546Sopenharmony_ci else { 86bf215546Sopenharmony_ci rgba[RCOMP] = UBYTE_TO_CHAN( ((EXP5TO8R(color0) + EXP5TO8R(color1)) / 2) ); 87bf215546Sopenharmony_ci rgba[GCOMP] = UBYTE_TO_CHAN( ((EXP6TO8G(color0) + EXP6TO8G(color1)) / 2) ); 88bf215546Sopenharmony_ci rgba[BCOMP] = UBYTE_TO_CHAN( ((EXP5TO8B(color0) + EXP5TO8B(color1)) / 2) ); 89bf215546Sopenharmony_ci } 90bf215546Sopenharmony_ci break; 91bf215546Sopenharmony_ci case 3: 92bf215546Sopenharmony_ci if ((dxt_type > 1) || (color0 > color1)) { 93bf215546Sopenharmony_ci rgba[RCOMP] = UBYTE_TO_CHAN( ((EXP5TO8R(color0) + EXP5TO8R(color1) * 2) / 3) ); 94bf215546Sopenharmony_ci rgba[GCOMP] = UBYTE_TO_CHAN( ((EXP6TO8G(color0) + EXP6TO8G(color1) * 2) / 3) ); 95bf215546Sopenharmony_ci rgba[BCOMP] = UBYTE_TO_CHAN( ((EXP5TO8B(color0) + EXP5TO8B(color1) * 2) / 3) ); 96bf215546Sopenharmony_ci } 97bf215546Sopenharmony_ci else { 98bf215546Sopenharmony_ci rgba[RCOMP] = 0; 99bf215546Sopenharmony_ci rgba[GCOMP] = 0; 100bf215546Sopenharmony_ci rgba[BCOMP] = 0; 101bf215546Sopenharmony_ci if (dxt_type == 1) rgba[ACOMP] = UBYTE_TO_CHAN(0); 102bf215546Sopenharmony_ci } 103bf215546Sopenharmony_ci break; 104bf215546Sopenharmony_ci default: 105bf215546Sopenharmony_ci /* CANNOT happen (I hope) */ 106bf215546Sopenharmony_ci break; 107bf215546Sopenharmony_ci } 108bf215546Sopenharmony_ci} 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_cistatic void fetch_2d_texel_rgb_dxt1(GLint srcRowStride, const GLubyte *pixdata, 112bf215546Sopenharmony_ci GLint i, GLint j, GLvoid *texel) 113bf215546Sopenharmony_ci{ 114bf215546Sopenharmony_ci /* Extract the (i,j) pixel from pixdata and return it 115bf215546Sopenharmony_ci * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP]. 116bf215546Sopenharmony_ci */ 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8); 119bf215546Sopenharmony_ci dxt135_decode_imageblock(blksrc, (i&3), (j&3), 0, texel); 120bf215546Sopenharmony_ci} 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_cistatic void fetch_2d_texel_rgba_dxt1(GLint srcRowStride, const GLubyte *pixdata, 124bf215546Sopenharmony_ci GLint i, GLint j, GLvoid *texel) 125bf215546Sopenharmony_ci{ 126bf215546Sopenharmony_ci /* Extract the (i,j) pixel from pixdata and return it 127bf215546Sopenharmony_ci * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP]. 128bf215546Sopenharmony_ci */ 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8); 131bf215546Sopenharmony_ci dxt135_decode_imageblock(blksrc, (i&3), (j&3), 1, texel); 132bf215546Sopenharmony_ci} 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_cistatic void fetch_2d_texel_rgba_dxt3(GLint srcRowStride, const GLubyte *pixdata, 135bf215546Sopenharmony_ci GLint i, GLint j, GLvoid *texel) { 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci /* Extract the (i,j) pixel from pixdata and return it 138bf215546Sopenharmony_ci * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP]. 139bf215546Sopenharmony_ci */ 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci GLchan *rgba = (GLchan *) texel; 142bf215546Sopenharmony_ci const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 16); 143bf215546Sopenharmony_ci const GLubyte anibble = (blksrc[((j&3) * 4 + (i&3)) / 2] >> (4 * (i&1))) & 0xf; 144bf215546Sopenharmony_ci dxt135_decode_imageblock(blksrc + 8, (i&3), (j&3), 2, texel); 145bf215546Sopenharmony_ci rgba[ACOMP] = UBYTE_TO_CHAN( (GLubyte)(EXP4TO8(anibble)) ); 146bf215546Sopenharmony_ci} 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_cistatic void fetch_2d_texel_rgba_dxt5(GLint srcRowStride, const GLubyte *pixdata, 149bf215546Sopenharmony_ci GLint i, GLint j, GLvoid *texel) { 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci /* Extract the (i,j) pixel from pixdata and return it 152bf215546Sopenharmony_ci * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP]. 153bf215546Sopenharmony_ci */ 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_ci GLchan *rgba = (GLchan *) texel; 156bf215546Sopenharmony_ci const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 16); 157bf215546Sopenharmony_ci const GLubyte alpha0 = blksrc[0]; 158bf215546Sopenharmony_ci const GLubyte alpha1 = blksrc[1]; 159bf215546Sopenharmony_ci const GLubyte bit_pos = ((j&3) * 4 + (i&3)) * 3; 160bf215546Sopenharmony_ci const GLubyte acodelow = blksrc[2 + bit_pos / 8]; 161bf215546Sopenharmony_ci const GLubyte acodehigh = blksrc[3 + bit_pos / 8]; 162bf215546Sopenharmony_ci const GLubyte code = (acodelow >> (bit_pos & 0x7) | 163bf215546Sopenharmony_ci (acodehigh << (8 - (bit_pos & 0x7)))) & 0x7; 164bf215546Sopenharmony_ci dxt135_decode_imageblock(blksrc + 8, (i&3), (j&3), 2, texel); 165bf215546Sopenharmony_ci if (code == 0) 166bf215546Sopenharmony_ci rgba[ACOMP] = UBYTE_TO_CHAN( alpha0 ); 167bf215546Sopenharmony_ci else if (code == 1) 168bf215546Sopenharmony_ci rgba[ACOMP] = UBYTE_TO_CHAN( alpha1 ); 169bf215546Sopenharmony_ci else if (alpha0 > alpha1) 170bf215546Sopenharmony_ci rgba[ACOMP] = UBYTE_TO_CHAN( ((alpha0 * (8 - code) + (alpha1 * (code - 1))) / 7) ); 171bf215546Sopenharmony_ci else if (code < 6) 172bf215546Sopenharmony_ci rgba[ACOMP] = UBYTE_TO_CHAN( ((alpha0 * (6 - code) + (alpha1 * (code - 1))) / 5) ); 173bf215546Sopenharmony_ci else if (code == 6) 174bf215546Sopenharmony_ci rgba[ACOMP] = 0; 175bf215546Sopenharmony_ci else 176bf215546Sopenharmony_ci rgba[ACOMP] = CHAN_MAX; 177bf215546Sopenharmony_ci} 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci/* weights used for error function, basically weights (unsquared 2/4/1) according to rgb->luminance conversion 181bf215546Sopenharmony_ci not sure if this really reflects visual perception */ 182bf215546Sopenharmony_ci#define REDWEIGHT 4 183bf215546Sopenharmony_ci#define GREENWEIGHT 16 184bf215546Sopenharmony_ci#define BLUEWEIGHT 1 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci#define ALPHACUT 127 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_cistatic void fancybasecolorsearch( UNUSED GLubyte *blkaddr, GLubyte srccolors[4][4][4], GLubyte *bestcolor[2], 189bf215546Sopenharmony_ci GLint numxpixels, GLint numypixels, UNUSED GLint type, UNUSED GLboolean haveAlpha) 190bf215546Sopenharmony_ci{ 191bf215546Sopenharmony_ci /* use same luminance-weighted distance metric to determine encoding as for finding the base colors */ 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci /* TODO could also try to find a better encoding for the 3-color-encoding type, this really should be done 194bf215546Sopenharmony_ci if it's rgba_dxt1 and we have alpha in the block, currently even values which will be mapped to black 195bf215546Sopenharmony_ci due to their alpha value will influence the result */ 196bf215546Sopenharmony_ci GLint i, j, colors, z; 197bf215546Sopenharmony_ci GLuint pixerror, pixerrorred, pixerrorgreen, pixerrorblue, pixerrorbest; 198bf215546Sopenharmony_ci GLint colordist, blockerrlin[2][3]; 199bf215546Sopenharmony_ci GLubyte nrcolor[2]; 200bf215546Sopenharmony_ci GLint pixerrorcolorbest[3] = {0}; 201bf215546Sopenharmony_ci GLubyte enc = 0; 202bf215546Sopenharmony_ci GLubyte cv[4][4]; 203bf215546Sopenharmony_ci GLubyte testcolor[2][3]; 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci/* fprintf(stderr, "color begin 0 r/g/b %d/%d/%d, 1 r/g/b %d/%d/%d\n", 206bf215546Sopenharmony_ci bestcolor[0][0], bestcolor[0][1], bestcolor[0][2], bestcolor[1][0], bestcolor[1][1], bestcolor[1][2]);*/ 207bf215546Sopenharmony_ci if (((bestcolor[0][0] & 0xf8) << 8 | (bestcolor[0][1] & 0xfc) << 3 | bestcolor[0][2] >> 3) < 208bf215546Sopenharmony_ci ((bestcolor[1][0] & 0xf8) << 8 | (bestcolor[1][1] & 0xfc) << 3 | bestcolor[1][2] >> 3)) { 209bf215546Sopenharmony_ci testcolor[0][0] = bestcolor[0][0]; 210bf215546Sopenharmony_ci testcolor[0][1] = bestcolor[0][1]; 211bf215546Sopenharmony_ci testcolor[0][2] = bestcolor[0][2]; 212bf215546Sopenharmony_ci testcolor[1][0] = bestcolor[1][0]; 213bf215546Sopenharmony_ci testcolor[1][1] = bestcolor[1][1]; 214bf215546Sopenharmony_ci testcolor[1][2] = bestcolor[1][2]; 215bf215546Sopenharmony_ci } 216bf215546Sopenharmony_ci else { 217bf215546Sopenharmony_ci testcolor[1][0] = bestcolor[0][0]; 218bf215546Sopenharmony_ci testcolor[1][1] = bestcolor[0][1]; 219bf215546Sopenharmony_ci testcolor[1][2] = bestcolor[0][2]; 220bf215546Sopenharmony_ci testcolor[0][0] = bestcolor[1][0]; 221bf215546Sopenharmony_ci testcolor[0][1] = bestcolor[1][1]; 222bf215546Sopenharmony_ci testcolor[0][2] = bestcolor[1][2]; 223bf215546Sopenharmony_ci } 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_ci for (i = 0; i < 3; i ++) { 226bf215546Sopenharmony_ci cv[0][i] = testcolor[0][i]; 227bf215546Sopenharmony_ci cv[1][i] = testcolor[1][i]; 228bf215546Sopenharmony_ci cv[2][i] = (testcolor[0][i] * 2 + testcolor[1][i]) / 3; 229bf215546Sopenharmony_ci cv[3][i] = (testcolor[0][i] + testcolor[1][i] * 2) / 3; 230bf215546Sopenharmony_ci } 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci blockerrlin[0][0] = 0; 233bf215546Sopenharmony_ci blockerrlin[0][1] = 0; 234bf215546Sopenharmony_ci blockerrlin[0][2] = 0; 235bf215546Sopenharmony_ci blockerrlin[1][0] = 0; 236bf215546Sopenharmony_ci blockerrlin[1][1] = 0; 237bf215546Sopenharmony_ci blockerrlin[1][2] = 0; 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_ci nrcolor[0] = 0; 240bf215546Sopenharmony_ci nrcolor[1] = 0; 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_ci for (j = 0; j < numypixels; j++) { 243bf215546Sopenharmony_ci for (i = 0; i < numxpixels; i++) { 244bf215546Sopenharmony_ci pixerrorbest = 0xffffffff; 245bf215546Sopenharmony_ci for (colors = 0; colors < 4; colors++) { 246bf215546Sopenharmony_ci colordist = srccolors[j][i][0] - (cv[colors][0]); 247bf215546Sopenharmony_ci pixerror = colordist * colordist * REDWEIGHT; 248bf215546Sopenharmony_ci pixerrorred = colordist; 249bf215546Sopenharmony_ci colordist = srccolors[j][i][1] - (cv[colors][1]); 250bf215546Sopenharmony_ci pixerror += colordist * colordist * GREENWEIGHT; 251bf215546Sopenharmony_ci pixerrorgreen = colordist; 252bf215546Sopenharmony_ci colordist = srccolors[j][i][2] - (cv[colors][2]); 253bf215546Sopenharmony_ci pixerror += colordist * colordist * BLUEWEIGHT; 254bf215546Sopenharmony_ci pixerrorblue = colordist; 255bf215546Sopenharmony_ci if (pixerror < pixerrorbest) { 256bf215546Sopenharmony_ci enc = colors; 257bf215546Sopenharmony_ci pixerrorbest = pixerror; 258bf215546Sopenharmony_ci pixerrorcolorbest[0] = pixerrorred; 259bf215546Sopenharmony_ci pixerrorcolorbest[1] = pixerrorgreen; 260bf215546Sopenharmony_ci pixerrorcolorbest[2] = pixerrorblue; 261bf215546Sopenharmony_ci } 262bf215546Sopenharmony_ci } 263bf215546Sopenharmony_ci if (enc == 0) { 264bf215546Sopenharmony_ci for (z = 0; z < 3; z++) { 265bf215546Sopenharmony_ci blockerrlin[0][z] += 3 * pixerrorcolorbest[z]; 266bf215546Sopenharmony_ci } 267bf215546Sopenharmony_ci nrcolor[0] += 3; 268bf215546Sopenharmony_ci } 269bf215546Sopenharmony_ci else if (enc == 2) { 270bf215546Sopenharmony_ci for (z = 0; z < 3; z++) { 271bf215546Sopenharmony_ci blockerrlin[0][z] += 2 * pixerrorcolorbest[z]; 272bf215546Sopenharmony_ci } 273bf215546Sopenharmony_ci nrcolor[0] += 2; 274bf215546Sopenharmony_ci for (z = 0; z < 3; z++) { 275bf215546Sopenharmony_ci blockerrlin[1][z] += 1 * pixerrorcolorbest[z]; 276bf215546Sopenharmony_ci } 277bf215546Sopenharmony_ci nrcolor[1] += 1; 278bf215546Sopenharmony_ci } 279bf215546Sopenharmony_ci else if (enc == 3) { 280bf215546Sopenharmony_ci for (z = 0; z < 3; z++) { 281bf215546Sopenharmony_ci blockerrlin[0][z] += 1 * pixerrorcolorbest[z]; 282bf215546Sopenharmony_ci } 283bf215546Sopenharmony_ci nrcolor[0] += 1; 284bf215546Sopenharmony_ci for (z = 0; z < 3; z++) { 285bf215546Sopenharmony_ci blockerrlin[1][z] += 2 * pixerrorcolorbest[z]; 286bf215546Sopenharmony_ci } 287bf215546Sopenharmony_ci nrcolor[1] += 2; 288bf215546Sopenharmony_ci } 289bf215546Sopenharmony_ci else if (enc == 1) { 290bf215546Sopenharmony_ci for (z = 0; z < 3; z++) { 291bf215546Sopenharmony_ci blockerrlin[1][z] += 3 * pixerrorcolorbest[z]; 292bf215546Sopenharmony_ci } 293bf215546Sopenharmony_ci nrcolor[1] += 3; 294bf215546Sopenharmony_ci } 295bf215546Sopenharmony_ci } 296bf215546Sopenharmony_ci } 297bf215546Sopenharmony_ci if (nrcolor[0] == 0) nrcolor[0] = 1; 298bf215546Sopenharmony_ci if (nrcolor[1] == 0) nrcolor[1] = 1; 299bf215546Sopenharmony_ci for (j = 0; j < 2; j++) { 300bf215546Sopenharmony_ci for (i = 0; i < 3; i++) { 301bf215546Sopenharmony_ci GLint newvalue = testcolor[j][i] + blockerrlin[j][i] / nrcolor[j]; 302bf215546Sopenharmony_ci if (newvalue <= 0) 303bf215546Sopenharmony_ci testcolor[j][i] = 0; 304bf215546Sopenharmony_ci else if (newvalue >= 255) 305bf215546Sopenharmony_ci testcolor[j][i] = 255; 306bf215546Sopenharmony_ci else testcolor[j][i] = newvalue; 307bf215546Sopenharmony_ci } 308bf215546Sopenharmony_ci } 309bf215546Sopenharmony_ci 310bf215546Sopenharmony_ci if ((abs(testcolor[0][0] - testcolor[1][0]) < 8) && 311bf215546Sopenharmony_ci (abs(testcolor[0][1] - testcolor[1][1]) < 4) && 312bf215546Sopenharmony_ci (abs(testcolor[0][2] - testcolor[1][2]) < 8)) { 313bf215546Sopenharmony_ci /* both colors are so close they might get encoded as the same 16bit values */ 314bf215546Sopenharmony_ci GLubyte coldiffred, coldiffgreen, coldiffblue, coldiffmax, factor, ind0, ind1; 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_ci coldiffred = abs(testcolor[0][0] - testcolor[1][0]); 317bf215546Sopenharmony_ci coldiffgreen = 2 * abs(testcolor[0][1] - testcolor[1][1]); 318bf215546Sopenharmony_ci coldiffblue = abs(testcolor[0][2] - testcolor[1][2]); 319bf215546Sopenharmony_ci coldiffmax = coldiffred; 320bf215546Sopenharmony_ci if (coldiffmax < coldiffgreen) coldiffmax = coldiffgreen; 321bf215546Sopenharmony_ci if (coldiffmax < coldiffblue) coldiffmax = coldiffblue; 322bf215546Sopenharmony_ci if (coldiffmax > 0) { 323bf215546Sopenharmony_ci if (coldiffmax > 4) factor = 2; 324bf215546Sopenharmony_ci else if (coldiffmax > 2) factor = 3; 325bf215546Sopenharmony_ci else factor = 4; 326bf215546Sopenharmony_ci /* Won't do much if the color value is near 255... */ 327bf215546Sopenharmony_ci /* argh so many ifs */ 328bf215546Sopenharmony_ci if (testcolor[1][1] >= testcolor[0][1]) { 329bf215546Sopenharmony_ci ind1 = 1; ind0 = 0; 330bf215546Sopenharmony_ci } 331bf215546Sopenharmony_ci else { 332bf215546Sopenharmony_ci ind1 = 0; ind0 = 1; 333bf215546Sopenharmony_ci } 334bf215546Sopenharmony_ci if ((testcolor[ind1][1] + factor * coldiffgreen) <= 255) 335bf215546Sopenharmony_ci testcolor[ind1][1] += factor * coldiffgreen; 336bf215546Sopenharmony_ci else testcolor[ind1][1] = 255; 337bf215546Sopenharmony_ci if ((testcolor[ind1][0] - testcolor[ind0][1]) > 0) { 338bf215546Sopenharmony_ci if ((testcolor[ind1][0] + factor * coldiffred) <= 255) 339bf215546Sopenharmony_ci testcolor[ind1][0] += factor * coldiffred; 340bf215546Sopenharmony_ci else testcolor[ind1][0] = 255; 341bf215546Sopenharmony_ci } 342bf215546Sopenharmony_ci else { 343bf215546Sopenharmony_ci if ((testcolor[ind0][0] + factor * coldiffred) <= 255) 344bf215546Sopenharmony_ci testcolor[ind0][0] += factor * coldiffred; 345bf215546Sopenharmony_ci else testcolor[ind0][0] = 255; 346bf215546Sopenharmony_ci } 347bf215546Sopenharmony_ci if ((testcolor[ind1][2] - testcolor[ind0][2]) > 0) { 348bf215546Sopenharmony_ci if ((testcolor[ind1][2] + factor * coldiffblue) <= 255) 349bf215546Sopenharmony_ci testcolor[ind1][2] += factor * coldiffblue; 350bf215546Sopenharmony_ci else testcolor[ind1][2] = 255; 351bf215546Sopenharmony_ci } 352bf215546Sopenharmony_ci else { 353bf215546Sopenharmony_ci if ((testcolor[ind0][2] + factor * coldiffblue) <= 255) 354bf215546Sopenharmony_ci testcolor[ind0][2] += factor * coldiffblue; 355bf215546Sopenharmony_ci else testcolor[ind0][2] = 255; 356bf215546Sopenharmony_ci } 357bf215546Sopenharmony_ci } 358bf215546Sopenharmony_ci } 359bf215546Sopenharmony_ci 360bf215546Sopenharmony_ci if (((testcolor[0][0] & 0xf8) << 8 | (testcolor[0][1] & 0xfc) << 3 | testcolor[0][2] >> 3) < 361bf215546Sopenharmony_ci ((testcolor[1][0] & 0xf8) << 8 | (testcolor[1][1] & 0xfc) << 3 | testcolor[1][2]) >> 3) { 362bf215546Sopenharmony_ci for (i = 0; i < 3; i++) { 363bf215546Sopenharmony_ci bestcolor[0][i] = testcolor[0][i]; 364bf215546Sopenharmony_ci bestcolor[1][i] = testcolor[1][i]; 365bf215546Sopenharmony_ci } 366bf215546Sopenharmony_ci } 367bf215546Sopenharmony_ci else { 368bf215546Sopenharmony_ci for (i = 0; i < 3; i++) { 369bf215546Sopenharmony_ci bestcolor[0][i] = testcolor[1][i]; 370bf215546Sopenharmony_ci bestcolor[1][i] = testcolor[0][i]; 371bf215546Sopenharmony_ci } 372bf215546Sopenharmony_ci } 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_ci/* fprintf(stderr, "color end 0 r/g/b %d/%d/%d, 1 r/g/b %d/%d/%d\n", 375bf215546Sopenharmony_ci bestcolor[0][0], bestcolor[0][1], bestcolor[0][2], bestcolor[1][0], bestcolor[1][1], bestcolor[1][2]);*/ 376bf215546Sopenharmony_ci} 377bf215546Sopenharmony_ci 378bf215546Sopenharmony_ci 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_cistatic void storedxtencodedblock( GLubyte *blkaddr, GLubyte srccolors[4][4][4], GLubyte *bestcolor[2], 381bf215546Sopenharmony_ci GLint numxpixels, GLint numypixels, GLuint type, GLboolean haveAlpha) 382bf215546Sopenharmony_ci{ 383bf215546Sopenharmony_ci /* use same luminance-weighted distance metric to determine encoding as for finding the base colors */ 384bf215546Sopenharmony_ci 385bf215546Sopenharmony_ci GLint i, j, colors; 386bf215546Sopenharmony_ci GLuint testerror, testerror2, pixerror, pixerrorbest; 387bf215546Sopenharmony_ci GLint colordist; 388bf215546Sopenharmony_ci GLushort color0, color1, tempcolor; 389bf215546Sopenharmony_ci GLuint bits = 0, bits2 = 0; 390bf215546Sopenharmony_ci GLubyte *colorptr; 391bf215546Sopenharmony_ci GLubyte enc = 0; 392bf215546Sopenharmony_ci GLubyte cv[4][4]; 393bf215546Sopenharmony_ci 394bf215546Sopenharmony_ci bestcolor[0][0] = bestcolor[0][0] & 0xf8; 395bf215546Sopenharmony_ci bestcolor[0][1] = bestcolor[0][1] & 0xfc; 396bf215546Sopenharmony_ci bestcolor[0][2] = bestcolor[0][2] & 0xf8; 397bf215546Sopenharmony_ci bestcolor[1][0] = bestcolor[1][0] & 0xf8; 398bf215546Sopenharmony_ci bestcolor[1][1] = bestcolor[1][1] & 0xfc; 399bf215546Sopenharmony_ci bestcolor[1][2] = bestcolor[1][2] & 0xf8; 400bf215546Sopenharmony_ci 401bf215546Sopenharmony_ci color0 = bestcolor[0][0] << 8 | bestcolor[0][1] << 3 | bestcolor[0][2] >> 3; 402bf215546Sopenharmony_ci color1 = bestcolor[1][0] << 8 | bestcolor[1][1] << 3 | bestcolor[1][2] >> 3; 403bf215546Sopenharmony_ci if (color0 < color1) { 404bf215546Sopenharmony_ci tempcolor = color0; color0 = color1; color1 = tempcolor; 405bf215546Sopenharmony_ci colorptr = bestcolor[0]; bestcolor[0] = bestcolor[1]; bestcolor[1] = colorptr; 406bf215546Sopenharmony_ci } 407bf215546Sopenharmony_ci 408bf215546Sopenharmony_ci 409bf215546Sopenharmony_ci for (i = 0; i < 3; i++) { 410bf215546Sopenharmony_ci cv[0][i] = bestcolor[0][i]; 411bf215546Sopenharmony_ci cv[1][i] = bestcolor[1][i]; 412bf215546Sopenharmony_ci cv[2][i] = (bestcolor[0][i] * 2 + bestcolor[1][i]) / 3; 413bf215546Sopenharmony_ci cv[3][i] = (bestcolor[0][i] + bestcolor[1][i] * 2) / 3; 414bf215546Sopenharmony_ci } 415bf215546Sopenharmony_ci 416bf215546Sopenharmony_ci testerror = 0; 417bf215546Sopenharmony_ci for (j = 0; j < numypixels; j++) { 418bf215546Sopenharmony_ci for (i = 0; i < numxpixels; i++) { 419bf215546Sopenharmony_ci pixerrorbest = 0xffffffff; 420bf215546Sopenharmony_ci for (colors = 0; colors < 4; colors++) { 421bf215546Sopenharmony_ci colordist = srccolors[j][i][0] - cv[colors][0]; 422bf215546Sopenharmony_ci pixerror = colordist * colordist * REDWEIGHT; 423bf215546Sopenharmony_ci colordist = srccolors[j][i][1] - cv[colors][1]; 424bf215546Sopenharmony_ci pixerror += colordist * colordist * GREENWEIGHT; 425bf215546Sopenharmony_ci colordist = srccolors[j][i][2] - cv[colors][2]; 426bf215546Sopenharmony_ci pixerror += colordist * colordist * BLUEWEIGHT; 427bf215546Sopenharmony_ci if (pixerror < pixerrorbest) { 428bf215546Sopenharmony_ci pixerrorbest = pixerror; 429bf215546Sopenharmony_ci enc = colors; 430bf215546Sopenharmony_ci } 431bf215546Sopenharmony_ci } 432bf215546Sopenharmony_ci testerror += pixerrorbest; 433bf215546Sopenharmony_ci bits |= (uint32_t)enc << (2 * (j * 4 + i)); 434bf215546Sopenharmony_ci } 435bf215546Sopenharmony_ci } 436bf215546Sopenharmony_ci /* some hw might disagree but actually decoding should always use 4-color encoding 437bf215546Sopenharmony_ci for non-dxt1 formats */ 438bf215546Sopenharmony_ci if (type == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || type == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) { 439bf215546Sopenharmony_ci for (i = 0; i < 3; i++) { 440bf215546Sopenharmony_ci cv[2][i] = (bestcolor[0][i] + bestcolor[1][i]) / 2; 441bf215546Sopenharmony_ci /* this isn't used. Looks like the black color constant can only be used 442bf215546Sopenharmony_ci with RGB_DXT1 if I read the spec correctly (note though that the radeon gpu disagrees, 443bf215546Sopenharmony_ci it will decode 3 to black even with DXT3/5), and due to how the color searching works 444bf215546Sopenharmony_ci it won't get used even then */ 445bf215546Sopenharmony_ci cv[3][i] = 0; 446bf215546Sopenharmony_ci } 447bf215546Sopenharmony_ci testerror2 = 0; 448bf215546Sopenharmony_ci for (j = 0; j < numypixels; j++) { 449bf215546Sopenharmony_ci for (i = 0; i < numxpixels; i++) { 450bf215546Sopenharmony_ci pixerrorbest = 0xffffffff; 451bf215546Sopenharmony_ci if ((type == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) && (srccolors[j][i][3] <= ALPHACUT)) { 452bf215546Sopenharmony_ci enc = 3; 453bf215546Sopenharmony_ci pixerrorbest = 0; /* don't calculate error */ 454bf215546Sopenharmony_ci } 455bf215546Sopenharmony_ci else { 456bf215546Sopenharmony_ci /* we're calculating the same what we have done already for colors 0-1 above... */ 457bf215546Sopenharmony_ci for (colors = 0; colors < 3; colors++) { 458bf215546Sopenharmony_ci colordist = srccolors[j][i][0] - cv[colors][0]; 459bf215546Sopenharmony_ci pixerror = colordist * colordist * REDWEIGHT; 460bf215546Sopenharmony_ci colordist = srccolors[j][i][1] - cv[colors][1]; 461bf215546Sopenharmony_ci pixerror += colordist * colordist * GREENWEIGHT; 462bf215546Sopenharmony_ci colordist = srccolors[j][i][2] - cv[colors][2]; 463bf215546Sopenharmony_ci pixerror += colordist * colordist * BLUEWEIGHT; 464bf215546Sopenharmony_ci if (pixerror < pixerrorbest) { 465bf215546Sopenharmony_ci pixerrorbest = pixerror; 466bf215546Sopenharmony_ci /* need to exchange colors later */ 467bf215546Sopenharmony_ci if (colors > 1) enc = colors; 468bf215546Sopenharmony_ci else enc = colors ^ 1; 469bf215546Sopenharmony_ci } 470bf215546Sopenharmony_ci } 471bf215546Sopenharmony_ci } 472bf215546Sopenharmony_ci testerror2 += pixerrorbest; 473bf215546Sopenharmony_ci bits2 |= (uint32_t)enc << (2 * (j * 4 + i)); 474bf215546Sopenharmony_ci } 475bf215546Sopenharmony_ci } 476bf215546Sopenharmony_ci } else { 477bf215546Sopenharmony_ci testerror2 = 0xffffffff; 478bf215546Sopenharmony_ci } 479bf215546Sopenharmony_ci 480bf215546Sopenharmony_ci /* finally we're finished, write back colors and bits */ 481bf215546Sopenharmony_ci if ((testerror > testerror2) || (haveAlpha)) { 482bf215546Sopenharmony_ci *blkaddr++ = color1 & 0xff; 483bf215546Sopenharmony_ci *blkaddr++ = color1 >> 8; 484bf215546Sopenharmony_ci *blkaddr++ = color0 & 0xff; 485bf215546Sopenharmony_ci *blkaddr++ = color0 >> 8; 486bf215546Sopenharmony_ci *blkaddr++ = bits2 & 0xff; 487bf215546Sopenharmony_ci *blkaddr++ = ( bits2 >> 8) & 0xff; 488bf215546Sopenharmony_ci *blkaddr++ = ( bits2 >> 16) & 0xff; 489bf215546Sopenharmony_ci *blkaddr = bits2 >> 24; 490bf215546Sopenharmony_ci } 491bf215546Sopenharmony_ci else { 492bf215546Sopenharmony_ci *blkaddr++ = color0 & 0xff; 493bf215546Sopenharmony_ci *blkaddr++ = color0 >> 8; 494bf215546Sopenharmony_ci *blkaddr++ = color1 & 0xff; 495bf215546Sopenharmony_ci *blkaddr++ = color1 >> 8; 496bf215546Sopenharmony_ci *blkaddr++ = bits & 0xff; 497bf215546Sopenharmony_ci *blkaddr++ = ( bits >> 8) & 0xff; 498bf215546Sopenharmony_ci *blkaddr++ = ( bits >> 16) & 0xff; 499bf215546Sopenharmony_ci *blkaddr = bits >> 24; 500bf215546Sopenharmony_ci } 501bf215546Sopenharmony_ci} 502bf215546Sopenharmony_ci 503bf215546Sopenharmony_cistatic void encodedxtcolorblockfaster( GLubyte *blkaddr, GLubyte srccolors[4][4][4], 504bf215546Sopenharmony_ci GLint numxpixels, GLint numypixels, GLuint type ) 505bf215546Sopenharmony_ci{ 506bf215546Sopenharmony_ci/* simplistic approach. We need two base colors, simply use the "highest" and the "lowest" color 507bf215546Sopenharmony_ci present in the picture as base colors */ 508bf215546Sopenharmony_ci 509bf215546Sopenharmony_ci /* define lowest and highest color as shortest and longest vector to 0/0/0, though the 510bf215546Sopenharmony_ci vectors are weighted similar to their importance in rgb-luminance conversion 511bf215546Sopenharmony_ci doesn't work too well though... 512bf215546Sopenharmony_ci This seems to be a rather difficult problem */ 513bf215546Sopenharmony_ci 514bf215546Sopenharmony_ci GLubyte *bestcolor[2]; 515bf215546Sopenharmony_ci GLubyte basecolors[2][3]; 516bf215546Sopenharmony_ci GLubyte i, j; 517bf215546Sopenharmony_ci GLuint lowcv, highcv, testcv; 518bf215546Sopenharmony_ci GLboolean haveAlpha = GL_FALSE; 519bf215546Sopenharmony_ci 520bf215546Sopenharmony_ci lowcv = highcv = srccolors[0][0][0] * srccolors[0][0][0] * REDWEIGHT + 521bf215546Sopenharmony_ci srccolors[0][0][1] * srccolors[0][0][1] * GREENWEIGHT + 522bf215546Sopenharmony_ci srccolors[0][0][2] * srccolors[0][0][2] * BLUEWEIGHT; 523bf215546Sopenharmony_ci bestcolor[0] = bestcolor[1] = srccolors[0][0]; 524bf215546Sopenharmony_ci for (j = 0; j < numypixels; j++) { 525bf215546Sopenharmony_ci for (i = 0; i < numxpixels; i++) { 526bf215546Sopenharmony_ci /* don't use this as a base color if the pixel will get black/transparent anyway */ 527bf215546Sopenharmony_ci if ((type != GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) || (srccolors[j][i][3] > ALPHACUT)) { 528bf215546Sopenharmony_ci testcv = srccolors[j][i][0] * srccolors[j][i][0] * REDWEIGHT + 529bf215546Sopenharmony_ci srccolors[j][i][1] * srccolors[j][i][1] * GREENWEIGHT + 530bf215546Sopenharmony_ci srccolors[j][i][2] * srccolors[j][i][2] * BLUEWEIGHT; 531bf215546Sopenharmony_ci if (testcv > highcv) { 532bf215546Sopenharmony_ci highcv = testcv; 533bf215546Sopenharmony_ci bestcolor[1] = srccolors[j][i]; 534bf215546Sopenharmony_ci } 535bf215546Sopenharmony_ci else if (testcv < lowcv) { 536bf215546Sopenharmony_ci lowcv = testcv; 537bf215546Sopenharmony_ci bestcolor[0] = srccolors[j][i]; 538bf215546Sopenharmony_ci } 539bf215546Sopenharmony_ci } 540bf215546Sopenharmony_ci else haveAlpha = GL_TRUE; 541bf215546Sopenharmony_ci } 542bf215546Sopenharmony_ci } 543bf215546Sopenharmony_ci /* make sure the original color values won't get touched... */ 544bf215546Sopenharmony_ci for (j = 0; j < 2; j++) { 545bf215546Sopenharmony_ci for (i = 0; i < 3; i++) { 546bf215546Sopenharmony_ci basecolors[j][i] = bestcolor[j][i]; 547bf215546Sopenharmony_ci } 548bf215546Sopenharmony_ci } 549bf215546Sopenharmony_ci bestcolor[0] = basecolors[0]; 550bf215546Sopenharmony_ci bestcolor[1] = basecolors[1]; 551bf215546Sopenharmony_ci 552bf215546Sopenharmony_ci /* try to find better base colors */ 553bf215546Sopenharmony_ci fancybasecolorsearch(blkaddr, srccolors, bestcolor, numxpixels, numypixels, type, haveAlpha); 554bf215546Sopenharmony_ci /* find the best encoding for these colors, and store the result */ 555bf215546Sopenharmony_ci storedxtencodedblock(blkaddr, srccolors, bestcolor, numxpixels, numypixels, type, haveAlpha); 556bf215546Sopenharmony_ci} 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_cistatic void writedxt5encodedalphablock( GLubyte *blkaddr, GLubyte alphabase1, GLubyte alphabase2, 559bf215546Sopenharmony_ci GLubyte alphaenc[16]) 560bf215546Sopenharmony_ci{ 561bf215546Sopenharmony_ci *blkaddr++ = alphabase1; 562bf215546Sopenharmony_ci *blkaddr++ = alphabase2; 563bf215546Sopenharmony_ci *blkaddr++ = alphaenc[0] | (alphaenc[1] << 3) | ((alphaenc[2] & 3) << 6); 564bf215546Sopenharmony_ci *blkaddr++ = (alphaenc[2] >> 2) | (alphaenc[3] << 1) | (alphaenc[4] << 4) | ((alphaenc[5] & 1) << 7); 565bf215546Sopenharmony_ci *blkaddr++ = (alphaenc[5] >> 1) | (alphaenc[6] << 2) | (alphaenc[7] << 5); 566bf215546Sopenharmony_ci *blkaddr++ = alphaenc[8] | (alphaenc[9] << 3) | ((alphaenc[10] & 3) << 6); 567bf215546Sopenharmony_ci *blkaddr++ = (alphaenc[10] >> 2) | (alphaenc[11] << 1) | (alphaenc[12] << 4) | ((alphaenc[13] & 1) << 7); 568bf215546Sopenharmony_ci *blkaddr++ = (alphaenc[13] >> 1) | (alphaenc[14] << 2) | (alphaenc[15] << 5); 569bf215546Sopenharmony_ci} 570bf215546Sopenharmony_ci 571bf215546Sopenharmony_cistatic void encodedxt5alpha(GLubyte *blkaddr, GLubyte srccolors[4][4][4], 572bf215546Sopenharmony_ci GLint numxpixels, GLint numypixels) 573bf215546Sopenharmony_ci{ 574bf215546Sopenharmony_ci GLubyte alphabase[2], alphause[2]; 575bf215546Sopenharmony_ci GLshort alphatest[2]; 576bf215546Sopenharmony_ci GLuint alphablockerror1, alphablockerror2, alphablockerror3; 577bf215546Sopenharmony_ci GLubyte i, j, aindex, acutValues[7]; 578bf215546Sopenharmony_ci GLubyte alphaenc1[16], alphaenc2[16], alphaenc3[16]; 579bf215546Sopenharmony_ci GLboolean alphaabsmin = GL_FALSE; 580bf215546Sopenharmony_ci GLboolean alphaabsmax = GL_FALSE; 581bf215546Sopenharmony_ci GLshort alphadist; 582bf215546Sopenharmony_ci 583bf215546Sopenharmony_ci /* find lowest and highest alpha value in block, alphabase[0] lowest, alphabase[1] highest */ 584bf215546Sopenharmony_ci alphabase[0] = 0xff; alphabase[1] = 0x0; 585bf215546Sopenharmony_ci for (j = 0; j < numypixels; j++) { 586bf215546Sopenharmony_ci for (i = 0; i < numxpixels; i++) { 587bf215546Sopenharmony_ci if (srccolors[j][i][3] == 0) 588bf215546Sopenharmony_ci alphaabsmin = GL_TRUE; 589bf215546Sopenharmony_ci else if (srccolors[j][i][3] == 255) 590bf215546Sopenharmony_ci alphaabsmax = GL_TRUE; 591bf215546Sopenharmony_ci else { 592bf215546Sopenharmony_ci if (srccolors[j][i][3] > alphabase[1]) 593bf215546Sopenharmony_ci alphabase[1] = srccolors[j][i][3]; 594bf215546Sopenharmony_ci if (srccolors[j][i][3] < alphabase[0]) 595bf215546Sopenharmony_ci alphabase[0] = srccolors[j][i][3]; 596bf215546Sopenharmony_ci } 597bf215546Sopenharmony_ci } 598bf215546Sopenharmony_ci } 599bf215546Sopenharmony_ci 600bf215546Sopenharmony_ci 601bf215546Sopenharmony_ci if ((alphabase[0] > alphabase[1]) && !(alphaabsmin && alphaabsmax)) { /* one color, either max or min */ 602bf215546Sopenharmony_ci /* shortcut here since it is a very common case (and also avoids later problems) */ 603bf215546Sopenharmony_ci /* || (alphabase[0] == alphabase[1] && !alphaabsmin && !alphaabsmax) */ 604bf215546Sopenharmony_ci /* could also thest for alpha0 == alpha1 (and not min/max), but probably not common, so don't bother */ 605bf215546Sopenharmony_ci 606bf215546Sopenharmony_ci *blkaddr++ = srccolors[0][0][3]; 607bf215546Sopenharmony_ci blkaddr++; 608bf215546Sopenharmony_ci *blkaddr++ = 0; 609bf215546Sopenharmony_ci *blkaddr++ = 0; 610bf215546Sopenharmony_ci *blkaddr++ = 0; 611bf215546Sopenharmony_ci *blkaddr++ = 0; 612bf215546Sopenharmony_ci *blkaddr++ = 0; 613bf215546Sopenharmony_ci *blkaddr++ = 0; 614bf215546Sopenharmony_ci/* fprintf(stderr, "enc0 used\n");*/ 615bf215546Sopenharmony_ci return; 616bf215546Sopenharmony_ci } 617bf215546Sopenharmony_ci 618bf215546Sopenharmony_ci /* find best encoding for alpha0 > alpha1 */ 619bf215546Sopenharmony_ci /* it's possible this encoding is better even if both alphaabsmin and alphaabsmax are true */ 620bf215546Sopenharmony_ci alphablockerror1 = 0x0; 621bf215546Sopenharmony_ci alphablockerror2 = 0xffffffff; 622bf215546Sopenharmony_ci alphablockerror3 = 0xffffffff; 623bf215546Sopenharmony_ci if (alphaabsmin) alphause[0] = 0; 624bf215546Sopenharmony_ci else alphause[0] = alphabase[0]; 625bf215546Sopenharmony_ci if (alphaabsmax) alphause[1] = 255; 626bf215546Sopenharmony_ci else alphause[1] = alphabase[1]; 627bf215546Sopenharmony_ci /* calculate the 7 cut values, just the middle between 2 of the computed alpha values */ 628bf215546Sopenharmony_ci for (aindex = 0; aindex < 7; aindex++) { 629bf215546Sopenharmony_ci /* don't forget here is always rounded down */ 630bf215546Sopenharmony_ci acutValues[aindex] = (alphause[0] * (2*aindex + 1) + alphause[1] * (14 - (2*aindex + 1))) / 14; 631bf215546Sopenharmony_ci } 632bf215546Sopenharmony_ci 633bf215546Sopenharmony_ci for (j = 0; j < numypixels; j++) { 634bf215546Sopenharmony_ci for (i = 0; i < numxpixels; i++) { 635bf215546Sopenharmony_ci /* maybe it's overkill to have the most complicated calculation just for the error 636bf215546Sopenharmony_ci calculation which we only need to figure out if encoding1 or encoding2 is better... */ 637bf215546Sopenharmony_ci if (srccolors[j][i][3] > acutValues[0]) { 638bf215546Sopenharmony_ci alphaenc1[4*j + i] = 0; 639bf215546Sopenharmony_ci alphadist = srccolors[j][i][3] - alphause[1]; 640bf215546Sopenharmony_ci } 641bf215546Sopenharmony_ci else if (srccolors[j][i][3] > acutValues[1]) { 642bf215546Sopenharmony_ci alphaenc1[4*j + i] = 2; 643bf215546Sopenharmony_ci alphadist = srccolors[j][i][3] - (alphause[1] * 6 + alphause[0] * 1) / 7; 644bf215546Sopenharmony_ci } 645bf215546Sopenharmony_ci else if (srccolors[j][i][3] > acutValues[2]) { 646bf215546Sopenharmony_ci alphaenc1[4*j + i] = 3; 647bf215546Sopenharmony_ci alphadist = srccolors[j][i][3] - (alphause[1] * 5 + alphause[0] * 2) / 7; 648bf215546Sopenharmony_ci } 649bf215546Sopenharmony_ci else if (srccolors[j][i][3] > acutValues[3]) { 650bf215546Sopenharmony_ci alphaenc1[4*j + i] = 4; 651bf215546Sopenharmony_ci alphadist = srccolors[j][i][3] - (alphause[1] * 4 + alphause[0] * 3) / 7; 652bf215546Sopenharmony_ci } 653bf215546Sopenharmony_ci else if (srccolors[j][i][3] > acutValues[4]) { 654bf215546Sopenharmony_ci alphaenc1[4*j + i] = 5; 655bf215546Sopenharmony_ci alphadist = srccolors[j][i][3] - (alphause[1] * 3 + alphause[0] * 4) / 7; 656bf215546Sopenharmony_ci } 657bf215546Sopenharmony_ci else if (srccolors[j][i][3] > acutValues[5]) { 658bf215546Sopenharmony_ci alphaenc1[4*j + i] = 6; 659bf215546Sopenharmony_ci alphadist = srccolors[j][i][3] - (alphause[1] * 2 + alphause[0] * 5) / 7; 660bf215546Sopenharmony_ci } 661bf215546Sopenharmony_ci else if (srccolors[j][i][3] > acutValues[6]) { 662bf215546Sopenharmony_ci alphaenc1[4*j + i] = 7; 663bf215546Sopenharmony_ci alphadist = srccolors[j][i][3] - (alphause[1] * 1 + alphause[0] * 6) / 7; 664bf215546Sopenharmony_ci } 665bf215546Sopenharmony_ci else { 666bf215546Sopenharmony_ci alphaenc1[4*j + i] = 1; 667bf215546Sopenharmony_ci alphadist = srccolors[j][i][3] - alphause[0]; 668bf215546Sopenharmony_ci } 669bf215546Sopenharmony_ci alphablockerror1 += alphadist * alphadist; 670bf215546Sopenharmony_ci } 671bf215546Sopenharmony_ci } 672bf215546Sopenharmony_ci/* for (i = 0; i < 16; i++) { 673bf215546Sopenharmony_ci fprintf(stderr, "%d ", alphaenc1[i]); 674bf215546Sopenharmony_ci } 675bf215546Sopenharmony_ci fprintf(stderr, "cutVals "); 676bf215546Sopenharmony_ci for (i = 0; i < 8; i++) { 677bf215546Sopenharmony_ci fprintf(stderr, "%d ", acutValues[i]); 678bf215546Sopenharmony_ci } 679bf215546Sopenharmony_ci fprintf(stderr, "srcVals "); 680bf215546Sopenharmony_ci for (j = 0; j < numypixels; j++) 681bf215546Sopenharmony_ci for (i = 0; i < numxpixels; i++) { 682bf215546Sopenharmony_ci fprintf(stderr, "%d ", srccolors[j][i][3]); 683bf215546Sopenharmony_ci } 684bf215546Sopenharmony_ci 685bf215546Sopenharmony_ci fprintf(stderr, "\n"); 686bf215546Sopenharmony_ci }*/ 687bf215546Sopenharmony_ci /* it's not very likely this encoding is better if both alphaabsmin and alphaabsmax 688bf215546Sopenharmony_ci are false but try it anyway */ 689bf215546Sopenharmony_ci if (alphablockerror1 >= 32) { 690bf215546Sopenharmony_ci 691bf215546Sopenharmony_ci /* don't bother if encoding is already very good, this condition should also imply 692bf215546Sopenharmony_ci we have valid alphabase colors which we absolutely need (alphabase[0] <= alphabase[1]) */ 693bf215546Sopenharmony_ci alphablockerror2 = 0; 694bf215546Sopenharmony_ci for (aindex = 0; aindex < 5; aindex++) { 695bf215546Sopenharmony_ci /* don't forget here is always rounded down */ 696bf215546Sopenharmony_ci acutValues[aindex] = (alphabase[0] * (10 - (2*aindex + 1)) + alphabase[1] * (2*aindex + 1)) / 10; 697bf215546Sopenharmony_ci } 698bf215546Sopenharmony_ci for (j = 0; j < numypixels; j++) { 699bf215546Sopenharmony_ci for (i = 0; i < numxpixels; i++) { 700bf215546Sopenharmony_ci /* maybe it's overkill to have the most complicated calculation just for the error 701bf215546Sopenharmony_ci calculation which we only need to figure out if encoding1 or encoding2 is better... */ 702bf215546Sopenharmony_ci if (srccolors[j][i][3] == 0) { 703bf215546Sopenharmony_ci alphaenc2[4*j + i] = 6; 704bf215546Sopenharmony_ci alphadist = 0; 705bf215546Sopenharmony_ci } 706bf215546Sopenharmony_ci else if (srccolors[j][i][3] == 255) { 707bf215546Sopenharmony_ci alphaenc2[4*j + i] = 7; 708bf215546Sopenharmony_ci alphadist = 0; 709bf215546Sopenharmony_ci } 710bf215546Sopenharmony_ci else if (srccolors[j][i][3] <= acutValues[0]) { 711bf215546Sopenharmony_ci alphaenc2[4*j + i] = 0; 712bf215546Sopenharmony_ci alphadist = srccolors[j][i][3] - alphabase[0]; 713bf215546Sopenharmony_ci } 714bf215546Sopenharmony_ci else if (srccolors[j][i][3] <= acutValues[1]) { 715bf215546Sopenharmony_ci alphaenc2[4*j + i] = 2; 716bf215546Sopenharmony_ci alphadist = srccolors[j][i][3] - (alphabase[0] * 4 + alphabase[1] * 1) / 5; 717bf215546Sopenharmony_ci } 718bf215546Sopenharmony_ci else if (srccolors[j][i][3] <= acutValues[2]) { 719bf215546Sopenharmony_ci alphaenc2[4*j + i] = 3; 720bf215546Sopenharmony_ci alphadist = srccolors[j][i][3] - (alphabase[0] * 3 + alphabase[1] * 2) / 5; 721bf215546Sopenharmony_ci } 722bf215546Sopenharmony_ci else if (srccolors[j][i][3] <= acutValues[3]) { 723bf215546Sopenharmony_ci alphaenc2[4*j + i] = 4; 724bf215546Sopenharmony_ci alphadist = srccolors[j][i][3] - (alphabase[0] * 2 + alphabase[1] * 3) / 5; 725bf215546Sopenharmony_ci } 726bf215546Sopenharmony_ci else if (srccolors[j][i][3] <= acutValues[4]) { 727bf215546Sopenharmony_ci alphaenc2[4*j + i] = 5; 728bf215546Sopenharmony_ci alphadist = srccolors[j][i][3] - (alphabase[0] * 1 + alphabase[1] * 4) / 5; 729bf215546Sopenharmony_ci } 730bf215546Sopenharmony_ci else { 731bf215546Sopenharmony_ci alphaenc2[4*j + i] = 1; 732bf215546Sopenharmony_ci alphadist = srccolors[j][i][3] - alphabase[1]; 733bf215546Sopenharmony_ci } 734bf215546Sopenharmony_ci alphablockerror2 += alphadist * alphadist; 735bf215546Sopenharmony_ci } 736bf215546Sopenharmony_ci } 737bf215546Sopenharmony_ci 738bf215546Sopenharmony_ci 739bf215546Sopenharmony_ci /* skip this if the error is already very small 740bf215546Sopenharmony_ci this encoding is MUCH better on average than #2 though, but expensive! */ 741bf215546Sopenharmony_ci if ((alphablockerror2 > 96) && (alphablockerror1 > 96)) { 742bf215546Sopenharmony_ci GLshort blockerrlin1 = 0; 743bf215546Sopenharmony_ci GLshort blockerrlin2 = 0; 744bf215546Sopenharmony_ci GLubyte nralphainrangelow = 0; 745bf215546Sopenharmony_ci GLubyte nralphainrangehigh = 0; 746bf215546Sopenharmony_ci alphatest[0] = 0xff; 747bf215546Sopenharmony_ci alphatest[1] = 0x0; 748bf215546Sopenharmony_ci /* if we have large range it's likely there are values close to 0/255, try to map them to 0/255 */ 749bf215546Sopenharmony_ci for (j = 0; j < numypixels; j++) { 750bf215546Sopenharmony_ci for (i = 0; i < numxpixels; i++) { 751bf215546Sopenharmony_ci if ((srccolors[j][i][3] > alphatest[1]) && (srccolors[j][i][3] < (255 -(alphabase[1] - alphabase[0]) / 28))) 752bf215546Sopenharmony_ci alphatest[1] = srccolors[j][i][3]; 753bf215546Sopenharmony_ci if ((srccolors[j][i][3] < alphatest[0]) && (srccolors[j][i][3] > (alphabase[1] - alphabase[0]) / 28)) 754bf215546Sopenharmony_ci alphatest[0] = srccolors[j][i][3]; 755bf215546Sopenharmony_ci } 756bf215546Sopenharmony_ci } 757bf215546Sopenharmony_ci /* shouldn't happen too often, don't really care about those degenerated cases */ 758bf215546Sopenharmony_ci if (alphatest[1] <= alphatest[0]) { 759bf215546Sopenharmony_ci alphatest[0] = 1; 760bf215546Sopenharmony_ci alphatest[1] = 254; 761bf215546Sopenharmony_ci/* fprintf(stderr, "only 1 or 0 colors for encoding!\n");*/ 762bf215546Sopenharmony_ci } 763bf215546Sopenharmony_ci for (aindex = 0; aindex < 5; aindex++) { 764bf215546Sopenharmony_ci /* don't forget here is always rounded down */ 765bf215546Sopenharmony_ci acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10; 766bf215546Sopenharmony_ci } 767bf215546Sopenharmony_ci 768bf215546Sopenharmony_ci /* find the "average" difference between the alpha values and the next encoded value. 769bf215546Sopenharmony_ci This is then used to calculate new base values. 770bf215546Sopenharmony_ci Should there be some weighting, i.e. those values closer to alphatest[x] have more weight, 771bf215546Sopenharmony_ci since they will see more improvement, and also because the values in the middle are somewhat 772bf215546Sopenharmony_ci likely to get no improvement at all (because the base values might move in different directions)? 773bf215546Sopenharmony_ci OTOH it would mean the values in the middle are even less likely to get an improvement 774bf215546Sopenharmony_ci */ 775bf215546Sopenharmony_ci for (j = 0; j < numypixels; j++) { 776bf215546Sopenharmony_ci for (i = 0; i < numxpixels; i++) { 777bf215546Sopenharmony_ci if (srccolors[j][i][3] <= alphatest[0] / 2) { 778bf215546Sopenharmony_ci } 779bf215546Sopenharmony_ci else if (srccolors[j][i][3] > ((255 + alphatest[1]) / 2)) { 780bf215546Sopenharmony_ci } 781bf215546Sopenharmony_ci else if (srccolors[j][i][3] <= acutValues[0]) { 782bf215546Sopenharmony_ci blockerrlin1 += (srccolors[j][i][3] - alphatest[0]); 783bf215546Sopenharmony_ci nralphainrangelow += 1; 784bf215546Sopenharmony_ci } 785bf215546Sopenharmony_ci else if (srccolors[j][i][3] <= acutValues[1]) { 786bf215546Sopenharmony_ci blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 4 + alphatest[1] * 1) / 5); 787bf215546Sopenharmony_ci blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 4 + alphatest[1] * 1) / 5); 788bf215546Sopenharmony_ci nralphainrangelow += 1; 789bf215546Sopenharmony_ci nralphainrangehigh += 1; 790bf215546Sopenharmony_ci } 791bf215546Sopenharmony_ci else if (srccolors[j][i][3] <= acutValues[2]) { 792bf215546Sopenharmony_ci blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 3 + alphatest[1] * 2) / 5); 793bf215546Sopenharmony_ci blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 3 + alphatest[1] * 2) / 5); 794bf215546Sopenharmony_ci nralphainrangelow += 1; 795bf215546Sopenharmony_ci nralphainrangehigh += 1; 796bf215546Sopenharmony_ci } 797bf215546Sopenharmony_ci else if (srccolors[j][i][3] <= acutValues[3]) { 798bf215546Sopenharmony_ci blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 2 + alphatest[1] * 3) / 5); 799bf215546Sopenharmony_ci blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 2 + alphatest[1] * 3) / 5); 800bf215546Sopenharmony_ci nralphainrangelow += 1; 801bf215546Sopenharmony_ci nralphainrangehigh += 1; 802bf215546Sopenharmony_ci } 803bf215546Sopenharmony_ci else if (srccolors[j][i][3] <= acutValues[4]) { 804bf215546Sopenharmony_ci blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 1 + alphatest[1] * 4) / 5); 805bf215546Sopenharmony_ci blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 1 + alphatest[1] * 4) / 5); 806bf215546Sopenharmony_ci nralphainrangelow += 1; 807bf215546Sopenharmony_ci nralphainrangehigh += 1; 808bf215546Sopenharmony_ci } 809bf215546Sopenharmony_ci else { 810bf215546Sopenharmony_ci blockerrlin2 += (srccolors[j][i][3] - alphatest[1]); 811bf215546Sopenharmony_ci nralphainrangehigh += 1; 812bf215546Sopenharmony_ci } 813bf215546Sopenharmony_ci } 814bf215546Sopenharmony_ci } 815bf215546Sopenharmony_ci /* shouldn't happen often, needed to avoid div by zero */ 816bf215546Sopenharmony_ci if (nralphainrangelow == 0) nralphainrangelow = 1; 817bf215546Sopenharmony_ci if (nralphainrangehigh == 0) nralphainrangehigh = 1; 818bf215546Sopenharmony_ci alphatest[0] = alphatest[0] + (blockerrlin1 / nralphainrangelow); 819bf215546Sopenharmony_ci/* fprintf(stderr, "block err lin low %d, nr %d\n", blockerrlin1, nralphainrangelow); 820bf215546Sopenharmony_ci fprintf(stderr, "block err lin high %d, nr %d\n", blockerrlin2, nralphainrangehigh);*/ 821bf215546Sopenharmony_ci /* again shouldn't really happen often... */ 822bf215546Sopenharmony_ci if (alphatest[0] < 0) { 823bf215546Sopenharmony_ci alphatest[0] = 0; 824bf215546Sopenharmony_ci/* fprintf(stderr, "adj alpha base val to 0\n");*/ 825bf215546Sopenharmony_ci } 826bf215546Sopenharmony_ci alphatest[1] = alphatest[1] + (blockerrlin2 / nralphainrangehigh); 827bf215546Sopenharmony_ci if (alphatest[1] > 255) { 828bf215546Sopenharmony_ci alphatest[1] = 255; 829bf215546Sopenharmony_ci/* fprintf(stderr, "adj alpha base val to 255\n");*/ 830bf215546Sopenharmony_ci } 831bf215546Sopenharmony_ci 832bf215546Sopenharmony_ci alphablockerror3 = 0; 833bf215546Sopenharmony_ci for (aindex = 0; aindex < 5; aindex++) { 834bf215546Sopenharmony_ci /* don't forget here is always rounded down */ 835bf215546Sopenharmony_ci acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10; 836bf215546Sopenharmony_ci } 837bf215546Sopenharmony_ci for (j = 0; j < numypixels; j++) { 838bf215546Sopenharmony_ci for (i = 0; i < numxpixels; i++) { 839bf215546Sopenharmony_ci /* maybe it's overkill to have the most complicated calculation just for the error 840bf215546Sopenharmony_ci calculation which we only need to figure out if encoding1 or encoding2 is better... */ 841bf215546Sopenharmony_ci if (srccolors[j][i][3] <= alphatest[0] / 2) { 842bf215546Sopenharmony_ci alphaenc3[4*j + i] = 6; 843bf215546Sopenharmony_ci alphadist = srccolors[j][i][3]; 844bf215546Sopenharmony_ci } 845bf215546Sopenharmony_ci else if (srccolors[j][i][3] > ((255 + alphatest[1]) / 2)) { 846bf215546Sopenharmony_ci alphaenc3[4*j + i] = 7; 847bf215546Sopenharmony_ci alphadist = 255 - srccolors[j][i][3]; 848bf215546Sopenharmony_ci } 849bf215546Sopenharmony_ci else if (srccolors[j][i][3] <= acutValues[0]) { 850bf215546Sopenharmony_ci alphaenc3[4*j + i] = 0; 851bf215546Sopenharmony_ci alphadist = srccolors[j][i][3] - alphatest[0]; 852bf215546Sopenharmony_ci } 853bf215546Sopenharmony_ci else if (srccolors[j][i][3] <= acutValues[1]) { 854bf215546Sopenharmony_ci alphaenc3[4*j + i] = 2; 855bf215546Sopenharmony_ci alphadist = srccolors[j][i][3] - (alphatest[0] * 4 + alphatest[1] * 1) / 5; 856bf215546Sopenharmony_ci } 857bf215546Sopenharmony_ci else if (srccolors[j][i][3] <= acutValues[2]) { 858bf215546Sopenharmony_ci alphaenc3[4*j + i] = 3; 859bf215546Sopenharmony_ci alphadist = srccolors[j][i][3] - (alphatest[0] * 3 + alphatest[1] * 2) / 5; 860bf215546Sopenharmony_ci } 861bf215546Sopenharmony_ci else if (srccolors[j][i][3] <= acutValues[3]) { 862bf215546Sopenharmony_ci alphaenc3[4*j + i] = 4; 863bf215546Sopenharmony_ci alphadist = srccolors[j][i][3] - (alphatest[0] * 2 + alphatest[1] * 3) / 5; 864bf215546Sopenharmony_ci } 865bf215546Sopenharmony_ci else if (srccolors[j][i][3] <= acutValues[4]) { 866bf215546Sopenharmony_ci alphaenc3[4*j + i] = 5; 867bf215546Sopenharmony_ci alphadist = srccolors[j][i][3] - (alphatest[0] * 1 + alphatest[1] * 4) / 5; 868bf215546Sopenharmony_ci } 869bf215546Sopenharmony_ci else { 870bf215546Sopenharmony_ci alphaenc3[4*j + i] = 1; 871bf215546Sopenharmony_ci alphadist = srccolors[j][i][3] - alphatest[1]; 872bf215546Sopenharmony_ci } 873bf215546Sopenharmony_ci alphablockerror3 += alphadist * alphadist; 874bf215546Sopenharmony_ci } 875bf215546Sopenharmony_ci } 876bf215546Sopenharmony_ci } 877bf215546Sopenharmony_ci } 878bf215546Sopenharmony_ci /* write the alpha values and encoding back. */ 879bf215546Sopenharmony_ci if ((alphablockerror1 <= alphablockerror2) && (alphablockerror1 <= alphablockerror3)) { 880bf215546Sopenharmony_ci/* if (alphablockerror1 > 96) fprintf(stderr, "enc1 used, error %d\n", alphablockerror1);*/ 881bf215546Sopenharmony_ci writedxt5encodedalphablock( blkaddr, alphause[1], alphause[0], alphaenc1 ); 882bf215546Sopenharmony_ci } 883bf215546Sopenharmony_ci else if (alphablockerror2 <= alphablockerror3) { 884bf215546Sopenharmony_ci/* if (alphablockerror2 > 96) fprintf(stderr, "enc2 used, error %d\n", alphablockerror2);*/ 885bf215546Sopenharmony_ci writedxt5encodedalphablock( blkaddr, alphabase[0], alphabase[1], alphaenc2 ); 886bf215546Sopenharmony_ci } 887bf215546Sopenharmony_ci else { 888bf215546Sopenharmony_ci/* fprintf(stderr, "enc3 used, error %d\n", alphablockerror3);*/ 889bf215546Sopenharmony_ci writedxt5encodedalphablock( blkaddr, (GLubyte)alphatest[0], (GLubyte)alphatest[1], alphaenc3 ); 890bf215546Sopenharmony_ci } 891bf215546Sopenharmony_ci} 892bf215546Sopenharmony_ci 893bf215546Sopenharmony_cistatic void extractsrccolors( GLubyte srcpixels[4][4][4], const GLchan *srcaddr, 894bf215546Sopenharmony_ci GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps) 895bf215546Sopenharmony_ci{ 896bf215546Sopenharmony_ci GLubyte i, j, c; 897bf215546Sopenharmony_ci const GLchan *curaddr; 898bf215546Sopenharmony_ci for (j = 0; j < numypixels; j++) { 899bf215546Sopenharmony_ci curaddr = srcaddr + j * srcRowStride * comps; 900bf215546Sopenharmony_ci for (i = 0; i < numxpixels; i++) { 901bf215546Sopenharmony_ci for (c = 0; c < comps; c++) { 902bf215546Sopenharmony_ci srcpixels[j][i][c] = *curaddr++ / (CHAN_MAX / 255); 903bf215546Sopenharmony_ci } 904bf215546Sopenharmony_ci } 905bf215546Sopenharmony_ci } 906bf215546Sopenharmony_ci} 907bf215546Sopenharmony_ci 908bf215546Sopenharmony_ci 909bf215546Sopenharmony_cistatic void 910bf215546Sopenharmony_citx_compress_dxt1(int srccomps, int width, int height, 911bf215546Sopenharmony_ci const GLubyte *srcPixData, GLubyte *dest, int dstRowStride, 912bf215546Sopenharmony_ci unsigned dstComps) 913bf215546Sopenharmony_ci{ 914bf215546Sopenharmony_ci GLenum destFormat = dstComps == 3 ? GL_COMPRESSED_RGB_S3TC_DXT1_EXT 915bf215546Sopenharmony_ci : GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; 916bf215546Sopenharmony_ci GLubyte *blkaddr = dest; 917bf215546Sopenharmony_ci GLubyte srcpixels[4][4][4]; 918bf215546Sopenharmony_ci const GLchan *srcaddr = srcPixData; 919bf215546Sopenharmony_ci int numxpixels, numypixels; 920bf215546Sopenharmony_ci 921bf215546Sopenharmony_ci /* hmm we used to get called without dstRowStride... */ 922bf215546Sopenharmony_ci int dstRowDiff = dstRowStride >= (width * 2) ? 923bf215546Sopenharmony_ci dstRowStride - (((width + 3) & ~3) * 2) : 0; 924bf215546Sopenharmony_ci /* fprintf(stderr, "dxt1 tex width %d tex height %d dstRowStride %d\n", 925bf215546Sopenharmony_ci width, height, dstRowStride); */ 926bf215546Sopenharmony_ci for (int j = 0; j < height; j += 4) { 927bf215546Sopenharmony_ci if (height > j + 3) numypixels = 4; 928bf215546Sopenharmony_ci else numypixels = height - j; 929bf215546Sopenharmony_ci srcaddr = srcPixData + j * width * srccomps; 930bf215546Sopenharmony_ci for (int i = 0; i < width; i += 4) { 931bf215546Sopenharmony_ci if (width > i + 3) numxpixels = 4; 932bf215546Sopenharmony_ci else numxpixels = width - i; 933bf215546Sopenharmony_ci extractsrccolors(srcpixels, srcaddr, width, numxpixels, numypixels, srccomps); 934bf215546Sopenharmony_ci encodedxtcolorblockfaster(blkaddr, srcpixels, numxpixels, numypixels, destFormat); 935bf215546Sopenharmony_ci srcaddr += srccomps * numxpixels; 936bf215546Sopenharmony_ci blkaddr += 8; 937bf215546Sopenharmony_ci } 938bf215546Sopenharmony_ci blkaddr += dstRowDiff; 939bf215546Sopenharmony_ci } 940bf215546Sopenharmony_ci} 941bf215546Sopenharmony_ci 942bf215546Sopenharmony_cistatic void 943bf215546Sopenharmony_citx_compress_dxt3(int srccomps, int width, int height, 944bf215546Sopenharmony_ci const GLubyte *srcPixData, GLubyte *dest, int dstRowStride) 945bf215546Sopenharmony_ci{ 946bf215546Sopenharmony_ci GLenum destFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; 947bf215546Sopenharmony_ci GLubyte *blkaddr = dest; 948bf215546Sopenharmony_ci GLubyte srcpixels[4][4][4]; 949bf215546Sopenharmony_ci const GLchan *srcaddr = srcPixData; 950bf215546Sopenharmony_ci int numxpixels, numypixels; 951bf215546Sopenharmony_ci 952bf215546Sopenharmony_ci int dstRowDiff = dstRowStride >= (width * 4) ? 953bf215546Sopenharmony_ci dstRowStride - (((width + 3) & ~3) * 4) : 0; 954bf215546Sopenharmony_ci /* fprintf(stderr, "dxt3 tex width %d tex height %d dstRowStride %d\n", 955bf215546Sopenharmony_ci width, height, dstRowStride); */ 956bf215546Sopenharmony_ci for (int j = 0; j < height; j += 4) { 957bf215546Sopenharmony_ci if (height > j + 3) numypixels = 4; 958bf215546Sopenharmony_ci else numypixels = height - j; 959bf215546Sopenharmony_ci srcaddr = srcPixData + j * width * srccomps; 960bf215546Sopenharmony_ci for (int i = 0; i < width; i += 4) { 961bf215546Sopenharmony_ci if (width > i + 3) numxpixels = 4; 962bf215546Sopenharmony_ci else numxpixels = width - i; 963bf215546Sopenharmony_ci extractsrccolors(srcpixels, srcaddr, width, numxpixels, numypixels, srccomps); 964bf215546Sopenharmony_ci *blkaddr++ = (srcpixels[0][0][3] >> 4) | (srcpixels[0][1][3] & 0xf0); 965bf215546Sopenharmony_ci *blkaddr++ = (srcpixels[0][2][3] >> 4) | (srcpixels[0][3][3] & 0xf0); 966bf215546Sopenharmony_ci *blkaddr++ = (srcpixels[1][0][3] >> 4) | (srcpixels[1][1][3] & 0xf0); 967bf215546Sopenharmony_ci *blkaddr++ = (srcpixels[1][2][3] >> 4) | (srcpixels[1][3][3] & 0xf0); 968bf215546Sopenharmony_ci *blkaddr++ = (srcpixels[2][0][3] >> 4) | (srcpixels[2][1][3] & 0xf0); 969bf215546Sopenharmony_ci *blkaddr++ = (srcpixels[2][2][3] >> 4) | (srcpixels[2][3][3] & 0xf0); 970bf215546Sopenharmony_ci *blkaddr++ = (srcpixels[3][0][3] >> 4) | (srcpixels[3][1][3] & 0xf0); 971bf215546Sopenharmony_ci *blkaddr++ = (srcpixels[3][2][3] >> 4) | (srcpixels[3][3][3] & 0xf0); 972bf215546Sopenharmony_ci encodedxtcolorblockfaster(blkaddr, srcpixels, numxpixels, numypixels, destFormat); 973bf215546Sopenharmony_ci srcaddr += srccomps * numxpixels; 974bf215546Sopenharmony_ci blkaddr += 8; 975bf215546Sopenharmony_ci } 976bf215546Sopenharmony_ci blkaddr += dstRowDiff; 977bf215546Sopenharmony_ci } 978bf215546Sopenharmony_ci} 979bf215546Sopenharmony_ci 980bf215546Sopenharmony_cistatic void 981bf215546Sopenharmony_citx_compress_dxt5(int srccomps, int width, int height, 982bf215546Sopenharmony_ci const GLubyte *srcPixData, GLubyte *dest, int dstRowStride) 983bf215546Sopenharmony_ci{ 984bf215546Sopenharmony_ci GLenum destFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; 985bf215546Sopenharmony_ci GLubyte *blkaddr = dest; 986bf215546Sopenharmony_ci GLubyte srcpixels[4][4][4]; 987bf215546Sopenharmony_ci const GLchan *srcaddr = srcPixData; 988bf215546Sopenharmony_ci int numxpixels, numypixels; 989bf215546Sopenharmony_ci 990bf215546Sopenharmony_ci int dstRowDiff = dstRowStride >= (width * 4) ? 991bf215546Sopenharmony_ci dstRowStride - (((width + 3) & ~3) * 4) : 0; 992bf215546Sopenharmony_ci /* fprintf(stderr, "dxt5 tex width %d tex height %d dstRowStride %d\n", 993bf215546Sopenharmony_ci width, height, dstRowStride); */ 994bf215546Sopenharmony_ci for (int j = 0; j < height; j += 4) { 995bf215546Sopenharmony_ci if (height > j + 3) numypixels = 4; 996bf215546Sopenharmony_ci else numypixels = height - j; 997bf215546Sopenharmony_ci srcaddr = srcPixData + j * width * srccomps; 998bf215546Sopenharmony_ci for (int i = 0; i < width; i += 4) { 999bf215546Sopenharmony_ci if (width > i + 3) numxpixels = 4; 1000bf215546Sopenharmony_ci else numxpixels = width - i; 1001bf215546Sopenharmony_ci extractsrccolors(srcpixels, srcaddr, width, numxpixels, numypixels, srccomps); 1002bf215546Sopenharmony_ci encodedxt5alpha(blkaddr, srcpixels, numxpixels, numypixels); 1003bf215546Sopenharmony_ci encodedxtcolorblockfaster(blkaddr + 8, srcpixels, numxpixels, numypixels, destFormat); 1004bf215546Sopenharmony_ci srcaddr += srccomps * numxpixels; 1005bf215546Sopenharmony_ci blkaddr += 16; 1006bf215546Sopenharmony_ci } 1007bf215546Sopenharmony_ci blkaddr += dstRowDiff; 1008bf215546Sopenharmony_ci } 1009bf215546Sopenharmony_ci} 1010bf215546Sopenharmony_ci 1011bf215546Sopenharmony_cistatic void 1012bf215546Sopenharmony_citx_compress_dxtn(GLint srccomps, GLint width, GLint height, 1013bf215546Sopenharmony_ci const GLubyte *srcPixData, GLenum destFormat, 1014bf215546Sopenharmony_ci GLubyte *dest, GLint dstRowStride) 1015bf215546Sopenharmony_ci{ 1016bf215546Sopenharmony_ci switch (destFormat) { 1017bf215546Sopenharmony_ci case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 1018bf215546Sopenharmony_ci tx_compress_dxt1(srccomps, width, height, srcPixData, 1019bf215546Sopenharmony_ci dest, dstRowStride, 3); 1020bf215546Sopenharmony_ci break; 1021bf215546Sopenharmony_ci case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 1022bf215546Sopenharmony_ci tx_compress_dxt1(srccomps, width, height, srcPixData, 1023bf215546Sopenharmony_ci dest, dstRowStride, 4); 1024bf215546Sopenharmony_ci break; 1025bf215546Sopenharmony_ci case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: 1026bf215546Sopenharmony_ci tx_compress_dxt3(srccomps, width, height, srcPixData, 1027bf215546Sopenharmony_ci dest, dstRowStride); 1028bf215546Sopenharmony_ci break; 1029bf215546Sopenharmony_ci case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: 1030bf215546Sopenharmony_ci tx_compress_dxt5(srccomps, width, height, srcPixData, 1031bf215546Sopenharmony_ci dest, dstRowStride); 1032bf215546Sopenharmony_ci break; 1033bf215546Sopenharmony_ci default: 1034bf215546Sopenharmony_ci unreachable("unknown DXTn format"); 1035bf215546Sopenharmony_ci } 1036bf215546Sopenharmony_ci} 1037bf215546Sopenharmony_ci 1038bf215546Sopenharmony_ci#endif 1039