/* $Id: fxddtex.c,v 1.46 2001/11/06 16:01:19 brianp Exp $ */ /* * Mesa 3-D graphics library * Version: 4.0 * * Copyright (C) 1999-2001 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. */ /* Authors: * David Bucciarelli * Brian Paul * Daryll Strauss * Keith Whitwell */ #ifdef HAVE_CONFIG_H #include "conf.h" #endif #if defined(FX) #include "fxdrv.h" #include "image.h" #include "teximage.h" #include "texformat.h" #include "texstore.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; } static tfxTexInfo * fxAllocTexObjData(fxMesaContext fxMesa) { tfxTexInfo *ti; if (!(ti = CALLOC(sizeof(tfxTexInfo)))) { fprintf(stderr, "fx Driver: out of memory !\n"); fxCloseHardware(); exit(-1); } 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; return ti; } 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; } 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); } } fxMesa->new_state |= FX_NEW_TEXTURING; } 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; 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; 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; } } 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, (void *) ti); } if (!ti) return; fxTMFreeTexture(fxMesa, tObj); FREE(ti); tObj->DriverData = NULL; } /* * 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->FloatTable); 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; } } 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(GR_TMU0, GR_TEXTABLE_PALETTE, &(fxMesa->glbPalette)); if (fxMesa->haveTwoTMUs) FX_grTexDownloadTable(GR_TMU1, GR_TEXTABLE_PALETTE, &(fxMesa->glbPalette)); } else { fxMesa->haveGlobalPaletteTexture = 0; if ((ctx->Texture.Unit[0]._Current == ctx->Texture.Unit[0].Current2D) && (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(l2) (0x800000 * l2) int fxTexGetInfo(int w, int h, GrLOD_t * lodlevel, GrAspectRatio_t * ar, float *sscale, float *tscale, int *i_sscale, int *i_tscale, int *wscale, int *hscale) { static GrLOD_t lod[9] = { GR_LOD_256, GR_LOD_128, GR_LOD_64, GR_LOD_32, GR_LOD_16, GR_LOD_8, GR_LOD_4, GR_LOD_2, GR_LOD_1 }; int logw, logh, ws, hs; GrLOD_t l; GrAspectRatio_t aspectratio; float s, t; int is, it; logw = logbase2(w); logh = logbase2(h); switch (logw - logh) { case 0: aspectratio = GR_ASPECT_1x1; l = lod[8 - logw]; s = t = 256.0f; is = it = INT_TRICK(8); ws = hs = 1; break; case 1: aspectratio = GR_ASPECT_2x1; l = lod[8 - logw]; s = 256.0f; t = 128.0f; is = INT_TRICK(8); it = INT_TRICK(7); ws = 1; hs = 1; break; case 2: aspectratio = GR_ASPECT_4x1; l = lod[8 - logw]; s = 256.0f; t = 64.0f; is = INT_TRICK(8); it = INT_TRICK(6); ws = 1; hs = 1; break; case 3: aspectratio = GR_ASPECT_8x1; l = lod[8 - logw]; s = 256.0f; t = 32.0f; is = INT_TRICK(8); it = INT_TRICK(5); ws = 1; hs = 1; break; case 4: aspectratio = GR_ASPECT_8x1; l = lod[8 - logw]; s = 256.0f; t = 32.0f; is = INT_TRICK(8); it = INT_TRICK(5); ws = 1; hs = 2; break; case 5: aspectratio = GR_ASPECT_8x1; l = lod[8 - logw]; s = 256.0f; t = 32.0f; is = INT_TRICK(8); it = INT_TRICK(5); ws = 1; hs = 4; break; case 6: aspectratio = GR_ASPECT_8x1; l = lod[8 - logw]; s = 256.0f; t = 32.0f; is = INT_TRICK(8); it = INT_TRICK(5); ws = 1; hs = 8; break; case 7: aspectratio = GR_ASPECT_8x1; l = lod[8 - logw]; s = 256.0f; t = 32.0f; is = INT_TRICK(8); it = INT_TRICK(5); ws = 1; hs = 16; break; case 8: aspectratio = GR_ASPECT_8x1; l = lod[8 - logw]; s = 256.0f; t = 32.0f; is = INT_TRICK(8); it = INT_TRICK(5); ws = 1; hs = 32; break; case -1: aspectratio = GR_ASPECT_1x2; l = lod[8 - logh]; s = 128.0f; t = 256.0f; is = INT_TRICK(7); it = INT_TRICK(8); ws = 1; hs = 1; break; case -2: aspectratio = GR_ASPECT_1x4; l = lod[8 - logh]; s = 64.0f; t = 256.0f; is = INT_TRICK(6); it = INT_TRICK(8); ws = 1; hs = 1; break; case -3: aspectratio = GR_ASPECT_1x8; l = lod[8 - logh]; s = 32.0f; t = 256.0f; is = INT_TRICK(5); it = INT_TRICK(8); ws = 1; hs = 1; break; case -4: aspectratio = GR_ASPECT_1x8; l = lod[8 - logh]; s = 32.0f; t = 256.0f; is = INT_TRICK(5); it = INT_TRICK(8); ws = 2; hs = 1; break; case -5: aspectratio = GR_ASPECT_1x8; l = lod[8 - logh]; s = 32.0f; t = 256.0f; is = INT_TRICK(5); it = INT_TRICK(8); ws = 4; hs = 1; break; case -6: aspectratio = GR_ASPECT_1x8; l = lod[8 - logh]; s = 32.0f; t = 256.0f; is = INT_TRICK(5); it = INT_TRICK(8); ws = 8; hs = 1; break; case -7: aspectratio = GR_ASPECT_1x8; l = lod[8 - logh]; s = 32.0f; t = 256.0f; is = INT_TRICK(5); it = INT_TRICK(8); ws = 16; hs = 1; break; case -8: aspectratio = GR_ASPECT_1x8; l = lod[8 - logh]; s = 32.0f; t = 256.0f; is = INT_TRICK(5); it = INT_TRICK(8); ws = 32; hs = 1; break; default: return 0; break; } if (lodlevel) (*lodlevel) = l; if (ar) (*ar) = aspectratio; 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; return 1; } /* * Given an OpenGL internal texture format, return the corresponding * Glide internal texture format and base texture format. */ void fxTexGetFormat(GLenum glformat, GrTextureFormat_t * tfmt, GLint * ifmt) { switch (glformat) { case 1: case GL_LUMINANCE: case GL_LUMINANCE4: case GL_LUMINANCE8: case GL_LUMINANCE12: case GL_LUMINANCE16: if (tfmt) (*tfmt) = GR_TEXFMT_INTENSITY_8; if (ifmt) (*ifmt) = GL_LUMINANCE; 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 (tfmt) (*tfmt) = GR_TEXFMT_ALPHA_INTENSITY_88; if (ifmt) (*ifmt) = GL_LUMINANCE_ALPHA; break; case GL_INTENSITY: case GL_INTENSITY4: case GL_INTENSITY8: case GL_INTENSITY12: case GL_INTENSITY16: if (tfmt) (*tfmt) = GR_TEXFMT_ALPHA_8; if (ifmt) (*ifmt) = GL_INTENSITY; break; case GL_ALPHA: case GL_ALPHA4: case GL_ALPHA8: case GL_ALPHA12: case GL_ALPHA16: if (tfmt) (*tfmt) = GR_TEXFMT_ALPHA_8; if (ifmt) (*ifmt) = GL_ALPHA; break; case 3: case GL_RGB: case GL_R3_G3_B2: case GL_RGB4: case GL_RGB5: case GL_RGB8: case GL_RGB10: case GL_RGB12: case GL_RGB16: if (tfmt) (*tfmt) = GR_TEXFMT_RGB_565; if (ifmt) (*ifmt) = GL_RGB; break; case 4: case GL_RGBA: case GL_RGBA2: case GL_RGBA4: case GL_RGBA8: case GL_RGB10_A2: case GL_RGBA12: case GL_RGBA16: if (tfmt) (*tfmt) = GR_TEXFMT_ARGB_4444; if (ifmt) (*ifmt) = GL_RGBA; break; case GL_RGB5_A1: if (tfmt) (*tfmt) = GR_TEXFMT_ARGB_1555; if (ifmt) (*ifmt) = GL_RGBA; 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 (tfmt) (*tfmt) = GR_TEXFMT_P_8; if (ifmt) (*ifmt) = GL_RGBA; /* XXX why is this RGBA? */ break; default: fprintf(stderr, "fx Driver: unsupported internalFormat (0x%x) in fxTexGetFormat()\n", glformat); fxCloseHardware(); exit(-1); break; } } static GLboolean fxIsTexSupported(GLenum target, GLint internalFormat, const struct gl_texture_image *image) { if (target != GL_TEXTURE_2D) return GL_FALSE; if (!fxTexGetInfo (image->Width, image->Height, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) return GL_FALSE; if (image->Border > 0) return GL_FALSE; return GL_TRUE; } /**********************************************************************/ /**** NEW TEXTURE IMAGE FUNCTIONS ****/ /**********************************************************************/ /* Texel-fetch functions for software texturing and glGetTexImage(). * We should have been able to use some "standard" fetch functions (which * may get defined in texutil.c) but we have to account for scaled texture * images on tdfx hardware (the 8:1 aspect ratio limit). * Hence, we need special functions here. */ static void fetch_intensity8(const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLvoid * texelOut) { GLchan *rgba = (GLchan *) texelOut; const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage); const GLubyte *texel; i = i * mml->wScale; j = j * mml->hScale; texel = ((GLubyte *) texImage->Data) + j * mml->width + i; rgba[RCOMP] = *texel; rgba[GCOMP] = *texel; rgba[BCOMP] = *texel; rgba[ACOMP] = *texel; } static void fetch_luminance8(const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLvoid * texelOut) { GLchan *rgba = (GLchan *) texelOut; const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage); const GLubyte *texel; i = i * mml->wScale; j = j * mml->hScale; texel = ((GLubyte *) texImage->Data) + j * mml->width + i; rgba[RCOMP] = *texel; rgba[GCOMP] = *texel; rgba[BCOMP] = *texel; rgba[ACOMP] = 255; } static void fetch_alpha8(const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLvoid * texelOut) { GLchan *rgba = (GLchan *) texelOut; const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage); const GLubyte *texel; i = i * mml->wScale; j = j * mml->hScale; i = i * mml->width / texImage->Width; j = j * mml->height / texImage->Height; texel = ((GLubyte *) texImage->Data) + j * mml->width + i; rgba[RCOMP] = 255; rgba[GCOMP] = 255; rgba[BCOMP] = 255; rgba[ACOMP] = *texel; } static void fetch_index8(const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLvoid * texelOut) { GLchan *indexOut = (GLchan *) texelOut; const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage); const GLubyte *texel; i = i * mml->wScale; j = j * mml->hScale; i = i * mml->width / texImage->Width; j = j * mml->height / texImage->Height; texel = ((GLubyte *) texImage->Data) + j * mml->width + i; *indexOut = *texel; } static void fetch_luminance8_alpha8(const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLvoid * texelOut) { GLchan *rgba = (GLchan *) texelOut; const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage); const GLubyte *texel; i = i * mml->wScale; j = j * mml->hScale; texel = ((GLubyte *) texImage->Data) + (j * mml->width + i) * 2; rgba[RCOMP] = texel[0]; rgba[GCOMP] = texel[0]; rgba[BCOMP] = texel[0]; rgba[ACOMP] = texel[1]; } static void fetch_r5g6b5(const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLvoid * texelOut) { GLchan *rgba = (GLchan *) texelOut; const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage); const GLushort *texel; i = i * mml->wScale; j = j * mml->hScale; texel = ((GLushort *) texImage->Data) + j * mml->width + i; rgba[RCOMP] = (((*texel) >> 11) & 0x1f) * 255 / 31; rgba[GCOMP] = (((*texel) >> 5) & 0x3f) * 255 / 63; rgba[BCOMP] = (((*texel) >> 0) & 0x1f) * 255 / 31; rgba[ACOMP] = 255; } static void fetch_r4g4b4a4(const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLvoid * texelOut) { GLchan *rgba = (GLchan *) texelOut; const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage); const GLushort *texel; i = i * mml->wScale; j = j * mml->hScale; texel = ((GLushort *) texImage->Data) + j * mml->width + i; rgba[RCOMP] = (((*texel) >> 12) & 0xf) * 255 / 15; rgba[GCOMP] = (((*texel) >> 8) & 0xf) * 255 / 15; rgba[BCOMP] = (((*texel) >> 4) & 0xf) * 255 / 15; rgba[ACOMP] = (((*texel) >> 0) & 0xf) * 255 / 15; } static void fetch_r5g5b5a1(const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLvoid * texelOut) { GLchan *rgba = (GLchan *) texelOut; const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage); const GLushort *texel; i = i * mml->wScale; j = j * mml->hScale; texel = ((GLushort *) texImage->Data) + j * mml->width + i; rgba[RCOMP] = (((*texel) >> 11) & 0x1f) * 255 / 31; rgba[GCOMP] = (((*texel) >> 6) & 0x1f) * 255 / 31; rgba[BCOMP] = (((*texel) >> 1) & 0x1f) * 255 / 31; rgba[ACOMP] = (((*texel) >> 0) & 0x01) * 255; } 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"); } } const struct gl_texture_format * fxDDChooseTextureFormat( GLcontext *ctx, GLint internalFormat, GLenum srcFormat, GLenum srcType ) { switch (internalFormat) { case GL_INTENSITY: case GL_INTENSITY4: case GL_INTENSITY8: case GL_INTENSITY12: case GL_INTENSITY16: return &_mesa_texformat_i8; case 1: case GL_LUMINANCE: case GL_LUMINANCE4: case GL_LUMINANCE8: case GL_LUMINANCE12: case GL_LUMINANCE16: return &_mesa_texformat_l8; case GL_ALPHA: case GL_ALPHA4: case GL_ALPHA8: case GL_ALPHA12: case GL_ALPHA16: return &_mesa_texformat_a8; 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: return &_mesa_texformat_ci8; 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: return &_mesa_texformat_al88; case 3: case GL_RGB: case GL_R3_G3_B2: case GL_RGB4: case GL_RGB5: case GL_RGB8: case GL_RGB10: case GL_RGB12: case GL_RGB16: return &_mesa_texformat_rgb565; case 4: case GL_RGBA: case GL_RGBA2: case GL_RGBA4: case GL_RGBA8: case GL_RGB10_A2: case GL_RGBA12: case GL_RGBA16: return &_mesa_texformat_argb4444; case GL_RGB5_A1: return &_mesa_texformat_argb1555; default: _mesa_problem(NULL, "unexpected format in fxDDChooseTextureFormat"); return NULL; } } static GrTextureFormat_t fxGlideFormat(GLint mesaFormat) { switch (mesaFormat) { case MESA_FORMAT_I8: return GR_TEXFMT_ALPHA_8; case MESA_FORMAT_A8: return GR_TEXFMT_ALPHA_8; case MESA_FORMAT_L8: return GR_TEXFMT_INTENSITY_8; case MESA_FORMAT_CI8: return GR_TEXFMT_P_8; case MESA_FORMAT_AL88: return GR_TEXFMT_ALPHA_INTENSITY_88; case MESA_FORMAT_RGB565: return GR_TEXFMT_RGB_565; case MESA_FORMAT_ARGB4444: return GR_TEXFMT_ARGB_4444; case MESA_FORMAT_ARGB1555: return GR_TEXFMT_ARGB_1555; default: _mesa_problem(NULL, "Unexpected format in fxGlideFormat"); return 0; } } static FetchTexelFunc fxFetchFunction(GLint mesaFormat) { switch (mesaFormat) { case MESA_FORMAT_I8: return fetch_intensity8; case MESA_FORMAT_A8: return fetch_alpha8; case MESA_FORMAT_L8: return fetch_luminance8; case MESA_FORMAT_CI8: return fetch_index8; case MESA_FORMAT_AL88: return fetch_luminance8_alpha8; case MESA_FORMAT_RGB565: return fetch_r5g6b5; case MESA_FORMAT_ARGB4444: return fetch_r4g4b4a4; case MESA_FORMAT_ARGB1555: return fetch_r5g5b5a1; default: _mesa_problem(NULL, "Unexpected format in fxGlideFormat"); return NULL; } } void fxDDTexImage2D(GLcontext * ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint height, GLint border, GLenum format, GLenum type, const GLvoid * pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx; tfxTexInfo *ti; tfxMipMapLevel *mml; GLint texelBytes; if (!fxIsTexSupported(target, internalFormat, texImage)) { _mesa_problem(NULL, "fx Driver: unsupported texture in fxDDTexImg()\n"); return; } if (!texObj->DriverData) { texObj->DriverData = fxAllocTexObjData(fxMesa); if (!texObj->DriverData) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); return; } } ti = fxTMGetTexInfo(texObj); if (!texImage->DriverData) { texImage->DriverData = MALLOC(sizeof(tfxMipMapLevel)); if (!texImage->DriverData) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); return; } } mml = FX_MIPMAP_DATA(texImage); fxTexGetInfo(width, height, NULL, NULL, NULL, NULL, NULL, NULL, &mml->wScale, &mml->hScale); mml->width = width * mml->wScale; mml->height = height * mml->hScale; /* choose the texture format */ assert(ctx->Driver.ChooseTextureFormat); texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, internalFormat, format, type); assert(texImage->TexFormat); texelBytes = texImage->TexFormat->TexelBytes; assert(texelBytes == 1 || texelBytes == 2); if (mml->wScale != 1 || mml->hScale != 1) { /* rescale image to overcome 1:8 aspect limitation */ GLvoid *tempImage; tempImage = MALLOC(width * height * texelBytes); if (!tempImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); return; } /* unpack image, apply transfer ops and store in tempImage */ _mesa_transfer_teximage(ctx, 2, texImage->Format, texImage->TexFormat, tempImage, width, height, 1, 0, 0, 0, width * texelBytes, 0, /* dstImageStride */ format, type, pixels, packing); assert(!texImage->Data); texImage->Data = MALLOC(mml->width * mml->height * texelBytes); if (!texImage->Data) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); FREE(tempImage); return; } _mesa_rescale_teximage2d(texelBytes, mml->width * texelBytes, /* dst stride */ width, height, mml->width, mml->height, tempImage /*src*/, texImage->Data /*dst*/ ); FREE(tempImage); } else { /* no rescaling needed */ assert(!texImage->Data); texImage->Data = MALLOC(mml->width * mml->height * texelBytes); if (!texImage->Data) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); return; } /* unpack image, apply transfer ops and store in texImage->Data */ _mesa_transfer_teximage(ctx, 2, texImage->Format, texImage->TexFormat, texImage->Data, width, height, 1, 0, 0, 0, texImage->Width * texelBytes, 0, /* dstImageStride */ format, type, pixels, packing); } mml->glideFormat = fxGlideFormat(texImage->TexFormat->MesaFormat); texImage->FetchTexel = fxFetchFunction(texImage->TexFormat->MesaFormat); fxTexInvalidate(ctx, texObj); if (ti->validated && ti->isInTM) { /*printf("reloadmipmaplevels\n"); */ fxTMReloadMipMapLevel(fxMesa, texObj, level); } else { /*printf("invalidate2\n"); */ fxTexInvalidate(ctx, texObj); } } void 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) { fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx; tfxTexInfo *ti; tfxMipMapLevel *mml; GLint texelBytes; if (!texObj->DriverData) { _mesa_problem(ctx, "problem in fxDDTexSubImage2D"); return; } ti = fxTMGetTexInfo(texObj); assert(ti); mml = FX_MIPMAP_DATA(texImage); assert(mml); assert(texImage->Data); /* must have an existing texture image! */ assert(texImage->Format); texelBytes = texImage->TexFormat->TexelBytes; if (mml->wScale != 1 || mml->hScale != 1) { /* need to rescale subimage to match mipmap level's rescale factors */ const GLint newWidth = width * mml->wScale; const GLint newHeight = height * mml->hScale; GLvoid *scaledImage, *tempImage; GLubyte *destAddr; tempImage = MALLOC(width * height * texelBytes); if (!tempImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D"); return; } _mesa_transfer_teximage(ctx, 2, texImage->Format,/* Tex int format */ texImage->TexFormat, /* dest format */ (GLubyte *) tempImage, /* dest */ width, height, 1, /* subimage size */ 0, 0, 0, /* subimage pos */ width * texelBytes, /* dest row stride */ 0, /* dst image stride */ format, type, pixels, packing); /* now rescale */ scaledImage = MALLOC(newWidth * newHeight * texelBytes); if (!scaledImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D"); FREE(tempImage); return; } /* compute address of dest subimage within the overal tex image */ destAddr = (GLubyte *) texImage->Data + (yoffset * mml->hScale * mml->width + xoffset * mml->wScale) * texelBytes; _mesa_rescale_teximage2d(texelBytes, mml->width * texelBytes, /* dst stride */ width, height, newWidth, newHeight, tempImage, destAddr); FREE(tempImage); FREE(scaledImage); } else { /* no rescaling needed */ _mesa_transfer_teximage(ctx, 2, texImage->Format, /* Tex int format */ texImage->TexFormat, /* dest format */ (GLubyte *) texImage->Data,/* dest */ width, height, 1, /* subimage size */ xoffset, yoffset, 0, /* subimage pos */ mml->width * texelBytes, /* dest row stride */ 0, /* dst image stride */ format, type, pixels, packing); } if (ti->validated && ti->isInTM) fxTMReloadMipMapLevel(fxMesa, texObj, level); else fxTexInvalidate(ctx, texObj); } #else /* FX */ /* * Need this to provide at least one external definition. */ extern int gl_fx_dummy_function_ddtex(void); int gl_fx_dummy_function_ddtex(void) { return 0; } #endif /* FX */