/* ======================================================================================= Name : TexCompress.c Author : Gliglou Corporation Description : compression of textures ======================================================================================= */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ #include "PvObj_st.h" #include "texture.h" #include "TEX.h" #include "DLLInter.h" #include "DLLCaps.h" #include "TexArray.h" #include "prf.h" /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* ---------------------------------------------------------------------------------------- Description : compress texture width ---------------------------------------------------------------------------------------- */ long GLI_lCompressTexturesSizeInX(struct GLI_tdstTexture_ *p_stTexture) { long lTextureSizeBefore; lTextureSizeBefore = GLI_DRV_lGetTextureSize(p_stTexture); p_stTexture -> lWidth >>= 1; return ( lTextureSizeBefore - GLI_DRV_lGetTextureSize(p_stTexture)); } /* ---------------------------------------------------------------------------------------- Description : compress texture height ---------------------------------------------------------------------------------------- */ long GLI_lCompressTexturesSizeInY(struct GLI_tdstTexture_ *p_stTexture) { long lTextureSizeBefore; lTextureSizeBefore = GLI_DRV_lGetTextureSize(p_stTexture); p_stTexture -> lHeight >>= 1; return ( lTextureSizeBefore - GLI_DRV_lGetTextureSize(p_stTexture)); } /* ---------------------------------------------------------------------------------------- Description : compress texture size ---------------------------------------------------------------------------------------- */ long GLI_lCompressTextureSize(GLI_tdstTexture *p_stTexture) { long lTextureSizeBefore; if ( (p_stTexture -> lHeight <= 4) || (p_stTexture -> lWidth <= 4) ) return 0; lTextureSizeBefore = GLI_DRV_lGetTextureSize(p_stTexture); p_stTexture -> lCompressionCounter ++; p_stTexture -> lHeight >>= 1; p_stTexture -> lWidth >>= 1; return ( lTextureSizeBefore - GLI_DRV_lGetTextureSize(p_stTexture)); } /* ---------------------------------------------------------------------------------------- Description : compute texture compression ---------------------------------------------------------------------------------------- */ long TEX_lComputeCompression() { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ long lSizeOfLevel,lSizeAvailable, lTextureCounter; long lCounterAntiInfinite, lNbTexLowQuality; unsigned long lMaxTextureSize,lIsAcceptNonSquaredTextures; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ lSizeOfLevel = GLI_lComputeTexturesSize(); /* lSizeAvailable = GLI_DRV_lGetHardwareTotalTextureMemorySize( GLI_lGetTextureMode() ); lMaxTextureSize = GLI_DRV_lGetHardwareMaxTextureSize() ; lIsAcceptNonSquaredTextures = GLI_DRV_lIsHardwareAcceptNonSquaredTextures(); */ lSizeAvailable = GLI_g_stCaps.ulTotalTextureMemory; lMaxTextureSize = GLI_g_stCaps.ulTextureMaxSize;; lIsAcceptNonSquaredTextures = GLI_g_stCaps.ulTextureCaps & GLICAPS_TEX_C_ulSupportNonSquare; PRF_fn_vSetIndependantVariable( PRF_C_ulIdpTextureSize, lSizeOfLevel ); PRF_fn_vSetIndependantVariable( PRF_C_ulIdpTextureMemorySize, lSizeAvailable ); /* * if hardware doesn't accept non-squared textures squared them * and compress texture if hardware size is smaller than texture */ if (lIsAcceptNonSquaredTextures == 0) { for (lTextureCounter = 0 ; lTextureCounter < GLI_C_lNBMaxOfTextures; lTextureCounter ++) { if (gs_aDEFTableOfTextureMemoryChannels[lTextureCounter] == GLI_TEXIsUnallocated) continue; /* Make them squared */ while (gs_aDEFTableOfTextureAlreadyRead[lTextureCounter]->lWidth > gs_aDEFTableOfTextureAlreadyRead[lTextureCounter]->lHeight) lSizeOfLevel -= GLI_lCompressTexturesSizeInX(gs_aDEFTableOfTextureAlreadyRead [lTextureCounter]); while (gs_aDEFTableOfTextureAlreadyRead[lTextureCounter]->lWidth < gs_aDEFTableOfTextureAlreadyRead[lTextureCounter]->lHeight) lSizeOfLevel -= GLI_lCompressTexturesSizeInY(gs_aDEFTableOfTextureAlreadyRead [lTextureCounter]); /* then compress too large textures */ while ( gs_aDEFTableOfTextureAlreadyRead[lTextureCounter]->lWidth > lMaxTextureSize ) { lSizeOfLevel -= GLI_lCompressTexturesSizeInX(gs_aDEFTableOfTextureAlreadyRead [lTextureCounter]); lSizeOfLevel -= GLI_lCompressTexturesSizeInY(gs_aDEFTableOfTextureAlreadyRead [lTextureCounter]); } } } else { /* Compress Height */ for (lTextureCounter = 0 ; lTextureCounter < GLI_C_lNBMaxOfTextures; lTextureCounter ++) { if (gs_aDEFTableOfTextureMemoryChannels[lTextureCounter] == GLI_TEXIsUnallocated) continue; while (gs_aDEFTableOfTextureAlreadyRead[lTextureCounter]->lWidth > lMaxTextureSize) lSizeOfLevel -= GLI_lCompressTexturesSizeInX(gs_aDEFTableOfTextureAlreadyRead [lTextureCounter]); } /* Compress Width */ for (lTextureCounter = 0 ; lTextureCounter < GLI_C_lNBMaxOfTextures; lTextureCounter ++) { if (gs_aDEFTableOfTextureMemoryChannels[lTextureCounter] == GLI_TEXIsUnallocated) continue; while (gs_aDEFTableOfTextureAlreadyRead[lTextureCounter]->lHeight > lMaxTextureSize) lSizeOfLevel -= GLI_lCompressTexturesSizeInY(gs_aDEFTableOfTextureAlreadyRead [lTextureCounter]); } } if (lSizeAvailable == -1) /* Case of the reality engine */ return 0; lCounterAntiInfinite = 10; lNbTexLowQuality = 1; while ((lSizeOfLevel > lSizeAvailable) && (lCounterAntiInfinite-- > 0)) { if( lNbTexLowQuality ) { lNbTexLowQuality--; /* First compress the low textures */ for (lTextureCounter =GLI_C_lNBMaxOfTextures - 1 ; (lTextureCounter >= 0) && (lSizeOfLevel > lSizeAvailable); lTextureCounter --) { if (gs_aDEFTableOfTextureMemoryChannels[lTextureCounter] == GLI_TEXIsUnallocated) continue; if (TEX_ucGetTextureQualityLevel(gs_aDEFTableOfTextureAlreadyRead[lTextureCounter]) != TEX_C_QNORMAL) { if (TEX_ucGetTextureQualityLevel(gs_aDEFTableOfTextureAlreadyRead[lTextureCounter]) != TEX_C_QHIGH) /* = LOW quality*/ /*if (GLI_M_bNotAnLODLevel(gs_aDEFTableOfTextureMemoryChannels[lTextureCounter]))*/ { lNbTexLowQuality++; lSizeOfLevel -= GLI_lCompressTextureSize(gs_aDEFTableOfTextureAlreadyRead [ lTextureCounter ]); if (lSizeOfLevel < lSizeAvailable) continue; lSizeOfLevel -= GLI_lCompressTextureSize(gs_aDEFTableOfTextureAlreadyRead [ lTextureCounter ]); } } } } /* then compress Normal textures;*/ for (lTextureCounter =0 ; (lTextureCounter < GLI_C_lNBMaxOfTextures) && (lSizeOfLevel > lSizeAvailable); lTextureCounter ++) { if (gs_aDEFTableOfTextureMemoryChannels[lTextureCounter] == GLI_TEXIsUnallocated) continue; if (TEX_ucGetTextureQualityLevel(gs_aDEFTableOfTextureAlreadyRead[lTextureCounter]) == TEX_C_QNORMAL) lSizeOfLevel -= GLI_lCompressTextureSize(gs_aDEFTableOfTextureAlreadyRead [ lTextureCounter ]); } } return 0; }