Path: blob/master/libmupen64plus/mupen64plus-video-glide64mk2/src/GlideHQ/tc-1.1+/dxtn.c
2 views
/*1* DXTn codec2* Version: 1.13*4* Copyright (C) 2004 Daniel Borca All Rights Reserved.5*6* this is free software; you can redistribute it and/or modify7* it under the terms of the GNU General Public License as published by8* the Free Software Foundation; either version 2, or (at your option)9* any later version.10*11* this is distributed in the hope that it will be useful,12* but WITHOUT ANY WARRANTY; without even the implied warranty of13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14* GNU General Public License for more details.15*16* You should have received a copy of the GNU General Public License17* along with GNU Make; see the file COPYING. If not, write to18* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.19*/2021/* Copyright (C) 2007 Hiroshi Morii <koolsmoky(at)users.sourceforge.net>22* Added support for ARGB inputs, DXT3,5 workaround for ATI Radeons, and23* YUV conversions to determine representative colors.24*/252627#include <stdlib.h>28#include <string.h>29#include <assert.h>3031#include <stdio.h>3233#include "types.h"34#include "internal.h"35#include "dxtn.h"363738/***************************************************************************\39* DXTn encoder40*41* The encoder was built by reversing the decoder,42* and is vaguely based on FXT1 codec. Note that this code43* is merely a proof of concept, since it is highly UNoptimized!44\***************************************************************************/454647#define MAX_COMP 4 /* ever needed maximum number of components in texel */48#define MAX_VECT 4 /* ever needed maximum number of base vectors to find */49#define N_TEXELS 16 /* number of texels in a block (always 16) */50#define COLOR565(v) (word)((((v)[RCOMP] & 0xf8) << 8) | (((v)[GCOMP] & 0xfc) << 3) | ((v)[BCOMP] >> 3))515253static const int dxtn_color_tlat[2][4] = {54{ 0, 2, 3, 1 },55{ 0, 2, 1, 3 }56};5758static const int dxtn_alpha_tlat[2][8] = {59{ 0, 2, 3, 4, 5, 6, 7, 1 },60{ 0, 2, 3, 4, 5, 1, 6, 7 }61};626364static void65dxt1_rgb_quantize (dword *cc, const byte *lines[], int comps)66{67float b, iv[MAX_COMP]; /* interpolation vector */6869dword hi; /* high doubleword */70int color0, color1;71int n_vect;72const int n_comp = 3;73int black = 0;7475#ifndef YUV76int minSum = 2000; /* big enough */77#else78int minSum = 2000000;79#endif80int maxSum = -1; /* small enough */81int minCol = 0; /* phoudoin: silent compiler! */82int maxCol = 0; /* phoudoin: silent compiler! */8384byte input[N_TEXELS][MAX_COMP];85int i, k, l;8687/* make the whole block opaque */88/* we will NEVER reference ACOMP of any pixel */8990/* 4 texels each line */91#ifndef ARGB92for (l = 0; l < 4; l++) {93for (k = 0; k < 4; k++) {94for (i = 0; i < comps; i++) {95input[k + l * 4][i] = *lines[l]++;96}97}98}99#else100/* H.Morii - support for ARGB inputs */101for (l = 0; l < 4; l++) {102for (k = 0; k < 4; k++) {103input[k + l * 4][2] = *lines[l]++;104input[k + l * 4][1] = *lines[l]++;105input[k + l * 4][0] = *lines[l]++;106if (comps == 4) input[k + l * 4][3] = *lines[l]++;107}108}109#endif110111/* Our solution here is to find the darkest and brightest colors in112* the 4x4 tile and use those as the two representative colors.113* There are probably better algorithms to use (histogram-based).114*/115for (k = 0; k < N_TEXELS; k++) {116int sum = 0;117#ifndef YUV118for (i = 0; i < n_comp; i++) {119sum += input[k][i];120}121#else122/* RGB to YUV conversion according to CCIR 601 specs123* Y = 0.299R+0.587G+0.114B124* U = 0.713(R - Y) = 0.500R-0.419G-0.081B125* V = 0.564(B - Y) = -0.169R-0.331G+0.500B126*/127sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] + 114 * input[k][BCOMP];128#endif129if (minSum > sum) {130minSum = sum;131minCol = k;132}133if (maxSum < sum) {134maxSum = sum;135maxCol = k;136}137if (sum == 0) {138black = 1;139}140}141142color0 = COLOR565(input[minCol]);143color1 = COLOR565(input[maxCol]);144145if (color0 == color1) {146/* we'll use 3-vector */147cc[0] = color0 | (color1 << 16);148hi = black ? -1 : 0;149} else {150if (black && ((color0 == 0) || (color1 == 0))) {151/* we still can use 4-vector */152black = 0;153}154155if (black ^ (color0 <= color1)) {156int aux;157aux = color0;158color0 = color1;159color1 = aux;160aux = minCol;161minCol = maxCol;162maxCol = aux;163}164n_vect = (color0 <= color1) ? 2 : 3;165166MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]);167168/* add in texels */169cc[0] = color0 | (color1 << 16);170hi = 0;171for (k = N_TEXELS - 1; k >= 0; k--) {172int texel = 3;173int sum = 0;174if (black) {175for (i = 0; i < n_comp; i++) {176sum += input[k][i];177}178}179if (!black || sum) {180/* interpolate color */181CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);182texel = dxtn_color_tlat[black][texel];183}184/* add in texel */185hi <<= 2;186hi |= texel;187}188}189cc[1] = hi;190}191192193static void194dxt1_rgba_quantize (dword *cc, const byte *lines[], int comps)195{196float b, iv[MAX_COMP]; /* interpolation vector */197198dword hi; /* high doubleword */199int color0, color1;200int n_vect;201const int n_comp = 3;202int transparent = 0;203204#ifndef YUV205int minSum = 2000; /* big enough */206#else207int minSum = 2000000;208#endif209int maxSum = -1; /* small enough */210int minCol = 0; /* phoudoin: silent compiler! */211int maxCol = 0; /* phoudoin: silent compiler! */212213byte input[N_TEXELS][MAX_COMP];214int i, k, l;215216if (comps == 3) {217/* make the whole block opaque */218memset(input, -1, sizeof(input));219}220221/* 4 texels each line */222#ifndef ARGB223for (l = 0; l < 4; l++) {224for (k = 0; k < 4; k++) {225for (i = 0; i < comps; i++) {226input[k + l * 4][i] = *lines[l]++;227}228}229}230#else231/* H.Morii - support for ARGB inputs */232for (l = 0; l < 4; l++) {233for (k = 0; k < 4; k++) {234input[k + l * 4][2] = *lines[l]++;235input[k + l * 4][1] = *lines[l]++;236input[k + l * 4][0] = *lines[l]++;237if (comps == 4) input[k + l * 4][3] = *lines[l]++;238}239}240#endif241242/* Our solution here is to find the darkest and brightest colors in243* the 4x4 tile and use those as the two representative colors.244* There are probably better algorithms to use (histogram-based).245*/246for (k = 0; k < N_TEXELS; k++) {247int sum = 0;248#ifndef YUV249for (i = 0; i < n_comp; i++) {250sum += input[k][i];251}252#else253sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] + 114 * input[k][BCOMP];254#endif255if (minSum > sum) {256minSum = sum;257minCol = k;258}259if (maxSum < sum) {260maxSum = sum;261maxCol = k;262}263if (input[k][ACOMP] < 128) {264transparent = 1;265}266}267268color0 = COLOR565(input[minCol]);269color1 = COLOR565(input[maxCol]);270271if (color0 == color1) {272/* we'll use 3-vector */273cc[0] = color0 | (color1 << 16);274hi = transparent ? -1 : 0;275} else {276if (transparent ^ (color0 <= color1)) {277int aux;278aux = color0;279color0 = color1;280color1 = aux;281aux = minCol;282minCol = maxCol;283maxCol = aux;284}285n_vect = (color0 <= color1) ? 2 : 3;286287MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]);288289/* add in texels */290cc[0] = color0 | (color1 << 16);291hi = 0;292for (k = N_TEXELS - 1; k >= 0; k--) {293int texel = 3;294if (input[k][ACOMP] >= 128) {295/* interpolate color */296CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);297texel = dxtn_color_tlat[transparent][texel];298}299/* add in texel */300hi <<= 2;301hi |= texel;302}303}304cc[1] = hi;305}306307308static void309dxt3_rgba_quantize (dword *cc, const byte *lines[], int comps)310{311float b, iv[MAX_COMP]; /* interpolation vector */312313dword lolo, lohi; /* low quadword: lo dword, hi dword */314dword hihi; /* high quadword: high dword */315int color0, color1;316const int n_vect = 3;317const int n_comp = 3;318319#ifndef YUV320int minSum = 2000; /* big enough */321#else322int minSum = 2000000;323#endif324int maxSum = -1; /* small enough */325int minCol = 0; /* phoudoin: silent compiler! */326int maxCol = 0; /* phoudoin: silent compiler! */327328byte input[N_TEXELS][MAX_COMP];329int i, k, l;330331if (comps == 3) {332/* make the whole block opaque */333memset(input, -1, sizeof(input));334}335336/* 4 texels each line */337#ifndef ARGB338for (l = 0; l < 4; l++) {339for (k = 0; k < 4; k++) {340for (i = 0; i < comps; i++) {341input[k + l * 4][i] = *lines[l]++;342}343}344}345#else346/* H.Morii - support for ARGB inputs */347for (l = 0; l < 4; l++) {348for (k = 0; k < 4; k++) {349input[k + l * 4][2] = *lines[l]++;350input[k + l * 4][1] = *lines[l]++;351input[k + l * 4][0] = *lines[l]++;352if (comps == 4) input[k + l * 4][3] = *lines[l]++;353}354}355#endif356357/* Our solution here is to find the darkest and brightest colors in358* the 4x4 tile and use those as the two representative colors.359* There are probably better algorithms to use (histogram-based).360*/361for (k = 0; k < N_TEXELS; k++) {362int sum = 0;363#ifndef YUV364for (i = 0; i < n_comp; i++) {365sum += input[k][i];366}367#else368sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] + 114 * input[k][BCOMP];369#endif370if (minSum > sum) {371minSum = sum;372minCol = k;373}374if (maxSum < sum) {375maxSum = sum;376maxCol = k;377}378}379380/* add in alphas */381lolo = lohi = 0;382for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {383/* add in alpha */384lohi <<= 4;385lohi |= input[k][ACOMP] >> 4;386}387cc[1] = lohi;388for (; k >= 0; k--) {389/* add in alpha */390lolo <<= 4;391lolo |= input[k][ACOMP] >> 4;392}393cc[0] = lolo;394395color0 = COLOR565(input[minCol]);396color1 = COLOR565(input[maxCol]);397398#ifdef RADEON399/* H.Morii - Workaround for ATI Radeon400* According to the OpenGL EXT_texture_compression_s3tc specs,401* the encoding of the RGB components for DXT3 and DXT5 formats402* use the non-transparent encodings of DXT1 but treated as403* though color0 > color1, regardless of the actual values of404* color0 and color1. ATI Radeons however require the values to405* be color0 > color1.406*/407if (color0 < color1) {408int aux;409aux = color0;410color0 = color1;411color1 = aux;412aux = minCol;413minCol = maxCol;414maxCol = aux;415}416#endif417418cc[2] = color0 | (color1 << 16);419420hihi = 0;421if (color0 != color1) {422MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]);423424/* add in texels */425for (k = N_TEXELS - 1; k >= 0; k--) {426int texel;427/* interpolate color */428CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);429texel = dxtn_color_tlat[0][texel];430/* add in texel */431hihi <<= 2;432hihi |= texel;433}434}435cc[3] = hihi;436}437438439static void440dxt5_rgba_quantize (dword *cc, const byte *lines[], int comps)441{442float b, iv[MAX_COMP]; /* interpolation vector */443444qword lo; /* low quadword */445dword hihi; /* high quadword: high dword */446int color0, color1;447const int n_vect = 3;448const int n_comp = 3;449450#ifndef YUV451int minSum = 2000; /* big enough */452#else453int minSum = 2000000;454#endif455int maxSum = -1; /* small enough */456int minCol = 0; /* phoudoin: silent compiler! */457int maxCol = 0; /* phoudoin: silent compiler! */458int alpha0 = 2000; /* big enough */459int alpha1 = -1; /* small enough */460int anyZero = 0, anyOne = 0;461int a_vect;462463byte input[N_TEXELS][MAX_COMP];464int i, k, l;465466if (comps == 3) {467/* make the whole block opaque */468memset(input, -1, sizeof(input));469}470471/* 4 texels each line */472#ifndef ARGB473for (l = 0; l < 4; l++) {474for (k = 0; k < 4; k++) {475for (i = 0; i < comps; i++) {476input[k + l * 4][i] = *lines[l]++;477}478}479}480#else481/* H.Morii - support for ARGB inputs */482for (l = 0; l < 4; l++) {483for (k = 0; k < 4; k++) {484input[k + l * 4][2] = *lines[l]++;485input[k + l * 4][1] = *lines[l]++;486input[k + l * 4][0] = *lines[l]++;487if (comps == 4) input[k + l * 4][3] = *lines[l]++;488}489}490#endif491492/* Our solution here is to find the darkest and brightest colors in493* the 4x4 tile and use those as the two representative colors.494* There are probably better algorithms to use (histogram-based).495*/496for (k = 0; k < N_TEXELS; k++) {497int sum = 0;498#ifndef YUV499for (i = 0; i < n_comp; i++) {500sum += input[k][i];501}502#else503sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] + 114 * input[k][BCOMP];504#endif505if (minSum > sum) {506minSum = sum;507minCol = k;508}509if (maxSum < sum) {510maxSum = sum;511maxCol = k;512}513if (alpha0 > input[k][ACOMP]) {514alpha0 = input[k][ACOMP];515}516if (alpha1 < input[k][ACOMP]) {517alpha1 = input[k][ACOMP];518}519if (input[k][ACOMP] == 0) {520anyZero = 1;521}522if (input[k][ACOMP] == 255) {523anyOne = 1;524}525}526527/* add in alphas */528if (alpha0 == alpha1) {529/* we'll use 6-vector */530cc[0] = alpha0 | (alpha1 << 8);531cc[1] = 0;532} else {533if (anyZero && ((alpha0 == 0) || (alpha1 == 0))) {534/* we still might use 8-vector */535anyZero = 0;536}537if (anyOne && ((alpha0 == 255) || (alpha1 == 255))) {538/* we still might use 8-vector */539anyOne = 0;540}541if ((anyZero | anyOne) ^ (alpha0 <= alpha1)) {542int aux;543aux = alpha0;544alpha0 = alpha1;545alpha1 = aux;546}547a_vect = (alpha0 <= alpha1) ? 5 : 7;548549/* compute interpolation vector */550iv[ACOMP] = (float)a_vect / (alpha1 - alpha0);551b = -iv[ACOMP] * alpha0 + 0.5F;552553/* add in alphas */554Q_MOV32(lo, 0);555for (k = N_TEXELS - 1; k >= 0; k--) {556int texel = -1;557if (anyZero | anyOne) {558if (input[k][ACOMP] == 0) {559texel = 6;560} else if (input[k][ACOMP] == 255) {561texel = 7;562}563}564/* interpolate alpha */565if (texel == -1) {566float dot = input[k][ACOMP] * iv[ACOMP];567texel = (int)(dot + b);568#if SAFECDOT569if (texel < 0) {570texel = 0;571} else if (texel > a_vect) {572texel = a_vect;573}574#endif575texel = dxtn_alpha_tlat[anyZero | anyOne][texel];576}577/* add in texel */578Q_SHL(lo, 3);579Q_OR32(lo, texel);580}581Q_SHL(lo, 16);582Q_OR32(lo, alpha0 | (alpha1 << 8));583((qword *)cc)[0] = lo;584}585586color0 = COLOR565(input[minCol]);587color1 = COLOR565(input[maxCol]);588589#ifdef RADEON /* H.Morii - Workaround for ATI Radeon */590if (color0 < color1) {591int aux;592aux = color0;593color0 = color1;594color1 = aux;595aux = minCol;596minCol = maxCol;597maxCol = aux;598}599#endif600601cc[2] = color0 | (color1 << 16);602603hihi = 0;604if (color0 != color1) {605MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]);606607/* add in texels */608for (k = N_TEXELS - 1; k >= 0; k--) {609int texel;610/* interpolate color */611CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);612texel = dxtn_color_tlat[0][texel];613/* add in texel */614hihi <<= 2;615hihi |= texel;616}617}618cc[3] = hihi;619}620621622#define ENCODER(dxtn, n) \623int TAPIENTRY \624dxtn##_encode (int width, int height, int comps, \625const void *source, int srcRowStride, \626void *dest, int destRowStride) \627{ \628int x, y; \629const byte *data; \630dword *encoded = (dword *)dest; \631void *newSource = NULL; \632\633/* Replicate image if width is not M4 or height is not M4 */ \634if ((width & 3) | (height & 3)) { \635int newWidth = (width + 3) & ~3; \636int newHeight = (height + 3) & ~3; \637newSource = malloc(comps * newWidth * newHeight * sizeof(byte *));\638_mesa_upscale_teximage2d(width, height, newWidth, newHeight, \639comps, (const byte *)source, \640srcRowStride, (byte *)newSource); \641source = newSource; \642width = newWidth; \643height = newHeight; \644srcRowStride = comps * newWidth; \645} \646\647data = (const byte *)source; \648destRowStride = (destRowStride - width * n) / 4; \649for (y = 0; y < height; y += 4) { \650unsigned int offs = 0 + (y + 0) * srcRowStride; \651for (x = 0; x < width; x += 4) { \652const byte *lines[4]; \653lines[0] = &data[offs]; \654lines[1] = lines[0] + srcRowStride; \655lines[2] = lines[1] + srcRowStride; \656lines[3] = lines[2] + srcRowStride; \657offs += 4 * comps; \658dxtn##_quantize(encoded, lines, comps); \659/* 4x4 block */ \660encoded += n; \661} \662encoded += destRowStride; \663} \664\665if (newSource != NULL) { \666free(newSource); \667} \668\669return 0; \670}671672ENCODER(dxt1_rgb, 2)673ENCODER(dxt1_rgba, 2)674ENCODER(dxt3_rgba, 4)675ENCODER(dxt5_rgba, 4)676677678/***************************************************************************\679* DXTn decoder680*681* The decoder is based on GL_EXT_texture_compression_s3tc682* specification and serves as a concept for the encoder.683\***************************************************************************/684685686/* lookup table for scaling 4 bit colors up to 8 bits */687static const byte _rgb_scale_4[] = {6880, 17, 34, 51, 68, 85, 102, 119,689136, 153, 170, 187, 204, 221, 238, 255690};691692/* lookup table for scaling 5 bit colors up to 8 bits */693static const byte _rgb_scale_5[] = {6940, 8, 16, 25, 33, 41, 49, 58,69566, 74, 82, 90, 99, 107, 115, 123,696132, 140, 148, 156, 165, 173, 181, 189,697197, 206, 214, 222, 230, 239, 247, 255698};699700/* lookup table for scaling 6 bit colors up to 8 bits */701static const byte _rgb_scale_6[] = {7020, 4, 8, 12, 16, 20, 24, 28,70332, 36, 40, 45, 49, 53, 57, 61,70465, 69, 73, 77, 81, 85, 89, 93,70597, 101, 105, 109, 113, 117, 121, 125,706130, 134, 138, 142, 146, 150, 154, 158,707162, 166, 170, 174, 178, 182, 186, 190,708194, 198, 202, 206, 210, 215, 219, 223,709227, 231, 235, 239, 243, 247, 251, 255710};711712713#define CC_SEL(cc, which) (((dword *)(cc))[(which) / 32] >> ((which) & 31))714#define UP4(c) _rgb_scale_4[(c) & 15]715#define UP5(c) _rgb_scale_5[(c) & 31]716#define UP6(c) _rgb_scale_6[(c) & 63]717#define ZERO_4UBV(v) *((dword *)(v)) = 0718719720void TAPIENTRY721dxt1_rgb_decode_1 (const void *texture, int stride,722int i, int j, byte *rgba)723{724const byte *src = (const byte *)texture725+ ((j / 4) * ((stride + 3) / 4) + i / 4) * 8;726const int code = (src[4 + (j & 3)] >> ((i & 3) * 2)) & 0x3;727if (code == 0) {728rgba[RCOMP] = UP5(CC_SEL(src, 11));729rgba[GCOMP] = UP6(CC_SEL(src, 5));730rgba[BCOMP] = UP5(CC_SEL(src, 0));731} else if (code == 1) {732rgba[RCOMP] = UP5(CC_SEL(src, 27));733rgba[GCOMP] = UP6(CC_SEL(src, 21));734rgba[BCOMP] = UP5(CC_SEL(src, 16));735} else {736const word col0 = src[0] | (src[1] << 8);737const word col1 = src[2] | (src[3] << 8);738if (col0 > col1) {739if (code == 2) {740rgba[RCOMP] = (UP5(col0 >> 11) * 2 + UP5(col1 >> 11)) / 3;741rgba[GCOMP] = (UP6(col0 >> 5) * 2 + UP6(col1 >> 5)) / 3;742rgba[BCOMP] = (UP5(col0 ) * 2 + UP5(col1 )) / 3;743} else {744rgba[RCOMP] = (UP5(col0 >> 11) + 2 * UP5(col1 >> 11)) / 3;745rgba[GCOMP] = (UP6(col0 >> 5) + 2 * UP6(col1 >> 5)) / 3;746rgba[BCOMP] = (UP5(col0 ) + 2 * UP5(col1 )) / 3;747}748} else {749if (code == 2) {750rgba[RCOMP] = (UP5(col0 >> 11) + UP5(col1 >> 11)) / 2;751rgba[GCOMP] = (UP6(col0 >> 5) + UP6(col1 >> 5)) / 2;752rgba[BCOMP] = (UP5(col0 ) + UP5(col1 )) / 2;753} else {754ZERO_4UBV(rgba);755}756}757}758rgba[ACOMP] = 255;759}760761762void TAPIENTRY763dxt1_rgba_decode_1 (const void *texture, int stride,764int i, int j, byte *rgba)765{766/* Same as rgb_dxt1 above, except alpha=0 if col0<=col1 and code=3. */767const byte *src = (const byte *)texture768+ ((j / 4) * ((stride + 3) / 4) + i / 4) * 8;769const int code = (src[4 + (j & 3)] >> ((i & 3) * 2)) & 0x3;770if (code == 0) {771rgba[RCOMP] = UP5(CC_SEL(src, 11));772rgba[GCOMP] = UP6(CC_SEL(src, 5));773rgba[BCOMP] = UP5(CC_SEL(src, 0));774rgba[ACOMP] = 255;775} else if (code == 1) {776rgba[RCOMP] = UP5(CC_SEL(src, 27));777rgba[GCOMP] = UP6(CC_SEL(src, 21));778rgba[BCOMP] = UP5(CC_SEL(src, 16));779rgba[ACOMP] = 255;780} else {781const word col0 = src[0] | (src[1] << 8);782const word col1 = src[2] | (src[3] << 8);783if (col0 > col1) {784if (code == 2) {785rgba[RCOMP] = (UP5(col0 >> 11) * 2 + UP5(col1 >> 11)) / 3;786rgba[GCOMP] = (UP6(col0 >> 5) * 2 + UP6(col1 >> 5)) / 3;787rgba[BCOMP] = (UP5(col0 ) * 2 + UP5(col1 )) / 3;788} else {789rgba[RCOMP] = (UP5(col0 >> 11) + 2 * UP5(col1 >> 11)) / 3;790rgba[GCOMP] = (UP6(col0 >> 5) + 2 * UP6(col1 >> 5)) / 3;791rgba[BCOMP] = (UP5(col0 ) + 2 * UP5(col1 )) / 3;792}793rgba[ACOMP] = 255;794} else {795if (code == 2) {796rgba[RCOMP] = (UP5(col0 >> 11) + UP5(col1 >> 11)) / 2;797rgba[GCOMP] = (UP6(col0 >> 5) + UP6(col1 >> 5)) / 2;798rgba[BCOMP] = (UP5(col0 ) + UP5(col1 )) / 2;799rgba[ACOMP] = 255;800} else {801ZERO_4UBV(rgba);802}803}804}805}806807808void TAPIENTRY809dxt3_rgba_decode_1 (const void *texture, int stride,810int i, int j, byte *rgba)811{812const byte *src = (const byte *)texture813+ ((j / 4) * ((stride + 3) / 4) + i / 4) * 16;814const int code = (src[12 + (j & 3)] >> ((i & 3) * 2)) & 0x3;815const dword *cc = (const dword *)(src + 8);816if (code == 0) {817rgba[RCOMP] = UP5(CC_SEL(cc, 11));818rgba[GCOMP] = UP6(CC_SEL(cc, 5));819rgba[BCOMP] = UP5(CC_SEL(cc, 0));820} else if (code == 1) {821rgba[RCOMP] = UP5(CC_SEL(cc, 27));822rgba[GCOMP] = UP6(CC_SEL(cc, 21));823rgba[BCOMP] = UP5(CC_SEL(cc, 16));824} else if (code == 2) {825/* (col0 * (4 - code) + col1 * (code - 1)) / 3 */826rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) * 2 + UP5(CC_SEL(cc, 27))) / 3;827rgba[GCOMP] = (UP6(CC_SEL(cc, 5)) * 2 + UP6(CC_SEL(cc, 21))) / 3;828rgba[BCOMP] = (UP5(CC_SEL(cc, 0)) * 2 + UP5(CC_SEL(cc, 16))) / 3;829} else {830rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) + 2 * UP5(CC_SEL(cc, 27))) / 3;831rgba[GCOMP] = (UP6(CC_SEL(cc, 5)) + 2 * UP6(CC_SEL(cc, 21))) / 3;832rgba[BCOMP] = (UP5(CC_SEL(cc, 0)) + 2 * UP5(CC_SEL(cc, 16))) / 3;833}834rgba[ACOMP] = UP4(src[((j & 3) * 4 + (i & 3)) / 2] >> ((i & 1) * 4));835}836837838void TAPIENTRY839dxt5_rgba_decode_1 (const void *texture, int stride,840int i, int j, byte *rgba)841{842const byte *src = (const byte *)texture843+ ((j / 4) * ((stride + 3) / 4) + i / 4) * 16;844const int code = (src[12 + (j & 3)] >> ((i & 3) * 2)) & 0x3;845const dword *cc = (const dword *)(src + 8);846const byte alpha0 = src[0];847const byte alpha1 = src[1];848const int alphaShift = (((j & 3) * 4) + (i & 3)) * 3 + 16;849const int acode = ((alphaShift == 31)850? CC_SEL(src + 2, alphaShift - 16)851: CC_SEL(src, alphaShift)) & 0x7;852if (code == 0) {853rgba[RCOMP] = UP5(CC_SEL(cc, 11));854rgba[GCOMP] = UP6(CC_SEL(cc, 5));855rgba[BCOMP] = UP5(CC_SEL(cc, 0));856} else if (code == 1) {857rgba[RCOMP] = UP5(CC_SEL(cc, 27));858rgba[GCOMP] = UP6(CC_SEL(cc, 21));859rgba[BCOMP] = UP5(CC_SEL(cc, 16));860} else if (code == 2) {861/* (col0 * (4 - code) + col1 * (code - 1)) / 3 */862rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) * 2 + UP5(CC_SEL(cc, 27))) / 3;863rgba[GCOMP] = (UP6(CC_SEL(cc, 5)) * 2 + UP6(CC_SEL(cc, 21))) / 3;864rgba[BCOMP] = (UP5(CC_SEL(cc, 0)) * 2 + UP5(CC_SEL(cc, 16))) / 3;865} else {866rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) + 2 * UP5(CC_SEL(cc, 27))) / 3;867rgba[GCOMP] = (UP6(CC_SEL(cc, 5)) + 2 * UP6(CC_SEL(cc, 21))) / 3;868rgba[BCOMP] = (UP5(CC_SEL(cc, 0)) + 2 * UP5(CC_SEL(cc, 16))) / 3;869}870if (acode == 0) {871rgba[ACOMP] = alpha0;872} else if (acode == 1) {873rgba[ACOMP] = alpha1;874} else if (alpha0 > alpha1) {875rgba[ACOMP] = ((8 - acode) * alpha0 + (acode - 1) * alpha1) / 7;876} else if (acode == 6) {877rgba[ACOMP] = 0;878} else if (acode == 7) {879rgba[ACOMP] = 255;880} else {881rgba[ACOMP] = ((6 - acode) * alpha0 + (acode - 1) * alpha1) / 5;882}883}884885886