| /* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */ |
| |
| /* |
| * 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. |
| */ |
| |
| |
| #ifdef HAVE_CONFIG_H |
| #include "conf.h" |
| #endif |
| |
| #if defined(FX) |
| |
| #include "fxdrv.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)))) { |
| 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; |
| |
| for(i=0;i<MAX_TEXTURE_LEVELS;i++) { |
| ti->mipmapLevel[i].data=NULL; |
| } |
| |
| 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; |
| 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); |
| } |
| |
| } |
| |
| 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; |
| } |
| } |
| |
| 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; |
| |
| /* Pushed into core: Set _NEW_TEXTURE whenever a bound texture is |
| * deleted (changes bound texture id). |
| */ |
| /* ctx->NewState |= _NEW_TEXTURE; */ |
| } |
| |
| |
| |
| /* |
| * 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; |
| 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(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].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(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 in fxTexGetFormat()\n"); |
| 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 ****/ |
| /**********************************************************************/ |
| |
| 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 = (fxMesaContext)ctx->DriverCtx; |
| |
| if (target != GL_TEXTURE_2D) |
| return GL_FALSE; |
| |
| if (!texObj->DriverData) |
| texObj->DriverData = fxAllocTexObjData(fxMesa); |
| |
| if (fxIsTexSupported(target, texImage->IntFormat, texImage)) { |
| GrTextureFormat_t gldformat; |
| tfxTexInfo *ti = fxTMGetTexInfo(texObj); |
| tfxMipMapLevel *mml = &ti->mipmapLevel[level]; |
| GLint dstWidth, dstHeight, wScale, hScale, texelSize, dstStride; |
| MesaIntTexFormat intFormat; |
| |
| fxTexGetFormat(texImage->IntFormat, &gldformat, NULL); |
| |
| fxTexGetInfo(texImage->Width, texImage->Height, NULL,NULL,NULL,NULL, |
| NULL,NULL, &wScale, &hScale); |
| |
| dstWidth = texImage->Width * wScale; |
| dstHeight = texImage->Height * hScale; |
| |
| switch (texImage->IntFormat) { |
| case GL_INTENSITY: |
| case GL_INTENSITY4: |
| case GL_INTENSITY8: |
| case GL_INTENSITY12: |
| case GL_INTENSITY16: |
| texelSize = 1; |
| intFormat = MESA_I8; |
| break; |
| case 1: |
| case GL_LUMINANCE: |
| case GL_LUMINANCE4: |
| case GL_LUMINANCE8: |
| case GL_LUMINANCE12: |
| case GL_LUMINANCE16: |
| texelSize = 1; |
| intFormat = MESA_L8; |
| break; |
| case GL_ALPHA: |
| case GL_ALPHA4: |
| case GL_ALPHA8: |
| case GL_ALPHA12: |
| case GL_ALPHA16: |
| texelSize = 1; |
| intFormat = MESA_A8; |
| 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: |
| texelSize = 1; |
| intFormat = MESA_C8; |
| 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: |
| texelSize = 2; |
| intFormat = MESA_A8_L8; |
| 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: |
| texelSize = 2; |
| intFormat = MESA_R5_G6_B5; |
| 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: |
| texelSize = 2; |
| intFormat = MESA_A4_R4_G4_B4; |
| break; |
| case GL_RGB5_A1: |
| texelSize = 2; |
| intFormat = MESA_A1_R5_G5_B5; |
| break; |
| default: |
| gl_problem(NULL, "tdfx driver: texbuildimagemap() bad format"); |
| return GL_FALSE; |
| } |
| |
| _mesa_set_teximage_component_sizes(intFormat, texImage); |
| |
| /*printf("teximage:\n");*/ |
| /* allocate new storage for texture image, if needed */ |
| if (!mml->data || mml->glideFormat != gldformat || |
| mml->width != dstWidth || mml->height != dstHeight) { |
| if (mml->data) |
| FREE(mml->data); |
| mml->data = MALLOC(dstWidth * dstHeight * texelSize); |
| if (!mml->data) |
| return GL_FALSE; |
| mml->glideFormat = gldformat; |
| mml->width = dstWidth; |
| mml->height = dstHeight; |
| fxTexInvalidate(ctx, texObj); |
| } |
| |
| dstStride = dstWidth * texelSize; |
| |
| /* store the texture image */ |
| if (!_mesa_convert_teximage(intFormat, dstWidth, dstHeight, mml->data, |
| dstStride, |
| texImage->Width, texImage->Height, |
| format, type, pixels, packing)) { |
| return GL_FALSE; |
| } |
| |
| if (ti->validated && ti->isInTM) { |
| /*printf("reloadmipmaplevels\n");*/ |
| fxTMReloadMipMapLevel(fxMesa, texObj, level); |
| } |
| else { |
| /*printf("invalidate2\n");*/ |
| fxTexInvalidate(ctx,texObj); |
| } |
| |
| *retainInternalCopy = GL_FALSE; |
| return GL_TRUE; |
| } |
| else { |
| gl_problem(NULL, "fx Driver: unsupported texture in fxDDTexImg()\n"); |
| return GL_FALSE; |
| } |
| } |
| |
| |
| 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) |
| { |
| fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx; |
| tfxTexInfo *ti; |
| GLint wscale, hscale, dstStride; |
| tfxMipMapLevel *mml; |
| GLboolean result; |
| |
| if (target != GL_TEXTURE_2D) |
| return GL_FALSE; |
| |
| if (!texObj->DriverData) |
| return GL_FALSE; |
| |
| ti = fxTMGetTexInfo(texObj); |
| mml = &ti->mipmapLevel[level]; |
| |
| fxTexGetInfo( texImage->Width, texImage->Height, NULL,NULL,NULL,NULL, |
| NULL,NULL, &wscale, &hscale); |
| |
| assert(mml->data); /* must have an existing texture image! */ |
| |
| 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_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) |
| fxTMReloadMipMapLevel(fxMesa, texObj, level); |
| else |
| fxTexInvalidate(ctx, texObj); |
| |
| return GL_TRUE; |
| } |
| |
| |
| 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"); |
| } |
| } |
| |
| |
| 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; |
| |
| GLubyte *data = (GLubyte *) MALLOC(texImage->Width * texImage->Height * 4); |
| if (!data) |
| return NULL; |
| |
| 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: |
| 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_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; |
| default: |
| gl_problem(NULL, "Bad glideFormat in fxDDGetTexImage"); |
| return NULL; |
| } |
| _mesa_unconvert_teximage(mesaFormat, mml->width, mml->height, mml->data, |
| srcStride, texImage->Width, texImage->Height, |
| glFormat, data); |
| *formatOut = glFormat; |
| *typeOut = GL_UNSIGNED_BYTE; |
| *freeImageOut = GL_TRUE; |
| return data; |
| } |
| else { |
| return NULL; |
| } |
| } |
| |
| |
| #else |
| |
| |
| /* |
| * Need this to provide at least one external definition. |
| */ |
| |
| int gl_fx_dummy_function_ddtex(void) |
| { |
| return 0; |
| } |
| |
| #endif /* FX */ |