summaryrefslogtreecommitdiff
path: root/xc/lib/GL/mesa/src/drv/tdfx/fxddtex.c
diff options
context:
space:
mode:
Diffstat (limited to 'xc/lib/GL/mesa/src/drv/tdfx/fxddtex.c')
-rw-r--r--xc/lib/GL/mesa/src/drv/tdfx/fxddtex.c1647
1 files changed, 1647 insertions, 0 deletions
diff --git a/xc/lib/GL/mesa/src/drv/tdfx/fxddtex.c b/xc/lib/GL/mesa/src/drv/tdfx/fxddtex.c
new file mode 100644
index 000000000..11438f440
--- /dev/null
+++ b/xc/lib/GL/mesa/src/drv/tdfx/fxddtex.c
@@ -0,0 +1,1647 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/fxddtex.c,v 1.1 2000/09/24 13:51:14 alanh Exp $ */
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.3
+ *
+ * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the
+ * terms stated above.
+ *
+ * Thank you for your contribution, David!
+ *
+ * Please make note of the above copyright/license statement. If you
+ * contributed code or bug fixes to this code under the previous (GNU
+ * Library) license and object to the new license, your code will be
+ * removed at your request. Please see the Mesa docs/COPYRIGHT file
+ * for more information.
+ *
+ * Additional Mesa/3Dfx driver developers:
+ * Daryll Strauss <daryll@precisioninsight.com>
+ * Keith Whitwell <keith@precisioninsight.com>
+ *
+ * See fxapi.h for more revision/author details.
+ */
+
+
+#include "fxdrv.h"
+#include "fxddtex.h"
+#include "fxtexman.h"
+#include "fxsetup.h"
+#include "image.h"
+#include "texutil.h"
+
+
+void
+fxPrintTextureData(tfxTexInfo * ti)
+{
+ fprintf(stderr, "Texture Data:\n");
+ if (ti->tObj) {
+ fprintf(stderr, "\tName: %d\n", ti->tObj->Name);
+ fprintf(stderr, "\tBaseLevel: %d\n", ti->tObj->BaseLevel);
+ fprintf(stderr, "\tSize: %d x %d\n",
+ ti->tObj->Image[ti->tObj->BaseLevel]->Width,
+ ti->tObj->Image[ti->tObj->BaseLevel]->Height);
+ }
+ else
+ fprintf(stderr, "\tName: UNNAMED\n");
+ fprintf(stderr, "\tLast used: %d\n", ti->lastTimeUsed);
+ fprintf(stderr, "\tTMU: %ld\n", ti->whichTMU);
+ fprintf(stderr, "\t%s\n", (ti->isInTM) ? "In TMU" : "Not in TMU");
+ if (ti->tm[0])
+ fprintf(stderr, "\tMem0: %x-%x\n", (unsigned) ti->tm[0]->startAddr,
+ (unsigned) ti->tm[0]->endAddr);
+ if (ti->tm[1])
+ fprintf(stderr, "\tMem1: %x-%x\n", (unsigned) ti->tm[1]->startAddr,
+ (unsigned) ti->tm[1]->endAddr);
+ fprintf(stderr, "\tMipmaps: %d-%d\n", ti->minLevel, ti->maxLevel);
+ fprintf(stderr, "\tFilters: min %d min %d\n",
+ (int) ti->minFilt, (int) ti->maxFilt);
+ fprintf(stderr, "\tClamps: s %d t %d\n", (int) ti->sClamp,
+ (int) ti->tClamp);
+ fprintf(stderr, "\tScales: s %f t %f\n", ti->sScale, ti->tScale);
+ fprintf(stderr, "\tInt Scales: s %d t %d\n",
+ ti->int_sScale / 0x800000, ti->int_tScale / 0x800000);
+ fprintf(stderr, "\t%s\n",
+ (ti->fixedPalette) ? "Fixed palette" : "Non fixed palette");
+ fprintf(stderr, "\t%s\n",
+ (ti->validated) ? "Validated" : "Not validated");
+}
+
+
+/************************************************************************/
+/*************************** Texture Mapping ****************************/
+/************************************************************************/
+
+static void
+fxTexInvalidate(GLcontext * ctx, struct gl_texture_object *tObj)
+{
+ fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
+ tfxTexInfo *ti;
+
+ ti = fxTMGetTexInfo(tObj);
+ if (ti->isInTM)
+ fxTMMoveOutTM(fxMesa, tObj); /* TO DO: SLOW but easy to write */
+
+ ti->validated = GL_FALSE;
+ fxMesa->new_state |= FX_NEW_TEXTURING;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+}
+
+static tfxTexInfo *
+fxAllocTexObjData(fxMesaContext fxMesa)
+{
+ tfxTexInfo *ti;
+ int i;
+
+ if (!(ti = CALLOC(sizeof(tfxTexInfo)))) {
+ gl_problem(NULL, "fx Driver: out of memory !\n");
+ return NULL;
+ }
+
+ ti->validated = GL_FALSE;
+ ti->isInTM = GL_FALSE;
+
+ ti->whichTMU = FX_TMU_NONE;
+
+ ti->tm[FX_TMU0] = NULL;
+ ti->tm[FX_TMU1] = NULL;
+
+ ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
+ ti->maxFilt = GR_TEXTUREFILTER_BILINEAR;
+
+ ti->sClamp = GR_TEXTURECLAMP_WRAP;
+ ti->tClamp = GR_TEXTURECLAMP_WRAP;
+
+ ti->mmMode = GR_MIPMAP_NEAREST;
+ ti->LODblend = FXFALSE;
+
+ for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
+ ti->mipmapLevel[i].data = NULL;
+ }
+
+ return ti;
+}
+
+
+/*
+ * Called via glBindTexture.
+ */
+void
+fxDDTexBind(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj)
+{
+ fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
+ tfxTexInfo *ti;
+
+ if (MESA_VERBOSE & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxmesa: fxDDTexBind(%d,%x)\n", tObj->Name,
+ (GLuint) tObj->DriverData);
+ }
+
+ if (target != GL_TEXTURE_2D)
+ return;
+
+ if (!tObj->DriverData) {
+ tObj->DriverData = fxAllocTexObjData(fxMesa);
+ }
+
+ ti = fxTMGetTexInfo(tObj);
+
+ fxMesa->texBindNumber++;
+ ti->lastTimeUsed = fxMesa->texBindNumber;
+
+ fxMesa->new_state |= FX_NEW_TEXTURING;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+}
+
+void
+fxDDTexEnv(GLcontext * ctx, GLenum target, GLenum pname,
+ const GLfloat * param)
+{
+ fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
+
+ if (MESA_VERBOSE & VERBOSE_DRIVER) {
+ if (param)
+ fprintf(stderr, "fxmesa: texenv(%x,%x)\n", pname,
+ (GLint) (*param));
+ else
+ fprintf(stderr, "fxmesa: texenv(%x)\n", pname);
+ }
+
+ /* apply any lod biasing right now */
+ if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
+ FX_grTexLodBiasValue(GR_TMU0, *param);
+ if (fxMesa->haveTwoTMUs) {
+ FX_grTexLodBiasValue(GR_TMU1, *param);
+ }
+ }
+
+ /* invalidate currently bound texture(s) */
+ {
+ int i;
+ for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
+ struct gl_texture_object *tObj = ctx->Texture.Unit[i].CurrentD[2];
+ if (!tObj->DriverData) {
+ tObj->DriverData = fxAllocTexObjData(fxMesa);
+ }
+ fxTexInvalidate(ctx, tObj);
+ }
+ }
+
+ fxMesa->new_state |= FX_NEW_TEXTURING;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+}
+
+void
+fxDDTexParam(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj,
+ GLenum pname, const GLfloat * params)
+{
+ fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
+ GLenum param = (GLenum) (GLint) params[0];
+ tfxTexInfo *ti;
+
+ if (MESA_VERBOSE & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxmesa: fxDDTexParam(%d,%x,%x,%x)\n", tObj->Name,
+ (GLuint) tObj->DriverData, pname, param);
+ }
+
+ if (target != GL_TEXTURE_2D)
+ return;
+
+ if (!tObj->DriverData)
+ tObj->DriverData = fxAllocTexObjData(fxMesa);
+
+ ti = fxTMGetTexInfo(tObj);
+
+ switch (pname) {
+
+ case GL_TEXTURE_MIN_FILTER:
+ switch (param) {
+ case GL_NEAREST:
+ ti->mmMode = GR_MIPMAP_DISABLE;
+ ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
+ ti->LODblend = FXFALSE;
+ break;
+ case GL_LINEAR:
+ ti->mmMode = GR_MIPMAP_DISABLE;
+ ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
+ ti->LODblend = FXFALSE;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ ti->mmMode = GR_MIPMAP_NEAREST;
+ ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
+ ti->LODblend = FXFALSE;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ ti->mmMode = GR_MIPMAP_NEAREST;
+ ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
+ ti->LODblend = FXFALSE;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ if (fxMesa->haveTwoTMUs) {
+ ti->mmMode = GR_MIPMAP_NEAREST;
+ ti->LODblend = FXTRUE;
+ }
+ else {
+ ti->mmMode = GR_MIPMAP_NEAREST_DITHER;
+ ti->LODblend = FXFALSE;
+ }
+ ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ if (fxMesa->haveTwoTMUs) {
+ ti->mmMode = GR_MIPMAP_NEAREST;
+ ti->LODblend = FXTRUE;
+ }
+ else {
+ ti->mmMode = GR_MIPMAP_NEAREST_DITHER;
+ ti->LODblend = FXFALSE;
+ }
+ ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
+ break;
+ default:
+ break;
+ }
+ fxTexInvalidate(ctx, tObj);
+ break;
+
+ case GL_TEXTURE_MAG_FILTER:
+ switch (param) {
+ case GL_NEAREST:
+ ti->maxFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
+ break;
+ case GL_LINEAR:
+ ti->maxFilt = GR_TEXTUREFILTER_BILINEAR;
+ break;
+ default:
+ break;
+ }
+ fxTexInvalidate(ctx, tObj);
+ break;
+
+ case GL_TEXTURE_WRAP_S:
+ switch (param) {
+ case GL_CLAMP:
+ ti->sClamp = GR_TEXTURECLAMP_CLAMP;
+ break;
+ case GL_REPEAT:
+ ti->sClamp = GR_TEXTURECLAMP_WRAP;
+ break;
+ default:
+ break;
+ }
+ fxMesa->new_state |= FX_NEW_TEXTURING;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ break;
+
+ case GL_TEXTURE_WRAP_T:
+ switch (param) {
+ case GL_CLAMP:
+ ti->tClamp = GR_TEXTURECLAMP_CLAMP;
+ break;
+ case GL_REPEAT:
+ ti->tClamp = GR_TEXTURECLAMP_WRAP;
+ break;
+ default:
+ break;
+ }
+ fxMesa->new_state |= FX_NEW_TEXTURING;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ break;
+
+ case GL_TEXTURE_BORDER_COLOR:
+ /* TO DO */
+ break;
+
+ case GL_TEXTURE_MIN_LOD:
+ /* TO DO */
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ /* TO DO */
+ break;
+ case GL_TEXTURE_BASE_LEVEL:
+ fxTexInvalidate(ctx, tObj);
+ break;
+ case GL_TEXTURE_MAX_LEVEL:
+ fxTexInvalidate(ctx, tObj);
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+/*
+ * Called via glDeleteTextures to delete a texture object.
+ * Here, we delete the Glide data associated with the texture.
+ */
+void
+fxDDTexDel(GLcontext * ctx, struct gl_texture_object *tObj)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxTexInfo *ti = fxTMGetTexInfo(tObj);
+
+ if (MESA_VERBOSE & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxmesa: fxDDTexDel(%d,%p)\n", tObj->Name, ti);
+ }
+
+ if (!ti)
+ return;
+
+ fxTMFreeTexture(fxMesa, tObj);
+
+ FREE(ti);
+ tObj->DriverData = NULL;
+
+ ctx->NewState |= NEW_TEXTURING;
+}
+
+
+/*
+ * Return true if texture is resident, false otherwise.
+ */
+GLboolean
+fxDDIsTextureResident(GLcontext *ctx, struct gl_texture_object *tObj)
+{
+ tfxTexInfo *ti = fxTMGetTexInfo(tObj);
+ /*printf("resident %d\n", (int) (ti && ti->isInTM));*/
+ return (GLboolean) (ti && ti->isInTM);
+}
+
+
+
+/*
+ * Convert a gl_color_table texture palette to Glide's format.
+ */
+static void
+convertPalette(FxU32 data[256], const struct gl_color_table *table)
+{
+ const GLubyte *tableUB = (const GLubyte *) table->Table;
+ GLint width = table->Size;
+ FxU32 r, g, b, a;
+ GLint i;
+
+ ASSERT(table->TableType == GL_UNSIGNED_BYTE);
+
+ switch (table->Format) {
+ case GL_INTENSITY:
+ for (i = 0; i < width; i++) {
+ r = tableUB[i];
+ g = tableUB[i];
+ b = tableUB[i];
+ a = tableUB[i];
+ data[i] = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ break;
+ case GL_LUMINANCE:
+ for (i = 0; i < width; i++) {
+ r = tableUB[i];
+ g = tableUB[i];
+ b = tableUB[i];
+ a = 255;
+ data[i] = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ break;
+ case GL_ALPHA:
+ for (i = 0; i < width; i++) {
+ r = g = b = 255;
+ a = tableUB[i];
+ data[i] = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ break;
+ case GL_LUMINANCE_ALPHA:
+ for (i = 0; i < width; i++) {
+ r = g = b = tableUB[i * 2 + 0];
+ a = tableUB[i * 2 + 1];
+ data[i] = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ break;
+ case GL_RGB:
+ for (i = 0; i < width; i++) {
+ r = tableUB[i * 3 + 0];
+ g = tableUB[i * 3 + 1];
+ b = tableUB[i * 3 + 2];
+ a = 255;
+ data[i] = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ break;
+ case GL_RGBA:
+ for (i = 0; i < width; i++) {
+ r = tableUB[i * 4 + 0];
+ g = tableUB[i * 4 + 1];
+ b = tableUB[i * 4 + 2];
+ a = tableUB[i * 4 + 3];
+ data[i] = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ break;
+ }
+}
+
+
+
+void
+fxDDTexPalette(GLcontext * ctx, struct gl_texture_object *tObj)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ if (tObj) {
+ /* per-texture palette */
+ tfxTexInfo *ti;
+ if (MESA_VERBOSE & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxmesa: fxDDTexPalette(%d,%x)\n",
+ tObj->Name, (GLuint) tObj->DriverData);
+ }
+ if (!tObj->DriverData)
+ tObj->DriverData = fxAllocTexObjData(fxMesa);
+ ti = fxTMGetTexInfo(tObj);
+ convertPalette(ti->palette.data, &tObj->Palette);
+ fxTexInvalidate(ctx, tObj);
+ }
+ else {
+ /* global texture palette */
+ if (MESA_VERBOSE & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxmesa: fxDDTexPalette(global)\n");
+ }
+ convertPalette(fxMesa->glbPalette.data, &ctx->Texture.Palette);
+ fxMesa->new_state |= FX_NEW_TEXTURING;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ }
+}
+
+
+void
+fxDDTexUseGlbPalette(GLcontext * ctx, GLboolean state)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxmesa: fxDDTexUseGlbPalette(%d)\n", state);
+ }
+
+ if (state) {
+ fxMesa->haveGlobalPaletteTexture = 1;
+
+ FX_grTexDownloadTable(fxMesa, GR_TMU0, GR_TEXTABLE_PALETTE_6666_EXT,
+ &(fxMesa->glbPalette));
+ if (fxMesa->haveTwoTMUs)
+ FX_grTexDownloadTable(fxMesa, GR_TMU1, GR_TEXTABLE_PALETTE_6666_EXT,
+ &(fxMesa->glbPalette));
+ }
+ else {
+ fxMesa->haveGlobalPaletteTexture = 0;
+
+ if ((ctx->Texture.Unit[0].Current == ctx->Texture.Unit[0].CurrentD[2])
+ && (ctx->Texture.Unit[0].Current != NULL)) {
+ struct gl_texture_object *tObj = ctx->Texture.Unit[0].Current;
+
+ if (!tObj->DriverData)
+ tObj->DriverData = fxAllocTexObjData(fxMesa);
+
+ fxTexInvalidate(ctx, tObj);
+ }
+ }
+}
+
+
+static int
+logbase2(int n)
+{
+ GLint i = 1;
+ GLint log2 = 0;
+
+ if (n < 0) {
+ return -1;
+ }
+
+ while (n > i) {
+ i *= 2;
+ log2++;
+ }
+ if (i != n) {
+ return -1;
+ }
+ else {
+ return log2;
+ }
+}
+
+/* Need different versions for different cpus.
+ */
+#define INT_TRICK(pow2) (0x800000 * (pow2))
+
+/*
+ * Compute various texture image parameters.
+ * Input: w, h - source texture width and height
+ * Output: lodlevel - Glide lod level token
+ * aspectratio - Glide aspect ratio token
+ * sscale - S scale factor used during triangle setup
+ * tscale - T scale factor used during triangle setup
+ * i_sscale - integer S scale used during triangle setup
+ * i_tscale - integer T scale used during triangle setup
+ * wscale - OpenGL -> Glide image width scale factor
+ * hscale - OpenGL -> Glide image height scale factor
+ */
+void
+fxTexGetInfo(const GLcontext *ctx, int w, int h,
+ GrLOD_t *lodlevel, GrAspectRatio_t *aspectratio,
+ float *sscale, float *tscale,
+ int *i_sscale, int *i_tscale,
+ int *wscale, int *hscale)
+{
+ int logw, logh, ar, lod, is, it, ws, hs;
+ float s, t;
+
+ ASSERT(w >= 1);
+ ASSERT(h >= 1);
+
+ logw = logbase2(w);
+ logh = logbase2(h);
+ ar = logw - logh; /* aspect ratio = difference in log dimensions */
+
+ /* Hardware only allows a maximum aspect ratio of 8x1, so handle
+ |ar| > 3 by scaling the image and using an 8x1 aspect ratio */
+ if (ar >= 0) {
+ ASSERT(width >= height);
+ lod = logw;
+#if 1
+ s = 256.0;
+ is = INT_TRICK(8);
+#else
+ s = ctx->Const.MaxTextureSize;
+ is = INT_TRICK(ctx->Const.MaxTextureLevels - 1);
+#endif
+ ws = 1;
+ if (ar < 3) {
+#if 1
+ t = 256 >> ar;
+ it = INT_TRICK(8 - ar);
+#else
+ t = ctx->Const.MaxTextureSize >> ar;
+ it = INT_TRICK(ctx->Const.MaxTextureLevels - 1 - ar);
+#endif
+ hs = 1;
+ }
+ else {
+ t = 32.0;
+ it = INT_TRICK(5);
+ hs = 1 << (ar - 3);
+ }
+ }
+ else {
+ ASSERT(width < height);
+ lod = logh;
+#if 1
+ t = 256.0;
+ it = INT_TRICK(8);
+#else
+ t = ctx->Const.MaxTextureSize;
+ it = INT_TRICK(ctx->Const.MaxTextureLevels - 1);
+#endif
+ hs = 1;
+ if (-ar < 3) {
+#if 1
+ s = 256 >> -ar;
+ is = INT_TRICK(8 + ar);
+#else
+ s = ctx->Const.MaxTextureSize >> - ar;
+ is = INT_TRICK(ctx->Const.MaxTextureLevels - 1 + ar);
+#endif
+ ws = 1;
+ }
+ else {
+ s = 32.0;
+ is = INT_TRICK(5);
+ ws = 1 << (-ar - 3);
+ }
+ }
+ if (ar < -3)
+ ar = -3;
+ if (ar > 3)
+ ar = 3;
+
+ if (lodlevel)
+ *lodlevel = (GrLOD_t) lod;
+ if (aspectratio)
+ *aspectratio = (GrAspectRatio_t) ar;
+ if (sscale)
+ *sscale = s;
+ if (tscale)
+ *tscale = t;
+ if (wscale)
+ *wscale = ws;
+ if (hscale)
+ *hscale = hs;
+ if (i_sscale)
+ *i_sscale = is;
+ if (i_tscale)
+ *i_tscale = it;
+}
+
+/*
+ * Given an OpenGL internal texture format, return the corresponding
+ * Glide internal texture format and base texture format.
+ * If allow32bpp is true, we'll return 32-bit texel formats when
+ * appropriate.
+ */
+void
+fxTexGetFormat(GLenum glformat, GrTextureFormat_t *glideFormat,
+ GLint *glFormat, MesaIntTexFormat *mesaFormat,
+ GLint *texelSize, GLboolean allow32bpp)
+{
+ switch (glformat) {
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ if (glideFormat)
+ *glideFormat = GR_TEXFMT_INTENSITY_8;
+ if (glFormat)
+ *glFormat = GL_LUMINANCE;
+ if (mesaFormat)
+ *mesaFormat = MESA_L8;
+ if (texelSize)
+ *texelSize = 1;
+ break;
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ if (glideFormat)
+ *glideFormat = GR_TEXFMT_ALPHA_INTENSITY_88;
+ if (glFormat)
+ *glFormat = GL_LUMINANCE_ALPHA;
+ if (mesaFormat)
+ *mesaFormat = MESA_A8_L8;
+ if (texelSize)
+ *texelSize = 2;
+ break;
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ if (glideFormat)
+ *glideFormat = GR_TEXFMT_ALPHA_8;
+ if (glFormat)
+ *glFormat = GL_INTENSITY;
+ if (mesaFormat)
+ *mesaFormat = MESA_I8;
+ if (texelSize)
+ *texelSize = 1;
+ break;
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ if (glideFormat)
+ *glideFormat = GR_TEXFMT_ALPHA_8;
+ if (glFormat)
+ *glFormat = GL_ALPHA;
+ if (mesaFormat)
+ *mesaFormat = MESA_A8;
+ if (texelSize)
+ *texelSize = 1;
+ break;
+ case GL_R3_G3_B2:
+ case GL_RGB4:
+ case GL_RGB5:
+ if (glideFormat)
+ *glideFormat = GR_TEXFMT_RGB_565;
+ if (glFormat)
+ *glFormat = GL_RGB;
+ if (mesaFormat)
+ *mesaFormat = MESA_R5_G6_B5;
+ if (texelSize)
+ *texelSize = 2;
+ break;
+ case 3:
+ case GL_RGB:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ if (allow32bpp) {
+ if (glideFormat)
+ *glideFormat = GR_TEXFMT_ARGB_8888;
+ if (glFormat)
+ *glFormat = GL_RGB;
+ if (mesaFormat)
+ *mesaFormat = MESA_FF_R8_G8_B8;
+ if (texelSize)
+ *texelSize = 4;
+ }
+ else {
+ if (glideFormat)
+ *glideFormat = GR_TEXFMT_RGB_565;
+ if (glFormat)
+ *glFormat = GL_RGB;
+ if (mesaFormat)
+ *mesaFormat = MESA_R5_G6_B5;
+ if (texelSize)
+ *texelSize = 2;
+ }
+ break;
+ case GL_RGBA2:
+ case GL_RGBA4:
+ if (glideFormat)
+ *glideFormat = GR_TEXFMT_ARGB_4444;
+ if (glFormat)
+ *glFormat = GL_RGBA;
+ if (mesaFormat)
+ *mesaFormat = MESA_A4_R4_G4_B4;
+ if (texelSize)
+ *texelSize = 2;
+ break;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ if (allow32bpp) {
+ if (glideFormat)
+ *glideFormat = GR_TEXFMT_ARGB_8888;
+ if (glFormat)
+ *glFormat = GL_RGBA;
+ if (mesaFormat)
+ *mesaFormat = MESA_A8_R8_G8_B8;
+ if (texelSize)
+ *texelSize = 4;
+ }
+ else {
+ if (glideFormat)
+ *glideFormat = GR_TEXFMT_ARGB_4444;
+ if (glFormat)
+ *glFormat = GL_RGBA;
+ if (mesaFormat)
+ *mesaFormat = MESA_A4_R4_G4_B4;
+ if (texelSize)
+ *texelSize = 2;
+ }
+ break;
+ case GL_RGB5_A1:
+ if (glideFormat)
+ *glideFormat = GR_TEXFMT_ARGB_1555;
+ if (glFormat)
+ *glFormat = GL_RGBA;
+ if (mesaFormat)
+ *mesaFormat = MESA_A1_R5_G5_B5;
+ if (texelSize)
+ *texelSize = 2;
+ break;
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ if (glideFormat)
+ *glideFormat = GR_TEXFMT_P_8;
+ if (glFormat)
+ *glFormat = GL_RGBA; /* XXX why is this RGBA? */
+ if (mesaFormat)
+ *mesaFormat = MESA_C8;
+ if (texelSize)
+ *texelSize = 1;
+ break;
+ case GL_COMPRESSED_RGB_FXT1_3DFX:
+ if (glideFormat)
+ *glideFormat = GR_TEXFMT_ARGB_CMP_FXT1;
+ if (glFormat)
+ *glFormat = GL_COMPRESSED_RGB_FXT1_3DFX;
+ if (mesaFormat)
+ *mesaFormat = MESA_A8_R8_G8_B8;
+ if (texelSize)
+ *texelSize = 4;
+ break;
+ case GL_COMPRESSED_RGBA_FXT1_3DFX:
+ if (glideFormat)
+ *glideFormat = GR_TEXFMT_ARGB_CMP_FXT1;
+ if (glFormat)
+ *glFormat = GL_COMPRESSED_RGBA_FXT1_3DFX;
+ if (mesaFormat)
+ *mesaFormat = MESA_A8_R8_G8_B8;
+ if (texelSize)
+ *texelSize = 4;
+ break;
+ default:
+ gl_problem(NULL, "bad texture format in fxTexGetFormat()\n");
+ break;
+ }
+}
+
+
+/**********************************************************************/
+/**** NEW TEXTURE IMAGE FUNCTIONS ****/
+/**********************************************************************/
+
+static FxBool TexusFatalError = FXFALSE;
+static FxBool TexusError = FXFALSE;
+
+#define TX_DITHER_NONE 0x00000000
+
+static void
+fxTexusError(const char *string, FxBool fatal)
+{
+ gl_problem(NULL, string);
+ /*
+ * Just propagate the fatal value up.
+ */
+ TexusError = FXTRUE;
+ TexusFatalError = fatal;
+}
+
+GLboolean
+fxDDTexImage2D(GLcontext * ctx, GLenum target, GLint level,
+ GLenum format, GLenum type, const GLvoid * pixels,
+ const struct gl_pixelstore_attrib * packing,
+ struct gl_texture_object * texObj,
+ struct gl_texture_image * texImage,
+ GLboolean * retainInternalCopy)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ const GLboolean allow32bpt = fxMesa->haveHwStencil;
+ GrTextureFormat_t gldformat;
+ tfxTexInfo *ti;
+ tfxMipMapLevel *mml;
+ GLint dstWidth, dstHeight, wScale, hScale, texelSize, dstStride;
+ MesaIntTexFormat intFormat;
+ GLboolean isCompressedFormat;
+ GLint texsize;
+ void *uncompressedImage;
+
+ if (target == GL_PROXY_TEXTURE_2D) {
+ /* XXX not possible for now */
+
+ }
+
+ isCompressedFormat = texImage->IsCompressed;
+ if (target != GL_TEXTURE_2D || texImage->Border > 0)
+ return GL_FALSE;
+
+ if (!texObj->DriverData)
+ texObj->DriverData = fxAllocTexObjData(fxMesa);
+
+ ti = fxTMGetTexInfo(texObj);
+ mml = &ti->mipmapLevel[level];
+
+ /* Determine the appropriate GL internal texel format, Mesa internal
+ * texel format, and texelSize (bytes) given the user's internal
+ * texture format hint.
+ */
+ fxTexGetFormat(texImage->IntFormat, &gldformat, NULL, &intFormat,
+ &texelSize, allow32bpt);
+
+ /* Determine width and height scale factors for texture.
+ * Remember, Glide is limited to 8:1 aspect ratios.
+ */
+ fxTexGetInfo(ctx,
+ texImage->Width, texImage->Height,
+ NULL, /* lod level */
+ NULL, /* aspect ratio */
+ NULL, NULL, /* sscale, tscale */
+ NULL, NULL, /* i_sscale, i_tscale */
+ &wScale, &hScale);
+ dstWidth = texImage->Width * wScale;
+ dstHeight = texImage->Height * hScale;
+ if (isCompressedFormat) {
+ texsize = fxDDCompressedImageSize(ctx,
+ texImage->IntFormat,
+ 2,
+ texImage->Width,
+ texImage->Height,
+ 1);
+ } else {
+ texsize = dstWidth * dstHeight * texelSize;
+ }
+ /*
+ * If the image is not compressed, this doesn't
+ * matter, but it might as well have a sensible
+ * value, and it might save a failure later on.
+ */
+ texImage->CompressedSize = texsize;
+ /* housekeeping */
+ _mesa_set_teximage_component_sizes(intFormat, texImage);
+
+ /*
+ * allocate new storage for texture image, if needed.
+ * This conditional wants to set uncompressedImage to
+ * point to the uncompressed image, and mml->data to
+ * the texture data. If the image is uncompressed,
+ * these are identical. If the image is not compressed,
+ * these are different.
+ */
+ if (!mml->data || mml->glideFormat != gldformat ||
+ mml->width != dstWidth || mml->height != dstHeight ||
+ texsize != mml->dataSize ) {
+ if (mml->data) {
+ FREE(mml->data);
+ }
+ uncompressedImage
+ = (void *)MALLOC(dstWidth * dstHeight * texelSize);
+ if (!uncompressedImage) {
+ return(GL_FALSE);
+ }
+ if (isCompressedFormat) {
+ mml->data = MALLOC(texsize);
+ if (!mml->data) {
+ FREE(uncompressedImage);
+ return GL_FALSE;
+ }
+ } else {
+ mml->data = uncompressedImage;
+ }
+ mml->texelSize = texelSize;
+ mml->glideFormat = gldformat;
+ mml->width = dstWidth;
+ mml->height = dstHeight;
+ mml->dataSize = texsize;
+ fxTexInvalidate(ctx, texObj);
+ } else {
+ /*
+ * Here we don't have to allocate anything, but we
+ * do have to point uncompressedImage to the uncompressed
+ * data.
+ */
+ if (isCompressedFormat) {
+ uncompressedImage
+ = (void *)MALLOC(dstWidth * dstHeight * texelSize);
+ if (!uncompressedImage) {
+ return GL_FALSE;
+ }
+ } else {
+ uncompressedImage = mml->data;
+ }
+ }
+
+ dstStride = dstWidth * texelSize;
+
+ /* store the texture image into uncompressedImage */
+ if (!_mesa_convert_teximage(intFormat,
+ dstWidth, dstHeight,
+ uncompressedImage,
+ dstStride,
+ texImage->Width, texImage->Height,
+ format, type, pixels, packing)) {
+ /*printf("convert failed\n");*/
+ return GL_FALSE; /* not necessarily an error */
+ }
+ /*
+ * Now compress it if necessary.
+ */
+ if (isCompressedFormat) {
+ TxErrorCallbackFnc_t oldErrorCallback;
+ (*txErrorSetCallbackPtr)(fxTexusError, &oldErrorCallback);
+ (*txImgQuantizePtr)((char *)mml->data,
+ (char *)uncompressedImage,
+ texImage->Width,
+ texImage->Height,
+ gldformat,
+ TX_DITHER_NONE);
+ (*txErrorSetCallbackPtr)(oldErrorCallback, NULL);
+ if (uncompressedImage != mml->data) {
+ /*
+ * We do not need this any more, errors or no.
+ */
+ FREE(uncompressedImage);
+ }
+ TexusError = FXFALSE;
+ if (TexusFatalError) {
+ FREE(mml->data);
+ mml->data = (unsigned short *)0;
+ TexusFatalError = FXFALSE;
+ return(GL_FALSE);
+ }
+ }
+ if (ti->validated && ti->isInTM) {
+ fxTMReloadMipMapLevel(ctx, texObj, level);
+ }
+ else {
+ fxTexInvalidate(ctx, texObj);
+ }
+
+ *retainInternalCopy = GL_FALSE;
+ return GL_TRUE;
+}
+
+
+GLboolean
+fxDDTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type, const GLvoid * pixels,
+ const struct gl_pixelstore_attrib * packing,
+ struct gl_texture_object * texObj,
+ struct gl_texture_image * texImage)
+{
+ tfxTexInfo *ti;
+ GLint wscale, hscale, dstStride = 0;
+ tfxMipMapLevel *mml;
+ GLboolean result;
+ void *uncompressedImage = (void *)0;
+ FxU32 uncompressedSize;
+ TxErrorCallbackFnc_t oldErrorCallback;
+
+ if (target != GL_TEXTURE_2D)
+ return GL_FALSE;
+
+ if (!texObj->DriverData)
+ return GL_FALSE;
+
+ ti = fxTMGetTexInfo(texObj);
+ mml = &ti->mipmapLevel[level];
+
+ fxTexGetInfo(ctx, texImage->Width, texImage->Height, NULL, NULL,
+ NULL, NULL, NULL, NULL, &wscale, &hscale);
+
+ /*
+ * Must have an existing texture image!
+ */
+ assert(mml->data);
+
+ switch (mml->glideFormat) {
+ case GR_TEXFMT_INTENSITY_8:
+ dstStride = mml->width;
+ result = _mesa_convert_texsubimage(MESA_I8, xoffset, yoffset,
+ mml->width, mml->height, mml->data,
+ dstStride, width, height,
+ texImage->Width, texImage->Height,
+ format, type, pixels, packing);
+ break;
+ case GR_TEXFMT_ALPHA_8:
+ dstStride = mml->width;
+ result = _mesa_convert_texsubimage(MESA_A8, xoffset, yoffset,
+ mml->width, mml->height, mml->data,
+ dstStride, width, height,
+ texImage->Width, texImage->Height,
+ format, type, pixels, packing);
+ break;
+ case GR_TEXFMT_P_8:
+ dstStride = mml->width;
+ result = _mesa_convert_texsubimage(MESA_C8, xoffset, yoffset,
+ mml->width, mml->height, mml->data,
+ dstStride, width, height,
+ texImage->Width, texImage->Height,
+ format, type, pixels, packing);
+ break;
+ case GR_TEXFMT_ALPHA_INTENSITY_88:
+ dstStride = mml->width * 2;
+ result = _mesa_convert_texsubimage(MESA_A8_L8, xoffset, yoffset,
+ mml->width, mml->height, mml->data,
+ dstStride, width, height,
+ texImage->Width, texImage->Height,
+ format, type, pixels, packing);
+ break;
+ case GR_TEXFMT_RGB_565:
+ dstStride = mml->width * 2;
+ result = _mesa_convert_texsubimage(MESA_R5_G6_B5, xoffset, yoffset,
+ mml->width, mml->height, mml->data,
+ dstStride, width, height,
+ texImage->Width, texImage->Height,
+ format, type, pixels, packing);
+ break;
+ case GR_TEXFMT_ARGB_4444:
+ dstStride = mml->width * 2;
+ result = _mesa_convert_texsubimage(MESA_A4_R4_G4_B4, xoffset, yoffset,
+ mml->width, mml->height, mml->data,
+ dstStride, width, height,
+ texImage->Width, texImage->Height,
+ format, type, pixels, packing);
+ break;
+ case GR_TEXFMT_ARGB_CMP_FXT1:
+ /*
+ * There are some special legality constraints for compressed
+ * textures.
+ */
+ if ((xoffset != texImage->Border)
+ || (yoffset != texImage->Border)) {
+ gl_error( ctx,
+ GL_INVALID_OPERATION,
+ "glTexSubImage2D(offset)" );
+ return GL_FALSE;
+ }
+ if ((width != texImage->Width)
+ || (height != texImage->Height)) {
+ gl_error( ctx,
+ GL_INVALID_VALUE,
+ "glTexSubImage2D(image size)" );
+ return GL_FALSE;
+ }
+ /*
+ * The width and height have to be multiples of
+ * 8 and 4 respectively.
+ */
+ width = (mml->width + 0x7) &~ 0x7;
+ height = (mml->height + 0x3) &~ 0x3;
+ /*
+ * A texel is 8888 for this format.
+ */
+ uncompressedSize = mml->width * mml->height * 4;
+ uncompressedImage = (void *)MALLOC(uncompressedSize);
+ /*
+ * Convert the data.
+ */
+ dstStride = mml->width * 4;
+ result = _mesa_convert_texsubimage(MESA_A8_R8_G8_B8, xoffset, yoffset,
+ mml->width, mml->height, uncompressedImage,
+ dstStride, width, height,
+ texImage->Width, texImage->Height,
+ format, type, pixels, packing);
+ if (!result) {
+ FREE(uncompressedImage);
+ return GL_FALSE;
+ }
+ /*
+ * Now that we have converted the data, then compress it.
+ */
+ (*txErrorSetCallbackPtr)(fxTexusError, &oldErrorCallback);
+ (*txImgQuantizePtr)((char *)mml->data,
+ (char *)uncompressedImage,
+ mml->width,
+ mml->height,
+ mml->glideFormat,
+ TX_DITHER_NONE);
+ (*txErrorSetCallbackPtr)(oldErrorCallback, NULL);
+ result = TexusFatalError;
+ TexusFatalError = TexusError = FXFALSE;
+ /*
+ * We don't need this any more.
+ */
+ FREE(uncompressedImage);
+ break;
+ case GR_TEXFMT_ARGB_8888:
+ {
+ MesaIntTexFormat intFormat;
+ if (texImage->Format == GL_RGB) {
+ /* An RGB image padded out to 4 bytes/texel */
+ intFormat = MESA_FF_R8_G8_B8;
+ }
+ else {
+ intFormat = MESA_A8_R8_G8_B8;
+ }
+ dstStride = mml->width * 4;
+ result = _mesa_convert_texsubimage(intFormat, xoffset, yoffset,
+ mml->width, mml->height, mml->data,
+ dstStride, width, height,
+ texImage->Width, texImage->Height,
+ format, type, pixels, packing);
+ }
+ break;
+ case GR_TEXFMT_ARGB_1555:
+ dstStride = mml->width * 2;
+ result = _mesa_convert_texsubimage(MESA_A1_R5_G5_B5, xoffset, yoffset,
+ mml->width, mml->height, mml->data,
+ dstStride, width, height,
+ texImage->Width, texImage->Height,
+ format, type, pixels, packing);
+ break;
+ default:
+ gl_problem(NULL, "tdfx driver: fxTexBuildSubImageMap() bad format");
+ result = GL_FALSE;
+ }
+
+ if (!result) {
+ return GL_FALSE;
+ }
+
+ if (ti->validated && ti->isInTM)
+ /* Don't use this, it's very broken. Download whole image for now.*/
+#if 0
+ fxTMReloadSubMipMapLevel(ctx, texObj, level, yoffset, height);
+#else
+ fxTMReloadMipMapLevel(ctx, texObj, level);
+#endif
+ else
+ fxTexInvalidate(ctx, texObj);
+
+ return GL_TRUE;
+}
+
+
+/**********************************************************************/
+/**** COMPRESSED TEXTURE IMAGE FUNCTIONS ****/
+/**********************************************************************/
+
+GLboolean
+fxDDCompressedTexImage2D( GLcontext *ctx, GLenum target,
+ GLint level, GLsizei imageSize,
+ const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage,
+ GLboolean *retainInternalCopy)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ const GLboolean allow32bpt = fxMesa->haveHwStencil;
+ GrTextureFormat_t gldformat;
+ tfxTexInfo *ti;
+ tfxMipMapLevel *mml;
+ GLint dstWidth, dstHeight, wScale, hScale, texelSize;
+ MesaIntTexFormat intFormat;
+ GLboolean isCompressedFormat;
+ GLsizei texsize;
+
+ if (target == GL_PROXY_TEXTURE_2D) {
+ /* XXX not possible for now */
+
+ }
+
+ if (target != GL_TEXTURE_2D || texImage->Border > 0)
+ return GL_FALSE;
+
+ if (!texObj->DriverData)
+ texObj->DriverData = fxAllocTexObjData(fxMesa);
+
+ ti = fxTMGetTexInfo(texObj);
+ mml = &ti->mipmapLevel[level];
+
+ isCompressedFormat = fxDDIsCompressedGlideFormatMacro(texImage->IntFormat);
+ if (!isCompressedFormat) {
+ gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(format)" );
+ return GL_FALSE;
+ }
+ /* Determine the apporpriate GL internal texel format, Mesa internal
+ * texel format, and texelSize (bytes) given the user's internal
+ * texture format hint.
+ */
+ fxTexGetFormat(texImage->IntFormat, &gldformat, NULL, &intFormat,
+ &texelSize, allow32bpt);
+
+ /* Determine width and height scale factors for texture.
+ * Remember, Glide is limited to 8:1 aspect ratios.
+ */
+ fxTexGetInfo(ctx,
+ texImage->Width, texImage->Height,
+ NULL, /* lod level */
+ NULL, /* aspect ratio */
+ NULL, NULL, /* sscale, tscale */
+ NULL, NULL, /* i_sscale, i_tscale */
+ &wScale, &hScale);
+ dstWidth = texImage->Width * wScale;
+ dstHeight = texImage->Height * hScale;
+ /* housekeeping */
+ _mesa_set_teximage_component_sizes(intFormat, texImage);
+
+ texsize = fxDDCompressedImageSize(ctx,
+ texImage->IntFormat,
+ 2,
+ texImage->Width,
+ texImage->Height,
+ 1);
+ if (texsize != imageSize) {
+ gl_error(ctx,
+ GL_INVALID_VALUE,
+ "glCompressedTexImage2D(texsize)");
+ return GL_FALSE;
+ }
+ /* allocate new storage for texture image, if needed */
+ if (!mml->data || mml->glideFormat != gldformat ||
+ mml->width != dstWidth || mml->height != dstHeight ||
+ texsize != mml->dataSize) {
+ if (mml->data) {
+ FREE(mml->data);
+ }
+ mml->data = MALLOC(texsize);
+ if (!mml->data) {
+ return GL_FALSE;
+ }
+ mml->texelSize = texelSize;
+ mml->glideFormat = gldformat;
+ mml->width = dstWidth;
+ mml->height = dstHeight;
+ fxTexInvalidate(ctx, texObj);
+ }
+
+ MEMCPY(mml->data, data, imageSize);
+ if (ti->validated && ti->isInTM) {
+ fxTMReloadMipMapLevel(ctx, texObj, level);
+ }
+ else {
+ fxTexInvalidate(ctx, texObj);
+ }
+
+ *retainInternalCopy = GL_FALSE;
+ return GL_TRUE;
+}
+
+GLboolean
+fxDDCompressedTexSubImage2D( GLcontext *ctx, GLenum target,
+ GLint level, GLint xoffset,
+ GLint yoffset, GLsizei width,
+ GLint height, GLenum format,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ tfxTexInfo *ti;
+ tfxMipMapLevel *mml;
+ /*
+ * We punt if we are not replacing the entire image. This
+ * is allowed by the spec.
+ */
+ if ((xoffset != 0) && (yoffset != 0)
+ && (width != texImage->Width)
+ && (height != texImage->Height)) {
+ return(GL_FALSE);
+ }
+ ti = fxTMGetTexInfo(texObj);
+ mml = &ti->mipmapLevel[level];
+ if (imageSize != mml->dataSize) {
+ return(GL_FALSE);
+ }
+ MEMCPY(data, mml->data, imageSize);
+ return(GL_TRUE);
+}
+
+#if 0
+static void
+PrintTexture(int w, int h, int c, const GLubyte * data)
+{
+ int i, j;
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ if (c == 2)
+ printf("%02x %02x ", data[0], data[1]);
+ else if (c == 3)
+ printf("%02x %02x %02x ", data[0], data[1], data[2]);
+ data += c;
+ }
+ printf("\n");
+ }
+}
+#endif
+
+
+/*
+ * Return a texture image to Mesa. This is either to satisfy
+ * a glGetTexImage() call or to prepare for software texturing.
+ */
+GLvoid *
+fxDDGetTexImage(GLcontext * ctx, GLenum target, GLint level,
+ const struct gl_texture_object *texObj,
+ GLenum * formatOut, GLenum * typeOut,
+ GLboolean * freeImageOut)
+{
+ tfxTexInfo *ti;
+ tfxMipMapLevel *mml;
+
+ if (target != GL_TEXTURE_2D)
+ return NULL;
+
+ if (!texObj->DriverData)
+ return NULL;
+
+ ti = fxTMGetTexInfo(texObj);
+ mml = &ti->mipmapLevel[level];
+ if (mml->data) {
+ MesaIntTexFormat mesaFormat;
+ GLenum glFormat;
+ struct gl_texture_image *texImage = texObj->Image[level];
+ GLint srcStride;
+ void *uncompressedImage = NULL;
+
+ GLubyte *data =
+ (GLubyte *) MALLOC(texImage->Width * texImage->Height * 4);
+ if (!data)
+ return NULL;
+
+ uncompressedImage = (void *)mml->data;
+ switch (mml->glideFormat) {
+ case GR_TEXFMT_INTENSITY_8:
+ mesaFormat = MESA_I8;
+ glFormat = GL_INTENSITY;
+ srcStride = mml->width;
+ break;
+ case GR_TEXFMT_ALPHA_INTENSITY_88:
+ mesaFormat = MESA_A8_L8;
+ glFormat = GL_LUMINANCE_ALPHA;
+ srcStride = mml->width;
+ break;
+ case GR_TEXFMT_ALPHA_8:
+ if (texImage->Format == GL_INTENSITY) {
+ mesaFormat = MESA_I8;
+ glFormat = GL_INTENSITY;
+ }
+ else {
+ mesaFormat = MESA_A8;
+ glFormat = GL_ALPHA;
+ }
+ srcStride = mml->width;
+ break;
+ case GR_TEXFMT_RGB_565:
+ mesaFormat = MESA_R5_G6_B5;
+ glFormat = GL_RGB;
+ srcStride = mml->width * 2;
+ break;
+ case GR_TEXFMT_ARGB_8888:
+ mesaFormat = MESA_A8_R8_G8_B8;
+ glFormat = GL_RGBA;
+ srcStride = mml->width * 4;
+ break;
+ case GR_TEXFMT_ARGB_4444:
+ mesaFormat = MESA_A4_R4_G4_B4;
+ glFormat = GL_RGBA;
+ srcStride = mml->width * 2;
+ break;
+ case GR_TEXFMT_ARGB_1555:
+ mesaFormat = MESA_A1_R5_G5_B5;
+ glFormat = GL_RGBA;
+ srcStride = mml->width * 2;
+ break;
+ case GR_TEXFMT_P_8:
+ mesaFormat = MESA_C8;
+ glFormat = GL_COLOR_INDEX;
+ srcStride = mml->width;
+ break;
+ case GR_TEXFMT_ARGB_CMP_FXT1:
+ mesaFormat = MESA_A8_R8_G8_B8;
+ glFormat = GL_RGBA;
+ srcStride = mml->width * 4;
+ /*
+ * Allocate data for the uncompressed image,
+ * decompress the image. The data will be deallocated
+ * after it is converted to the mesa format.
+ */
+ uncompressedImage = MALLOC(mml->width * mml->height * 4);
+ if (!uncompressedImage) {
+ gl_problem(NULL, "can't get memory in fxDDGetTexImage");
+ return(NULL);
+ }
+ (*txImgDequantizeFXT1Ptr)((FxU32 *)uncompressedImage,
+ (FxU32 *)mml->data,
+ mml->width,
+ mml->height);
+ break;
+ default:
+ gl_problem(NULL, "Bad glideFormat in fxDDGetTexImage");
+ return NULL;
+ }
+ _mesa_unconvert_teximage(mesaFormat, mml->width, mml->height,
+ uncompressedImage, srcStride, texImage->Width,
+ texImage->Height, glFormat, data);
+ if (uncompressedImage != mml->data) {
+ FREE(uncompressedImage);
+ }
+ *formatOut = glFormat;
+ *typeOut = GL_UNSIGNED_BYTE;
+ *freeImageOut = GL_TRUE;
+ return data;
+ }
+ else {
+ return NULL;
+ }
+}
+
+/*
+ * This is called from _mesa_GetCompressedTexImage. We just
+ * copy out the compressed data.
+ */
+void
+fxDDGetCompressedTexImage( GLcontext *ctx, GLenum target,
+ GLint lod, void *image,
+ const struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ tfxTexInfo *ti;
+ tfxMipMapLevel *mml;
+
+ if (target != GL_TEXTURE_2D)
+ return;
+
+ if (!texObj->DriverData)
+ return;
+
+ ti = fxTMGetTexInfo(texObj);
+ mml = &ti->mipmapLevel[lod];
+ if (mml->data) {
+ MEMCPY(image, mml->data, mml->dataSize);
+ }
+}
+
+/*
+ * Calculate a specific texture format given a generic
+ * texture format.
+ */
+GLint
+fxDDSpecificCompressedTexFormat(GLcontext *ctx,
+ GLint internalFormat,
+ GLint numDimensions)
+{
+ if (numDimensions != 2) {
+ return internalFormat;
+ }
+ /*
+ * If we don't have pointers to the functions, then
+ * we drop back to uncompressed format. The logic
+ * in Mesa proper handles this for us.
+ *
+ * This is just to ease the transition to a Glide with
+ * the texus2 library.
+ */
+ if (!txImgQuantizePtr || !txImgDequantizeFXT1Ptr) {
+ return(internalFormat);
+ }
+ switch (internalFormat) {
+ case GL_COMPRESSED_RGB_ARB:
+ return GL_COMPRESSED_RGB_FXT1_3DFX;
+ case GL_COMPRESSED_RGBA_ARB:
+ return GL_COMPRESSED_RGBA_FXT1_3DFX;
+ }
+ return internalFormat;
+}
+
+/*
+ * Calculate a specific texture format given a generic
+ * texture format.
+ */
+GLint
+fxDDBaseCompressedTexFormat(GLcontext *ctx,
+ GLint internalFormat)
+{
+ switch (internalFormat) {
+ case GL_COMPRESSED_RGB_FXT1_3DFX:
+ return(GL_RGB);
+ case GL_COMPRESSED_RGBA_FXT1_3DFX:
+ return(GL_RGBA);
+ }
+ return -1;
+}
+
+/*
+ * Tell us if an image is compressed. The real work is done
+ * in a macro, but we need to have a function to create a
+ * function pointer.
+ */
+GLboolean
+fxDDIsCompressedFormat(GLcontext *ctx, GLint internalFormat)
+{
+ return(fxDDIsCompressedFormatMacro(internalFormat));
+}
+
+
+/*
+ * Calculate the image size of a compressed texture.
+ *
+ * The current compressed format, the FXT1 family, all
+ * map 8x32 texel blocks into 128 bits.
+ *
+ * We return 0 if we can't calculate the size.
+ *
+ * Glide would report this out to us, but we don't have
+ * exactly the right parameters.
+ */
+GLsizei
+fxDDCompressedImageSize(GLcontext *ctx,
+ GLenum intFormat,
+ GLuint numDimensions,
+ GLuint width,
+ GLuint height,
+ GLuint depth)
+{
+ if (numDimensions != 2) {
+ return 0;
+ }
+ switch (intFormat) {
+ case GL_COMPRESSED_RGB_FXT1_3DFX:
+ case GL_COMPRESSED_RGBA_FXT1_3DFX:
+ /*
+ * Round height and width to multiples of 4 and 8,
+ * divide the resulting product by 32 to get the number
+ * of blocks, and multiply by 32 = 128/8 to get the.
+ * number of bytes required. That is to say, just
+ * return the product. Remember that we are returning
+ * bytes, not texels, so we have shrunk the texture
+ * by a factor of the texel size.
+ */
+ width = (width + 0x7) &~ 0x7;
+ height = (height + 0x3) &~ 0x3;
+ return(width * height);
+ }
+ return(0);
+}