Esempio n. 1
0
int CNvTNTCombiner::ParseDecodedMux()
{
    TNT2CombinerSaveType res;
    res.numOfUnits = 2;

    (*m_ppDecodedMux)->To_AB_Add_CD_Format();

    for( int i=0; i<res.numOfUnits*2; i++ ) // Set combiner for each texture unit
    {
        // For each texture unit, set both RGB and Alpha channel
        // Keep in mind that the m_pDecodeMux has been reformated and simplified very well

        TNT2CombinerType &unit = res.units[i/2];
        TNT2CombType &comb = unit.Combs[i%2];

        CombinerFormatType type = (*m_ppDecodedMux)->splitType[i];
        N64CombinerType &m = (*m_ppDecodedMux)->m_n64Combiners[i];

        comb.arg0 = comb.arg1 = comb.arg2 = comb.arg3 = MUX_0;
        unit.ops[i%2] = 0x0104; //Add;
        //Subtract

        switch( type )
        {
        case CM_FMT_TYPE_NOT_USED:
            comb.arg0 = MUX_COMBINED;
            comb.arg1 = MUX_1;
            comb.arg2 = MUX_0;
            comb.arg3 = MUX_1;
        case CM_FMT_TYPE_D:             // = A
            comb.arg0 = m.d;
            comb.arg1 = MUX_1;
            comb.arg2 = MUX_0;
            comb.arg3 = MUX_0;
            break;
        case CM_FMT_TYPE_A_ADD_D:           // = A+D
            comb.arg0 = m.a;
            comb.arg1 = MUX_1;
            comb.arg2 = m.d;
            comb.arg3 = MUX_1;
            if( isComb(m.d) )
            {
                swap(comb.arg0, comb.arg2);
                swap(comb.arg1, comb.arg3);
            }
            break;
        case CM_FMT_TYPE_A_SUB_B:           // = A-B
            comb.arg0 = m.a^MUX_COMPLEMENT;
            comb.arg1 = MUX_1;
            unit.ops[i%2] = GL_SUBTRACT_ARB;
            comb.arg2 = m.b;
            comb.arg3 = MUX_1;
            break;
        case CM_FMT_TYPE_A_MOD_C:           // = A*C
            comb.arg0 = m.a;
            comb.arg1 = m.c;
            comb.arg2 = MUX_0;
            comb.arg3 = MUX_0;
            break;
        case CM_FMT_TYPE_A_MOD_C_ADD_D: // = A*C+D
            comb.arg0 = m.a;
            comb.arg1 = m.c;
            comb.arg2 = m.d;
            comb.arg3 = MUX_1;
            if( isComb(m.d) )
            {
                swap(comb.arg0, comb.arg2);
                swap(comb.arg1, comb.arg3);
            }
            break;
        case CM_FMT_TYPE_A_LERP_B_C:        // = (A-B)*C+B
            comb.arg0 = m.a;
            comb.arg1 = m.c;
            comb.arg2 = m.c^MUX_COMPLEMENT;
            comb.arg3 = m.b;
            if( isComb(m.b) )
            {
                swap(comb.arg0, comb.arg2);
                swap(comb.arg1, comb.arg3);
            }
            break;
        case CM_FMT_TYPE_A_SUB_B_ADD_D: // = A-B+D
            // fix me, to use 2 texture units
            if( isTex(m.b) && isTex(m.d) )
            {
                comb.arg0 = m.a;
                comb.arg1 = m.b;
                comb.arg2 = m.d;
                comb.arg3 = MUX_1;
                if( isComb(m.d) )
                {
                    swap(comb.arg0, comb.arg2);
                    swap(comb.arg1, comb.arg3);
                }
            }
            else if( isTex(m.b) && !isComb(m.d) )
            {
                comb.arg0 = m.a^MUX_COMPLEMENT;
                comb.arg1 = MUX_1;
                comb.arg2 = m.b;
                comb.arg3 = MUX_1;
                unit.ops[i%2] = GL_SUBTRACT_ARB;
            }
            else if( !isTex(m.b) && isTex(m.d) )
            {
                comb.arg0 = m.a;
                comb.arg1 = MUX_1;
                comb.arg2 = m.d;
                comb.arg3 = MUX_1;
                if( isComb(m.d) )
                {
                    swap(comb.arg0, comb.arg2);
                    swap(comb.arg1, comb.arg3);
                }
            }
            else
            {
                comb.arg0 = m.a;
                comb.arg1 = m.b;
                comb.arg2 = m.d;
                comb.arg3 = MUX_1;
                if( isComb(m.d) )
                {
                    swap(comb.arg0, comb.arg2);
                    swap(comb.arg1, comb.arg3);
                }
            }
            break;
        case CM_FMT_TYPE_A_SUB_B_MOD_C: // = (A-B)*C
            comb.arg0 = m.a^MUX_COMPLEMENT;
            comb.arg1 = m.c;
            comb.arg2 = m.c;
            comb.arg3 = m.b;
            unit.ops[i%2] = GL_SUBTRACT_ARB;
            break;
        case CM_FMT_TYPE_AB_ADD_CD:         // = AB+CD
            comb.arg0 = m.a;
            comb.arg1 = m.b;
            comb.arg2 = m.c;
            comb.arg3 = m.d;
            if( isComb(m.d) || isComb(m.c) )
            {
                swap(comb.arg0, comb.arg2);
                swap(comb.arg1, comb.arg3);
            }

            break;
        case CM_FMT_TYPE_AB_SUB_CD:         // = AB-CD
            comb.arg0 = m.a^MUX_COMPLEMENT;
            comb.arg1 = m.b;
            unit.ops[i%2] = GL_SUBTRACT_ARB;
            comb.arg2 = m.c;
            comb.arg3 = m.d;
            break;
        case CM_FMT_TYPE_A_B_C_D:           // = (A-B)*C+D
        default:
            if( !isComb(m.d) && !isTex(m.d) )
            {
                comb.arg0 = m.a^MUX_COMPLEMENT;
                comb.arg1 = m.c;
                unit.ops[i%2] = GL_SUBTRACT_ARB;
                comb.arg2 = m.c;
                comb.arg3 = m.b;
            }
            else if( !isComb(m.b) && !isTex(m.b) )
            {
                comb.arg0 = m.a;
                comb.arg1 = m.c;
                comb.arg2 = m.d;
                comb.arg3 = MUX_1;
                if( isComb(m.d) )
                {
                    swap(comb.arg0, comb.arg2);
                    swap(comb.arg1, comb.arg3);
                }
            }
            else if( !isComb(m.c) && !isTex(m.c) )
            {
                comb.arg0 = m.a;
                comb.arg1 = m.b;
                comb.arg2 = m.d;
                comb.arg3 = MUX_1;
                if( isComb(m.d) )
                {
                    swap(comb.arg0, comb.arg2);
                    swap(comb.arg1, comb.arg3);
                }
            }
            else
            {
                comb.arg0 = m.a;
                comb.arg1 = m.c;
                comb.arg2 = m.d;
                comb.arg3 = MUX_1;
                if( isComb(m.d) )
                {
                    swap(comb.arg0, comb.arg2);
                    swap(comb.arg1, comb.arg3);
                }
            }
            break;
        }
    }

    ParseDecodedMuxForConstants(res);
    return SaveParserResult(res);
}
Esempio n. 2
0
int COGLColorCombinerNvidia::Parse1Mux(COGLDecodedMux &mux, N64StageNumberType stage, NVGeneralCombinerType &res)           // Compile the decodedMux into NV register combiner setting
{
    // Parse 1 N64 combiner, generate result and return how many NV stage is needed.
    // result will be put into only 1 NV stage, not the 2nd one even if 2nd one is needed.
    // The caller of this function will handle the 2nd NV stage if it is needed


    // Up to here, the m_pDecodedMux is already simplied, N64 stage 1 and stage 2 have been
    // adjusted so stage1 is almost always complicated than stage 2

    // The stage type in decodedMux is still in (A-B)*C+D format
    // we need to parser and translate it to A*B+C*D format for NV register general combiner
    // and to A*D+(1-A)*C+D format for the NV final combiner

    // Remember that N64 has two stages, NV has two general combiner stages and 1 final combiner stage
    // NV should be able to simulate exactly all possible N64 combiner settings
/*
    CM_FMT_TYPE1_D,                 // = A              ==> can be done in 1 NV stage
    CM_FMT_TYPE2_A_ADD_D,           // = A+D            ==> can be done in 1 NV stage
    CM_FMT_TYPE3_A_MOD_C,           // = A*C            ==> can be done in 1 NV stage
    CM_FMT_TYPE4_A_SUB_B,           // = A-B            ==> can be done in 1 NV stage
    CM_FMT_TYPE5_A_MOD_C_ADD_D,     // = A*C+D          ==> can be done in 1 NV stage
    CM_FMT_TYPE6_A_LERP_B_C,        // = (A-B)*C+B      ==> can be done in 1 NV stage
    CM_FMT_TYPE8_A_SUB_B_MOD_C,     // = (A-B)*C        ==> can be done in 1 NV stage
    
    CM_FMT_TYPE7_A_SUB_B_ADD_D,     // = A-B+C          ==> can not be done in 1 stage
    CM_FMT_TYPE9_A_B_C_D,           // = (A-B)*C+D      ==> can not be done in 1 stage

    the last two ones, since we can neither do it in the final stage, if the 1st N64 stage
    happen to be one of the two types and have used the two NV general combiners, and if the 2nd N64
    combiner happens to be one of the two types as well, then we have to simplify the N64 combiner so
    to implement it. In such as case, the N64 combiners are too complicated, we just do what either as
    we can to implement it.

    Use UNSIGNED_INVERT of ZERO ==> ONE

    // If the 1st N64 stage can not be done in 1 NV stage, then we will do 1st N64 stage
    // by using 2 NV general combiner stages, and the 2nd N64 stage by using the NV final
    // combiner stage.

    // RGB channel and alpha channel is the same in the general combiner, but different in
    // the final combiner. In fact, final combiner does not do anything for alpha channel
    // so alpha channel setting of both N64 combiner must be implemented by the two NV general
    // combiner

    If we can not implement the two alpha setting in 2 NV combiner stages, we will do what either
    as we can.

    */
    N64CombinerType &m = mux.m_n64Combiners[stage];

    switch(mux.splitType[stage])
    {
    case CM_FMT_TYPE_NOT_USED:
        res.a=MUX_0;
        res.b=MUX_0;
        res.c=MUX_0;
        res.d=MUX_0;
        return 0;
        break;
    case CM_FMT_TYPE_D:             // = A              ==> can be done in 1 NV stage
        res.a=m.d;
        res.b=MUX_1;
        res.c=MUX_0;
        res.d=MUX_0;
        return 1;
        break;
    case CM_FMT_TYPE_A_ADD_D:           // = A+D            ==> can be done in 1 NV stage
        res.a=m.a;
        res.b=MUX_1;
        res.c=m.d;
        res.d=MUX_1;
        return 1;
        break;
    case CM_FMT_TYPE_A_MOD_C:           // = A*C            ==> can be done in 1 NV stage
        res.a=m.a;
        res.b=m.c;
        res.c=MUX_0;
        res.d=MUX_0;
        return 1;
        break;
    case CM_FMT_TYPE_A_SUB_B:           // = A-B            ==> can be done in 1 NV stage
        res.a=m.a;
        res.b=MUX_1;
        res.c=m.b|MUX_NEG;
        res.d=MUX_1;
        return 1;
        break;
    case CM_FMT_TYPE_A_MOD_C_ADD_D: // = A*C+D          ==> can be done in 1 NV stage
        res.a=m.a;
        res.b=m.c;
        res.c=m.d;
        res.d=MUX_1;
        return 1;
        break;
    case CM_FMT_TYPE_A_LERP_B_C:        // = (A-B)*C+B      ==> can be done in 1 NV stage
                                        // = AC+(1-C)B
        res.a=m.a;
        res.b=m.c;
        res.c=m.c^MUX_COMPLEMENT;
        res.d=m.b;
        return 1;
        break;
    case CM_FMT_TYPE_A_SUB_B_MOD_C: // = (A-B)*C        ==> can be done in 1 NV stage
        res.a=m.a;
        res.b=m.c;
        res.c=m.b|MUX_NEG;
        res.d=m.c;
        return 1;
        break;
    case CM_FMT_TYPE_AB_ADD_CD:         // = AB+CD
        res.a = m.a;
        res.b = m.b;
        res.c = m.c;
        res.d = m.d;
        return 1;
        break;
    case CM_FMT_TYPE_AB_SUB_CD:         // = AB-CD
        res.a = m.a;
        res.b = m.b;
        res.c = m.c|MUX_NEG;
        res.d = m.d;
        return 1;
        break;
    case CM_FMT_TYPE_A_SUB_B_ADD_D: // = A-B+D          ==> can not be done in 1 stage
        if( m.a == m.d )    // = 2A-B, simply it to A-B, in fact,we can do 2A-B with NV register combiner
        {
            res.a=m.a;
            res.b=MUX_1;
            res.c=m.b|MUX_NEG;
            res.d=MUX_1;
            return 1;
        }
        else    // Need two NV stages for this N64 combiner
        {
            // Stage 1: R1=A-B
            res.a=m.a;
            res.b=MUX_1;

            if( isTex(res.b) || !isTex(res.d) )
            {
                res.c=m.b|MUX_NEG;
                res.d=MUX_1;
            }
            else
            {
                res.c=m.d;
                res.d=MUX_1;
            }
            return 1;
        }
        break;
    case CM_FMT_TYPE_A_B_C_D:           // = (A-B)*C+D      ==> can not be done in 1 stage
    default:
        if( m.a == m.d )    // = (A-B)*C+A = A(C+1)-B*C = A-B*C
        {
            res.a=m.a;
            res.b=m.c;
            res.c=m.b|MUX_NEG;
            res.d=m.c;
            return 1;
        }
        else if( m.d == m.c )   // = (A-B)*C+C = A*C+(1-B)*C
        {
            res.a=m.a;
            res.b=m.c;
            res.c=m.b^MUX_COMPLEMENT;
            res.d=m.c;
            return 1;
        }
        else    // = (A-B)*C+D, need two NV stages
        {
            // Stage 1: R1=(A-B)*C = AC-BC
            if( isTex(m.d) )
            {
                // = A*C+D
                res.a=m.a;
                res.b=m.c;
                res.c=m.d;
                res.d=MUX_1;
            }
            else
            {
                // = (A-B)*C = A*C - B*C
                res.a=m.a;
                res.b=m.c;
                res.c=m.b|MUX_NEG;
                res.d=m.c;
            }
            return 1;
        }
        break;
    }
}