diff options
Diffstat (limited to 'src/mesa/drivers/glide/fxddtex.c')
-rw-r--r-- | src/mesa/drivers/glide/fxddtex.c | 1299 |
1 files changed, 1299 insertions, 0 deletions
diff --git a/src/mesa/drivers/glide/fxddtex.c b/src/mesa/drivers/glide/fxddtex.c new file mode 100644 index 00000000000..05ef77570c1 --- /dev/null +++ b/src/mesa/drivers/glide/fxddtex.c @@ -0,0 +1,1299 @@ +/* -*- mode: C; tab-width:8; -*- + + fxddtex.c - 3Dfx VooDoo Texture mapping functions +*/ + +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * See the file fxapi.c for more informations about authors + * + */ + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#if defined(FX) + +#include "fxdrv.h" + +/************************************************************************/ +/*************************** Texture Mapping ****************************/ +/************************************************************************/ + +static void fxTexInvalidate(GLcontext *ctx, struct gl_texture_object *tObj) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + tfxTexInfo *ti; + + fxTMMoveOutTM(fxMesa,tObj); /* TO DO: SLOW but easy to write */ + + ti=(tfxTexInfo *)tObj->DriverData; + 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=malloc(sizeof(tfxTexInfo)))) { + fprintf(stderr,"fx Driver: out of memory !\n"); + fxCloseHardware(); + exit(-1); + } + + ti->validated=GL_FALSE; + ti->tmi.isInTM=GL_FALSE; + + ti->tmi.whichTMU=FX_TMU_NONE; + + ti->tmi.tm[FX_TMU0]=NULL; + ti->tmi.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; + + if(fxMesa->haveTwoTMUs) { + ti->mmMode=GR_MIPMAP_NEAREST; + ti->LODblend=FXTRUE; + } else { + ti->mmMode=GR_MIPMAP_NEAREST_DITHER; + ti->LODblend=FXFALSE; + } + + for(i=0;i<MAX_TEXTURE_LEVELS;i++) { + ti->tmi.mipmapLevel[i].used=GL_FALSE; + ti->tmi.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=(tfxTexInfo *)tObj->DriverData; + + fxMesa->texBindNumber++; + ti->tmi.lastTimeUsed=fxMesa->texBindNumber; + + fxMesa->new_state|=FX_NEW_TEXTURING; + ctx->Driver.RenderStart = fxSetupFXUnits; +} + +void fxDDTexEnv(GLcontext *ctx, 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); + } + + 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=(tfxTexInfo *)tObj->DriverData; + + 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=(fxMesaContext)ctx->DriverCtx; + tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxDDTexDel(%d,%x)\n",tObj->Name,(GLuint)ti); + } + + if(!ti) + return; + + fxTMFreeTexture(fxMesa,tObj); + + free(ti); + tObj->DriverData=NULL; + + ctx->NewState|=NEW_TEXTURING; +} + +void fxDDTexPalette(GLcontext *ctx, struct gl_texture_object *tObj) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + int i; + FxU32 r,g,b,a; + tfxTexInfo *ti; + + if(tObj) { + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxDDTexPalette(%d,%x)\n",tObj->Name,(GLuint)tObj->DriverData); + } + + if(tObj->PaletteFormat!=GL_RGBA) { +#ifndef FX_SILENT + fprintf(stderr,"fx Driver: unsupported palette format in texpalette()\n"); +#endif + return; + } + + if(tObj->PaletteSize>256) { +#ifndef FX_SILENT + fprintf(stderr,"fx Driver: unsupported palette size in texpalette()\n"); +#endif + return; + } + + if(!tObj->DriverData) + tObj->DriverData=fxAllocTexObjData(fxMesa); + + ti=(tfxTexInfo *)tObj->DriverData; + + for(i=0;i<tObj->PaletteSize;i++) { + r=tObj->Palette[i*4]; + g=tObj->Palette[i*4+1]; + b=tObj->Palette[i*4+2]; + a=tObj->Palette[i*4+3]; + ti->palette.data[i]=(a<<24)|(r<<16)|(g<<8)|b; + } + + fxTexInvalidate(ctx,tObj); + } else { + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: fxDDTexPalette(global)\n"); + } + if(ctx->Texture.PaletteFormat!=GL_RGBA) { +#ifndef FX_SILENT + fprintf(stderr,"fx Driver: unsupported palette format in texpalette()\n"); +#endif + return; + } + + if(ctx->Texture.PaletteSize>256) { +#ifndef FX_SILENT + fprintf(stderr,"fx Driver: unsupported palette size in texpalette()\n"); +#endif + return; + } + + for(i=0;i<ctx->Texture.PaletteSize;i++) { + r=ctx->Texture.Palette[i*4]; + g=ctx->Texture.Palette[i*4+1]; + b=ctx->Texture.Palette[i*4+2]; + a=ctx->Texture.Palette[i*4+3]; + fxMesa->glbPalette.data[i]=(a<<24)|(r<<16)|(g<<8)|b; + } + + fxMesa->new_state|=FX_NEW_TEXTURING; + ctx->Driver.RenderStart = fxSetupFXUnits; + } +} + +void fxDDTexUseGlbPalette(GLcontext *ctx, GLboolean state) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + + 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; + tfxTexInfo *ti; + + if(!tObj->DriverData) + tObj->DriverData=fxAllocTexObjData(fxMesa); + + ti=(tfxTexInfo *)tObj->DriverData; + + 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; +} + +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_RGB5_A1: + 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_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; + break; + default: + fprintf(stderr,"fx Driver: unsupported internalFormat in fxTexGetFormat()\n"); + fxCloseHardware(); + exit(-1); + break; + } +} + +static int fxIsTexSupported(GLenum target, GLint internalFormat, + const struct gl_texture_image *image) +{ + if(target!=GL_TEXTURE_2D) + return GL_FALSE; + + switch(internalFormat) { + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + 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: + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + 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: + case 4: + case GL_RGBA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + 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: + break; + default: + return GL_FALSE; + } + + if(image->Width>256) + return GL_FALSE; + + if(image->Height>256) + return GL_FALSE; + + if(!fxTexGetInfo(image->Width,image->Height,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL)) + return GL_FALSE; + + return GL_TRUE; +} + +static void fxTexBuildImageMap(const struct gl_texture_image *image, + GLint internalFormat, unsigned short **dest, + GLboolean *istranslate) +{ + unsigned short *src; + unsigned char *data; + int x,y,w,h,wscale,hscale,idx; + + fxTexGetInfo(image->Width,image->Height,NULL,NULL,NULL,NULL,NULL,NULL, + &wscale,&hscale); + w=image->Width*wscale; + h=image->Height*hscale; + + data=image->Data; + switch(internalFormat) { + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + 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: + /* Optimized for GLQuake */ + + if(wscale==hscale==1) { + (*istranslate)=GL_FALSE; + + (*dest)=(unsigned short *)data; + } else { + unsigned char *srcb; + + (*istranslate)=GL_TRUE; + + if(!(*dest)) { + if(!((*dest)=src=(unsigned short *)malloc(sizeof(unsigned char)*w*h))) { + fprintf(stderr,"fx Driver: out of memory !\n"); + fxCloseHardware(); + exit(-1); + } + } else + src=(*dest); + + srcb=(unsigned char *)src; + + for(y=0;y<h;y++) + for(x=0;x<w;x++) { + idx=(x/wscale+(y/hscale)*(w/wscale)); + srcb[x+y*w]=data[idx]; + } + } + 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: + (*istranslate)=GL_TRUE; + + if(!(*dest)) { + if(!((*dest)=src=(unsigned short *)malloc(sizeof(unsigned short)*w*h))) { + fprintf(stderr,"fx Driver: out of memory !\n"); + fxCloseHardware(); + exit(-1); + } + } else + src=(*dest); + + if(wscale==hscale==1) { + int i=0; + int lenght=h*w; + unsigned short a,l; + + while(i++<lenght) { + l=*data++; + a=*data++; + + *src++=(a << 8) | l; + } + } else { + unsigned short a,l; + + for(y=0;y<h;y++) + for(x=0;x<w;x++) { + idx=(x/wscale+(y/hscale)*(w/wscale))*2; + l=data[idx]; + a=data[idx+1]; + + src[x+y*w]=(a << 8) | l; + } + } + 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: + (*istranslate)=GL_TRUE; + + if(!(*dest)) { + if(!((*dest)=src=(unsigned short *)malloc(sizeof(unsigned short)*w*h))) { + fprintf(stderr,"fx Driver: out of memory !\n"); + fxCloseHardware(); + exit(-1); + } + } else + src=(*dest); + + if(wscale==hscale==1) { + int i=0; + int lenght=h*w; + unsigned short r,g,b; + + while(i++<lenght) { + r=*data++; + g=*data++; + b=*data++; + + *src++=((0xf8 & r) << (11-3)) | + ((0xfc & g) << (5-3+1)) | + ((0xf8 & b) >> 3); + } + } else { + unsigned short r,g,b; + + for(y=0;y<h;y++) + for(x=0;x<w;x++) { + idx=(x/wscale+(y/hscale)*(w/wscale))*3; + r=data[idx]; + g=data[idx+1]; + b=data[idx+2]; + + src[x+y*w]=((0xf8 & r) << (11-3)) | + ((0xfc & g) << (5-3+1)) | + ((0xf8 & b) >> 3); + } + } + break; + case 4: + case GL_RGBA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + (*istranslate)=GL_TRUE; + + if(!(*dest)) { + if(!((*dest)=src=(unsigned short *)malloc(sizeof(unsigned short)*w*h))) { + fprintf(stderr,"fx Driver: out of memory !\n"); + fxCloseHardware(); + exit(-1); + } + } else + src=(*dest); + + if(wscale==hscale==1) { + int i=0; + int lenght=h*w; + unsigned short r,g,b,a; + + while(i++<lenght) { + r=*data++; + g=*data++; + b=*data++; + a=*data++; + + *src++=((0xf0 & a) << 8) | + ((0xf0 & r) << 4) | + (0xf0 & g) | + ((0xf0 & b) >> 4); + } + } else { + unsigned short r,g,b,a; + + for(y=0;y<h;y++) + for(x=0;x<w;x++) { + idx=(x/wscale+(y/hscale)*(w/wscale))*4; + r=data[idx]; + g=data[idx+1]; + b=data[idx+2]; + a=data[idx+3]; + + src[x+y*w]=((0xf0 & a) << 8) | + ((0xf0 & r) << 4) | + (0xf0 & g) | + ((0xf0 & b) >> 4); + } + } + break; + default: + fprintf(stderr,"fx Driver: wrong internalFormat in texbuildimagemap()\n"); + fxCloseHardware(); + exit(-1); + break; + } +} + +void fxDDTexImg(GLcontext *ctx, GLenum target, + struct gl_texture_object *tObj, GLint level, GLint internalFormat, + const struct gl_texture_image *image) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + tfxTexInfo *ti; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: (%d) fxDDTexImg(...,%d,%x,%d,%d...)\n",tObj->Name, + target,internalFormat,image->Width,image->Height); + } + + if(target!=GL_TEXTURE_2D) + return; + + if(!tObj->DriverData) + tObj->DriverData=fxAllocTexObjData(fxMesa); + + ti=(tfxTexInfo *)tObj->DriverData; + + if(fxIsTexSupported(target,internalFormat,image)) { + GrTextureFormat_t gldformat; + tfxMipMapLevel *mml=&ti->tmi.mipmapLevel[level]; + + fxTexGetFormat(internalFormat,&gldformat,NULL); + + if(mml->used) { + if((mml->glideFormat==gldformat) && + (mml->width==image->Width) && + (mml->height==image->Height)) { + fxTexBuildImageMap(image,internalFormat,&(mml->data), + &(mml->translated)); + + if(ti->validated && ti->tmi.isInTM) + fxTMReloadMipMapLevel(fxMesa,tObj,level); + else + fxTexInvalidate(ctx,tObj); + + return; + } else { + if(mml->translated) + free(mml->data); + mml->data=NULL; + } + } + + mml->glideFormat=gldformat; + mml->width=image->Width; + mml->height=image->Height; + mml->used=GL_TRUE; + + fxTexBuildImageMap(image,internalFormat,&(mml->data), + &(mml->translated)); + + fxTexInvalidate(ctx,tObj); + } +#ifndef FX_SILENT + else + fprintf(stderr,"fx Driver: unsupported texture in fxDDTexImg()\n"); +#endif +} + +static void fxTexBuildSubImageMap(const struct gl_texture_image *image, + GLint internalFormat, + GLint xoffset, GLint yoffset, GLint width, GLint height, + unsigned short *destimg) +{ + fxTexGetInfo(image->Width,image->Height,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL); + + switch(internalFormat) { + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + 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: + { + + int y; + unsigned char *bsrc,*bdst; + + bsrc=(unsigned char *)(image->Data+(yoffset*image->Width+xoffset)); + bdst=((unsigned char *)destimg)+(yoffset*image->Width+xoffset); + + for(y=0;y<height;y++) { + MEMCPY(bdst,bsrc,width); + bsrc += image->Width; + bdst += image->Width; + } + } + 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: + { + int x,y; + unsigned char *src; + unsigned short *dst,a,l; + int simgw,dimgw; + + src=(unsigned char *)(image->Data+(yoffset*image->Width+xoffset)*2); + dst=destimg+(yoffset*image->Width+xoffset); + + simgw=(image->Width-width)*2; + dimgw=image->Width-width; + for(y=0;y<height;y++) { + for(x=0;x<width;x++) { + l=*src++; + a=*src++; + *dst++=(a << 8) | l; + } + + src += simgw; + dst += dimgw; + } + } + 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: + { + int x,y; + unsigned char *src; + unsigned short *dst,r,g,b; + int simgw,dimgw; + + src=(unsigned char *)(image->Data+(yoffset*image->Width+xoffset)*3); + dst=destimg+(yoffset*image->Width+xoffset); + + simgw=(image->Width-width)*3; + dimgw=image->Width-width; + for(y=0;y<height;y++) { + for(x=0;x<width;x++) { + r=*src++; + g=*src++; + b=*src++; + *dst++=((0xf8 & r) << (11-3)) | + ((0xfc & g) << (5-3+1)) | + ((0xf8 & b) >> 3); + } + + src += simgw; + dst += dimgw; + } + } + break; + case 4: + case GL_RGBA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + { + int x,y; + unsigned char *src; + unsigned short *dst,r,g,b,a; + int simgw,dimgw; + + src=(unsigned char *)(image->Data+(yoffset*image->Width+xoffset)*4); + dst=destimg+(yoffset*image->Width+xoffset); + + simgw=(image->Width-width)*4; + dimgw=image->Width-width; + for(y=0;y<height;y++) { + for(x=0;x<width;x++) { + r=*src++; + g=*src++; + b=*src++; + a=*src++; + *dst++=((0xf0 & a) << 8) | + ((0xf0 & r) << 4) | + (0xf0 & g) | + ((0xf0 & b) >> 4); + } + + src += simgw; + dst += dimgw; + } + } + break; + default: + fprintf(stderr,"fx Driver: wrong internalFormat in fxTexBuildSubImageMap()\n"); + fxCloseHardware(); + exit(-1); + break; + } +} + + +void fxDDTexSubImg(GLcontext *ctx, GLenum target, + struct gl_texture_object *tObj, GLint level, + GLint xoffset, GLint yoffset, GLint width, GLint height, + GLint internalFormat, const struct gl_texture_image *image) +{ + fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; + tfxTexInfo *ti; + GrTextureFormat_t gldformat; + int wscale,hscale; + tfxMipMapLevel *mml; + + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: (%d) fxDDTexSubImg(...,%d,%x,%d,%d...)\n",tObj->Name, + target,internalFormat,image->Width,image->Height); + } + + if(target!=GL_TEXTURE_2D) + return; + + if(!tObj->DriverData) + return; + + ti=(tfxTexInfo *)tObj->DriverData; + mml=&ti->tmi.mipmapLevel[level]; + + fxTexGetFormat(internalFormat,&gldformat,NULL); + + if(mml->glideFormat!=gldformat) { + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: ti->info.format!=format in fxDDTexSubImg()\n"); + } + fxDDTexImg(ctx,target,tObj,level,internalFormat,image); + + return; + } + + fxTexGetInfo(image->Width,image->Height,NULL,NULL,NULL,NULL,NULL,NULL,&wscale,&hscale); + + if((wscale!=1) || (hscale!=1)) { + if (MESA_VERBOSE&VERBOSE_DRIVER) { + fprintf(stderr,"fxmesa: (wscale!=1) || (hscale!=1) in fxDDTexSubImg()\n"); + } + fxDDTexImg(ctx,target,tObj,level,internalFormat,image); + + return; + } + + if(mml->translated) + fxTexBuildSubImageMap(image,internalFormat,xoffset,yoffset, + width,height,mml->data); + + if(ti->validated && ti->tmi.isInTM) + fxTMReloadSubMipMapLevel(fxMesa,tObj,level,yoffset,height); + else + fxTexInvalidate(ctx,tObj); +} + + +#else + + +/* + * Need this to provide at least one external definition. + */ + +int gl_fx_dummy_function_ddtex(void) +{ + return 0; +} + +#endif /* FX */ |