Exemplo n.º 1
0
TC_PluginError GenericLoadFunction(FILE*& pFile, DDSD2*& pDDSD, MipSet*& pMipSet, void*& extra,
                                   ChannelFormat channelFormat, TextureDataType textureDataType, 
                                   PreLoopFunction fnPreLoop, LoopFunction fnLoop, PostLoopFunction fnPostLoop)
{
    DWORD dwWidth, dwHeight;
    TC_PluginError err;

    DetermineTextureType(pDDSD, pMipSet);
    if(!DDS_CMips->AllocateMipSet(pMipSet, channelFormat, textureDataType, pMipSet->m_TextureType, 
        pDDSD->dwWidth, pDDSD->dwHeight, pMipSet->m_nDepth))
        return PE_Unknown;

    if(pDDSD->dwFlags & DDSD_MIPMAPCOUNT)
        pMipSet->m_nMipLevels = pDDSD->dwMipMapCount;
    else
        pMipSet->m_nMipLevels = pDDSD->dwMipMapCount;

    if(pMipSet->m_nMipLevels < 1)
        pMipSet->m_nMipLevels = 1;

    err = fnPreLoop(pFile, pDDSD, pMipSet, extra);
    if(err != PE_OK)
        return err;

    if(pMipSet->m_dwFourCC)
        return fnLoop(pFile, pDDSD, pMipSet, extra, 0, 0, pDDSD->dwWidth, pDDSD->dwHeight);
    else
    {
        //pMipSet now allocated
        if(pMipSet->m_TextureType == TT_2D || pMipSet->m_TextureType == TT_CubeMap)
        {
            for(int nFace = 0; nFace < pMipSet->m_nDepth; nFace++)
            {
                dwWidth = pDDSD->dwWidth;
                dwHeight = pDDSD->dwHeight;
                for(int nMipLevel = 0; nMipLevel < pMipSet->m_nMipLevels; nMipLevel++)
                {
                    err = fnLoop(pFile, pDDSD, pMipSet, extra, nMipLevel, nFace, dwWidth, dwHeight);
                    if(err != PE_OK)
                        return err;
                    dwWidth = (dwWidth>1) ? (dwWidth>>1) : 1;
                    dwHeight = (dwHeight>1) ? (dwHeight>>1) : 1;
                }
            }
        }
        else if(pMipSet->m_TextureType == TT_VolumeTexture)
        {
            dwWidth = pDDSD->dwWidth;
            dwHeight = pDDSD->dwHeight;
            for(int nMipLevel = 0; nMipLevel < pMipSet->m_nMipLevels; nMipLevel++)
            {
                int nMaxSlices = MaxFacesOrSlices(pMipSet, nMipLevel);
                for(int nSlice=0; nSlice<nMaxSlices; nSlice++)
                {
                    err = fnLoop(pFile, pDDSD, pMipSet, extra, nMipLevel, nSlice, dwWidth, dwHeight);
                    if(err != PE_OK)
                        return err;
                }
                dwWidth = dwWidth>1 ? dwWidth>>1 : 1;
                dwHeight = dwHeight>1 ? dwHeight>>1 : 1;
            }
        }
Exemplo n.º 2
0
//nMinSize : The size in pixels used to determine how many mip levels to generate. Once all dimensions are less than or equal to nMinSize your mipper should generate no more mip levels.
int Plugin_BoxFilter::TC_GenerateMIPLevels(MipSet *pMipSet, int nMinSize)
{
    assert(pMipSet);
    assert(pMipSet->m_nMipLevels);

    
    int nPrevMipLevels = pMipSet->m_nMipLevels;
    int nWidth = pMipSet->m_nWidth;
    int nHeight = pMipSet->m_nHeight;

    while(nWidth > nMinSize && nHeight > nMinSize)
    {
        nWidth = max(nWidth >> 1, 1);
        nHeight = max(nHeight >> 1, 1);
        int nCurMipLevel = pMipSet->m_nMipLevels;
        int maxFacesOrSlices = max((pMipSet->m_TextureType == TT_VolumeTexture) ? (MaxFacesOrSlices(pMipSet, nCurMipLevel-1)>>1) : MaxFacesOrSlices(pMipSet, nCurMipLevel-1), 1);
        for(int nFaceOrSlice=0; nFaceOrSlice<maxFacesOrSlices; nFaceOrSlice++)
        {
            MipLevel* pThisMipLevel = CMips->GetMipLevel(pMipSet, nCurMipLevel, nFaceOrSlice);
            if (!pThisMipLevel) continue;
            assert(CMips->GetMipLevel(pMipSet, nCurMipLevel-1, nFaceOrSlice)->m_pbData);    //prev miplevel ok

            if(pThisMipLevel->m_pbData) // Space for mip level already allocated ?
            {
                if(pThisMipLevel->m_nWidth != nWidth || pThisMipLevel->m_nHeight != nHeight)
                {
                    // Wrong size - release & reallocate
                    //CMips->FreeMipLevelData(pThisMipLevel);
                    if(CMips->AllocateMipLevelData(pThisMipLevel, nWidth, nHeight, pMipSet->m_ChannelFormat, pMipSet->m_TextureDataType) == NULL)
                    {
                        return PE_Unknown;
                    }
                }
            }
            else if(CMips->AllocateMipLevelData(pThisMipLevel, nWidth, nHeight, pMipSet->m_ChannelFormat, pMipSet->m_TextureDataType) == NULL)
            {
                return PE_Unknown;
            }

            assert(pThisMipLevel->m_pbData);
            if(pMipSet->m_TextureType != TT_VolumeTexture)
            {
                MipLevel *tempMipOne = CMips->GetMipLevel(pMipSet, nCurMipLevel - 1, nFaceOrSlice);
                if(pMipSet->m_ChannelFormat == CF_8bit)
                    GenerateMipLevel(pThisMipLevel, tempMipOne);
                else if (pMipSet->m_ChannelFormat == CF_Float16)
                    GenerateMipLevelF(pThisMipLevel, tempMipOne, NULL, pThisMipLevel->m_phfData, tempMipOne->m_phfData);
                else if(pMipSet->m_ChannelFormat == CF_Float32)
                    GenerateMipLevelF(pThisMipLevel, tempMipOne, NULL, pThisMipLevel->m_pfData, tempMipOne->m_pfData);
            }
            else
            {
                if(MaxFacesOrSlices(pMipSet, nCurMipLevel-1) > 1)
                {
                    MipLevel *tempMipOne = CMips->GetMipLevel(pMipSet, nCurMipLevel - 1, nFaceOrSlice * 2);
                    MipLevel *tempMipTwo = CMips->GetMipLevel(pMipSet, nCurMipLevel - 1, nFaceOrSlice * 2 + 1);
                    //prev miplevel had 2 or more slices, so avg together slices
                    if(pMipSet->m_ChannelFormat == CF_8bit)
                        GenerateMipLevel(pThisMipLevel, tempMipOne, tempMipTwo);
                    else if (pMipSet->m_ChannelFormat == CF_Float16)
                        GenerateMipLevelF(pThisMipLevel, tempMipOne, tempMipTwo, pThisMipLevel->m_phfData, tempMipOne->m_phfData, tempMipTwo->m_phfData);
                    else if(pMipSet->m_ChannelFormat == CF_Float32)
                        GenerateMipLevelF(pThisMipLevel, tempMipOne, tempMipTwo, pThisMipLevel->m_pfData, tempMipOne->m_pfData, tempMipTwo->m_pfData);
                }
                else
                {
                    MipLevel *tempMipOne = CMips->GetMipLevel(pMipSet, nCurMipLevel - 1, nFaceOrSlice);
                    if(pMipSet->m_ChannelFormat == CF_8bit)
                        GenerateMipLevel(pThisMipLevel, tempMipOne);
                    else if (pMipSet->m_ChannelFormat == CF_Float16)
                        GenerateMipLevelF(pThisMipLevel, tempMipOne, NULL, pThisMipLevel->m_phfData, tempMipOne->m_phfData);
                    else if(pMipSet->m_ChannelFormat == CF_Float32)
                        GenerateMipLevelF(pThisMipLevel, tempMipOne, NULL, pThisMipLevel->m_pfData, tempMipOne->m_pfData);
                }
            }
        }

        if (pMipSet->m_nMipLevels < MAX_MIPLEVEL_SUPPORTED)
            ++pMipSet->m_nMipLevels;
        else
            break;
        if (nWidth == 1 || nHeight == 1)
            break;
    }


    // Increment for the one that already existed
    // pMipSet->m_nMipLevels++;

    //free up unused miplevels. shouldn't be any b/c we should have made all possible
    //for(int i=pMipSet->m_nMipLevels; i<nPrevMipLevels; i++)
    //{
    //    for(int j=0; j<MaxFacesOrSlices(pMipSet, i); j++)
    //    {
    //        CMips->FreeMipLevelData(CMips->GetMipLevel(pMipSet, i, j));
    //    }
    //}

    return PE_OK;
}