/* ** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY ** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT ** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX ** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE ** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com). ** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER ** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A ** FULL TEXT OF THE NON-WARRANTY PROVISIONS. ** ** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO ** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN ** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, ** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR ** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF ** THE UNITED STATES. ** ** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED ** ** $Revision: 1.2 $ ** $Date: 2000/06/15 00:11:40 $ */ #include #include #include #include #include "texusint.h" /* * For resampling in the x direction: * Assume ix input pixels become ox output pixels. * Imagine that ix input pixels are each divided into ox fragments, for a total * of ix * ox fragments. * Imagine also that ox output pixels are each divided into ix fragments, for a * total of ox * ix fragments, same as before. * Initialize an accumulator to 0. Add the first input pixel, multiplied by ox * the number of fragments per input pixel. Keep track of the number of * fragments in the accumulator; when this is >= ix, (the number of fragments * it takes to make an output pixel), multiply the accumulator by */ static void _txResampleX(FxU32 *out, const FxU32 *in, int ox, int ix) { FxU32 accr, accg, accb, acca, r, g, b, a; int i, accf, o, nf; // printf("\n"); accf = accr = accg = accb = acca = o = 0; for (i=0; i> 24; r = (in[i] & 0x00ff0000) >> 16; g = (in[i] & 0x0000ff00) >> 8; b = (in[i] & 0x000000ff) ; // Each input pixel brings ox fragments nf = ox; while ((accf + nf) >= ix) { int ef; int oa, or, og, ob; // Yes, we have (possibly more than) enough to generate an output // pixel. Of the nf new fragments, use up enough to generate an // output pixel. ef = ix - accf; // the excessive # of fragments. // printf("New: accf = %3d, nf = %3d, ef = %3d, ix = %3d, ox = %3d\n", // accf, nf, ef, ix, ox); acca += a * ef; accr += r * ef; accg += g * ef; accb += b * ef; oa = acca / ix; or = accr / ix; og = accg / ix; ob = accb / ix; if( (oa < 0) || (oa > 255) || (or < 0) || (or > 255) || (og < 0) || (og > 255) || (ob < 0) || (ob > 255) ) { printf(" %d %d %d %d\n" , oa, or, og, ob); txPanic("ARGB: out of range\n"); } *out++ = (oa << 24) | (or << 16) | (og << 8) | ob; // printf("Output pixel %4d: %.02x %.02x %.02x %.02x\n", // o, oa, or, og, ob); o++; acca = accr = accg = accb = accf = 0; nf -= ef; } // If there's any fragments left over, accumulate them. if (nf) { acca += a * nf; accr += r * nf; accg += g * nf; accb += b * nf; accf += nf; // printf("i= %4d, accf = %4d, aa=%.06x, ar=%.06x, ag=%.06x, ab=%.06x\n", // i, accf, acca, accr, accg, accb); } } if (accf != 0) { txPanic("Row resampling: accf != 0!\n"); } } static FxU32 AccA[MAX_TEXWIDTH]; static FxU32 AccR[MAX_TEXWIDTH]; static FxU32 AccG[MAX_TEXWIDTH]; static FxU32 AccB[MAX_TEXWIDTH]; static FxU32 argb[MAX_TEXWIDTH]; static void _txImgResample(FxU32 *out, int ox, int oy, const FxU32 *in, int ix, int iy) { int r, g, b, a; int i, j, accf, o, nf; for (i=0; i= iy) { int ef; // Yes, we have (possibly more than) enough to generate an output // pixel. Of the nf new fragments, use up enough to generate an // output pixel. ef = iy - accf; // the excessive # of fragments. // Accumulate input * ef + acc, and generate a line of output. for (j=0; j> 24; r = (argb[j] & 0x00ff0000) >> 16; g = (argb[j] & 0x0000ff00) >> 8; b = (argb[j] & 0x000000ff) ; AccA[j] += a * ef; AccR[j] += r * ef; AccG[j] += g * ef; AccB[j] += b * ef; a = AccA[j] / iy; r = AccR[j] / iy; g = AccG[j] / iy; b = AccB[j] / iy; if( (a < 0) || (a > 255) || (r < 0) || (r > 255) || (g < 0) || (g > 255) || (b < 0) || (b > 255) ) { printf(" %d %d %d %d\n" , a, r, g, b); txPanic("ARGB: out of range\n"); } out[j] = (a << 24) | (r << 16) | (g << 8) | b; AccA[j] = 0; AccR[j] = 0; AccG[j] = 0; AccB[j] = 0; } out += ox; accf = 0; nf -= ef; // printf("[%4d] Generating output row %4d\n", i, o); o++; } // If there's any fragments left over, accumulate them. if (nf) { for (j=0; j> 24; r = (argb[j] & 0x00ff0000) >> 16; g = (argb[j] & 0x0000ff00) >> 8; b = (argb[j] & 0x000000ff) ; AccA[j] += a * nf; AccR[j] += r * nf; AccG[j] += g * nf; AccB[j] += b * nf; } accf += nf; // printf("i= %4d, accf = %4d\n", i, accf); } } if (accf != 0) { txPanic("Img resampling: accf != 0!\n"); } // Ideally, accf must be 0 now. // printf("Finally: accf = %d\n", accf); } void txMipResample(TxMip *destMip, TxMip *srcMip) { int i, sw, sh, dw, dh; if ((destMip->width > MAX_TEXWIDTH) || (destMip->height > MAX_TEXWIDTH)) { txPanic("Bad width/height in txImageResize()\n"); } if ((srcMip->format != GR_TEXFMT_ARGB_8888) || (destMip->format != GR_TEXFMT_ARGB_8888)) { txPanic("Bad image format in txMipResample."); } if ((srcMip->width == destMip->width) && (srcMip->height == destMip->height) && (srcMip->data[0] == destMip->data[0])) { if( txVerbose ) printf("No Resampling necessary.\n"); return; } if ((srcMip->data[0] == NULL) || (destMip->data[0] == NULL)) txPanic("txImageResize: Null buffer\n"); if( txVerbose ) printf("Resampling to %dx%d: ", destMip->width, destMip->height); sw = srcMip->width; sh = srcMip->height; dw = destMip->width; dh = destMip->height; for (i=0; i< srcMip->depth; i++) { if(!destMip->data[i]) txPanic("txImageResize: no miplevel present\n"); _txImgResample (destMip->data[i], dw, dh, srcMip->data[i], sw, sh); if( txVerbose ) { printf(" %dx%d", sw, sh); fflush(stdout); } if (sw > 1) sw >>= 1; if (sh > 1) sh >>= 1; if (dw > 1) dw >>= 1; if (dh > 1) dh >>= 1; } if( txVerbose ) printf(".\n"); }