inline uint32_t ComputeFVF()

in Utilities/FlexibleVertexFormat.h [834:1061]


    inline uint32_t ComputeFVF(
        _In_reads_(maxDeclLength) const D3DVERTEXELEMENT9* pDecl, size_t maxDeclLength)
    {
        if (!pDecl)
            return 0;

        if (maxDeclLength > MAXD3DDECLLENGTH + 1)
            return 0;

        // validate vertex declaration
        auto pCurrent = pDecl;
        size_t count = 0;
        size_t offset = 0;
        while (pCurrent->Stream != 0xFF)
        {
            ++count;
            if (count > maxDeclLength)
                return 0;

            if (pCurrent->Stream != 0)
                return 0;

            if (pCurrent->Type > D3DDECLTYPE_SHORT4)
                return 0;

            if (offset != pCurrent->Offset)
                return 0;

            if (pCurrent->Method > D3DDECLMETHOD_LOOKUP)
                return 0;

            if (((pCurrent->Usage > D3DDECLUSAGE_TEXCOORD)
                && (pCurrent->Usage != D3DDECLUSAGE_POSITIONT)
                && (pCurrent->Usage != D3DDECLUSAGE_COLOR)))
            {
                return 0;
            }

            if ((pCurrent->Usage == D3DDECLUSAGE_COLOR) && (pCurrent->UsageIndex > 1))
            {
                return 0;
            }

            offset += g_declTypeSizes[pCurrent->Type];

            ++pCurrent;
        }

        // Build FVF code
        pCurrent = pDecl;
        count = 0;
        uint32_t fvfCode = 0;
        if (pCurrent->Usage == D3DDECLUSAGE_POSITION)
        {
            if (pCurrent->Type == D3DDECLTYPE_FLOAT3)
            {
                size_t weights = 0;
                ++count;
                if (count > maxDeclLength)
                    return 0;
                ++pCurrent;

                if (pCurrent->Usage == D3DDECLUSAGE_BLENDWEIGHT)
                {
                    if ((pCurrent->Type >= D3DDECLTYPE_FLOAT1) && (pCurrent->Type <= D3DDECLTYPE_FLOAT4))
                    {
                        weights = pCurrent->Type - D3DDECLTYPE_FLOAT1 + 1;
                        ++count;
                        if (count > maxDeclLength)
                            return 0;
                        ++pCurrent;
                    }
                    else
                    {
                        return 0;
                    }
                }

                if (pCurrent->Usage == D3DDECLUSAGE_BLENDINDICES)
                {
                    if (pCurrent->Type == D3DDECLTYPE_UBYTE4)
                    {
                        fvfCode |= D3DFVF_LASTBETA_UBYTE4;

                        ++weights;
                        ++count;
                        if (count > maxDeclLength)
                            return 0;
                        ++pCurrent;
                    }
                    else if (pCurrent->Type == D3DDECLTYPE_D3DCOLOR)
                    {
                        fvfCode |= D3DFVF_LASTBETA_D3DCOLOR;

                        ++weights;
                        ++count;
                        if (count > maxDeclLength)
                            return 0;
                        ++pCurrent;
                    }
                    else
                    {
                        return 0;
                    }
                }

                switch (weights)
                {
                case 0: fvfCode |= D3DFVF_XYZ;   break;
                case 1: fvfCode |= D3DFVF_XYZB1; break;
                case 2: fvfCode |= D3DFVF_XYZB2; break;
                case 3: fvfCode |= D3DFVF_XYZB3; break;
                case 4: fvfCode |= D3DFVF_XYZB4; break;
                case 5: fvfCode |= D3DFVF_XYZB5; break;
                }
            }
            else if (pCurrent->Type == D3DDECLTYPE_FLOAT4)
            {
                fvfCode |= D3DFVF_XYZW;
                ++count;
                if (count > maxDeclLength)
                    return 0;
                ++pCurrent;
            }
        }
        else if ((pCurrent->Usage == D3DDECLUSAGE_POSITIONT)
            && (pCurrent->Type == D3DDECLTYPE_FLOAT4))
        {
            fvfCode |= D3DFVF_XYZRHW;
            ++count;
            if (count > maxDeclLength)
                return 0;
            ++pCurrent;
        }

        // Normal
        if ((pCurrent->Usage == D3DDECLUSAGE_NORMAL)
            && (pCurrent->Type == D3DDECLTYPE_FLOAT3))
        {
            fvfCode |= D3DFVF_NORMAL;
            ++count;
            if (count > maxDeclLength)
                return 0;
            ++pCurrent;
        }

        // Point size
        if ((pCurrent->Usage == D3DDECLUSAGE_PSIZE)
            && (pCurrent->Type == D3DDECLTYPE_FLOAT1))
        {
            fvfCode |= D3DFVF_PSIZE;
            ++count;
            if (count > maxDeclLength)
                return 0;
            ++pCurrent;
        }

        // Diffuse
        if ((pCurrent->Usage == D3DDECLUSAGE_COLOR)
            && (pCurrent->UsageIndex == 0)
            && (pCurrent->Type == D3DDECLTYPE_D3DCOLOR))
        {
            fvfCode |= D3DFVF_DIFFUSE;
            ++count;
            if (count > maxDeclLength)
                return 0;
            ++pCurrent;
        }

        // Specular
        if ((pCurrent->Usage == D3DDECLUSAGE_COLOR)
            && (pCurrent->UsageIndex == 1)
            && (pCurrent->Type == D3DDECLTYPE_D3DCOLOR))
        {
            fvfCode |= D3DFVF_SPECULAR;
            ++count;
            if (count > maxDeclLength)
                return 0;
            ++pCurrent;
        }

        // Texture coordinates
        size_t i;

        for (i = 0; i < 8; ++i)
        {
            if ((pCurrent->Usage == D3DDECLUSAGE_TEXCOORD)
                && (pCurrent->Type == D3DDECLTYPE_FLOAT1)
                && (pCurrent->UsageIndex == i))
            {
                fvfCode |= static_cast<uint32_t>(D3DFVF_TEXCOORDSIZE1(i));
            }
            else if ((pCurrent->Usage == D3DDECLUSAGE_TEXCOORD)
                && (pCurrent->Type == D3DDECLTYPE_FLOAT2)
                && (pCurrent->UsageIndex == i))
            {
                fvfCode |= static_cast<uint32_t>(D3DFVF_TEXCOORDSIZE2(i));
            }
            else if ((pCurrent->Usage == D3DDECLUSAGE_TEXCOORD)
                && (pCurrent->Type == D3DDECLTYPE_FLOAT3)
                && (pCurrent->UsageIndex == i))
            {
                fvfCode |= static_cast<uint32_t>(D3DFVF_TEXCOORDSIZE3(i));
            }
            else if ((pCurrent->Usage == D3DDECLUSAGE_TEXCOORD)
                && (pCurrent->Type == D3DDECLTYPE_FLOAT4)
                && (pCurrent->UsageIndex == i))
            {
                fvfCode |= static_cast<uint32_t>(D3DFVF_TEXCOORDSIZE4(i));
            }
            else
                break;

            ++count;
            if (count > maxDeclLength)
                return 0;
            ++pCurrent;
        }

        fvfCode |= static_cast<uint32_t>(i << D3DFVF_TEXCOUNT_SHIFT);

        if (pCurrent->Stream != 0xff)
        {
            return 0;
        }

        return fvfCode;
    }