// File: /workspace/github_cpp_makefile_star2_O1/YiweiMao[P]tessDX/src/tessellator.cpp
// Function: CHWTessellator::QuadGenerateConnectivity(CHWTessellator::PROCESSED_TESS_FACTORS_QUAD const&)
void CHWTessellator::QuadGenerateConnectivity( const PROCESSED_TESS_FACTORS_QUAD& processedTessFactors )
{
    // Generate primitives for all the concentric rings, one side at a time for each ring
    static const int startRing = 1;
    int numPointRowsToCenter[QUAD_AXES] = {((processedTessFactors.numPointsForInsideTessFactor[U]+1) >> 1),
                                            ((processedTessFactors.numPointsForInsideTessFactor[V]+1) >> 1)}; // +1 is so even tess includes the center point
    int numRings = min(numPointRowsToCenter[U],numPointRowsToCenter[V]);
    int degeneratePointRing[QUAD_AXES] = { // Even partitioning causes degenerate row of points,
                                           // which results in exceptions to the point ordering conventions 
                                           // when travelling around the rings counterclockwise.
        (TESSELLATOR_PARITY_EVEN == processedTessFactors.insideTessFactorParity[V]) ? numPointRowsToCenter[V] - 1 : -1,
        (TESSELLATOR_PARITY_EVEN == processedTessFactors.insideTessFactorParity[U]) ? numPointRowsToCenter[U] - 1 : -1 };

    const TESS_FACTOR_CONTEXT* outsideTessFactorCtx[QUAD_EDGES] = {&processedTessFactors.outsideTessFactorCtx[Ueq0],
                                                    &processedTessFactors.outsideTessFactorCtx[Veq0],
                                                    &processedTessFactors.outsideTessFactorCtx[Ueq1],
                                                    &processedTessFactors.outsideTessFactorCtx[Veq1]};
    TESSELLATOR_PARITY outsideTessFactorParity[QUAD_EDGES] = {processedTessFactors.outsideTessFactorParity[Ueq0],
                                                        processedTessFactors.outsideTessFactorParity[Veq0],
                                                        processedTessFactors.outsideTessFactorParity[Ueq1],
                                                        processedTessFactors.outsideTessFactorParity[Veq1]};
    int numPointsForOutsideEdge[QUAD_EDGES] = {processedTessFactors.numPointsForOutsideEdge[Ueq0],
                                              processedTessFactors.numPointsForOutsideEdge[Veq0],
                                              processedTessFactors.numPointsForOutsideEdge[Ueq1],
                                              processedTessFactors.numPointsForOutsideEdge[Veq1]};

    int insideEdgePointBaseOffset = processedTessFactors.insideEdgePointBaseOffset;
    int outsideEdgePointBaseOffset = 0;
    int edge;
    for(int ring = startRing; ring < numRings; ring++)
    {
        int numPointsForInsideEdge[QUAD_AXES] = {processedTessFactors.numPointsForInsideTessFactor[U] - 2*ring,
                                                 processedTessFactors.numPointsForInsideTessFactor[V] - 2*ring};

        int edge0InsidePointBaseOffset = insideEdgePointBaseOffset;
        int edge0OutsidePointBaseOffset = outsideEdgePointBaseOffset;

        for(edge = 0; edge < QUAD_EDGES; edge++ )
        {
            int parity = (edge+1)&0x1;

            int numTriangles = numPointsForInsideEdge[parity] + numPointsForOutsideEdge[edge] - 2;
            int insideBaseOffset;
            int outsideBaseOffset;
            if( edge == 3 ) // We need to patch the indexing so Stitch() can think it sees
                            // 2 sequentially increasing rows of points, even though we have wrapped around
                            // to the end of the inner and outer ring's points, so the last point is really
                            // the first point for the ring.  
                            // We make it so that when Stitch() calls AddIndex(), that function
                            // will do any necessary index adjustment.
            {
                if( ring == degeneratePointRing[parity] )
                {
                    m_IndexPatchContext2.baseIndexToInvert = insideEdgePointBaseOffset + 1;
                    m_IndexPatchContext2.cornerCaseBadValue = outsideEdgePointBaseOffset + numPointsForOutsideEdge[edge] - 1;
                    m_IndexPatchContext2.cornerCaseReplacementValue = edge0OutsidePointBaseOffset;
                    m_IndexPatchContext2.indexInversionEndPoint = (m_IndexPatchContext2.baseIndexToInvert << 1) - 1;
                    insideBaseOffset = m_IndexPatchContext2.baseIndexToInvert;
                    outsideBaseOffset = outsideEdgePointBaseOffset;
                    SetUsingPatchedIndices2(true);
                }
                else
                {
                    m_IndexPatchContext.insidePointIndexDeltaToRealValue    = insideEdgePointBaseOffset;
                    m_IndexPatchContext.insidePointIndexBadValue            = numPointsForInsideEdge[parity] - 1;
                    m_IndexPatchContext.insidePointIndexReplacementValue    = edge0InsidePointBaseOffset;
                    m_IndexPatchContext.outsidePointIndexPatchBase          = m_IndexPatchContext.insidePointIndexBadValue+1; // past inside patched index range
                    m_IndexPatchContext.outsidePointIndexDeltaToRealValue   = outsideEdgePointBaseOffset 
                                                                                - m_IndexPatchContext.outsidePointIndexPatchBase;
                    m_IndexPatchContext.outsidePointIndexBadValue           = m_IndexPatchContext.outsidePointIndexPatchBase
                                                                                + numPointsForOutsideEdge[edge] - 1;
                    m_IndexPatchContext.outsidePointIndexReplacementValue   = edge0OutsidePointBaseOffset;

                    insideBaseOffset = 0;
                    outsideBaseOffset = m_IndexPatchContext.outsidePointIndexPatchBase;
                    SetUsingPatchedIndices(true);
                }
            }
            else if( (edge == 2) && (ring == degeneratePointRing[parity]) )
            {
                m_IndexPatchContext2.baseIndexToInvert = insideEdgePointBaseOffset;
                m_IndexPatchContext2.cornerCaseBadValue = -1; // unused
                m_IndexPatchContext2.cornerCaseReplacementValue = -1; // unused
                m_IndexPatchContext2.indexInversionEndPoint = m_IndexPatchContext2.baseIndexToInvert << 1;
                insideBaseOffset = m_IndexPatchContext2.baseIndexToInvert;
                outsideBaseOffset = outsideEdgePointBaseOffset;
                SetUsingPatchedIndices2(true);
            }
            else
            {
                insideBaseOffset = insideEdgePointBaseOffset;
                outsideBaseOffset = outsideEdgePointBaseOffset;
            }
            if( ring == startRing )
            {
                StitchTransition(/*baseIndexOffset: */m_NumIndices, 
                               insideBaseOffset,processedTessFactors.insideTessFactorCtx[parity].numHalfTessFactorPoints,processedTessFactors.insideTessFactorParity[parity],
                               outsideBaseOffset,outsideTessFactorCtx[edge]->numHalfTessFactorPoints,outsideTessFactorParity[edge]);
            }
            else
            {
                StitchRegular(/*bTrapezoid*/true, DIAGONALS_MIRRORED,
                              /*baseIndexOffset: */m_NumIndices,
                              numPointsForInsideEdge[parity],
                              insideBaseOffset,outsideBaseOffset);
            }
            SetUsingPatchedIndices(false);
            SetUsingPatchedIndices2(false);
            m_NumIndices += numTriangles*3;
            outsideEdgePointBaseOffset += numPointsForOutsideEdge[edge] - 1;
            if( (edge == 2) && (ring == degeneratePointRing[parity]) )
            {
                insideEdgePointBaseOffset -= numPointsForInsideEdge[parity] - 1;
            }
            else
            {
                insideEdgePointBaseOffset += numPointsForInsideEdge[parity] - 1;
            }
            numPointsForOutsideEdge[edge] = numPointsForInsideEdge[parity];
        }
        if( startRing == ring )
        {
            for(edge = 0; edge < QUAD_EDGES; edge++ )
            {
                outsideTessFactorCtx[edge] = &processedTessFactors.insideTessFactorCtx[edge&1];
                outsideTessFactorParity[edge] = processedTessFactors.insideTessFactorParity[edge&1];
            }
        }
    }

    // Triangulate center - a row of quads if odd
    // This triangulation may be producing diagonals that are asymmetric about 
    // the center of the patch in this region.  
    if( (processedTessFactors.numPointsForInsideTessFactor[U] > processedTessFactors.numPointsForInsideTessFactor[V]) && 
        (TESSELLATOR_PARITY_ODD == processedTessFactors.insideTessFactorParity[V] ) )
    {
        SetUsingPatchedIndices2(true);
        int stripNumQuads = (((processedTessFactors.numPointsForInsideTessFactor[U]>>1) - (processedTessFactors.numPointsForInsideTessFactor[V]>>1))<<1)+
                            ((TESSELLATOR_PARITY_EVEN == processedTessFactors.insideTessFactorParity[U] ) ? 2 : 1);
        m_IndexPatchContext2.baseIndexToInvert = outsideEdgePointBaseOffset + stripNumQuads + 2;
        m_IndexPatchContext2.cornerCaseBadValue = m_IndexPatchContext2.baseIndexToInvert;
        m_IndexPatchContext2.cornerCaseReplacementValue = outsideEdgePointBaseOffset;
        m_IndexPatchContext2.indexInversionEndPoint = m_IndexPatchContext2.baseIndexToInvert + 
                                                      m_IndexPatchContext2.baseIndexToInvert + stripNumQuads;
        StitchRegular(/*bTrapezoid*/false,DIAGONALS_INSIDE_TO_OUTSIDE,
                       /*baseIndexOffset: */m_NumIndices, /*numInsideEdgePoints:*/stripNumQuads+1,
                       /*insideEdgePointBaseOffset*/m_IndexPatchContext2.baseIndexToInvert,
                       outsideEdgePointBaseOffset+1);
        SetUsingPatchedIndices2(false);
        m_NumIndices += stripNumQuads*6;
    }
    else if((processedTessFactors.numPointsForInsideTessFactor[V] >= processedTessFactors.numPointsForInsideTessFactor[U]) && 
            (TESSELLATOR_PARITY_ODD == processedTessFactors.insideTessFactorParity[U]) )
    {
        SetUsingPatchedIndices2(true);
        int stripNumQuads = (((processedTessFactors.numPointsForInsideTessFactor[V]>>1) - (processedTessFactors.numPointsForInsideTessFactor[U]>>1))<<1)+
                            ((TESSELLATOR_PARITY_EVEN == processedTessFactors.insideTessFactorParity[V] ) ? 2 : 1);
        m_IndexPatchContext2.baseIndexToInvert = outsideEdgePointBaseOffset + stripNumQuads + 1;
        m_IndexPatchContext2.cornerCaseBadValue = -1; // unused
        m_IndexPatchContext2.indexInversionEndPoint = m_IndexPatchContext2.baseIndexToInvert + 
                                                      m_IndexPatchContext2.baseIndexToInvert + stripNumQuads;
		DIAGONALS diag = (TESSELLATOR_PARITY_EVEN == processedTessFactors.insideTessFactorParity[V]) ?  
							DIAGONALS_INSIDE_TO_OUTSIDE : DIAGONALS_INSIDE_TO_OUTSIDE_EXCEPT_MIDDLE;
        StitchRegular(/*bTrapezoid*/false,diag,
                       /*baseIndexOffset: */m_NumIndices, /*numInsideEdgePoints:*/stripNumQuads+1,
                       /*insideEdgePointBaseOffset*/m_IndexPatchContext2.baseIndexToInvert,
                       outsideEdgePointBaseOffset);
        SetUsingPatchedIndices2(false);
        m_NumIndices += stripNumQuads*6;
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa8, %rsp
movl 0xbc(%rsi), %eax
movl 0xc0(%rsi), %ecx
incl %eax
sarl %eax
incl %ecx
sarl %ecx
cmpl %ecx, %eax
movl %ecx, %r8d
cmovll %eax, %r8d
decl %ecx
xorl %r11d, %r11d
cmpl 0x2c(%rsi), %r11d
movl $0x0, %edx
sbbl %edx, %edx
orl %ecx, %edx
movl %edx, 0x20(%rsp)
decl %eax
cmpl 0x28(%rsi), %r11d
movl $0x0, %ecx
sbbl %ecx, %ecx
movq %rdi, %r12
orl %eax, %ecx
movl %ecx, 0x24(%rsp)
leaq 0x30(%rsi), %rax
movq %rax, 0x80(%rsp)
leaq 0x44(%rsi), %rax
movq %rax, 0x88(%rsp)
leaq 0x58(%rsi), %rax
movq %rax, 0x90(%rsp)
leaq 0x6c(%rsi), %rax
movq %rax, 0x98(%rsp)
movl 0x18(%rsi), %eax
movl %eax, 0x40(%rsp)
movl 0x1c(%rsi), %eax
movl %eax, 0x44(%rsp)
movl 0x20(%rsi), %eax
movl %eax, 0x48(%rsp)
movl 0x24(%rsi), %eax
movl %eax, 0x4c(%rsp)
movl 0xac(%rsi), %eax
movl %eax, 0x30(%rsp)
movl 0xb0(%rsi), %eax
movl %eax, 0x34(%rsp)
movl 0xb4(%rsi), %eax
movl %eax, 0x38(%rsp)
movl 0xb8(%rsi), %eax
movl %eax, 0x3c(%rsp)
movl %r8d, 0x28(%rsp)
cmpl $0x2, %r8d
jl 0x402f48
movl 0xc4(%rsi), %r10d
leaq 0x80(%rsi), %r9
movl $0x1, %r8d
xorl %r11d, %r11d
movq %rsi, 0x58(%rsp)
movq %r9, 0x50(%rsp)
movl 0xbc(%rsi), %eax
leal (%r8,%r8), %ecx
subl %ecx, %eax
movl %eax, 0x60(%rsp)
movl 0xc0(%rsi), %eax
subl %ecx, %eax
movl %eax, 0x64(%rsp)
movl $0x1, %r13d
movl %r10d, 0x2c(%rsp)
movl %r11d, 0x1c(%rsp)
movl %r13d, %ebp
andl $0x1, %ebp
movl %ebp, %eax
movl 0x60(%rsp,%rax,4), %r15d
movl 0x2c(%rsp,%r13,4), %edx
leal (%rdx,%r15), %ebx
leal -0x1(%r13), %ecx
movl %r10d, %eax
movl %r11d, %r9d
cmpl $0x2, %ecx
je 0x402db5
cmpl $0x3, %ecx
jne 0x402e24
cmpl 0x20(%rsp,%rbp,4), %r8d
jne 0x402de1
leal 0x1(%r10), %eax
movl %eax, 0x50(%r12)
leal (%r11,%rdx), %ecx
decl %ecx
movl %ecx, 0x58(%r12)
movl 0x1c(%rsp), %ecx
movl %ecx, 0x5c(%r12)
leal 0x1(,%r10,2), %ecx
movl %ecx, 0x54(%r12)
movb $0x1, 0x32(%r12)
jmp 0x402ddc
cmpl 0x20(%rsp,%rbp,4), %r8d
jne 0x402e24
movl %r10d, 0x50(%r12)
movq $-0x1, 0x58(%r12)
leal (%r10,%r10), %eax
movl %eax, 0x54(%r12)
movb $0x1, 0x32(%r12)
movl %r10d, %eax
movl %r11d, %r9d
jmp 0x402e24
movl %r10d, 0x34(%r12)
leal -0x1(%r15), %eax
movl %eax, 0x38(%r12)
movl 0x2c(%rsp), %eax
movl %eax, 0x3c(%r12)
movl %r15d, 0x40(%r12)
movl %r11d, %eax
subl %r15d, %eax
movl %eax, 0x44(%r12)
leal -0x1(%rbx), %eax
movl %eax, 0x48(%r12)
movl 0x1c(%rsp), %eax
movl %eax, 0x4c(%r12)
movb $0x1, 0x31(%r12)
xorl %eax, %eax
movl %r15d, %r9d
movq %rdx, 0x70(%rsp)
movq %r11, 0x78(%rsp)
movq %r10, 0x68(%rsp)
movq %r8, %r14
cmpl $0x1, %r8d
jne 0x402e80
movl 0x2c(%r12), %esi
leaq (,%rbp,4), %rcx
addq %rbp, %rcx
movq 0x50(%rsp), %rdx
movl 0xc(%rdx,%rcx,4), %ecx
movq 0x58(%rsp), %rdx
movl 0x28(%rdx,%rbp,4), %r8d
movq 0x78(%rsp,%r13,8), %rdx
movl 0xc(%rdx), %edx
movl 0x3c(%rsp,%r13,4), %r10d
movl %r10d, 0x8(%rsp)
movl %edx, (%rsp)
movq %r12, %rdi
movl %eax, %edx
callq 0x403248
jmp 0x402ea1
movl 0x2c(%r12), %ecx
movl %r9d, (%rsp)
movq %r12, %rdi
movl $0x1, %esi
movl $0x2, %edx
movl %r15d, %r8d
movl %eax, %r9d
callq 0x40353c
movw $0x0, 0x31(%r12)
leal (%rbx,%rbx,2), %eax
movl 0x2c(%r12), %ecx
addl %ecx, %eax
addl $-0x6, %eax
movl %eax, 0x2c(%r12)
cmpq $0x3, %r13
movq %r14, %r8
movq 0x68(%rsp), %r10
movq 0x78(%rsp), %r11
movq 0x70(%rsp), %rax
jne 0x402ee2
cmpl 0x20(%rsp,%rbp,4), %r8d
jne 0x402ee2
subl %r15d, %r10d
incl %r10d
jmp 0x402ee8
addl %r15d, %r10d
decl %r10d
addl %eax, %r11d
decl %r11d
movl %r15d, 0x2c(%rsp,%r13,4)
incq %r13
cmpq $0x5, %r13
jne 0x402d4e
cmpl $0x1, %r8d
movq 0x58(%rsp), %rsi
movq 0x50(%rsp), %r9
jne 0x402f3a
xorl %eax, %eax
movl %eax, %ecx
andl $0x1, %ecx
leaq (%rcx,%rcx,4), %rdx
leaq (%r9,%rdx,4), %rdx
movq %rdx, 0x80(%rsp,%rax,8)
movl %ecx, %ecx
movl 0x28(%rsi,%rcx,4), %ecx
movl %ecx, 0x40(%rsp,%rax,4)
incq %rax
cmpq $0x4, %rax
jne 0x402f12
incl %r8d
cmpl 0x28(%rsp), %r8d
jne 0x402d22
movl 0x2c(%rsi), %ecx
movl 0xbc(%rsi), %edx
movl 0xc0(%rsi), %eax
cmpl %eax, %edx
setg %r8b
cmpl $0x1, %ecx
sete %r9b
testb %r9b, %r8b
je 0x402fd1
leaq 0x32(%r12), %r14
movb $0x1, 0x32(%r12)
andl $-0x2, %eax
subl %eax, %edx
andl $-0x2, %edx
xorl %eax, %eax
cmpl $0x0, 0x28(%rsi)
sete %al
leal (%rax,%rdx), %ecx
leal 0x1(%rax,%rdx), %r15d
leal 0x1(%r11,%rcx), %esi
leal 0x3(%r11,%rcx), %r9d
movl %r9d, 0x50(%r12)
movl %r9d, 0x58(%r12)
movl %r11d, 0x5c(%r12)
leal 0x5(%rcx,%rsi,2), %ecx
movl %ecx, 0x54(%r12)
leaq 0x2c(%r12), %r13
movl 0x2c(%r12), %ecx
leal (%rax,%rdx), %r8d
addl $0x2, %r8d
incl %r11d
movl %r11d, (%rsp)
movq %r12, %rdi
xorl %esi, %esi
xorl %edx, %edx
jmp 0x40303b
cmpl %edx, %eax
jl 0x40304e
cmpl $0x1, 0x28(%rsi)
jne 0x40304e
leaq 0x32(%r12), %r14
movb $0x1, 0x32(%r12)
andl $-0x2, %edx
subl %edx, %eax
andl $-0x2, %eax
xorl %esi, %esi
xorl %edx, %edx
testl %ecx, %ecx
sete %sil
setne %dl
leal (%rsi,%rax), %ecx
leal 0x1(%rsi,%rax), %r15d
leal 0x2(%r11,%rcx), %r9d
movl %r9d, 0x50(%r12)
movl $0xffffffff, 0x58(%r12) # imm = 0xFFFFFFFF
leal 0x1(%rcx,%r9,2), %ecx
movl %ecx, 0x54(%r12)
leaq 0x2c(%r12), %r13
movl 0x2c(%r12), %ecx
leal (%rsi,%rax), %r8d
addl $0x2, %r8d
movl %r11d, (%rsp)
movq %r12, %rdi
xorl %esi, %esi
callq 0x40353c
movb $0x0, (%r14)
leal (%r15,%r15,2), %eax
addl %eax, %eax
addl %eax, (%r13)
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq