#ifdef _WIN32 #include #include #else // _WIN32 #include "../winlnxdefs.h" #include #endif // _WIN32 #include "glide.h" #include "main.h" #define TMU_SIZE 8*1024*1024 int tex0_width, tex0_height, tex1_width, tex1_height; float lambda; static int min_filter0, mag_filter0, wrap_s0, wrap_t0; static int min_filter1, mag_filter1, wrap_s1, wrap_t1; unsigned char *filter(unsigned char *source, int width, int height, int *width2, int *height2); typedef struct _texlist { unsigned int id; struct _texlist *next; } texlist; static int nbTex; static texlist *list; void remove_tex(unsigned int idmin, unsigned int idmax) { unsigned int *t; int n = 0; texlist *aux = list; if (aux == NULL) return; t = (unsigned int*)malloc(nbTex * sizeof(int)); while (aux->id >= idmin && aux->id < idmax) { t[n++] = aux->id; aux = aux->next; free(list); list = aux; nbTex--; } while (aux != NULL && aux->next != NULL) { if (aux->next->id >= idmin && aux->next->id < idmax) { texlist *aux2 = aux->next->next; t[n++] = aux->next->id; free(aux->next); aux->next = aux2; nbTex--; } aux = aux->next; } glDeleteTextures(n, t); free(t); } void add_tex(unsigned int id) { texlist *aux = list; texlist *aux2; nbTex++; if (list == NULL || id < list->id) { list = (texlist*)malloc(sizeof(texlist)); list->next = aux; list->id = id; return; } while (aux->next != NULL && aux->next->id < id) aux = aux->next; aux2 = aux->next; aux->next = (texlist*)malloc(sizeof(texlist)); aux->next->id = id; aux->next->next = aux2; } void init_textures() { tex0_width = tex0_height = tex1_width = tex1_height = 2; list = NULL; nbTex = 0; } void free_textures() { remove_tex(0x00000000, 0xFFFFFFFF); } FX_ENTRY FxU32 FX_CALL grTexMinAddress( GrChipID_t tmu ) { return tmu*TMU_SIZE; } FX_ENTRY FxU32 FX_CALL grTexMaxAddress( GrChipID_t tmu ) { return tmu*TMU_SIZE + TMU_SIZE - 1; } FX_ENTRY FxU32 FX_CALL grTexTextureMemRequired( FxU32 evenOdd, GrTexInfo *info ) { int width, height; if (info->largeLodLog2 != info->smallLodLog2) display_warning((unsigned char*)"grTexTextureMemRequired : loading more than one LOD"); if (info->aspectRatioLog2 < 0) { height = 1 << info->largeLodLog2; width = height >> -info->aspectRatioLog2; } else { width = 1 << info->largeLodLog2; height = width >> info->aspectRatioLog2; } switch(info->format) { case GR_TEXFMT_ALPHA_8: case GR_TEXFMT_ALPHA_INTENSITY_44: return width*height; break; case GR_TEXFMT_ARGB_1555: case GR_TEXFMT_ARGB_4444: case GR_TEXFMT_ALPHA_INTENSITY_88: return width*height*2; break; default: display_warning((unsigned char*)"grTexTextureMemRequired : unknown texture format: %x", info->format); } return 0; } FX_ENTRY FxU32 FX_CALL grTexCalcMemRequired( GrLOD_t lodmin, GrLOD_t lodmax, GrAspectRatio_t aspect, GrTextureFormat_t fmt) { int width, height; if (lodmax != lodmin) display_warning((unsigned char*)"grTexCalcMemRequired : loading more than one LOD"); if (aspect < 0) { height = 1 << lodmax; width = height >> -aspect; } else { width = 1 << lodmax; height = width >> aspect; } switch(fmt) { case GR_TEXFMT_ALPHA_8: case GR_TEXFMT_ALPHA_INTENSITY_44: return width*height; break; case GR_TEXFMT_ARGB_1555: case GR_TEXFMT_ARGB_4444: case GR_TEXFMT_ALPHA_INTENSITY_88: case GR_TEXFMT_RGB_565: return width*height*2; break; default: display_warning((unsigned char*)"grTexTextureMemRequired : unknown texture format: %x", fmt); } return 0; } FX_ENTRY void FX_CALL grTexDownloadMipMap( GrChipID_t tmu, FxU32 startAddress, FxU32 evenOdd, GrTexInfo *info ) { int width, height, i, j; unsigned char* texture = NULL; unsigned char* filtered_texture = NULL; int factor = 0; if (info->largeLodLog2 != info->smallLodLog2) display_warning((unsigned char*)"grTexDownloadMipMap : loading more than one LOD"); if (info->aspectRatioLog2 < 0) { height = 1 << info->largeLodLog2; width = height >> -info->aspectRatioLog2; } else { width = 1 << info->largeLodLog2; height = width >> info->aspectRatioLog2; } texture = (unsigned char*)malloc(width*height*4); switch(info->format) { case GR_TEXFMT_ALPHA_8: for (j=0; jdata)[i*width+j]; texture[i*width*4+j*4+1]= ((unsigned char*)info->data)[i*width+j]; texture[i*width*4+j*4+2]= ((unsigned char*)info->data)[i*width+j]; texture[i*width*4+j*4+3]= ((unsigned char*)info->data)[i*width+j]; } } factor = 1; break; case GR_TEXFMT_ALPHA_INTENSITY_44: for (j=0; jdata)[i*width+j]&0xF0); texture[i*width*4+j*4+0]= ((((unsigned char*)info->data)[i*width+j]&0xF)<<4); texture[i*width*4+j*4+1]= ((((unsigned char*)info->data)[i*width+j]&0xF)<<4); texture[i*width*4+j*4+2]= ((((unsigned char*)info->data)[i*width+j]&0xF)<<4); } } factor = 1; break; case GR_TEXFMT_ARGB_1555: for (j=0; jdata)[i*width+j]>>15)!=0 ? 0xFF : 0; texture[i*width*4+j*4+0]=((((unsigned short*)info->data)[i*width+j]>>10)&0x1F)<<3; texture[i*width*4+j*4+1]=((((unsigned short*)info->data)[i*width+j]>> 5)&0x1F)<<3; texture[i*width*4+j*4+2]=((((unsigned short*)info->data)[i*width+j]>> 0)&0x1F)<<3; } } factor = 2; break; case GR_TEXFMT_ALPHA_INTENSITY_88: for (j=0; jdata)[i*width*2+j*2+1]; texture[i*width*4+j*4+0]= ((unsigned char*)info->data)[i*width*2+j*2]; texture[i*width*4+j*4+1]= ((unsigned char*)info->data)[i*width*2+j*2]; texture[i*width*4+j*4+2]= ((unsigned char*)info->data)[i*width*2+j*2]; } } factor = 2; break; case GR_TEXFMT_ARGB_4444: for (j=0; jdata)[i*width+j]>>12)&0xF)<<4; texture[i*width*4+j*4+0]=((((unsigned short*)info->data)[i*width+j]>> 8)&0xF)<<4; texture[i*width*4+j*4+1]=((((unsigned short*)info->data)[i*width+j]>> 4)&0xF)<<4; texture[i*width*4+j*4+2]=((((unsigned short*)info->data)[i*width+j]>> 0)&0xF)<<4; } } factor = 2; break; default: display_warning((unsigned char*)"grTexDownloadMipMap : unknown texture format: %x", info->format); } if (nbTextureUnits <= 2) glActiveTextureARB(GL_TEXTURE1_ARB); else glActiveTextureARB(GL_TEXTURE2_ARB); remove_tex(startAddress+1, startAddress+1+width*height*factor); add_tex(startAddress+1); glBindTexture(GL_TEXTURE_2D, startAddress+1); if (getFilter() == 0) glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture); else { int width2, height2; filtered_texture = filter(texture, width, height, &width2, &height2); glTexImage2D(GL_TEXTURE_2D, 0, 4, width2, height2, 0, GL_RGBA, GL_UNSIGNED_BYTE, filtered_texture); } glBindTexture(GL_TEXTURE_2D, 32*1024*1024); if (texture) free(texture); if (filtered_texture) free(filtered_texture); } FX_ENTRY void FX_CALL grTexSource( GrChipID_t tmu, FxU32 startAddress, FxU32 evenOdd, GrTexInfo *info ) { if ((startAddress+1) == pBufferAddress && render_to_texture) updateTexture(); if (tmu == GR_TMU1 || nbTextureUnits <= 2) { if (tmu == GR_TMU1 && nbTextureUnits <= 2) return; glActiveTextureARB(GL_TEXTURE0_ARB); if (info->aspectRatioLog2 < 0) { tex0_height = 256; tex0_width = tex0_height >> -info->aspectRatioLog2; } else { tex0_width = 256; tex0_height = tex0_width >> info->aspectRatioLog2; } glBindTexture(GL_TEXTURE_2D, startAddress+1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t0); if(!glsl_support) { if (need_lambda[0]) glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, lambda_color[0]); else glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, texture_env_color); updateCombiner(0); updateCombinera(0); } } else { glActiveTextureARB(GL_TEXTURE1_ARB); if (info->aspectRatioLog2 < 0) { tex1_height = 256; tex1_width = tex1_height >> -info->aspectRatioLog2; } else { tex1_width = 256; tex1_height = tex1_width >> info->aspectRatioLog2; } glBindTexture(GL_TEXTURE_2D, startAddress+1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t1); if(!glsl_support) { if (need_lambda[1]) glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, lambda_color[1]); else glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, texture_env_color); updateCombiner(1); updateCombinera(1); } } } FX_ENTRY void FX_CALL grTexDetailControl( GrChipID_t tmu, int lod_bias, FxU8 detail_scale, float detail_max ) { if (lod_bias != 31 && detail_scale != 7) { if (!lod_bias && !detail_scale && !detail_max) return; else display_warning((unsigned char*)"grTexDetailControl : %d, %d, %f", lod_bias, detail_scale, detail_max); } lambda = detail_max; if(lambda > 1.0f) { lambda = 1.0f - (255.0f - lambda); } if(lambda > 1.0f) display_warning((unsigned char*)"lambda:%f", lambda); if(!glsl_support) { if (tmu == GR_TMU1 || nbTextureUnits <= 2) { if (tmu == GR_TMU1 && nbTextureUnits <= 2) return; if (need_lambda[0]) { int i; glActiveTextureARB(GL_TEXTURE0_ARB); for (i=0; i<3; i++) lambda_color[0][i] = texture_env_color[i]; lambda_color[0][3] = lambda; glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, lambda_color[0]); } } else { if (need_lambda[1]) { int i; glActiveTextureARB(GL_TEXTURE1_ARB); for (i=0; i<3; i++) lambda_color[1][i] = texture_env_color[i]; lambda_color[1][3] = lambda; glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, lambda_color[1]); } } } else set_lambda(); } FX_ENTRY void FX_CALL grTexLodBiasValue(GrChipID_t tmu, float bias ) { /*if (bias != 0 && bias != 1.0f) display_warning("grTexLodBiasValue : %f", bias);*/ } FX_ENTRY void FX_CALL grTexFilterMode( GrChipID_t tmu, GrTextureFilterMode_t minfilter_mode, GrTextureFilterMode_t magfilter_mode ) { if (tmu == GR_TMU1 || nbTextureUnits <= 2) { if (tmu == GR_TMU1 && nbTextureUnits <= 2) return; if (minfilter_mode == GR_TEXTUREFILTER_POINT_SAMPLED) min_filter0 = GL_NEAREST; else min_filter0 = GL_LINEAR; if (magfilter_mode == GR_TEXTUREFILTER_POINT_SAMPLED) mag_filter0 = GL_NEAREST; else mag_filter0 = GL_LINEAR; glActiveTextureARB(GL_TEXTURE0_ARB); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter0); } else { if (minfilter_mode == GR_TEXTUREFILTER_POINT_SAMPLED) min_filter1 = GL_NEAREST; else min_filter1 = GL_LINEAR; if (magfilter_mode == GR_TEXTUREFILTER_POINT_SAMPLED) mag_filter1 = GL_NEAREST; else mag_filter1 = GL_LINEAR; glActiveTextureARB(GL_TEXTURE1_ARB); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter1); } } FX_ENTRY void FX_CALL grTexClampMode( GrChipID_t tmu, GrTextureClampMode_t s_clampmode, GrTextureClampMode_t t_clampmode ) { if (tmu == GR_TMU1 || nbTextureUnits <= 2) { if (tmu == GR_TMU1 && nbTextureUnits <= 2) return; switch(s_clampmode) { case GR_TEXTURECLAMP_WRAP: wrap_s0 = GL_REPEAT; break; case GR_TEXTURECLAMP_CLAMP: wrap_s0 = GL_CLAMP_TO_EDGE; break; case GR_TEXTURECLAMP_MIRROR_EXT: wrap_s0 = GL_MIRRORED_REPEAT_ARB; break; default: display_warning((unsigned char*)"grTexClampMode : unknown s_clampmode : %x", s_clampmode); } switch(t_clampmode) { case GR_TEXTURECLAMP_WRAP: wrap_t0 = GL_REPEAT; break; case GR_TEXTURECLAMP_CLAMP: wrap_t0 = GL_CLAMP_TO_EDGE; break; case GR_TEXTURECLAMP_MIRROR_EXT: wrap_t0 = GL_MIRRORED_REPEAT_ARB; break; default: display_warning((unsigned char*)"grTexClampMode : unknown t_clampmode : %x", t_clampmode); } glActiveTextureARB(GL_TEXTURE0_ARB); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t0); } else { switch(s_clampmode) { case GR_TEXTURECLAMP_WRAP: wrap_s1 = GL_REPEAT; break; case GR_TEXTURECLAMP_CLAMP: wrap_s1 = GL_CLAMP_TO_EDGE; break; case GR_TEXTURECLAMP_MIRROR_EXT: wrap_s1 = GL_MIRRORED_REPEAT_ARB; break; default: display_warning((unsigned char*)"grTexClampMode : unknown s_clampmode : %x", s_clampmode); } switch(t_clampmode) { case GR_TEXTURECLAMP_WRAP: wrap_t1 = GL_REPEAT; break; case GR_TEXTURECLAMP_CLAMP: wrap_t1 = GL_CLAMP_TO_EDGE; break; case GR_TEXTURECLAMP_MIRROR_EXT: wrap_t1 = GL_MIRRORED_REPEAT_ARB; break; default: display_warning((unsigned char*)"grTexClampMode : unknown t_clampmode : %x", t_clampmode); } glActiveTextureARB(GL_TEXTURE1_ARB); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t1); } }